summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf5
-rw-r--r--examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc6
-rw-r--r--examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc8
-rw-r--r--examples/qt3d/audio-visualizer-qml/touchsettings.cpp3
-rw-r--r--examples/qt3d/controlsunderlay/Logo.qml126
-rw-r--r--examples/qt3d/controlsunderlay/Qt_logo.obj4071
-rw-r--r--examples/qt3d/controlsunderlay/controls.qrc7
-rw-r--r--examples/qt3d/controlsunderlay/controlsunderlay.pro12
-rw-r--r--examples/qt3d/controlsunderlay/main.cpp70
-rw-r--r--examples/qt3d/controlsunderlay/main.qml231
-rw-r--r--examples/qt3d/planets-qml/SolarSystem.qml14
-rw-r--r--examples/qt3d/planets-qml/android/AndroidManifest.xml8
-rw-r--r--examples/qt3d/planets-qml/doc/src/planets-qml.qdoc14
-rw-r--r--examples/qt3d/planets-qml/planets.js32
-rw-r--r--examples/qt3d/qt3d.pro4
-rw-r--r--examples/qt3d/scene3dview/AnimatedEntity.qml143
-rw-r--r--examples/qt3d/scene3dview/doc/images/scene3dview.pngbin0 -> 28772 bytes
-rw-r--r--examples/qt3d/scene3dview/doc/src/scene3dview.qdoc62
-rw-r--r--examples/qt3d/scene3dview/main.cpp66
-rw-r--r--examples/qt3d/scene3dview/main.qml142
-rw-r--r--examples/qt3d/scene3dview/scene3dview.pro15
-rw-r--r--examples/qt3d/scene3dview/scene3dview.qrc6
-rw-r--r--examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc2
-rw-r--r--src/animation/animation.pro3
-rw-r--r--src/animation/backend/abstractevaluateclipanimatorjob.cpp122
-rw-r--r--src/animation/backend/abstractevaluateclipanimatorjob_p.h74
-rw-r--r--src/animation/backend/additiveclipblend.cpp31
-rw-r--r--src/animation/backend/additiveclipblend_p.h4
-rw-r--r--src/animation/backend/animationclip.cpp76
-rw-r--r--src/animation/backend/animationclip_p.h3
-rw-r--r--src/animation/backend/animationutils.cpp50
-rw-r--r--src/animation/backend/animationutils_p.h37
-rw-r--r--src/animation/backend/backend.pri2
-rw-r--r--src/animation/backend/backendnode.cpp9
-rw-r--r--src/animation/backend/backendnode_p.h2
-rw-r--r--src/animation/backend/blendedclipanimator.cpp87
-rw-r--r--src/animation/backend/blendedclipanimator_p.h6
-rw-r--r--src/animation/backend/buildblendtreesjob.cpp6
-rw-r--r--src/animation/backend/channelmapper.cpp50
-rw-r--r--src/animation/backend/channelmapper_p.h3
-rw-r--r--src/animation/backend/channelmapping.cpp96
-rw-r--r--src/animation/backend/channelmapping_p.h4
-rw-r--r--src/animation/backend/clipanimator.cpp83
-rw-r--r--src/animation/backend/clipanimator_p.h7
-rw-r--r--src/animation/backend/clipblendnode.cpp2
-rw-r--r--src/animation/backend/clipblendvalue.cpp21
-rw-r--r--src/animation/backend/clipblendvalue_p.h4
-rw-r--r--src/animation/backend/clock.cpp28
-rw-r--r--src/animation/backend/clock_p.h4
-rw-r--r--src/animation/backend/evaluateblendclipanimatorjob.cpp33
-rw-r--r--src/animation/backend/evaluateblendclipanimatorjob_p.h5
-rw-r--r--src/animation/backend/evaluateclipanimatorjob.cpp28
-rw-r--r--src/animation/backend/evaluateclipanimatorjob_p.h4
-rw-r--r--src/animation/backend/findrunningclipanimatorsjob.cpp3
-rw-r--r--src/animation/backend/gltfimporter.cpp3
-rw-r--r--src/animation/backend/lerpclipblend.cpp34
-rw-r--r--src/animation/backend/lerpclipblend_p.h4
-rw-r--r--src/animation/backend/loadanimationclipjob.cpp46
-rw-r--r--src/animation/backend/loadanimationclipjob_p.h1
-rw-r--r--src/animation/backend/skeleton.cpp49
-rw-r--r--src/animation/backend/skeleton_p.h7
-rw-r--r--src/animation/frontend/qabstractanimationclip.cpp21
-rw-r--r--src/animation/frontend/qabstractanimationclip.h2
-rw-r--r--src/animation/frontend/qabstractchannelmapping.cpp1
-rw-r--r--src/animation/frontend/qabstractclipanimator.cpp12
-rw-r--r--src/animation/frontend/qabstractclipanimator.h2
-rw-r--r--src/animation/frontend/qanimationaspect.cpp26
-rw-r--r--src/animation/frontend/qanimationaspect_p.h2
-rw-r--r--src/animation/frontend/qanimationcallback.qdoc51
-rw-r--r--src/animation/frontend/qanimationclip.cpp4
-rw-r--r--src/animation/frontend/qanimationclipdata.cpp2
-rw-r--r--src/animation/frontend/qanimationcliploader.cpp19
-rw-r--r--src/animation/frontend/qanimationcliploader.h1
-rw-r--r--src/animation/frontend/qcallbackmapping.cpp18
-rw-r--r--src/animation/frontend/qchannel.cpp2
-rw-r--r--src/animation/frontend/qchannelmapper.cpp17
-rw-r--r--src/animation/frontend/qchannelmapping.cpp28
-rw-r--r--src/animation/frontend/qclipanimator.cpp3
-rw-r--r--src/animation/frontend/qclipblendvalue.cpp4
-rw-r--r--src/animation/frontend/qclock.cpp1
-rw-r--r--src/animation/frontend/qmorphtarget.cpp4
-rw-r--r--src/animation/frontend/qvertexblendanimation.cpp4
-rw-r--r--src/core/aspects/aspects.pri6
-rw-r--r--src/core/aspects/qabstractaspect.cpp297
-rw-r--r--src/core/aspects/qabstractaspect.h3
-rw-r--r--src/core/aspects/qabstractaspect_p.h50
-rw-r--r--src/core/aspects/qaspectengine.cpp140
-rw-r--r--src/core/aspects/qaspectengine.h11
-rw-r--r--src/core/aspects/qaspectengine_p.h12
-rw-r--r--src/core/aspects/qaspectmanager.cpp402
-rw-r--r--src/core/aspects/qaspectmanager_p.h33
-rw-r--r--src/core/aspects/qaspectthread.cpp99
-rw-r--r--src/core/changes/qscenechange.h1
-rw-r--r--src/core/changes/qscenechange_p.h8
-rw-r--r--src/core/core.pri6
-rw-r--r--src/core/core.pro3
-rw-r--r--src/core/jobs/qaspectjob.cpp12
-rw-r--r--src/core/jobs/qaspectjob.h1
-rw-r--r--src/core/jobs/qaspectjob_p.h8
-rw-r--r--src/core/jobs/qaspectjobmanager.cpp2
-rw-r--r--src/core/jobs/qthreadpooler.cpp12
-rw-r--r--src/core/jobs/task.cpp3
-rw-r--r--src/core/nodes/qbackendnode.cpp36
-rw-r--r--src/core/nodes/qbackendnode.h2
-rw-r--r--src/core/nodes/qbackendnode_p.h7
-rw-r--r--src/core/nodes/qcomponent.cpp7
-rw-r--r--src/core/nodes/qentity.cpp39
-rw-r--r--src/core/nodes/qnode.cpp131
-rw-r--r--src/core/nodes/qnode.h1
-rw-r--r--src/core/nodes/qnode_p.h8
-rw-r--r--src/core/qchangearbiter.cpp80
-rw-r--r--src/core/qchangearbiter_p.h28
-rw-r--r--src/core/qscene.cpp6
-rw-r--r--src/core/qscene_p.h5
-rw-r--r--src/core/qscheduler.cpp5
-rw-r--r--src/core/resources/qframeallocator.cpp2
-rw-r--r--src/core/services/qdownloadhelperservice.cpp4
-rw-r--r--src/core/services/qeventfilterservice.cpp29
-rw-r--r--src/core/transforms/qabstractskeleton.cpp27
-rw-r--r--src/core/transforms/qabstractskeleton.h3
-rw-r--r--src/core/transforms/qabstractskeleton_p.h6
-rw-r--r--src/core/transforms/qarmature_p.h2
-rw-r--r--src/core/transforms/qjoint.cpp18
-rw-r--r--src/core/transforms/qjoint_p.h2
-rw-r--r--src/core/transforms/qskeleton_p.h2
-rw-r--r--src/core/transforms/qskeletonloader.cpp50
-rw-r--r--src/core/transforms/qskeletonloader_p.h3
-rw-r--r--src/core/transforms/qtransform.cpp68
-rw-r--r--src/core/transforms/qtransform.h5
-rw-r--r--src/core/transforms/qtransform_p.h6
-rw-r--r--src/core/transforms/sqt_p.h2
-rw-r--r--src/extras/defaults/qabstractspritesheet.cpp2
-rw-r--r--src/extras/defaults/qforwardrenderer.cpp25
-rw-r--r--src/extras/defaults/qforwardrenderer.h6
-rw-r--r--src/extras/defaults/qt3dwindow.cpp8
-rw-r--r--src/extras/defaults/qtexturematerial.cpp6
-rw-r--r--src/extras/extras.pro3
-rw-r--r--src/extras/text/qdistancefieldglyphcache.cpp4
-rw-r--r--src/extras/text/qtextureatlas.cpp3
-rw-r--r--src/input/backend/abstractactioninput.cpp2
-rw-r--r--src/input/backend/abstractactioninput_p.h4
-rw-r--r--src/input/backend/abstractaxisinput.cpp25
-rw-r--r--src/input/backend/abstractaxisinput_p.h7
-rw-r--r--src/input/backend/action.cpp47
-rw-r--r--src/input/backend/action_p.h8
-rw-r--r--src/input/backend/actioninput.cpp30
-rw-r--r--src/input/backend/actioninput_p.h4
-rw-r--r--src/input/backend/analogaxisinput.cpp24
-rw-r--r--src/input/backend/analogaxisinput_p.h4
-rw-r--r--src/input/backend/assignkeyboardfocusjob.cpp38
-rw-r--r--src/input/backend/assignkeyboardfocusjob_p.h1
-rw-r--r--src/input/backend/axis.cpp48
-rw-r--r--src/input/backend/axis_p.h8
-rw-r--r--src/input/backend/axisaccumulator.cpp63
-rw-r--r--src/input/backend/axisaccumulator_p.h7
-rw-r--r--src/input/backend/axisaccumulatorjob.cpp39
-rw-r--r--src/input/backend/axisaccumulatorjob_p.h1
-rw-r--r--src/input/backend/axissetting.cpp33
-rw-r--r--src/input/backend/axissetting_p.h8
-rw-r--r--src/input/backend/backend.pri2
-rw-r--r--src/input/backend/backendnode.cpp (renamed from src/render/renderers/opengl/renderer/glcommands.cpp)37
-rw-r--r--src/input/backend/backendnode_p.h (renamed from src/core/aspects/qaspectthread_p.h)39
-rw-r--r--src/input/backend/buttonaxisinput.cpp36
-rw-r--r--src/input/backend/buttonaxisinput_p.h3
-rw-r--r--src/input/backend/eventsourcesetterhelper.cpp25
-rw-r--r--src/input/backend/eventsourcesetterhelper_p.h6
-rw-r--r--src/input/backend/genericdevicebackendnode.cpp28
-rw-r--r--src/input/backend/genericdevicebackendnode_p.h2
-rw-r--r--src/input/backend/inputchord.cpp50
-rw-r--r--src/input/backend/inputchord_p.h4
-rw-r--r--src/input/backend/inputhandler.cpp20
-rw-r--r--src/input/backend/inputsequence.cpp57
-rw-r--r--src/input/backend/inputsequence_p.h4
-rw-r--r--src/input/backend/inputsettings.cpp22
-rw-r--r--src/input/backend/inputsettings_p.h9
-rw-r--r--src/input/backend/keyboarddevice.cpp5
-rw-r--r--src/input/backend/keyboarddevice_p.h3
-rw-r--r--src/input/backend/keyboardeventfilter.cpp1
-rw-r--r--src/input/backend/keyboardhandler.cpp58
-rw-r--r--src/input/backend/keyboardhandler_p.h9
-rw-r--r--src/input/backend/keyeventdispatcherjob.cpp47
-rw-r--r--src/input/backend/keyeventdispatcherjob_p.h3
-rw-r--r--src/input/backend/loadproxydevicejob.cpp43
-rw-r--r--src/input/backend/loadproxydevicejob_p.h1
-rw-r--r--src/input/backend/logicaldevice.cpp45
-rw-r--r--src/input/backend/logicaldevice_p.h8
-rw-r--r--src/input/backend/mousedevice.cpp23
-rw-r--r--src/input/backend/mousedevice_p.h4
-rw-r--r--src/input/backend/mouseeventdispatcherjob.cpp57
-rw-r--r--src/input/backend/mouseeventdispatcherjob_p.h6
-rw-r--r--src/input/backend/mouseeventfilter.cpp1
-rw-r--r--src/input/backend/mousehandler.cpp50
-rw-r--r--src/input/backend/mousehandler_p.h12
-rw-r--r--src/input/backend/physicaldeviceproxy.cpp28
-rw-r--r--src/input/backend/physicaldeviceproxy_p.h8
-rw-r--r--src/input/backend/qabstractphysicaldevicebackendnode.cpp93
-rw-r--r--src/input/backend/qabstractphysicaldevicebackendnode_p.h8
-rw-r--r--src/input/backend/qabstractphysicaldevicebackendnode_p_p.h5
-rw-r--r--src/input/backend/updateaxisactionjob.cpp63
-rw-r--r--src/input/backend/updateaxisactionjob_p.h1
-rw-r--r--src/input/frontend/qabstractphysicaldevice.cpp31
-rw-r--r--src/input/frontend/qabstractphysicaldevice_p.h3
-rw-r--r--src/input/frontend/qabstractphysicaldeviceproxy.cpp52
-rw-r--r--src/input/frontend/qabstractphysicaldeviceproxy_p.h3
-rw-r--r--src/input/frontend/qabstractphysicaldeviceproxy_p_p.h2
-rw-r--r--src/input/frontend/qaction.cpp24
-rw-r--r--src/input/frontend/qaction.h1
-rw-r--r--src/input/frontend/qactioninput.cpp2
-rw-r--r--src/input/frontend/qaxis.cpp25
-rw-r--r--src/input/frontend/qaxis.h1
-rw-r--r--src/input/frontend/qaxisaccumulator.cpp11
-rw-r--r--src/input/frontend/qaxisaccumulator.h1
-rw-r--r--src/input/frontend/qinputaspect.cpp46
-rw-r--r--src/input/frontend/qinputaspect_p.h1
-rw-r--r--src/input/frontend/qinputchord.cpp16
-rw-r--r--src/input/frontend/qinputsequence.cpp15
-rw-r--r--src/input/frontend/qkeyboarddevice.cpp12
-rw-r--r--src/input/frontend/qkeyboarddevice.h1
-rw-r--r--src/input/frontend/qkeyboardhandler.cpp23
-rw-r--r--src/input/frontend/qkeyboardhandler.h1
-rw-r--r--src/input/frontend/qkeyevent.cpp6
-rw-r--r--src/input/frontend/qlogicaldevice.cpp28
-rw-r--r--src/input/frontend/qmouseevent.cpp60
-rw-r--r--src/input/frontend/qmouseevent.h6
-rw-r--r--src/input/frontend/qmousehandler.cpp30
-rw-r--r--src/input/frontend/qmousehandler.h1
-rw-r--r--src/input/frontend/qphysicaldevicecreatedchange.cpp2
-rw-r--r--src/input/input.pro3
-rw-r--r--src/logic/executor.cpp6
-rw-r--r--src/logic/executor_p.h2
-rw-r--r--src/logic/logic.pro3
-rw-r--r--src/logic/manager.cpp8
-rw-r--r--src/logic/manager_p.h1
-rw-r--r--src/plugins/geometryloaders/default/default.pro3
-rw-r--r--src/plugins/geometryloaders/fbx/fbx.pro3
-rw-r--r--src/plugins/geometryloaders/gltf/gltf.pro3
-rw-r--r--src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp3
-rw-r--r--src/plugins/renderplugins/scene2d/scene2d.pro3
-rw-r--r--src/plugins/renderplugins/scene2d/scene2dplugin.cpp2
-rw-r--r--src/plugins/sceneparsers/assimp/assimp.pro3
-rw-r--r--src/plugins/sceneparsers/assimp/assimphelpers.cpp57
-rw-r--r--src/plugins/sceneparsers/assimp/assimphelpers.h6
-rw-r--r--src/plugins/sceneparsers/assimp/assimpimporter.h2
-rw-r--r--src/plugins/sceneparsers/gltf/gltf.pro3
-rw-r--r--src/plugins/sceneparsers/gltf/gltfimporter.cpp20
-rw-r--r--src/plugins/sceneparsers/gltf/gltfparser.cpp1560
-rw-r--r--src/plugins/sceneparsers/gltfexport/gltfexport.pro3
-rw-r--r--src/plugins/sceneparsers/gltfexport/gltfexporter.cpp7
-rw-r--r--src/quick3d/imports/animation/importsanimation.pro3
-rw-r--r--src/quick3d/imports/animation/plugins.qmltypes55
-rw-r--r--src/quick3d/imports/core/importscore.pro3
-rw-r--r--src/quick3d/imports/core/plugins.qmltypes73
-rw-r--r--src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp1
-rw-r--r--src/quick3d/imports/extras/importsextras.pro3
-rw-r--r--src/quick3d/imports/extras/plugins.qmltypes55
-rw-r--r--src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp1
-rw-r--r--src/quick3d/imports/input/importsinput.pro3
-rw-r--r--src/quick3d/imports/input/plugins.qmltypes2
-rw-r--r--src/quick3d/imports/logic/importslogic.pro3
-rw-r--r--src/quick3d/imports/logic/plugins.qmltypes2
-rw-r--r--src/quick3d/imports/render/importsrender.pro3
-rw-r--r--src/quick3d/imports/render/plugins.qmltypes255
-rw-r--r--src/quick3d/imports/render/qt3dquick3drenderplugin.cpp12
-rw-r--r--src/quick3d/imports/scene2d/importsscene2d.pro3
-rw-r--r--src/quick3d/imports/scene2d/plugins.qmltypes2
-rw-r--r--src/quick3d/imports/scene3d/importsscene3d.pro9
-rw-r--r--src/quick3d/imports/scene3d/plugins.qmltypes38
-rw-r--r--src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp3
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem.cpp346
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem_p.h26
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer.cpp196
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer_p.h23
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterial.cpp1
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterial_p.h4
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp37
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h1
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgnode.cpp13
-rw-r--r--src/quick3d/imports/scene3d/scene3dsgnode_p.h4
-rw-r--r--src/quick3d/imports/scene3d/scene3dview.cpp320
-rw-r--r--src/quick3d/imports/scene3d/scene3dview_p.h (renamed from src/render/renderers/opengl/renderer/commandthread_p.h)108
-rw-r--r--src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp6
-rw-r--r--src/quick3d/quick3d/qt3dquick_global.cpp5
-rw-r--r--src/quick3d/quick3d/quick3d.pro3
-rw-r--r--src/quick3d/quick3danimation/quick3danimation.pro3
-rw-r--r--src/quick3d/quick3dextras/quick3dextras.pro3
-rw-r--r--src/quick3d/quick3dinput/quick3dinput.pro3
-rw-r--r--src/quick3d/quick3drender/items/quick3dparameter_p.h4
-rw-r--r--src/quick3d/quick3drender/items/quick3draycaster.cpp38
-rw-r--r--src/quick3d/quick3drender/quick3drender.pro3
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.cpp31
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d.h5
-rw-r--r--src/quick3d/quick3dscene2d/items/qscene2d_p.h2
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d.cpp165
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2d_p.h10
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dmanager.cpp2
-rw-r--r--src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp3
-rw-r--r--src/quick3d/quick3dscene2d/quick3dscene2d.pro3
-rw-r--r--src/render/backend/abstractrenderer_p.h8
-rw-r--r--src/render/backend/backendnode.cpp14
-rw-r--r--src/render/backend/backendnode_p.h9
-rw-r--r--src/render/backend/cameralens.cpp93
-rw-r--r--src/render/backend/cameralens_p.h6
-rw-r--r--src/render/backend/commandexecuter.cpp24
-rw-r--r--src/render/backend/computecommand.cpp81
-rw-r--r--src/render/backend/computecommand_p.h6
-rw-r--r--src/render/backend/entity.cpp200
-rw-r--r--src/render/backend/entity_p.h16
-rw-r--r--src/render/backend/entity_p_p.h87
-rw-r--r--src/render/backend/handle_types_p.h4
-rw-r--r--src/render/backend/layer.cpp33
-rw-r--r--src/render/backend/layer_p.h4
-rw-r--r--src/render/backend/levelofdetail.cpp75
-rw-r--r--src/render/backend/levelofdetail_p.h3
-rw-r--r--src/render/backend/managers_p.h11
-rw-r--r--src/render/backend/nodemanagers.cpp95
-rw-r--r--src/render/backend/nodemanagers_p.h168
-rw-r--r--src/render/backend/render-backend.pri1
-rw-r--r--src/render/backend/rendersettings.cpp72
-rw-r--r--src/render/backend/rendersettings_p.h4
-rw-r--r--src/render/backend/rendertarget.cpp48
-rw-r--r--src/render/backend/rendertarget_p.h4
-rw-r--r--src/render/backend/rendertargetoutput.cpp66
-rw-r--r--src/render/backend/rendertargetoutput_p.h3
-rw-r--r--src/render/backend/resourceaccessor.cpp1
-rw-r--r--src/render/backend/transform.cpp45
-rw-r--r--src/render/backend/transform_p.h7
-rw-r--r--src/render/backend/uniform_p.h8
-rw-r--r--src/render/framegraph/blitframebuffer.cpp77
-rw-r--r--src/render/framegraph/blitframebuffer_p.h4
-rw-r--r--src/render/framegraph/buffercapture.cpp1
-rw-r--r--src/render/framegraph/cameraselectornode.cpp28
-rw-r--r--src/render/framegraph/cameraselectornode_p.h5
-rw-r--r--src/render/framegraph/clearbuffers.cpp71
-rw-r--r--src/render/framegraph/clearbuffers_p.h5
-rw-r--r--src/render/framegraph/dispatchcompute.cpp41
-rw-r--r--src/render/framegraph/dispatchcompute_p.h4
-rw-r--r--src/render/framegraph/framegraph.pri13
-rw-r--r--src/render/framegraph/framegraphnode.cpp50
-rw-r--r--src/render/framegraph/framegraphnode_p.h8
-rw-r--r--src/render/framegraph/framegraphvisitor.cpp21
-rw-r--r--src/render/framegraph/framegraphvisitor_p.h2
-rw-r--r--src/render/framegraph/frustumculling.cpp1
-rw-r--r--src/render/framegraph/layerfilternode.cpp51
-rw-r--r--src/render/framegraph/layerfilternode_p.h6
-rw-r--r--src/render/framegraph/memorybarrier.cpp27
-rw-r--r--src/render/framegraph/memorybarrier_p.h3
-rw-r--r--src/render/framegraph/nodraw.cpp1
-rw-r--r--src/render/framegraph/nopicking.cpp (renamed from src/core/qsceneobserverinterface.cpp)19
-rw-r--r--src/render/framegraph/nopicking_p.h (renamed from src/core/qbackendnodefactory_p.h)27
-rw-r--r--src/render/framegraph/proximityfilter.cpp36
-rw-r--r--src/render/framegraph/proximityfilter_p.h4
-rw-r--r--src/render/framegraph/qblitframebuffer.cpp6
-rw-r--r--src/render/framegraph/qbuffercapture.cpp1
-rw-r--r--src/render/framegraph/qcameraselector.cpp1
-rw-r--r--src/render/framegraph/qclearbuffers.cpp1
-rw-r--r--src/render/framegraph/qframegraphnode.cpp11
-rw-r--r--src/render/framegraph/qlayerfilter.cpp15
-rw-r--r--src/render/framegraph/qmemorybarrier.cpp2
-rw-r--r--src/render/framegraph/qnopicking.cpp139
-rw-r--r--src/render/framegraph/qnopicking.h (renamed from src/core/qbackendnodefactory.cpp)21
-rw-r--r--src/render/framegraph/qrendercapture.cpp12
-rw-r--r--src/render/framegraph/qrendercapture_p.h14
-rw-r--r--src/render/framegraph/qrenderpassfilter.cpp27
-rw-r--r--src/render/framegraph/qrenderstateset.cpp15
-rw-r--r--src/render/framegraph/qrendersurfaceselector.cpp31
-rw-r--r--src/render/framegraph/qrendertargetselector.cpp9
-rw-r--r--src/render/framegraph/qsetfence.cpp9
-rw-r--r--src/render/framegraph/qsortpolicy.cpp6
-rw-r--r--src/render/framegraph/qsortpolicy.h3
-rw-r--r--src/render/framegraph/qsubtreeenabler.cpp185
-rw-r--r--src/render/framegraph/qsubtreeenabler.h83
-rw-r--r--src/render/framegraph/qsubtreeenabler_p.h80
-rw-r--r--src/render/framegraph/qtechniquefilter.cpp27
-rw-r--r--src/render/framegraph/qviewport.cpp1
-rw-r--r--src/render/framegraph/qwaitfence.cpp12
-rw-r--r--src/render/framegraph/rendercapture.cpp23
-rw-r--r--src/render/framegraph/rendercapture_p.h3
-rw-r--r--src/render/framegraph/renderpassfilternode.cpp68
-rw-r--r--src/render/framegraph/renderpassfilternode_p.h4
-rw-r--r--src/render/framegraph/rendersurfaceselector.cpp67
-rw-r--r--src/render/framegraph/rendersurfaceselector_p.h5
-rw-r--r--src/render/framegraph/rendertargetselectornode.cpp36
-rw-r--r--src/render/framegraph/rendertargetselectornode_p.h4
-rw-r--r--src/render/framegraph/sortpolicy.cpp30
-rw-r--r--src/render/framegraph/sortpolicy_p.h4
-rw-r--r--src/render/framegraph/statesetnode.cpp43
-rw-r--r--src/render/framegraph/statesetnode_p.h4
-rw-r--r--src/render/framegraph/subtreeenabler.cpp74
-rw-r--r--src/render/framegraph/subtreeenabler_p.h (renamed from src/core/qsceneobserverinterface_p.h)36
-rw-r--r--src/render/framegraph/techniquefilternode.cpp65
-rw-r--r--src/render/framegraph/techniquefilternode_p.h4
-rw-r--r--src/render/framegraph/viewportnode.cpp50
-rw-r--r--src/render/framegraph/viewportnode_p.h4
-rw-r--r--src/render/framegraph/waitfence.cpp48
-rw-r--r--src/render/framegraph/waitfence_p.h4
-rw-r--r--src/render/frontend/qcamera.cpp26
-rw-r--r--src/render/frontend/qcamera.h3
-rw-r--r--src/render/frontend/qcameralens.cpp17
-rw-r--r--src/render/frontend/qcameralens_p.h23
-rw-r--r--src/render/frontend/qcomputecommand.cpp12
-rw-r--r--src/render/frontend/qlevelofdetail.cpp48
-rw-r--r--src/render/frontend/qlevelofdetail.h1
-rw-r--r--src/render/frontend/qlevelofdetail_p.h2
-rw-r--r--src/render/frontend/qlevelofdetailswitch.cpp28
-rw-r--r--src/render/frontend/qlevelofdetailswitch.h1
-rw-r--r--src/render/frontend/qlevelofdetailswitch_p.h77
-rw-r--r--src/render/frontend/qpickingsettings.cpp2
-rw-r--r--src/render/frontend/qrenderaspect.cpp175
-rw-r--r--src/render/frontend/qrenderaspect_p.h5
-rw-r--r--src/render/frontend/qrenderplugin_p.h5
-rw-r--r--src/render/frontend/qrendersettings.cpp13
-rw-r--r--src/render/frontend/qrendersettings_p.h2
-rw-r--r--src/render/frontend/qrendertarget.cpp15
-rw-r--r--src/render/frontend/qrendertargetoutput.cpp1
-rw-r--r--src/render/frontend/render-frontend.pri1
-rw-r--r--src/render/geometry/armature.cpp33
-rw-r--r--src/render/geometry/armature_p.h4
-rw-r--r--src/render/geometry/attribute.cpp115
-rw-r--r--src/render/geometry/attribute_p.h4
-rw-r--r--src/render/geometry/buffer.cpp110
-rw-r--r--src/render/geometry/buffer_p.h3
-rw-r--r--src/render/geometry/buffermanager.cpp8
-rw-r--r--src/render/geometry/geometry.cpp58
-rw-r--r--src/render/geometry/geometry_p.h4
-rw-r--r--src/render/geometry/geometryrenderer.cpp148
-rw-r--r--src/render/geometry/geometryrenderer_p.h13
-rw-r--r--src/render/geometry/joint.cpp100
-rw-r--r--src/render/geometry/joint_p.h4
-rw-r--r--src/render/geometry/qattribute.cpp15
-rw-r--r--src/render/geometry/qbuffer.cpp56
-rw-r--r--src/render/geometry/qbuffer.h7
-rw-r--r--src/render/geometry/qbuffer_p.h2
-rw-r--r--src/render/geometry/qgeometry.cpp14
-rw-r--r--src/render/geometry/qgeometryrenderer.cpp28
-rw-r--r--src/render/geometry/qgeometryrenderer.h1
-rw-r--r--src/render/geometry/qmesh.cpp33
-rw-r--r--src/render/geometry/qmesh.h1
-rw-r--r--src/render/geometry/skeleton.cpp315
-rw-r--r--src/render/geometry/skeleton_p.h38
-rw-r--r--src/render/io/qsceneloader.cpp59
-rw-r--r--src/render/io/qsceneloader.h1
-rw-r--r--src/render/io/qsceneloader_p.h1
-rw-r--r--src/render/io/scene.cpp68
-rw-r--r--src/render/io/scene_p.h5
-rw-r--r--src/render/jobs/abstractpickingjob.cpp15
-rw-r--r--src/render/jobs/abstractpickingjob_p.h2
-rw-r--r--src/render/jobs/filterentitybycomponentjob_p.h4
-rw-r--r--src/render/jobs/filterproximitydistancejob.cpp6
-rw-r--r--src/render/jobs/framecleanupjob.cpp1
-rw-r--r--src/render/jobs/genericlambdajob_p.h43
-rw-r--r--src/render/jobs/job_common_p.h12
-rw-r--r--src/render/jobs/jobs.pri4
-rw-r--r--src/render/jobs/lightgatherer.cpp3
-rw-r--r--src/render/jobs/loadbufferjob.cpp32
-rw-r--r--src/render/jobs/loadbufferjob_p.h1
-rw-r--r--src/render/jobs/loadgeometryjob.cpp35
-rw-r--r--src/render/jobs/loadgeometryjob_p.h1
-rw-r--r--src/render/jobs/loadscenejob.cpp58
-rw-r--r--src/render/jobs/loadscenejob_p.h22
-rw-r--r--src/render/jobs/loadskeletonjob.cpp247
-rw-r--r--src/render/jobs/loadskeletonjob_p.h19
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp127
-rw-r--r--src/render/jobs/pickboundingvolumejob_p.h7
-rw-r--r--src/render/jobs/pickboundingvolumeutils.cpp14
-rw-r--r--src/render/jobs/pickboundingvolumeutils_p.h1
-rw-r--r--src/render/jobs/raycastingjob.cpp41
-rw-r--r--src/render/jobs/raycastingjob_p.h2
-rw-r--r--src/render/jobs/sendbuffercapturejob.cpp68
-rw-r--r--src/render/jobs/sendbuffercapturejob_p.h9
-rw-r--r--src/render/jobs/updatelevelofdetailjob.cpp46
-rw-r--r--src/render/jobs/updatelevelofdetailjob_p.h1
-rw-r--r--src/render/jobs/updatetreeenabledjob.cpp1
-rw-r--r--src/render/jobs/updateworldtransformjob.cpp52
-rw-r--r--src/render/jobs/updateworldtransformjob_p.h1
-rw-r--r--src/render/lights/environmentlight.cpp14
-rw-r--r--src/render/lights/environmentlight_p.h3
-rw-r--r--src/render/lights/light.cpp17
-rw-r--r--src/render/lights/light_p.h4
-rw-r--r--src/render/lights/qdirectionallight.cpp1
-rw-r--r--src/render/lights/qspotlight.cpp1
-rw-r--r--src/render/materialsystem/effect.cpp57
-rw-r--r--src/render/materialsystem/effect_p.h4
-rw-r--r--src/render/materialsystem/filterkey.cpp29
-rw-r--r--src/render/materialsystem/filterkey_p.h4
-rw-r--r--src/render/materialsystem/material.cpp61
-rw-r--r--src/render/materialsystem/material_p.h4
-rw-r--r--src/render/materialsystem/materialsystem.pri5
-rw-r--r--src/render/materialsystem/parameter.cpp48
-rw-r--r--src/render/materialsystem/parameter_p.h6
-rw-r--r--src/render/materialsystem/qeffect.cpp33
-rw-r--r--src/render/materialsystem/qfilterkey.cpp1
-rw-r--r--src/render/materialsystem/qgraphicsapifilter.cpp5
-rw-r--r--src/render/materialsystem/qgraphicsapifilter_p.h1
-rw-r--r--src/render/materialsystem/qmaterial.cpp15
-rw-r--r--src/render/materialsystem/qparameter.cpp1
-rw-r--r--src/render/materialsystem/qrenderpass.cpp45
-rw-r--r--src/render/materialsystem/qshaderimage.cpp991
-rw-r--r--src/render/materialsystem/qshaderimage.h170
-rw-r--r--src/render/materialsystem/qshaderimage_p.h93
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder.cpp107
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder.h1
-rw-r--r--src/render/materialsystem/qshaderprogrambuilder_p.h6
-rw-r--r--src/render/materialsystem/qtechnique.cpp52
-rw-r--r--src/render/materialsystem/qtechnique.h1
-rw-r--r--src/render/materialsystem/renderpass.cpp71
-rw-r--r--src/render/materialsystem/renderpass_p.h4
-rw-r--r--src/render/materialsystem/shader.cpp101
-rw-r--r--src/render/materialsystem/shader_p.h11
-rw-r--r--src/render/materialsystem/shaderbuilder.cpp122
-rw-r--r--src/render/materialsystem/shaderbuilder_p.h40
-rw-r--r--src/render/materialsystem/shaderdata.cpp241
-rw-r--r--src/render/materialsystem/shaderdata_p.h31
-rw-r--r--src/render/materialsystem/shaderimage.cpp118
-rw-r--r--src/render/materialsystem/shaderimage_p.h103
-rw-r--r--src/render/materialsystem/technique.cpp92
-rw-r--r--src/render/materialsystem/technique_p.h4
-rw-r--r--src/render/picking/objectpicker.cpp101
-rw-r--r--src/render/picking/objectpicker_p.h10
-rw-r--r--src/render/picking/picking.pri1
-rw-r--r--src/render/picking/qabstractraycaster.cpp10
-rw-r--r--src/render/picking/qobjectpicker.cpp46
-rw-r--r--src/render/picking/qobjectpicker.h7
-rw-r--r--src/render/picking/qobjectpicker_p.h9
-rw-r--r--src/render/picking/qpickevent.cpp51
-rw-r--r--src/render/picking/qpickevent.h14
-rw-r--r--src/render/picking/qpickevent_p.h9
-rw-r--r--src/render/picking/qpicktriangleevent.cpp51
-rw-r--r--src/render/picking/qpicktriangleevent_p.h69
-rw-r--r--src/render/picking/qraycaster.cpp5
-rw-r--r--src/render/picking/qscreenraycaster.cpp5
-rw-r--r--src/render/picking/raycaster.cpp113
-rw-r--r--src/render/picking/raycaster_p.h5
-rw-r--r--src/render/raycasting/qcollisionqueryresult.cpp1
-rw-r--r--src/render/raycasting/qcollisionqueryresult_p.h2
-rw-r--r--src/render/raycasting/qraycastingservice.cpp1
-rw-r--r--src/render/render.pro3
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp44
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h7
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp27
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h3
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp75
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1_p.h1
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp57
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h3
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp25
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h3
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp25
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h3
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp24
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h3
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp167
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h3
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h6
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri2
-rw-r--r--src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext.cpp306
-rw-r--r--src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext_p.h (renamed from src/render/jobs/loadtexturedatajob_p.h)51
-rw-r--r--src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp93
-rw-r--r--src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h2
-rw-r--r--src/render/renderers/opengl/jobs/jobs.pri6
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp (renamed from src/render/jobs/updateentityhierarchyjob.cpp)38
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h89
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp (renamed from src/render/renderers/opengl/jobs/renderviewbuilderjob.cpp)50
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h (renamed from src/render/renderers/opengl/jobs/renderviewbuilderjob_p.h)27
-rw-r--r--src/render/renderers/opengl/jobs/renderviewjobutils.cpp50
-rw-r--r--src/render/renderers/opengl/opengl.pri3
-rw-r--r--src/render/renderers/opengl/renderer/commandthread.cpp205
-rw-r--r--src/render/renderers/opengl/renderer/rendercommand.cpp15
-rw-r--r--src/render/renderers/opengl/renderer/rendercommand_p.h68
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp730
-rw-r--r--src/render/renderers/opengl/renderer/renderer.pri4
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h71
-rw-r--r--src/render/renderers/opengl/renderer/renderercache_p.h13
-rw-r--r--src/render/renderers/opengl/renderer/renderview.cpp720
-rw-r--r--src/render/renderers/opengl/renderer/renderview_p.h20
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder.cpp550
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder_p.h56
-rw-r--r--src/render/renderers/opengl/renderer/shaderparameterpack.cpp18
-rw-r--r--src/render/renderers/opengl/renderer/shaderparameterpack_p.h93
-rw-r--r--src/render/renderers/opengl/textures/gltexture.cpp324
-rw-r--r--src/render/renderers/opengl/textures/gltexture_p.h90
-rw-r--r--src/render/renderers/opengl/textures/gltexturemanager_p.h17
-rw-r--r--src/render/renderstates/genericstate_p.h2
-rw-r--r--src/render/renderstates/qdepthrange.cpp156
-rw-r--r--src/render/renderstates/qdepthrange.h81
-rw-r--r--src/render/renderstates/qdepthrange_p.h (renamed from src/render/jobs/updateentityhierarchyjob_p.h)46
-rw-r--r--src/render/renderstates/qdithering.cpp1
-rw-r--r--src/render/renderstates/qmultisampleantialiasing.cpp1
-rw-r--r--src/render/renderstates/qnodepthmask.cpp1
-rw-r--r--src/render/renderstates/qrastermode.cpp195
-rw-r--r--src/render/renderstates/qrastermode.h (renamed from src/render/jobs/loadtexturedatajob.cpp)81
-rw-r--r--src/render/renderstates/qrastermode_p.h84
-rw-r--r--src/render/renderstates/qseamlesscubemap.cpp1
-rw-r--r--src/render/renderstates/qstenciloperation.cpp14
-rw-r--r--src/render/renderstates/qstenciloperation_p.h1
-rw-r--r--src/render/renderstates/qstenciltest.cpp14
-rw-r--r--src/render/renderstates/qstenciltest_p.h1
-rw-r--r--src/render/renderstates/renderstatenode.cpp161
-rw-r--r--src/render/renderstates/renderstatenode_p.h4
-rw-r--r--src/render/renderstates/renderstates.cpp194
-rw-r--r--src/render/renderstates/renderstates.pri10
-rw-r--r--src/render/renderstates/renderstates_p.h46
-rw-r--r--src/render/renderstates/statemask_p.h2
-rw-r--r--src/render/renderstates/statevariant.cpp4
-rw-r--r--src/render/renderstates/statevariant_p.h1
-rw-r--r--src/render/services/vsyncframeadvanceservice.cpp22
-rw-r--r--src/render/texture/apitexturemanager_p.h411
-rw-r--r--src/render/texture/qabstracttexture.cpp113
-rw-r--r--src/render/texture/qabstracttexture.h9
-rw-r--r--src/render/texture/qabstracttexture_p.h8
-rw-r--r--src/render/texture/qabstracttextureimage.cpp18
-rw-r--r--src/render/texture/qabstracttextureimage_p.h2
-rw-r--r--src/render/texture/qtexture.cpp207
-rw-r--r--src/render/texture/qtexture_p.h4
-rw-r--r--src/render/texture/qtexturedataupdate.cpp186
-rw-r--r--src/render/texture/qtexturedataupdate.h105
-rw-r--r--src/render/texture/qtexturedataupdate_p.h (renamed from src/render/renderers/opengl/renderer/glcommands_p.h)42
-rw-r--r--src/render/texture/qtexturegenerator.cpp3
-rw-r--r--src/render/texture/qtextureimage.cpp4
-rw-r--r--src/render/texture/qtextureimagedata.cpp27
-rw-r--r--src/render/texture/qtextureimagedata_p.h13
-rw-r--r--src/render/texture/texture.cpp246
-rw-r--r--src/render/texture/texture.pri7
-rw-r--r--src/render/texture/texture_p.h25
-rw-r--r--src/render/texture/texturedatamanager_p.h238
-rw-r--r--src/render/texture/textureimage.cpp76
-rw-r--r--src/render/texture/textureimage_p.h15
-rw-r--r--tests/auto/animation/additiveclipblend/tst_additiveclipblend.cpp35
-rw-r--r--tests/auto/animation/animationclip/tst_animationclip.cpp88
-rw-r--r--tests/auto/animation/animationutils/tst_animationutils.cpp208
-rw-r--r--tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp75
-rw-r--r--tests/auto/animation/channelmapper/tst_channelmapper.cpp37
-rw-r--r--tests/auto/animation/channelmapping/tst_channelmapping.cpp84
-rw-r--r--tests/auto/animation/clipanimator/tst_clipanimator.cpp55
-rw-r--r--tests/auto/animation/clipblendnode/tst_clipblendnode.cpp4
-rw-r--r--tests/auto/animation/clipblendnodevisitor/tst_clipblendnodevisitor.cpp18
-rw-r--r--tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp21
-rw-r--r--tests/auto/animation/clock/tst_clock.cpp19
-rw-r--r--tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp1
-rw-r--r--tests/auto/animation/lerpclipblend/tst_lerpclipblend.cpp36
-rw-r--r--tests/auto/animation/qadditiveclipblend/tst_qadditiveclipblend.cpp43
-rw-r--r--tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp46
-rw-r--r--tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp66
-rw-r--r--tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp35
-rw-r--r--tests/auto/animation/qchannelmapper/tst_qchannelmapper.cpp14
-rw-r--r--tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp85
-rw-r--r--tests/auto/animation/qclipanimator/tst_qclipanimator.cpp53
-rw-r--r--tests/auto/animation/qclipblendvalue/tst_qclipblendvalue.cpp14
-rw-r--r--tests/auto/animation/qclock/tst_qclock.cpp16
-rw-r--r--tests/auto/animation/qlerpclipblend/tst_qlerpclipblend.cpp40
-rw-r--r--tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp14
-rw-r--r--tests/auto/animation/skeleton/tst_skeleton.cpp35
-rw-r--r--tests/auto/core/common/qbackendnodetester.cpp1
-rw-r--r--tests/auto/core/common/qbackendnodetester.h16
-rw-r--r--tests/auto/core/common/testpostmanarbiter.cpp23
-rw-r--r--tests/auto/core/common/testpostmanarbiter.h7
-rw-r--r--tests/auto/core/nodes/tst_nodes.cpp1094
-rw-r--r--tests/auto/core/qarmature/tst_qarmature.cpp24
-rw-r--r--tests/auto/core/qaspectengine/tst_qaspectengine.cpp2
-rw-r--r--tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp143
-rw-r--r--tests/auto/core/qframeallocator/tst_qframeallocator.cpp12
-rw-r--r--tests/auto/core/qjoint/tst_qjoint.cpp53
-rw-r--r--tests/auto/core/qpostman/tst_qpostman.cpp2
-rw-r--r--tests/auto/core/qscene/qscene.pro2
-rw-r--r--tests/auto/core/qscene/tst_qscene.cpp32
-rw-r--r--tests/auto/core/qskeleton/tst_qskeleton.cpp58
-rw-r--r--tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp80
-rw-r--r--tests/auto/core/qtransform/tst_qtransform.cpp102
-rw-r--r--tests/auto/core/threadpooler/tst_threadpooler.cpp7
-rw-r--r--tests/auto/coretest/coretest.pro2
-rw-r--r--tests/auto/coretest/testpostmanarbiter.cpp5
-rw-r--r--tests/auto/coretest/testpostmanarbiter_p.h1
-rw-r--r--tests/auto/extras/extras.pro3
-rw-r--r--tests/auto/extras/qtext2dentity/qtext2dentity.pro13
-rw-r--r--tests/auto/extras/qtext2dentity/qtext2dentity.qml93
-rw-r--r--tests/auto/extras/qtext2dentity/qtext2dentity.qrc5
-rw-r--r--tests/auto/extras/qtext2dentity/tst_qtext2dentity.cpp98
-rw-r--r--tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp22
-rw-r--r--tests/auto/input/action/tst_action.cpp58
-rw-r--r--tests/auto/input/actioninput/tst_actioninput.cpp31
-rw-r--r--tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp32
-rw-r--r--tests/auto/input/axis/tst_axis.cpp57
-rw-r--r--tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp90
-rw-r--r--tests/auto/input/axisaccumulatorjob/tst_axisaccumulatorjob.cpp5
-rw-r--r--tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp62
-rw-r--r--tests/auto/input/commons/testdeviceproxy.h5
-rw-r--r--tests/auto/input/input.pro3
-rw-r--r--tests/auto/input/inputchord/tst_inputchord.cpp51
-rw-r--r--tests/auto/input/inputsequence/tst_inputsequence.cpp69
-rw-r--r--tests/auto/input/keyboardhandler/tst_keyboardhandler.cpp44
-rw-r--r--tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp12
-rw-r--r--tests/auto/input/logicaldevice/tst_logicaldevice.cpp54
-rw-r--r--tests/auto/input/mousedevice/tst_mousedevice.cpp19
-rw-r--r--tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp31
-rw-r--r--tests/auto/input/qabstractaxisinput/tst_qabstractaxisinput.cpp11
-rw-r--r--tests/auto/input/qabstractphysicaldevicebackendnode/tst_qabstractphysicaldevicebackendnode.cpp41
-rw-r--r--tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp31
-rw-r--r--tests/auto/input/qaction/tst_qaction.cpp38
-rw-r--r--tests/auto/input/qactioninput/tst_qactioninput.cpp20
-rw-r--r--tests/auto/input/qanalogaxisinput/tst_qanalogaxisinput.cpp20
-rw-r--r--tests/auto/input/qaxis/tst_qaxis.cpp43
-rw-r--r--tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp62
-rw-r--r--tests/auto/input/qbuttonaxisinput/tst_qbuttonaxisinput.cpp53
-rw-r--r--tests/auto/input/qkeyboardhandler/tst_qkeyboardhandler.cpp21
-rw-r--r--tests/auto/input/qlogicaldevice/tst_qlogicaldevice.cpp46
-rw-r--r--tests/auto/input/qmousedevice/tst_qmousedevice.cpp17
-rw-r--r--tests/auto/input/qmouseevent/qmouseevent.pro11
-rw-r--r--tests/auto/input/qmouseevent/tst_qmouseevent.cpp93
-rw-r--r--tests/auto/input/utils/tst_utils.cpp9
-rw-r--r--tests/auto/quick3d/3dcore/3dcore.qml3
-rw-r--r--tests/auto/quick3d/3drender/3drender.qml5
-rw-r--r--tests/auto/render/armature/tst_armature.cpp22
-rw-r--r--tests/auto/render/attribute/tst_attribute.cpp77
-rw-r--r--tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp101
-rw-r--r--tests/auto/render/boundingsphere/tst_boundingsphere.cpp79
-rw-r--r--tests/auto/render/buffer/tst_buffer.cpp241
-rw-r--r--tests/auto/render/commons/testaspect.cpp39
-rw-r--r--tests/auto/render/commons/testaspect.h1
-rw-r--r--tests/auto/render/commons/testrenderer.h6
-rw-r--r--tests/auto/render/computecommand/tst_computecommand.cpp193
-rw-r--r--tests/auto/render/coordinatereader/tst_coordinatereader.cpp36
-rw-r--r--tests/auto/render/effect/tst_effect.cpp37
-rw-r--r--tests/auto/render/entity/tst_entity.cpp289
-rw-r--r--tests/auto/render/filtercompatibletechniquejob/BLACKLIST6
-rw-r--r--tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp25
-rw-r--r--tests/auto/render/filterkey/tst_filterkey.cpp45
-rw-r--r--tests/auto/render/framegraphnode/framegraphnode.pro1
-rw-r--r--tests/auto/render/framegraphnode/tst_framegraphnode.cpp58
-rw-r--r--tests/auto/render/geometry/tst_geometry.cpp36
-rw-r--r--tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp191
-rw-r--r--tests/auto/render/gltexture/gltexture.pro13
-rw-r--r--tests/auto/render/gltexture/image.jpgbin0 -> 6173 bytes
-rw-r--r--tests/auto/render/gltexture/resources.qrc5
-rw-r--r--tests/auto/render/gltexture/tst_gltexture.cpp909
-rw-r--r--tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp18
-rw-r--r--tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp17
-rw-r--r--tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp16
-rw-r--r--tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp108
-rw-r--r--tests/auto/render/joint/tst_joint.cpp140
-rw-r--r--tests/auto/render/ktxtextures/data/16_16.pngbin0 -> 346 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_7.KTXbin0 -> 324 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_8.KTXbin0 -> 324 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGBA_11.KTXbin0 -> 324 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGB_13.KTXbin0 -> 196 bytes
-rw-r--r--tests/auto/render/ktxtextures/data/16_16_PNG_ETC_RGB_12.KTXbin0 -> 196 bytes
-rw-r--r--tests/auto/render/ktxtextures/ktxtextures.pro11
-rw-r--r--tests/auto/render/ktxtextures/tst_ktxtextures.cpp75
-rw-r--r--tests/auto/render/layerfiltering/tst_layerfiltering.cpp5
-rw-r--r--tests/auto/render/levelofdetail/tst_levelofdetail.cpp39
-rw-r--r--tests/auto/render/loadscenejob/tst_loadscenejob.cpp80
-rw-r--r--tests/auto/render/material/tst_material.cpp59
-rw-r--r--tests/auto/render/materialparametergathererjob/tst_materialparametergathererjob.cpp26
-rw-r--r--tests/auto/render/memorybarrier/tst_memorybarrier.cpp26
-rw-r--r--tests/auto/render/objectpicker/tst_objectpicker.cpp93
-rw-r--r--tests/auto/render/parameter/tst_parameter.cpp45
-rw-r--r--tests/auto/render/pickboundingvolumejob/pickboundingvolumejob.qrc1
-rw-r--r--tests/auto/render/pickboundingvolumejob/testscene_nopicking.qml134
-rw-r--r--tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp725
-rw-r--r--tests/auto/render/picking/tst_picking.cpp67
-rw-r--r--tests/auto/render/proximityfilter/tst_proximityfilter.cpp36
-rw-r--r--tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp18
-rw-r--r--tests/auto/render/qabstractlight/tst_qabstractlight.cpp112
-rw-r--r--tests/auto/render/qabstracttexture/tst_qabstracttexture.cpp198
-rw-r--r--tests/auto/render/qabstracttextureimage/tst_qabstracttextureimage.cpp40
-rw-r--r--tests/auto/render/qattribute/tst_qattribute.cpp107
-rw-r--r--tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp158
-rw-r--r--tests/auto/render/qbuffer/tst_qbuffer.cpp47
-rw-r--r--tests/auto/render/qcamera/tst_qcamera.cpp65
-rw-r--r--tests/auto/render/qcameralens/tst_qcameralens.cpp132
-rw-r--r--tests/auto/render/qcameraselector/tst_qcameraselector.cpp36
-rw-r--r--tests/auto/render/qclearbuffers/tst_qclearbuffers.cpp28
-rw-r--r--tests/auto/render/qcomputecommand/tst_qcomputecommand.cpp127
-rw-r--r--tests/auto/render/qdispatchcompute/tst_qdispatchcompute.cpp34
-rw-r--r--tests/auto/render/qeffect/tst_qeffect.cpp43
-rw-r--r--tests/auto/render/qfilterkey/tst_qfilterkey.cpp23
-rw-r--r--tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp25
-rw-r--r--tests/auto/render/qgeometry/tst_qgeometry.cpp23
-rw-r--r--tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp124
-rw-r--r--tests/auto/render/qlayerfilter/tst_qlayerfilter.cpp37
-rw-r--r--tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp18
-rw-r--r--tests/auto/render/qmaterial/tst_qmaterial.cpp132
-rw-r--r--tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp12
-rw-r--r--tests/auto/render/qmesh/tst_qmesh.cpp58
-rw-r--r--tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp131
-rw-r--r--tests/auto/render/qparameter/tst_qparameter.cpp34
-rw-r--r--tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp23
-rw-r--r--tests/auto/render/qray3d/tst_qray3d.cpp2
-rw-r--r--tests/auto/render/qraycaster/tst_qraycaster.cpp11
-rw-r--r--tests/auto/render/qrendercapture/tst_qrendercapture.cpp17
-rw-r--r--tests/auto/render/qrenderpass/tst_qrenderpass.cpp60
-rw-r--r--tests/auto/render/qrenderpassfilter/tst_qrenderpassfilter.cpp52
-rw-r--r--tests/auto/render/qrendersettings/tst_qrendersettings.cpp67
-rw-r--r--tests/auto/render/qrenderstate/tst_qrenderstate.cpp26
-rw-r--r--tests/auto/render/qrenderstateset/tst_qrenderstateset.cpp30
-rw-r--r--tests/auto/render/qrendersurfaceselector/tst_qrendersurfaceselector.cpp34
-rw-r--r--tests/auto/render/qrendertarget/tst_qrendertarget.cpp22
-rw-r--r--tests/auto/render/qrendertargetoutput/tst_qrendertargetoutput.cpp56
-rw-r--r--tests/auto/render/qrendertargetselector/tst_qrendertargetselector.cpp47
-rw-r--r--tests/auto/render/qscene2d/tst_qscene2d.cpp37
-rw-r--r--tests/auto/render/qsceneloader/tst_qsceneloader.cpp62
-rw-r--r--tests/auto/render/qscreenraycaster/tst_qscreenraycaster.cpp12
-rw-r--r--tests/auto/render/qshaderimage/qshaderimage.pro (renamed from tests/auto/render/texturedatamanager/texturedatamanager.pro)4
-rw-r--r--tests/auto/render/qshaderimage/tst_qshaderimage.cpp488
-rw-r--r--tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp72
-rw-r--r--tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp120
-rw-r--r--tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp12
-rw-r--r--tests/auto/render/qsortpolicy/tst_qsortpolicy.cpp10
-rw-r--r--tests/auto/render/qtechnique/tst_qtechnique.cpp116
-rw-r--r--tests/auto/render/qtechniquefilter/tst_qtechniquefilter.cpp53
-rw-r--r--tests/auto/render/qtexturedataupdate/qtexturedataupdate.pro10
-rw-r--r--tests/auto/render/qtexturedataupdate/tst_qtexturedataupdate.cpp289
-rw-r--r--tests/auto/render/qtextureimage/tst_qtextureimage.cpp21
-rw-r--r--tests/auto/render/qtextureloader/tst_qtextureloader.cpp24
-rw-r--r--tests/auto/render/qviewport/tst_qviewport.cpp48
-rw-r--r--tests/auto/render/qwaitfence/tst_qwaitfence.cpp45
-rw-r--r--tests/auto/render/raycaster/tst_raycaster.cpp37
-rw-r--r--tests/auto/render/raycasting/tst_raycasting.cpp6
-rw-r--r--tests/auto/render/raycastingjob/testscene_screenraycasting.qml11
-rw-r--r--tests/auto/render/raycastingjob/testscene_worldraycasting.qml9
-rw-r--r--tests/auto/render/raycastingjob/testscene_worldraycastingalllayers.qml9
-rw-r--r--tests/auto/render/raycastingjob/testscene_worldraycastinglayer.qml9
-rw-r--r--tests/auto/render/raycastingjob/testscene_worldraycastingparentlayer.qml9
-rw-r--r--tests/auto/render/raycastingjob/tst_raycastingjob.cpp124
-rw-r--r--tests/auto/render/render.pro10
-rw-r--r--tests/auto/render/rendercapture/tst_rendercapture.cpp26
-rw-r--r--tests/auto/render/renderer/tst_renderer.cpp168
-rw-r--r--tests/auto/render/renderpass/tst_renderpass.cpp95
-rw-r--r--tests/auto/render/rendertarget/tst_rendertarget.cpp33
-rw-r--r--tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp221
-rw-r--r--tests/auto/render/renderviews/renderviews.pro1
-rw-r--r--tests/auto/render/renderviews/tst_renderviews.cpp191
-rw-r--r--tests/auto/render/renderviewutils/tst_renderviewutils.cpp59
-rw-r--r--tests/auto/render/scene2d/tst_scene2d.cpp74
-rw-r--r--tests/auto/render/sceneloader/tst_sceneloader.cpp81
-rw-r--r--tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp80
-rw-r--r--tests/auto/render/setfence/tst_setfence.cpp18
-rw-r--r--tests/auto/render/shader/tst_shader.cpp54
-rw-r--r--tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp271
-rw-r--r--tests/auto/render/shaderimage/shaderimage.pro12
-rw-r--r--tests/auto/render/shaderimage/tst_shaderimage.cpp210
-rw-r--r--tests/auto/render/skeleton/tst_skeleton.cpp220
-rw-r--r--tests/auto/render/sortpolicy/tst_sortpolicy.cpp23
-rw-r--r--tests/auto/render/technique/tst_technique.cpp90
-rw-r--r--tests/auto/render/texture/tst_texture.cpp249
-rw-r--r--tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp249
-rw-r--r--tests/auto/render/textures/tst_textures.cpp214
-rw-r--r--tests/auto/render/transform/tst_transform.cpp50
-rw-r--r--tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp38
-rw-r--r--tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp100
-rw-r--r--tests/auto/render/uniform/tst_uniform.cpp2
-rw-r--r--tests/auto/render/updatemeshtrianglelistjob/tst_updatemeshtrianglelistjob.cpp50
-rw-r--r--tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp73
-rw-r--r--tests/auto/render/waitfence/tst_waitfence.cpp43
-rw-r--r--tests/benchmarks/core/qframeallocator/tst_bench_qframeallocator.cpp4
-rw-r--r--tests/benchmarks/core/qresourcesmanager/arraypolicy/tst_bench_arraypolicy.cpp2
-rw-r--r--tests/benchmarks/render/jobs/tst_bench_jobs.cpp39
-rw-r--r--tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp24
-rw-r--r--tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp24
-rw-r--r--tests/manual/assimp/main.cpp4
-rw-r--r--tests/manual/compressed_textures/compressed_textures.pro12
-rw-r--r--tests/manual/compressed_textures/compressed_textures.qrc5
-rw-r--r--tests/manual/compressed_textures/data/16_16.pngbin0 -> 346 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ASTC_7.KTXbin0 -> 324 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ASTC_8.KTXbin0 -> 324 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGBA_11.KTXbin0 -> 324 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGB_13.KTXbin0 -> 196 bytes
-rw-r--r--tests/manual/compressed_textures/data/16_16_PNG_ETC_RGB_12.KTXbin0 -> 196 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16-etc1.pkmbin0 -> 144 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16-etc2.pkmbin0 -> 144 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc1-dx10.ddsbin0 -> 332 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips-dx10.ddsbin0 -> 276 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips.ddsbin0 -> 256 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc1.ddsbin0 -> 312 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc3-dx10.ddsbin0 -> 516 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips-dx10.ddsbin0 -> 404 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips.ddsbin0 -> 384 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-bc3.ddsbin0 -> 496 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-lumi-nomips.ddsbin0 -> 384 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-lumi.ddsbin0 -> 469 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-rgb-nomips.ddsbin0 -> 1152 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-1-rgb.ddsbin0 -> 1492 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc1-dx10.ddsbin0 -> 1252 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips-dx10.ddsbin0 -> 916 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips.ddsbin0 -> 896 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc1.ddsbin0 -> 1232 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc3-dx10.ddsbin0 -> 2356 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips-dx10.ddsbin0 -> 1684 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips.ddsbin0 -> 1664 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-bc3.ddsbin0 -> 2336 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-lumi-nomips.ddsbin0 -> 1664 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-lumi.ddsbin0 -> 2174 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-rgb-nomips.ddsbin0 -> 6272 bytes
-rw-r--r--tests/manual/compressed_textures/data/16x16x1-6-rgb.ddsbin0 -> 8312 bytes
-rw-r--r--tests/manual/compressed_textures/main.cpp75
-rw-r--r--tests/manual/compressed_textures/main.qml118
-rw-r--r--tests/manual/compute-manual/ComputeFrameGraph.qml91
-rw-r--r--tests/manual/compute-manual/ComputeMaterial.qml118
-rw-r--r--tests/manual/compute-manual/ParticlesScene.qml200
-rw-r--r--tests/manual/compute-manual/compute-manual.pro14
-rw-r--r--tests/manual/compute-manual/compute-manual.qrc11
-rw-r--r--tests/manual/compute-manual/main.cpp66
-rw-r--r--tests/manual/compute-manual/main.qml109
-rw-r--r--tests/manual/compute-manual/particles.comp31
-rw-r--r--tests/manual/compute-manual/particles.frag33
-rw-r--r--tests/manual/compute-manual/particles.vert27
-rw-r--r--tests/manual/custom-mesh-cpp-indirect/main.cpp14
-rw-r--r--tests/manual/custom-mesh-cpp/main.cpp8
-rw-r--r--tests/manual/custom-mesh-update-data-cpp/main.cpp25
-rw-r--r--tests/manual/deferred-renderer-cpp/deferredrenderer.cpp4
-rw-r--r--tests/manual/manual-renderloop/main.cpp211
-rw-r--r--tests/manual/manual-renderloop/manual-renderloop.pro8
-rw-r--r--tests/manual/manual.pro16
-rw-r--r--tests/manual/raster-cpp/main.cpp131
-rw-r--r--tests/manual/raster-cpp/raster-cpp.pro9
-rw-r--r--tests/manual/raster-qml/main.cpp63
-rw-r--r--tests/manual/raster-qml/main.qml117
-rw-r--r--tests/manual/raster-qml/raster-qml.pro14
-rw-r--r--tests/manual/raster-qml/raster-qml.qrc5
-rw-r--r--tests/manual/scene3d-in-sync/main.cpp66
-rw-r--r--tests/manual/scene3d-in-sync/main.qml174
-rw-r--r--tests/manual/scene3d-in-sync/scene3d-in-sync.pro10
-rw-r--r--tests/manual/scene3d-in-sync/scene3d-in-sync.qrc5
-rw-r--r--tests/manual/scene3d-visibility/main.cpp66
-rw-r--r--tests/manual/scene3d-visibility/main.qml161
-rw-r--r--tests/manual/scene3d-visibility/scene3d-visibility.pro10
-rw-r--r--tests/manual/scene3d-visibility/scene3d-visibility.qrc5
-rw-r--r--tests/manual/shader-image-qml/image_512x512.jpgbin0 -> 24081 bytes
-rw-r--r--tests/manual/shader-image-qml/main.cpp63
-rw-r--r--tests/manual/shader-image-qml/main.qml231
-rw-r--r--tests/manual/shader-image-qml/shader-image-qml.pro14
-rw-r--r--tests/manual/shader-image-qml/shader-image-qml.qrc6
-rw-r--r--tests/manual/sharedtexture/main.cpp3
-rw-r--r--tests/manual/sharedtexture/videoplayer.cpp28
-rw-r--r--tests/manual/sharedtexture/videoplayer.h10
-rw-r--r--tests/manual/sharedtextureqml/main.cpp3
-rw-r--r--tests/manual/subtree-enabler-qml/FrameGraph.qml100
-rw-r--r--tests/manual/subtree-enabler-qml/SimpleCamera.qml79
-rw-r--r--tests/manual/subtree-enabler-qml/main.cpp64
-rw-r--r--tests/manual/subtree-enabler-qml/main.qml110
-rw-r--r--tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro17
-rw-r--r--tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc7
-rw-r--r--tests/manual/tessellation-modes/tessellatedquadmesh.cpp2
-rw-r--r--tests/manual/texture-updates-cpp/main.cpp118
-rw-r--r--tests/manual/texture-updates-cpp/scene.cpp146
-rw-r--r--tests/manual/texture-updates-cpp/scene.h84
-rw-r--r--tests/manual/texture-updates-cpp/texture-updates-cpp.pro12
-rw-r--r--tools/qgltf/qgltf.cpp51
-rw-r--r--tools/qgltf/qgltf.pro3
947 files changed, 29926 insertions, 17774 deletions
diff --git a/.qmake.conf b/.qmake.conf
index d9464b0c8..0b1ebe807 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -3,4 +3,7 @@ QT3D_BUILD_ROOT = $$shadowed($$PWD)
load(qt_build_config)
-MODULE_VERSION = 5.13.2
+DEFINES += QT_NO_FOREACH
+DEFINES += QT_NO_JAVA_STYLE_ITERATORS
+
+MODULE_VERSION = 5.14.0
diff --git a/examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc b/examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc
index 377bb952c..d845fa8da 100644
--- a/examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc
+++ b/examples/qt3d/advancedcustommaterial/doc/src/advancedcustommaterial.qdoc
@@ -42,7 +42,7 @@
Advanced custom material example shows more complex shaders, and demonstrates controlling your
shader properties with QtQuick user interface and Animation. Water is a 3D mesh, that is
modeled and uv mapped inside Blender, and then brought into Scene 3D as an \c {.obj} file.
- Shader properties that user can control, are defined in \l {advancedcustommaterial/WaterMaterial.qml}{WaterMaterial}.
+ Shader properties that user can control, are defined in \c {advancedcustommaterial/WaterMaterial.qml}.
\section1 Controls
\section2 Texture scale slider
@@ -53,7 +53,7 @@
\section2 Texture speed slider
Offsets values for texture coordinates which are animated in
- \l {advancedcustommaterial/Water.qml}{Water.qml} and then passed to vertex shader.
+ \c {advancedcustommaterial/Water.qml} and then passed to vertex shader.
Creates the effect of textures scrolling over the surface.
\section2 Specularity
@@ -80,5 +80,5 @@
\section2 Mesh rotation
- Rotates the water mesh in \l {advancedcustommaterial/Water.qml}{Water.qml}.
+ Rotates the water mesh in \c {advancedcustommaterial/Water.qml}.
*/
diff --git a/examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc b/examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc
index 5a204757e..6c0b40301 100644
--- a/examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc
+++ b/examples/qt3d/audio-visualizer-qml/doc/src/audio-visualizer-qml.qdoc
@@ -41,7 +41,7 @@
\section1 Qt Quick 2D Implementation
- The Qt Quick Implementation \l{audio-visualizer-qml/main.qml}{main.qml} of the example uses
+ The Qt Quick Implementation in \c {audio-visualizer-qml/main.qml} of the example uses
\c{MediaPlayer} to play audio content.
\snippet audio-visualizer-qml/main.qml 0
@@ -57,8 +57,8 @@
\section1 Qt 3D Implementation
- The 3D elements of the example are created in the
- \l{audio-visualizer-qml/Visualizer.qml}{Visualizer.qml}. The camera is set to a fixed position
+ The 3D elements of the example are created in
+ \c {audio-visualizer-qml/Visualizer.qml}. The camera is set to a fixed position
to show the visualized bars from a correct angle.
\snippet audio-visualizer-qml/Visualizer.qml 0
@@ -73,7 +73,7 @@
\snippet audio-visualizer-qml/Visualizer.qml 2
- In \l{audio-visualizer-qml/BarEntity.qml}{BarEntity.qml} there are animations for rotating the
+ In \c {audio-visualizer-qml/BarEntity.qml} there are animations for rotating the
bars and changing the bar color. The bars are rotated on a level following a ring form. At the
same time the color of the bars is animated.
diff --git a/examples/qt3d/audio-visualizer-qml/touchsettings.cpp b/examples/qt3d/audio-visualizer-qml/touchsettings.cpp
index 160dc6a76..312dfa7e6 100644
--- a/examples/qt3d/audio-visualizer-qml/touchsettings.cpp
+++ b/examples/qt3d/audio-visualizer-qml/touchsettings.cpp
@@ -62,8 +62,9 @@ bool TouchSettings::isHoverEnabled() const
#if defined(Q_OS_IOS) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_WINRT)
return false;
#else
+ const auto devices = QTouchDevice::devices();
bool isTouch = false;
- foreach (const QTouchDevice *dev, QTouchDevice::devices())
+ for (const QTouchDevice *dev : devices)
if (dev->type() == QTouchDevice::TouchScreen) {
isTouch = true;
break;
diff --git a/examples/qt3d/controlsunderlay/Logo.qml b/examples/qt3d/controlsunderlay/Logo.qml
new file mode 100644
index 000000000..4ebaba287
--- /dev/null
+++ b/examples/qt3d/controlsunderlay/Logo.qml
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.0
+import Qt3D.Render 2.0
+import QtQuick 2.0
+import Qt3D.Extras 2.0
+
+Entity {
+ id: sceneRoot
+
+ readonly property double cameraZ: camera.position.z
+
+ function viewAll() {
+ camera.viewAll()
+ }
+ function viewLogo() {
+ camera.viewEntity(logoEntity)
+ }
+ function setPositionZ(z) {
+ camera.position = Qt.vector3d( 0.0, 0.0, z )
+ }
+
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 40
+ aspectRatio: 4/3
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 0.0, 7.5 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ camera: camera
+ clearColor: "white"
+ }
+ renderPolicy: RenderSettings.OnDemand
+ }
+ ]
+
+ PhongMaterial {
+ id: material
+ diffuse: Qt.rgba( color_r.value/255, color_g.value/255, color_b.value/255, 1.0 )
+ ambient: Qt.rgba( 0.1, 0.1, 0.1, 1.0 )
+ shininess: shining.value
+ }
+
+ Transform {
+ id: logoTransform
+ rotation: fromEulerAngles( rotation_x.value, rotation_y.value, rotation_z.value )
+ }
+
+ Mesh {
+ id: logoMesh
+ source: "Qt_logo.obj"
+ }
+
+ Entity {
+ id: logoEntity
+ components: [ logoMesh, material, logoTransform ]
+ }
+
+ Entity {
+ components: [
+ PointLight {
+ color: "white"
+ intensity: 0.6
+ },
+ Transform {
+ translation: Qt.vector3d(0, 0, 10)
+ }
+ ]
+ }
+}
diff --git a/examples/qt3d/controlsunderlay/Qt_logo.obj b/examples/qt3d/controlsunderlay/Qt_logo.obj
new file mode 100644
index 000000000..71f566661
--- /dev/null
+++ b/examples/qt3d/controlsunderlay/Qt_logo.obj
@@ -0,0 +1,4071 @@
+# Blender v2.76 (sub 0) OBJ File: 'Qt_Logo_cutout2.blend'
+# www.blender.org
+mtllib Qt_logo.mtl
+o Curve.001_Mesh
+v 1.624641 -1.318420 -0.182387
+v 1.624641 -1.318420 0.182387
+v 1.604945 -1.374372 0.182387
+v 1.604945 -1.374372 -0.182387
+v 1.580433 -1.427071 0.182387
+v -0.981784 -0.203307 -0.182387
+v -0.972293 -0.281231 -0.182387
+v -1.543393 -0.228187 -0.182387
+v 0.724135 -0.831789 -0.182387
+v 0.262260 -0.831150 -0.182387
+v 0.711830 -0.814225 -0.182387
+v 1.639159 -1.259835 -0.182387
+v 1.639159 -1.259835 0.182387
+v 1.304468 -1.652686 0.182386
+v 1.551467 -1.475895 0.182387
+v 0.945710 -0.926501 0.182387
+v -1.543393 0.165341 0.182387
+v -0.997645 0.052952 0.182387
+v -0.998706 0.145841 0.182387
+v 1.580433 -1.427071 -0.182387
+v 1.121240 -0.657773 -0.182387
+v 1.121898 -0.657740 -0.182387
+v 1.121898 -0.657740 0.182387
+v 1.120596 -0.657802 -0.182387
+v 1.121240 -0.657773 0.182387
+v 1.119957 -0.657828 -0.182387
+v 1.120596 -0.657802 0.182387
+v 1.119311 -0.657849 -0.182387
+v 1.119957 -0.657828 0.182387
+v 1.118648 -0.657866 -0.182387
+v 1.119311 -0.657849 0.182387
+v 1.117959 -0.657879 -0.182387
+v 1.118648 -0.657866 0.182387
+v 1.117232 -0.657886 -0.182387
+v 1.117959 -0.657879 0.182387
+v 1.116459 -0.657889 -0.182387
+v 1.117232 -0.657886 0.182387
+v 1.108379 -0.657669 -0.182387
+v 1.116459 -0.657889 0.182387
+v 1.100785 -0.657008 -0.182387
+v 1.108379 -0.657669 0.182387
+v 1.093652 -0.655907 -0.182387
+v 1.100785 -0.657008 0.182387
+v 1.086952 -0.654363 -0.182387
+v 1.093652 -0.655907 0.182387
+v 1.080662 -0.652376 -0.182387
+v 1.086952 -0.654363 0.182387
+v 1.074757 -0.649945 -0.182387
+v 1.080662 -0.652376 0.182387
+v 1.069211 -0.647069 -0.182387
+v 1.074757 -0.649945 0.182387
+v 1.063999 -0.643748 -0.182387
+v 1.069211 -0.647069 0.182387
+v 1.059095 -0.639980 -0.182387
+v 1.063999 -0.643748 0.182387
+v 1.054475 -0.635764 -0.182387
+v 1.059095 -0.639980 0.182387
+v 1.050114 -0.631101 -0.182387
+v 1.054475 -0.635764 0.182387
+v 1.045986 -0.625988 -0.182387
+v 1.050114 -0.631101 0.182387
+v 1.041773 -0.619568 -0.182387
+v 1.045986 -0.625988 0.182387
+v 1.038066 -0.611957 -0.182387
+v 1.041773 -0.619568 0.182387
+v 1.034837 -0.603155 -0.182387
+v 1.038066 -0.611957 0.182387
+v 1.032062 -0.593160 -0.182387
+v 1.034837 -0.603155 0.182387
+v 1.029713 -0.581973 -0.182387
+v 1.032062 -0.593160 0.182387
+v 1.027764 -0.569593 -0.182387
+v 1.029713 -0.581973 0.182387
+v 1.026187 -0.556018 -0.182387
+v 1.027764 -0.569593 0.182387
+v 1.024956 -0.541250 -0.182387
+v 1.026187 -0.556018 0.182387
+v 1.024046 -0.525286 -0.182387
+v 1.024956 -0.541250 0.182387
+v 1.023428 -0.508127 -0.182387
+v 1.024046 -0.525286 0.182387
+v 1.023077 -0.489772 -0.182387
+v 1.023428 -0.508127 0.182387
+v 1.022966 -0.470221 -0.182387
+v 1.023077 -0.489772 0.182387
+v 1.022966 -0.457888 -0.182387
+v 1.022966 -0.470221 0.182387
+v 1.022966 -0.423033 -0.182387
+v 1.022966 -0.457888 0.182387
+v 1.022966 -0.368875 -0.182387
+v 1.022966 -0.423033 0.182387
+v 1.022966 -0.298629 -0.182387
+v 1.022966 -0.368875 0.182387
+v 1.022966 -0.215515 -0.182387
+v 1.022966 -0.298629 0.182387
+v 1.022966 -0.122748 -0.182387
+v 1.022966 -0.215515 0.182387
+v 1.022966 -0.023547 -0.182387
+v 1.022966 -0.122748 0.182387
+v 1.022966 0.078872 -0.182387
+v 1.022966 -0.023547 0.182387
+v 1.022966 0.181290 -0.182387
+v 1.022966 0.078872 0.182387
+v 1.022966 0.280492 -0.182387
+v 1.022966 0.181290 0.182387
+v 1.022966 0.373259 -0.182387
+v 1.022966 0.280492 0.182387
+v 1.022966 0.456373 -0.182387
+v 1.022966 0.373259 0.182387
+v 1.263622 0.444411 -0.182387
+v 1.022966 0.456373 0.182387
+v 1.263622 0.697952 -0.182387
+v 1.263622 0.444411 0.182387
+v 1.022966 0.716351 -0.182387
+v 1.263622 0.697952 0.182387
+v 1.022966 1.120478 -0.182387
+v 1.022966 0.716351 0.182387
+v 0.788843 1.145252 -0.182387
+v 1.022966 1.120478 0.182387
+v 0.693403 0.739209 -0.182387
+v 0.788843 1.145252 0.182387
+v 0.541780 0.750073 -0.182387
+v 0.693403 0.739209 0.182387
+v 0.541780 0.478384 -0.182387
+v 0.541780 0.750073 0.182387
+v 0.648683 0.472763 -0.182387
+v 0.541780 0.478384 0.182387
+v 0.648683 -0.554368 -0.182387
+v 0.648683 0.472763 0.182387
+v 0.649385 -0.587227 -0.182387
+v 0.648683 -0.554368 0.182387
+v 0.651461 -0.618561 -0.182387
+v 0.649385 -0.587227 0.182387
+v 0.654864 -0.648369 -0.182387
+v 0.651461 -0.618561 0.182387
+v 0.659545 -0.676652 -0.182387
+v 0.654864 -0.648369 0.182387
+v 0.665458 -0.703407 -0.182387
+v 0.659545 -0.676652 0.182387
+v 0.672554 -0.728633 -0.182387
+v 0.665458 -0.703407 0.182387
+v 0.680787 -0.752329 -0.182387
+v 0.672554 -0.728633 0.182387
+v 0.690109 -0.774494 -0.182387
+v 0.680787 -0.752329 0.182387
+v 0.700473 -0.795126 -0.182387
+v 0.690109 -0.774494 0.182387
+v 0.700473 -0.795126 0.182387
+v 0.711830 -0.814225 0.182387
+v 0.737338 -0.847817 -0.182387
+v 0.724135 -0.831789 0.182387
+v 0.749557 -0.860433 -0.182387
+v 0.737338 -0.847817 0.182387
+v 0.762797 -0.871939 -0.182387
+v 0.749557 -0.860433 0.182387
+v 0.777034 -0.882338 -0.182387
+v 0.762797 -0.871939 0.182387
+v 0.792240 -0.891632 -0.182387
+v 0.777034 -0.882338 0.182387
+v 0.808392 -0.899824 -0.182387
+v 0.792240 -0.891632 0.182387
+v 0.825461 -0.906916 -0.182387
+v 0.808392 -0.899824 0.182387
+v 0.843423 -0.912910 -0.182387
+v 0.825461 -0.906916 0.182387
+v 0.862251 -0.917809 -0.182387
+v 0.843423 -0.912910 0.182387
+v 0.881920 -0.921615 -0.182387
+v 0.862251 -0.917809 0.182387
+v 0.902404 -0.924331 -0.182387
+v 0.881920 -0.921615 0.182387
+v 0.923676 -0.925959 -0.182387
+v 0.902404 -0.924331 0.182387
+v 0.945710 -0.926501 -0.182387
+v 0.923676 -0.925959 0.182387
+v 1.211767 -0.874782 -0.182387
+v 1.237589 -0.865408 -0.182387
+v 1.651209 -0.996532 -0.182387
+v 1.651209 0.500221 -0.182387
+v 1.651209 0.805648 0.182387
+v 1.651209 0.500221 0.182387
+v 1.651209 -1.100473 -0.182387
+v 1.651209 -1.100473 0.182387
+v 1.651209 -1.137252 0.182387
+v 1.651209 -1.137252 -0.182387
+v 1.648136 -1.199239 0.182387
+v 1.648136 -1.199239 -0.182387
+v 1.551467 -1.475895 -0.182387
+v 1.518411 -1.520223 0.182387
+v 1.518411 -1.520223 -0.182387
+v 1.481627 -1.559434 0.182386
+v 1.481627 -1.559434 -0.182388
+v 1.441478 -1.592906 0.182386
+v 1.441478 -1.592906 -0.182388
+v 1.398327 -1.620021 0.182386
+v 1.398327 -1.620021 -0.182388
+v 1.352536 -1.640154 0.182386
+v 1.352536 -1.640154 -0.182388
+v 1.304468 -1.652686 -0.182388
+v -1.543393 -2.132013 0.182386
+v -1.543393 -0.634479 -0.182387
+v -1.543393 -1.040770 -0.182387
+v -1.543393 -1.040770 0.182387
+v -1.543393 1.494827 -0.182387
+v -1.543393 1.494827 0.182387
+v -1.543393 1.543752 0.182388
+v -1.543393 1.543752 -0.182386
+v -1.538053 1.625037 0.182388
+v -1.538053 1.625037 -0.182386
+v -1.522528 1.701349 0.182388
+v -1.522528 1.701349 -0.182386
+v -1.497558 1.772077 0.182388
+v -1.497558 1.772077 -0.182386
+v -1.463884 1.836608 0.182388
+v -1.463884 1.836608 -0.182386
+v -1.422248 1.894331 0.182388
+v -1.422248 1.894331 -0.182386
+v -1.373390 1.944634 0.182388
+v -1.373390 1.944634 -0.182386
+v -1.318050 1.986905 0.182388
+v -1.318050 1.986905 -0.182386
+v -1.256971 2.020532 0.182388
+v -1.256971 2.020532 -0.182386
+v -1.190891 2.044903 0.182388
+v -1.190891 2.044903 -0.182386
+v -1.120553 2.059406 0.182388
+v -1.120553 2.059406 -0.182386
+v -1.046697 2.063429 0.182388
+v -1.046697 2.063429 -0.182386
+v -0.970064 2.056361 0.182388
+v -0.970064 2.056361 -0.182386
+v -0.935175 2.050632 0.182388
+v -0.935175 2.050632 -0.182386
+v -0.836574 2.034443 0.182388
+v 0.873018 1.753752 -0.182386
+v 0.583283 1.801322 -0.182386
+v 0.583283 1.801322 0.182388
+v 1.290285 -0.632343 -0.182387
+v 1.290285 -0.655661 -0.182387
+v 1.290285 -0.655661 0.182387
+v 1.290285 -0.611451 -0.182387
+v 1.290285 -0.632343 0.182387
+v 1.276783 -0.618072 -0.182387
+v 1.290285 -0.611451 0.182387
+v 1.263028 -0.624200 -0.182387
+v 1.276783 -0.618072 0.182387
+v 1.249080 -0.629828 -0.182387
+v 1.263028 -0.624200 0.182387
+v 1.235000 -0.634956 -0.182387
+v 1.249080 -0.629828 0.182387
+v 1.220848 -0.639580 -0.182387
+v 1.235000 -0.634956 0.182387
+v 1.206685 -0.643697 -0.182387
+v 1.220848 -0.639580 0.182387
+v 1.192572 -0.647303 -0.182387
+v 1.206685 -0.643697 0.182387
+v 1.178569 -0.650396 -0.182387
+v 1.192572 -0.647303 0.182387
+v 1.164738 -0.652973 -0.182387
+v 1.178569 -0.650396 0.182387
+v 1.151138 -0.655030 -0.182387
+v 1.164738 -0.652973 0.182387
+v 1.137830 -0.656565 -0.182387
+v 1.151138 -0.655030 0.182387
+v 1.124875 -0.657574 -0.182387
+v 1.137830 -0.656565 0.182387
+v 1.124058 -0.657620 -0.182387
+v 1.124875 -0.657574 0.182387
+v 1.123296 -0.657663 -0.182387
+v 1.124058 -0.657620 0.182387
+v 1.122580 -0.657703 -0.182387
+v 1.123296 -0.657663 0.182387
+v 1.122580 -0.657703 0.182387
+v 1.651209 -0.996532 0.182387
+v 1.651209 -0.835023 0.182387
+v 1.290285 -0.844363 0.182387
+v 0.949063 -0.926488 -0.182387
+v 0.973284 -0.925691 -0.182387
+v 0.969757 -0.925878 -0.182387
+v 0.969757 -0.925878 0.182387
+v 0.976827 -0.925481 -0.182387
+v 0.973284 -0.925691 0.182387
+v 0.980386 -0.925247 -0.182387
+v 0.976827 -0.925481 0.182387
+v 0.983958 -0.924990 -0.182387
+v 0.980386 -0.925247 0.182387
+v 0.987542 -0.924711 -0.182387
+v 0.983958 -0.924990 0.182387
+v 1.012237 -0.922225 -0.182387
+v 0.987542 -0.924711 0.182387
+v 1.036888 -0.918973 -0.182387
+v 1.012237 -0.922225 0.182387
+v 1.061538 -0.914956 -0.182387
+v 1.036888 -0.918973 0.182387
+v 1.086227 -0.910174 -0.182387
+v 1.061538 -0.914956 0.182387
+v 1.111001 -0.904626 -0.182387
+v 1.086227 -0.910174 0.182387
+v 1.135899 -0.898313 -0.182387
+v 1.111001 -0.904626 0.182387
+v 1.160964 -0.891235 -0.182387
+v 1.135899 -0.898313 0.182387
+v 1.186239 -0.883391 -0.182387
+v 1.160964 -0.891235 0.182387
+v 1.186239 -0.883391 0.182387
+v 1.211767 -0.874782 0.182387
+v 1.263747 -0.855268 -0.182387
+v 1.237589 -0.865408 0.182387
+v 1.290285 -0.844363 -0.182387
+v 1.263747 -0.855268 0.182387
+v 1.290285 -0.841263 -0.182387
+v 1.290285 -0.832502 -0.182387
+v 1.290285 -0.841263 0.182387
+v 1.290285 -0.818888 -0.182387
+v 1.290285 -0.832502 0.182387
+v 1.290285 -0.801231 -0.182387
+v 1.290285 -0.818888 0.182387
+v 1.290285 -0.780339 -0.182387
+v 1.290285 -0.801231 0.182387
+v 1.290285 -0.757021 -0.182387
+v 1.290285 -0.780339 0.182387
+v 1.290285 -0.732085 -0.182387
+v 1.290285 -0.757021 0.182387
+v 1.290285 -0.706341 -0.182387
+v 1.290285 -0.732085 0.182387
+v 1.290285 -0.680596 -0.182387
+v 1.290285 -0.706341 0.182387
+v 1.290285 -0.680596 0.182387
+v 0.952447 -0.926449 -0.182387
+v 0.949063 -0.926488 0.182387
+v 0.955859 -0.926385 -0.182387
+v 0.952447 -0.926449 0.182387
+v 0.959298 -0.926295 -0.182387
+v 0.955859 -0.926385 0.182387
+v 0.962762 -0.926181 -0.182387
+v 0.959298 -0.926295 0.182387
+v 0.966249 -0.926042 -0.182387
+v 0.962762 -0.926181 0.182387
+v 0.966249 -0.926042 0.182387
+v 0.426419 -0.445305 -0.182387
+v 0.412138 -0.503110 -0.182387
+v 0.412138 -0.503110 0.182387
+v 0.439008 -0.384638 -0.182387
+v 0.426419 -0.445305 0.182387
+v 0.396163 -0.558060 -0.182387
+v 0.396163 -0.558060 0.182387
+v 0.449909 -0.321098 -0.182387
+v 0.439008 -0.384638 0.182387
+v 0.378490 -0.610163 -0.182387
+v 0.378490 -0.610163 0.182387
+v 0.459124 -0.254677 -0.182387
+v 0.449909 -0.321098 0.182387
+v 0.359117 -0.659430 -0.182387
+v 0.359117 -0.659430 0.182387
+v 0.466657 -0.185367 -0.182387
+v 0.459124 -0.254677 0.182387
+v 0.337635 -0.706565 -0.182387
+v 0.337635 -0.706565 0.182387
+v 0.472510 -0.113159 -0.182387
+v 0.466657 -0.185367 0.182387
+v 0.314338 -0.750899 -0.182387
+v 0.314338 -0.750899 0.182387
+v 0.476688 -0.038043 -0.182387
+v 0.472510 -0.113159 0.182387
+v 0.289217 -0.792428 -0.182387
+v 0.289217 -0.792428 0.182387
+v 0.479192 0.039988 -0.182387
+v 0.476688 -0.038043 0.182387
+v 0.262260 -0.831150 0.182387
+v 0.480026 0.120943 -0.182387
+v 0.479192 0.039988 0.182387
+v 0.233457 -0.867059 -0.182387
+v 0.233457 -0.867059 0.182387
+v 0.478892 0.209136 -0.182387
+v 0.480026 0.120943 0.182387
+v 0.202799 -0.900153 -0.182387
+v 0.202799 -0.900153 0.182387
+v 0.475486 0.293762 -0.182387
+v 0.478892 0.209136 0.182387
+v 0.170275 -0.930427 -0.182387
+v 0.170275 -0.930427 0.182387
+v 0.469801 0.374832 -0.182387
+v 0.475486 0.293762 0.182387
+v 0.135875 -0.957879 -0.182387
+v 0.135875 -0.957879 0.182387
+v 0.461829 0.452356 -0.182387
+v 0.469801 0.374832 0.182387
+v 0.099588 -0.982504 -0.182387
+v 0.099588 -0.982504 0.182387
+v 0.451565 0.526344 -0.182387
+v 0.461829 0.452356 0.182387
+v 0.061404 -1.004298 -0.182387
+v 0.061404 -1.004298 0.182387
+v 0.438999 0.596807 -0.182387
+v 0.451565 0.526344 0.182387
+v 0.021314 -1.023258 -0.182387
+v 0.021314 -1.023258 0.182387
+v 0.424126 0.663755 -0.182387
+v 0.438999 0.596807 0.182387
+v -0.020694 -1.039381 -0.182387
+v -0.020694 -1.039381 0.182387
+v 0.406938 0.727197 -0.182387
+v 0.424126 0.663755 0.182387
+v -0.016169 -1.061018 -0.182387
+v -0.016169 -1.061018 0.182387
+v 0.387429 0.787144 -0.182387
+v 0.406938 0.727197 0.182387
+v -0.011276 -1.081441 -0.182387
+v -0.011276 -1.081441 0.182387
+v 0.365590 0.843607 -0.182387
+v 0.387429 0.787144 0.182387
+v -0.006016 -1.100653 -0.182387
+v -0.006016 -1.100653 0.182387
+v 0.341416 0.896596 -0.182387
+v 0.365590 0.843607 0.182387
+v -0.000390 -1.118659 -0.182387
+v -0.000390 -1.118659 0.182387
+v 0.314899 0.946121 -0.182387
+v 0.341416 0.896596 0.182387
+v 0.005602 -1.135461 -0.182387
+v 0.005602 -1.135461 0.182387
+v 0.285433 0.993262 -0.182387
+v 0.314899 0.946121 0.182387
+v 0.011959 -1.151064 -0.182387
+v 0.011959 -1.151064 0.182387
+v 0.253428 1.036951 -0.182387
+v 0.285433 0.993262 0.182387
+v 0.018682 -1.165471 -0.182387
+v 0.018682 -1.165471 0.182387
+v 0.218864 1.077179 -0.182387
+v 0.253428 1.036951 0.182387
+v 0.025769 -1.178687 -0.182387
+v 0.025769 -1.178687 0.182387
+v 0.181722 1.113937 -0.182387
+v 0.218864 1.077179 0.182387
+v 0.033220 -1.190714 -0.182387
+v 0.033220 -1.190714 0.182387
+v 0.141985 1.147215 -0.182387
+v 0.181722 1.113937 0.182387
+v 0.041036 -1.201556 -0.182387
+v 0.041036 -1.201556 0.182387
+v 0.099634 1.177004 -0.182387
+v 0.141985 1.147215 0.182387
+v 0.049214 -1.211217 -0.182387
+v 0.049214 -1.211217 0.182387
+v 0.054650 1.203293 -0.182387
+v 0.099634 1.177004 0.182387
+v 0.057755 -1.219701 -0.182387
+v 0.057755 -1.219701 0.182387
+v 0.007014 1.226074 -0.182387
+v 0.054650 1.203293 0.182387
+v 0.062803 -1.223925 -0.182387
+v 0.062803 -1.223925 0.182387
+v -0.043291 1.245338 -0.182387
+v 0.007014 1.226074 0.182387
+v 0.068176 -1.227869 -0.182387
+v 0.068176 -1.227869 0.182387
+v -0.096284 1.261074 -0.182387
+v -0.043291 1.245338 0.182387
+v 0.073872 -1.231538 -0.182387
+v 0.073872 -1.231538 0.182387
+v -0.151985 1.273272 -0.182387
+v -0.096284 1.261074 0.182387
+v 0.079888 -1.234935 -0.182387
+v 0.079888 -1.234935 0.182387
+v -0.210411 1.281925 -0.182387
+v -0.151985 1.273272 0.182387
+v 0.086222 -1.238063 -0.182387
+v 0.086222 -1.238063 0.182387
+v -0.219049 1.282895 -0.182387
+v -0.210411 1.281925 0.182387
+v 0.092870 -1.240926 -0.182387
+v 0.092870 -1.240926 0.182387
+v -0.227645 1.283780 -0.182387
+v -0.219049 1.282895 0.182387
+v 0.099831 -1.243528 -0.182387
+v 0.099831 -1.243528 0.182387
+v -0.236197 1.284580 -0.182387
+v -0.227645 1.283780 0.182387
+v 0.107101 -1.245871 -0.182387
+v 0.107101 -1.245871 0.182387
+v -0.244706 1.285296 -0.182387
+v -0.236197 1.284580 0.182387
+v 0.114677 -1.247959 -0.182387
+v 0.114677 -1.247959 0.182387
+v -0.253173 1.285927 -0.182387
+v -0.244706 1.285296 0.182387
+v 0.122558 -1.249797 -0.182387
+v 0.122558 -1.249797 0.182387
+v -0.261597 1.286474 -0.182387
+v -0.253173 1.285927 0.182387
+v 0.130740 -1.251386 -0.182387
+v 0.130740 -1.251386 0.182387
+v -0.269979 1.286936 -0.182387
+v -0.261597 1.286474 0.182387
+v 0.139220 -1.252732 -0.182387
+v 0.139220 -1.252732 0.182387
+v -0.278318 1.287314 -0.182387
+v -0.269979 1.286936 0.182387
+v 0.139392 -1.252755 -0.182387
+v 0.139392 -1.252755 0.182387
+v -0.286614 1.287608 -0.182387
+v -0.278318 1.287314 0.182387
+v 0.139563 -1.252762 -0.182387
+v 0.139563 -1.252762 0.182387
+v -0.294869 1.287817 -0.182387
+v -0.286614 1.287608 0.182387
+v 0.139734 -1.252757 -0.182387
+v 0.139734 -1.252757 0.182387
+v -0.303082 1.287943 -0.182387
+v -0.294869 1.287817 0.182387
+v 0.139905 -1.252744 -0.182387
+v 0.139905 -1.252744 0.182387
+v -0.311252 1.287985 -0.182387
+v -0.303082 1.287943 0.182387
+v 0.140076 -1.252724 -0.182387
+v 0.140076 -1.252724 0.182387
+v -0.361180 1.286331 -0.182387
+v -0.311252 1.287985 0.182387
+v 0.140248 -1.252701 -0.182387
+v 0.140248 -1.252701 0.182387
+v -0.409360 1.281363 -0.182387
+v -0.361180 1.286331 0.182387
+v 0.140422 -1.252678 -0.182387
+v 0.140422 -1.252678 0.182387
+v -0.455776 1.273071 -0.182387
+v -0.409360 1.281363 0.182387
+v 0.140597 -1.252657 -0.182387
+v 0.140597 -1.252657 0.182387
+v -0.500415 1.261445 -0.182387
+v -0.455776 1.273071 0.182387
+v 0.140774 -1.252644 -0.182387
+v 0.140774 -1.252644 0.182387
+v -0.543260 1.246475 -0.182387
+v -0.500415 1.261445 0.182387
+v 0.140954 -1.252639 -0.182387
+v 0.140954 -1.252639 0.182387
+v -0.584298 1.228152 -0.182387
+v -0.543260 1.246475 0.182387
+v 0.141137 -1.252646 -0.182387
+v 0.141137 -1.252646 0.182387
+v -0.623514 1.206466 -0.182387
+v -0.584298 1.228152 0.182387
+v 0.141324 -1.252669 -0.182387
+v 0.141324 -1.252669 0.182387
+v -0.660894 1.181408 -0.182387
+v -0.623514 1.206466 0.182387
+v 0.141785 -1.252711 -0.182387
+v 0.141785 -1.252711 0.182387
+v -0.696421 1.152968 -0.182387
+v -0.660894 1.181408 0.182387
+v 0.142256 -1.252718 -0.182387
+v 0.142256 -1.252718 0.182387
+v -0.730083 1.121135 -0.182387
+v -0.696421 1.152968 0.182387
+v 0.142734 -1.252694 -0.182387
+v 0.142734 -1.252694 0.182387
+v -0.761863 1.085901 -0.182387
+v -0.730083 1.121135 0.182387
+v 0.143219 -1.252649 -0.182387
+v 0.143219 -1.252649 0.182387
+v -0.791747 1.047255 -0.182387
+v -0.761863 1.085901 0.182387
+v 0.143707 -1.252589 -0.182387
+v 0.143707 -1.252589 0.182387
+v -0.824643 0.997153 -0.182387
+v -0.791747 1.047255 0.182387
+v 0.144198 -1.252520 -0.182387
+v 0.144198 -1.252520 0.182387
+v -0.854719 0.942465 -0.182387
+v -0.824643 0.997153 0.182387
+v 0.144688 -1.252450 -0.182387
+v 0.144688 -1.252450 0.182387
+v -0.881969 0.883201 -0.182387
+v -0.854719 0.942465 0.182387
+v 0.145176 -1.252385 -0.182387
+v 0.145176 -1.252385 0.182387
+v -0.906384 0.819374 -0.182387
+v -0.881969 0.883201 0.182387
+v 0.145661 -1.252334 -0.182387
+v 0.145661 -1.252334 0.182387
+v -0.927957 0.750994 -0.182387
+v -0.906384 0.819374 0.182387
+v 0.146139 -1.252301 -0.182387
+v 0.146139 -1.252301 0.182387
+v -0.946680 0.678073 -0.182387
+v -0.927957 0.750994 0.182387
+v 0.146610 -1.252296 -0.182387
+v 0.146610 -1.252296 0.182387
+v -0.962543 0.600624 -0.182387
+v -0.946680 0.678073 0.182387
+v 0.147071 -1.252324 -0.182387
+v 0.147071 -1.252324 0.182387
+v -0.975540 0.518656 -0.182387
+v -0.962543 0.600624 0.182387
+v 0.149900 -1.252584 -0.182387
+v 0.149900 -1.252584 0.182387
+v -0.985663 0.432183 -0.182387
+v -0.975540 0.518656 0.182387
+v 0.152764 -1.252761 -0.182387
+v 0.152764 -1.252761 0.182387
+v -0.992904 0.341214 -0.182387
+v -0.985663 0.432183 0.182387
+v 0.155663 -1.252865 -0.182387
+v 0.155663 -1.252865 0.182387
+v -0.997254 0.245763 -0.182387
+v -0.992904 0.341214 0.182387
+v 0.158594 -1.252909 -0.182387
+v 0.158594 -1.252909 0.182387
+v -0.998706 0.145841 -0.182387
+v -0.997254 0.245763 0.182387
+v 0.161558 -1.252904 -0.182387
+v 0.161558 -1.252904 0.182387
+v -0.997645 0.052952 -0.182387
+v 0.164552 -1.252862 -0.182387
+v 0.164552 -1.252862 0.182387
+v -0.994467 -0.036208 -0.182387
+v 0.167575 -1.252794 -0.182387
+v 0.167575 -1.252794 0.182387
+v -0.989178 -0.121631 -0.182387
+v -0.994467 -0.036208 0.182387
+v 0.170627 -1.252712 -0.182387
+v 0.170627 -1.252712 0.182387
+v -0.989178 -0.121631 0.182387
+v 0.173706 -1.252628 -0.182387
+v 0.173706 -1.252628 0.182387
+v -0.981784 -0.203307 0.182387
+v 0.176810 -1.252554 -0.182387
+v 0.176810 -1.252554 0.182387
+v -0.960710 -0.355393 -0.182387
+v -0.972293 -0.281231 0.182387
+v 0.179940 -1.252501 -0.182387
+v 0.179940 -1.252501 0.182387
+v -0.947042 -0.425786 -0.182387
+v -0.960710 -0.355393 0.182387
+v 0.183092 -1.252481 -0.182387
+v 0.183092 -1.252481 0.182387
+v -0.931295 -0.492402 -0.182387
+v -0.947042 -0.425786 0.182387
+v 0.183174 -1.252481 -0.182387
+v 0.183174 -1.252481 0.182387
+v -0.913475 -0.555233 -0.182387
+v -0.931295 -0.492402 0.182387
+v 0.183265 -1.252481 -0.182387
+v 0.183265 -1.252481 0.182387
+v -0.893590 -0.614272 -0.182387
+v -0.913475 -0.555233 0.182387
+v 0.183363 -1.252481 -0.182387
+v 0.183363 -1.252481 0.182387
+v -0.871646 -0.669510 -0.182387
+v -0.893590 -0.614272 0.182387
+v 0.183463 -1.252481 -0.182387
+v 0.183463 -1.252481 0.182387
+v -0.847648 -0.720939 -0.182387
+v -0.871646 -0.669510 0.182387
+v 0.183564 -1.252481 -0.182387
+v 0.183564 -1.252481 0.182387
+v -0.822076 -0.768036 -0.182387
+v -0.847648 -0.720939 0.182387
+v 0.183662 -1.252481 -0.182387
+v 0.183662 -1.252481 0.182387
+v -0.794690 -0.811855 -0.182387
+v -0.822076 -0.768036 0.182387
+v 0.183753 -1.252481 -0.182387
+v 0.183753 -1.252481 0.182387
+v -0.765502 -0.852402 -0.182387
+v -0.794690 -0.811855 0.182387
+v 0.183835 -1.252481 -0.182387
+v 0.183835 -1.252481 0.182387
+v -0.734525 -0.889683 -0.182387
+v -0.765502 -0.852402 0.182387
+v 0.183904 -1.252481 -0.182387
+v 0.183904 -1.252481 0.182387
+v -0.701772 -0.923703 -0.182387
+v -0.734525 -0.889683 0.182387
+v 0.183957 -1.252481 -0.182387
+v 0.183957 -1.252481 0.182387
+v -0.667254 -0.954468 -0.182387
+v -0.701772 -0.923703 0.182387
+v 0.183991 -1.252481 -0.182387
+v 0.183991 -1.252481 0.182387
+v -0.630985 -0.981984 -0.182387
+v -0.667254 -0.954468 0.182387
+v 0.184003 -1.252481 -0.182387
+v 0.184003 -1.252481 0.182387
+v -0.592977 -1.006257 -0.182387
+v -0.630985 -0.981984 0.182387
+v 0.187874 -1.252534 -0.182387
+v 0.187874 -1.252534 0.182387
+v -0.553243 -1.027292 -0.182387
+v -0.592977 -1.006257 0.182387
+v 0.191482 -1.252676 -0.182387
+v 0.191482 -1.252676 0.182387
+v -0.511795 -1.045095 -0.182387
+v -0.553243 -1.027292 0.182387
+v 0.194921 -1.252880 -0.182387
+v 0.194921 -1.252880 0.182387
+v -0.468646 -1.059673 -0.182387
+v -0.511795 -1.045095 0.182387
+v 0.198291 -1.253120 -0.182387
+v 0.198291 -1.253120 0.182387
+v -0.423807 -1.071030 -0.182387
+v -0.468646 -1.059673 0.182387
+v 0.201688 -1.253370 -0.182387
+v 0.201688 -1.253370 0.182387
+v -0.413388 -1.117919 -0.182387
+v -0.423807 -1.071030 0.182387
+v 0.205209 -1.253603 -0.182387
+v 0.205209 -1.253603 0.182387
+v -0.402043 -1.162206 -0.182387
+v -0.413388 -1.117919 0.182387
+v 0.208952 -1.253793 -0.182387
+v 0.208952 -1.253793 0.182387
+v -0.389771 -1.203891 -0.182387
+v -0.402043 -1.162206 0.182387
+v 0.213012 -1.253913 -0.182387
+v 0.213012 -1.253913 0.182387
+v -0.376574 -1.242972 -0.182387
+v -0.389771 -1.203891 0.182387
+v 0.217488 -1.253938 -0.182387
+v 0.217488 -1.253938 0.182387
+v -0.362454 -1.279447 -0.182387
+v -0.376574 -1.242972 0.182387
+v 0.222476 -1.253840 -0.182387
+v 0.222476 -1.253840 0.182387
+v -0.347411 -1.313315 -0.182387
+v -0.362454 -1.279447 0.182387
+v 0.228073 -1.253593 -0.182387
+v 0.228073 -1.253593 0.182387
+v -0.331446 -1.344574 -0.182387
+v -0.347411 -1.313315 0.182387
+v 0.234377 -1.253171 -0.182387
+v 0.234377 -1.253171 0.182387
+v -0.314560 -1.373223 -0.182387
+v -0.331446 -1.344574 0.182387
+v 0.234377 -1.515692 -0.182387
+v 0.234377 -1.515692 0.182387
+v -0.296754 -1.399261 -0.182387
+v -0.314560 -1.373223 0.182387
+v 0.223663 -1.517095 -0.182387
+v 0.223663 -1.517095 0.182387
+v -0.278030 -1.422685 -0.182387
+v -0.296754 -1.399261 0.182387
+v 0.211706 -1.518660 -0.182387
+v 0.211706 -1.518660 0.182387
+v -0.258387 -1.443494 -0.182387
+v -0.278030 -1.422685 0.182387
+v 0.198920 -1.520334 -0.182387
+v 0.198920 -1.520334 0.182387
+v -0.237828 -1.461687 -0.182387
+v -0.258387 -1.443494 0.182387
+v 0.185719 -1.522063 -0.182387
+v 0.185719 -1.522063 0.182387
+v -0.221488 -1.473931 -0.182387
+v -0.237828 -1.461687 0.182387
+v 0.172517 -1.523791 -0.182387
+v 0.172517 -1.523791 0.182387
+v -0.204283 -1.485104 -0.182387
+v -0.221488 -1.473931 0.182387
+v 0.159731 -1.525465 -0.182387
+v 0.159731 -1.525465 0.182387
+v -0.186216 -1.495208 -0.182387
+v -0.204283 -1.485104 0.182387
+v 0.147774 -1.527030 -0.182387
+v 0.147774 -1.527030 0.182387
+v -0.167291 -1.504244 -0.182387
+v -0.186216 -1.495208 0.182387
+v 0.137061 -1.528433 -0.182387
+v 0.137061 -1.528433 0.182387
+v -0.147509 -1.512212 -0.182387
+v -0.167291 -1.504244 0.182387
+v 0.128007 -1.529619 -0.182387
+v 0.128007 -1.529619 0.182387
+v -0.126874 -1.519115 -0.182387
+v -0.147509 -1.512212 0.182387
+v 0.121026 -1.530532 -0.182387
+v 0.121026 -1.530532 0.182387
+v -0.105388 -1.524953 -0.182387
+v -0.126874 -1.519115 0.182387
+v 0.116533 -1.531121 -0.182387
+v 0.116533 -1.531121 0.182387
+v -0.083055 -1.529726 -0.182387
+v -0.105388 -1.524953 0.182387
+v 0.114944 -1.531329 -0.182387
+v 0.114944 -1.531329 0.182387
+v -0.059876 -1.533437 -0.182388
+v -0.083055 -1.529726 0.182387
+v 0.106191 -1.532421 -0.182388
+v 0.106191 -1.532421 0.182386
+v -0.035856 -1.536087 -0.182388
+v -0.059876 -1.533437 0.182386
+v 0.097506 -1.533419 -0.182388
+v 0.097506 -1.533419 0.182386
+v -0.010996 -1.537676 -0.182388
+v -0.035856 -1.536087 0.182386
+v 0.088889 -1.534324 -0.182388
+v 0.088889 -1.534324 0.182386
+v 0.014699 -1.538205 -0.182388
+v -0.010996 -1.537676 0.182386
+v 0.080342 -1.535135 -0.182388
+v 0.080342 -1.535135 0.182386
+v 0.022624 -1.538157 -0.182388
+v 0.014699 -1.538205 0.182386
+v 0.071868 -1.535852 -0.182388
+v 0.071868 -1.535852 0.182386
+v 0.030633 -1.538012 -0.182388
+v 0.022624 -1.538157 0.182386
+v 0.063467 -1.536474 -0.182388
+v 0.063467 -1.536474 0.182386
+v 0.038723 -1.537771 -0.182388
+v 0.030633 -1.538012 0.182386
+v 0.055141 -1.537002 -0.182388
+v 0.055141 -1.537002 0.182386
+v 0.046893 -1.537434 -0.182388
+v 0.038723 -1.537771 0.182386
+v 0.046893 -1.537434 0.182386
+v 0.069721 0.127787 -0.182387
+v -0.507111 0.055574 -0.182387
+v -0.507627 0.137615 -0.182387
+v 0.030318 -0.471963 0.182387
+v -0.465641 -0.453883 0.182387
+v -0.455769 -0.499161 0.182387
+v -0.273302 0.974642 -0.182387
+v -0.292921 0.969356 -0.182387
+v -0.292921 0.969356 0.182387
+v -0.252844 0.977813 -0.182387
+v -0.273302 0.974642 0.182387
+v -0.311702 0.961955 -0.182387
+v -0.311702 0.961955 0.182387
+v -0.231547 0.978869 -0.182387
+v -0.252844 0.977813 0.182387
+v -0.329644 0.952436 -0.182387
+v -0.329644 0.952436 0.182387
+v -0.229829 0.978862 -0.182387
+v -0.231547 0.978869 0.182387
+v -0.346747 0.940799 -0.182387
+v -0.346747 0.940799 0.182387
+v -0.228101 0.978840 -0.182387
+v -0.229829 0.978862 0.182387
+v -0.363012 0.927042 -0.182387
+v -0.363012 0.927042 0.182387
+v -0.226363 0.978804 -0.182387
+v -0.228101 0.978840 0.182387
+v -0.378438 0.911165 -0.182387
+v -0.378438 0.911165 0.182387
+v -0.224615 0.978755 -0.182387
+v -0.226363 0.978804 0.182387
+v -0.393025 0.893167 -0.182387
+v -0.393025 0.893167 0.182387
+v -0.222860 0.978691 -0.182387
+v -0.224615 0.978755 0.182387
+v -0.406773 0.873046 -0.182387
+v -0.406773 0.873046 0.182387
+v -0.221097 0.978614 -0.182387
+v -0.222860 0.978691 0.182387
+v -0.419682 0.850800 -0.182387
+v -0.419682 0.850800 0.182387
+v -0.219327 0.978523 -0.182387
+v -0.221097 0.978614 0.182387
+v -0.431753 0.826431 -0.182387
+v -0.431753 0.826431 0.182387
+v -0.217552 0.978418 -0.182387
+v -0.219327 0.978523 0.182387
+v -0.443828 0.796221 -0.182387
+v -0.443828 0.796221 0.182387
+v -0.215772 0.978299 -0.182387
+v -0.217552 0.978418 0.182387
+v -0.454864 0.761058 -0.182387
+v -0.454864 0.761058 0.182387
+v -0.213988 0.978168 -0.182387
+v -0.215772 0.978299 0.182387
+v -0.464860 0.720945 -0.182387
+v -0.464860 0.720945 0.182387
+v -0.212200 0.978023 -0.182387
+v -0.213988 0.978168 0.182387
+v -0.473812 0.675884 -0.182387
+v -0.473812 0.675884 0.182387
+v -0.210411 0.977865 -0.182387
+v -0.212200 0.978023 0.182387
+v -0.481720 0.625878 -0.182387
+v -0.481720 0.625878 0.182387
+v -0.187470 0.974624 -0.182387
+v -0.210411 0.977865 0.182387
+v -0.488580 0.570931 -0.182387
+v -0.488580 0.570931 0.182387
+v -0.165518 0.969019 -0.182387
+v -0.187470 0.974624 0.182387
+v -0.494391 0.511044 -0.182387
+v -0.494391 0.511044 0.182387
+v -0.144552 0.961056 -0.182387
+v -0.165518 0.969019 0.182387
+v -0.499150 0.446221 -0.182387
+v -0.499150 0.446221 0.182387
+v -0.124571 0.950738 -0.182387
+v -0.144552 0.961056 0.182387
+v -0.502855 0.376463 -0.182387
+v -0.502855 0.376463 0.182387
+v -0.105573 0.938070 -0.182387
+v -0.124571 0.950738 0.182387
+v -0.505505 0.301775 -0.182387
+v -0.505505 0.301775 0.182387
+v -0.087555 0.923059 -0.182387
+v -0.105573 0.938070 0.182387
+v -0.507096 0.222158 -0.182387
+v -0.507096 0.222158 0.182387
+v -0.070516 0.905708 -0.182387
+v -0.087555 0.923059 0.182387
+v -0.507627 0.137615 0.182387
+v -0.054454 0.886023 -0.182387
+v -0.070516 0.905708 0.182387
+v -0.507111 0.055574 0.182387
+v -0.039367 0.864009 -0.182387
+v -0.054454 0.886023 0.182387
+v -0.505560 -0.022395 -0.182387
+v -0.505560 -0.022395 0.182387
+v -0.025253 0.839671 -0.182387
+v -0.039367 0.864009 0.182387
+v -0.502975 -0.096287 -0.182387
+v -0.502975 -0.096287 0.182387
+v -0.012110 0.813014 -0.182387
+v -0.025253 0.839671 0.182387
+v -0.499352 -0.166100 -0.182387
+v -0.499352 -0.166100 0.182387
+v 0.000065 0.784043 -0.182387
+v -0.012110 0.813014 0.182387
+v -0.494692 -0.231832 -0.182387
+v -0.494692 -0.231832 0.182387
+v 0.011252 0.752004 -0.182387
+v 0.000065 0.784043 0.182387
+v -0.488992 -0.293479 -0.182387
+v -0.488992 -0.293479 0.182387
+v 0.021450 0.715855 -0.182387
+v 0.011252 0.752004 0.182387
+v -0.482251 -0.351039 -0.182387
+v -0.482251 -0.351039 0.182387
+v 0.030663 0.675595 -0.182387
+v 0.021450 0.715855 0.182387
+v -0.474468 -0.404507 -0.182387
+v -0.474468 -0.404507 0.182387
+v 0.038893 0.631220 -0.182387
+v 0.030663 0.675595 0.182387
+v -0.465641 -0.453883 -0.182387
+v 0.046143 0.582729 -0.182387
+v 0.038893 0.631220 0.182387
+v -0.455769 -0.499161 -0.182387
+v 0.052417 0.530117 -0.182387
+v 0.046143 0.582729 0.182387
+v -0.444850 -0.540341 -0.182387
+v -0.444850 -0.540341 0.182387
+v 0.057717 0.473383 -0.182387
+v 0.052417 0.530117 0.182387
+v -0.432883 -0.577418 -0.182387
+v -0.432883 -0.577418 0.182387
+v 0.062046 0.412525 -0.182387
+v 0.057717 0.473383 0.182387
+v -0.420633 -0.609377 -0.182387
+v -0.420633 -0.609377 0.182387
+v 0.065408 0.347538 -0.182387
+v 0.062046 0.412525 0.182387
+v -0.407408 -0.638535 -0.182387
+v -0.407408 -0.638535 0.182387
+v 0.067806 0.278422 -0.182387
+v 0.065408 0.347538 0.182387
+v -0.393214 -0.664896 -0.182387
+v -0.393214 -0.664896 0.182387
+v 0.069243 0.205172 -0.182387
+v 0.067806 0.278422 0.182387
+v -0.378055 -0.688465 -0.182387
+v -0.378055 -0.688465 0.182387
+v 0.069243 0.205172 0.182387
+v -0.361938 -0.709246 -0.182387
+v -0.361938 -0.709246 0.182387
+v 0.069238 0.041715 -0.182387
+v 0.069721 0.127787 0.182387
+v -0.344867 -0.727242 -0.182387
+v -0.344867 -0.727242 0.182387
+v 0.067786 -0.039494 -0.182387
+v 0.069238 0.041715 0.182387
+v -0.326849 -0.742459 -0.182387
+v -0.326849 -0.742459 0.182387
+v 0.065364 -0.115843 -0.182387
+v 0.067786 -0.039494 0.182387
+v -0.307887 -0.754899 -0.182387
+v -0.307887 -0.754899 0.182387
+v 0.061970 -0.187334 -0.182387
+v 0.065364 -0.115843 0.182387
+v -0.287989 -0.764568 -0.182387
+v -0.287989 -0.764568 0.182387
+v 0.057600 -0.253967 -0.182387
+v 0.061970 -0.187334 0.182387
+v -0.267158 -0.771469 -0.182387
+v -0.267158 -0.771469 0.182387
+v 0.052252 -0.315745 -0.182387
+v 0.057600 -0.253967 0.182387
+v -0.245400 -0.775607 -0.182387
+v -0.245400 -0.775607 0.182387
+v 0.045924 -0.372668 -0.182387
+v 0.052252 -0.315745 0.182387
+v -0.222722 -0.776985 -0.182387
+v -0.222722 -0.776985 0.182387
+v 0.038614 -0.424741 -0.182387
+v 0.045924 -0.372668 0.182387
+v -0.221695 -0.776981 -0.182387
+v -0.221695 -0.776981 0.182387
+v 0.030318 -0.471963 -0.182387
+v 0.038614 -0.424741 0.182387
+v -0.220669 -0.776970 -0.182387
+v -0.220669 -0.776970 0.182387
+v 0.021036 -0.514336 -0.182387
+v -0.219646 -0.776952 -0.182387
+v -0.219646 -0.776952 0.182387
+v 0.010764 -0.551863 -0.182387
+v 0.021036 -0.514336 0.182387
+v -0.218623 -0.776927 -0.182387
+v -0.218623 -0.776927 0.182387
+v -0.000501 -0.584545 -0.182387
+v 0.010764 -0.551863 0.182387
+v -0.217601 -0.776896 -0.182387
+v -0.217601 -0.776896 0.182387
+v -0.012809 -0.613863 -0.182387
+v -0.000501 -0.584545 0.182387
+v -0.216578 -0.776860 -0.182387
+v -0.216578 -0.776860 0.182387
+v -0.026056 -0.640763 -0.182387
+v -0.012809 -0.613863 0.182387
+v -0.215555 -0.776818 -0.182387
+v -0.215555 -0.776818 0.182387
+v -0.040242 -0.665243 -0.182387
+v -0.026056 -0.640763 0.182387
+v -0.214531 -0.776771 -0.182387
+v -0.214531 -0.776771 0.182387
+v -0.055369 -0.687302 -0.182387
+v -0.040242 -0.665243 0.182387
+v -0.213505 -0.776720 -0.182387
+v -0.213505 -0.776720 0.182387
+v -0.071438 -0.706941 -0.182387
+v -0.055369 -0.687302 0.182387
+v -0.212477 -0.776665 -0.182387
+v -0.212477 -0.776665 0.182387
+v -0.088450 -0.724158 -0.182387
+v -0.071438 -0.706941 0.182387
+v -0.211446 -0.776607 -0.182387
+v -0.211446 -0.776607 0.182387
+v -0.106407 -0.738952 -0.182387
+v -0.088450 -0.724158 0.182387
+v -0.210411 -0.776546 -0.182387
+v -0.210411 -0.776546 0.182387
+v -0.125311 -0.751321 -0.182387
+v -0.106407 -0.738952 0.182387
+v -0.187710 -0.773880 -0.182387
+v -0.187710 -0.773880 0.182387
+v -0.145162 -0.761267 -0.182387
+v -0.125311 -0.751321 0.182387
+v -0.165961 -0.768786 -0.182387
+v -0.165961 -0.768786 0.182387
+v -0.145162 -0.761267 0.182387
+v -0.836574 2.034443 -0.182386
+v -1.543393 -1.434298 -0.182387
+v -1.543393 -1.802300 -0.182388
+v -1.543393 -2.132013 -0.182388
+v -1.543393 1.356561 -0.182387
+v -1.543393 1.141716 -0.182387
+v -1.543393 0.863055 -0.182387
+v -1.543393 0.533343 -0.182387
+v -1.543393 0.165341 -0.182387
+v -0.683363 2.009288 -0.182386
+v -0.484644 1.976661 -0.182386
+v -0.249518 1.938057 -0.182386
+v 0.012913 1.894969 -0.182386
+v 0.293547 1.848894 -0.182386
+v 1.153652 1.707676 -0.182386
+v 1.416083 1.664589 -0.182386
+v 1.651209 1.378124 -0.182387
+v 1.651209 1.625984 -0.182386
+v 1.651209 1.101481 -0.182387
+v 0.293547 1.848894 0.182388
+v -0.683363 2.009288 0.182388
+v -0.484644 1.976661 0.182388
+v -0.249518 1.938057 0.182388
+v 0.012913 1.894969 0.182388
+v 0.873018 1.753752 0.182388
+v 1.153652 1.707676 0.182388
+v 1.416083 1.664589 0.182388
+v 1.651209 1.378124 0.182387
+v 1.651209 1.625984 0.182388
+v 1.651209 1.101481 0.182387
+v -1.543393 -1.434298 0.182387
+v -1.543393 -1.802300 0.182386
+v -1.543393 1.356561 0.182387
+v -1.543393 1.141716 0.182387
+v -1.543393 0.863055 0.182387
+v -1.543393 -0.634479 0.182387
+v -1.543393 0.533343 0.182387
+v -1.543393 -0.228187 0.182387
+v 1.651209 -0.835023 -0.182387
+v 1.651209 -0.625542 -0.182387
+v 1.651209 0.805648 -0.182387
+v 1.651209 0.194794 -0.182387
+v 1.651209 -0.101039 -0.182387
+v 1.651209 -0.377682 -0.182387
+v 1.651209 -0.101039 0.182387
+v 1.651209 -0.625542 0.182387
+v 1.651209 0.194794 0.182387
+v 1.651209 -0.377682 0.182387
+vn 0.943300 -0.332000 0.000000
+vn 0.906700 -0.421700 0.000000
+vn 0.000000 0.000000 -1.000000
+vn 0.970600 -0.240500 0.000000
+vn -0.000000 -0.000000 1.000000
+vn 0.860000 -0.510200 0.000000
+vn 0.050100 -0.998700 -0.000000
+vn 0.045400 -0.999000 -0.000000
+vn 0.045700 -0.999000 -0.000000
+vn 0.039800 -0.999200 -0.000000
+vn 0.040000 -0.999200 -0.000000
+vn 0.032900 -0.999500 -0.000000
+vn 0.033000 -0.999500 0.000000
+vn 0.032600 -0.999500 -0.000000
+vn 0.025300 -0.999700 -0.000000
+vn 0.025600 -0.999700 -0.000000
+vn 0.018200 -0.999800 -0.000000
+vn 0.018000 -0.999800 -0.000000
+vn 0.010500 -0.999900 -0.000000
+vn 0.010400 -0.999900 -0.000000
+vn 0.003300 -1.000000 -0.000000
+vn 0.003200 -1.000000 -0.000000
+vn -0.027200 -0.999600 -0.000000
+vn -0.086700 -0.996200 -0.000000
+vn -0.152500 -0.988300 -0.000000
+vn -0.224600 -0.974500 -0.000000
+vn -0.301200 -0.953600 -0.000000
+vn -0.380700 -0.924700 -0.000000
+vn -0.460400 -0.887700 -0.000000
+vn -0.537400 -0.843300 -0.000000
+vn -0.609300 -0.793000 -0.000000
+vn -0.674100 -0.738700 -0.000000
+vn -0.730400 -0.683100 -0.000000
+vn -0.730400 -0.683000 -0.000000
+vn -0.778100 -0.628200 -0.000000
+vn -0.836100 -0.548600 -0.000000
+vn -0.836000 -0.548700 -0.000000
+vn -0.899000 -0.437900 -0.000000
+vn -0.938800 -0.344400 -0.000000
+vn -0.963600 -0.267500 -0.000000
+vn -0.978700 -0.205500 -0.000000
+vn -0.987800 -0.155500 -0.000000
+vn -0.993300 -0.115400 -0.000000
+vn -0.996500 -0.083100 -0.000000
+vn -0.998400 -0.056900 -0.000000
+vn -0.999400 -0.036000 -0.000000
+vn -0.999800 -0.019100 -0.000000
+vn -1.000000 -0.005700 -0.000000
+vn -1.000000 0.000000 0.000000
+vn 0.049600 0.998800 0.000000
+vn -0.076200 -0.997100 -0.000000
+vn -0.105200 -0.994400 0.000000
+vn 0.973500 -0.228800 -0.000000
+vn -0.071500 -0.997400 -0.000000
+vn 1.000000 0.000000 0.000000
+vn 0.052500 0.998600 0.000000
+vn 0.999800 0.021400 0.000000
+vn 0.997800 0.066100 0.000000
+vn 0.993500 0.113400 0.000000
+vn 0.986600 0.163300 0.000000
+vn 0.976400 0.215800 0.000000
+vn 0.962600 0.270800 0.000000
+vn 0.944600 0.328200 0.000000
+vn 0.921800 0.387700 0.000000
+vn 0.893600 0.448900 0.000000
+vn 0.859500 0.511100 0.000000
+vn 0.819000 0.573800 0.000000
+vn 0.771800 0.635800 0.000000
+vn 0.718300 0.695700 0.000000
+vn 0.656000 0.754800 0.000000
+vn 0.589800 0.807500 0.000000
+vn 0.521500 0.853200 0.000000
+vn 0.452300 0.891800 0.000000
+vn 0.383700 0.923500 0.000000
+vn 0.316500 0.948600 0.000000
+vn 0.251800 0.967800 0.000000
+vn 0.190000 0.981800 0.000000
+vn 0.131400 0.991300 0.000000
+vn 0.076300 0.997100 0.000000
+vn 0.024600 0.999700 0.000000
+vn 0.998800 -0.049500 0.000000
+vn 0.989200 -0.146500 0.000000
+vn 0.801600 -0.597800 0.000000
+vn 0.729300 -0.684200 0.000000
+vn 0.640300 -0.768100 0.000000
+vn 0.532100 -0.846700 0.000000
+vn 0.402500 -0.915400 0.000000
+vn 0.252300 -0.967700 0.000000
+vn 0.166000 -0.986100 0.000000
+vn -0.997800 0.065600 0.000000
+vn -0.979900 0.199400 0.000000
+vn -0.943000 0.332900 0.000000
+vn -0.886600 0.462600 0.000000
+vn -0.811000 0.585000 0.000000
+vn -0.717300 0.696700 0.000000
+vn -0.607000 0.794700 0.000000
+vn -0.482300 0.876000 0.000000
+vn -0.346000 0.938200 0.000000
+vn -0.201900 0.979400 0.000000
+vn -0.054400 0.998500 0.000000
+vn 0.091800 0.995800 0.000000
+vn 0.162000 0.986800 0.000000
+vn 0.440300 -0.897900 -0.000000
+vn 0.407000 -0.913400 -0.000000
+vn 0.406900 -0.913500 -0.000000
+vn 0.374200 -0.927400 -0.000000
+vn 0.342200 -0.939600 -0.000000
+vn 0.310600 -0.950500 -0.000000
+vn 0.279100 -0.960300 -0.000000
+vn 0.247600 -0.968900 -0.000000
+vn 0.215700 -0.976500 -0.000000
+vn 0.183200 -0.983100 -0.000000
+vn 0.149500 -0.988800 -0.000000
+vn 0.114600 -0.993400 -0.000000
+vn 0.077600 -0.997000 -0.000000
+vn 0.056300 -0.998400 -0.000000
+vn 0.055900 -0.998400 -0.000000
+vn 0.056200 -0.998400 -0.000000
+vn 0.056000 -0.998400 -0.000000
+vn 0.055800 -0.998400 -0.000000
+vn 0.053300 -0.998600 -0.000000
+vn 0.053700 -0.998600 -0.000000
+vn -0.003900 1.000000 0.000000
+vn -0.052900 0.998600 0.000000
+vn -0.059200 0.998200 0.000000
+vn -0.065600 0.997800 0.000000
+vn -0.071800 0.997400 0.000000
+vn -0.077600 0.997000 0.000000
+vn -0.100200 0.995000 0.000000
+vn -0.130800 0.991400 0.000000
+vn -0.160800 0.987000 0.000000
+vn -0.190200 0.981800 0.000000
+vn -0.218500 0.975800 0.000000
+vn -0.245800 0.969300 0.000000
+vn -0.271800 0.962400 0.000000
+vn -0.296400 0.955100 0.000000
+vn -0.319600 0.947600 0.000000
+vn -0.341200 0.940000 0.000000
+vn -0.361400 0.932400 0.000000
+vn -0.380100 0.925000 0.000000
+vn -0.011500 0.999900 0.000000
+vn -0.018800 0.999800 0.000000
+vn -0.026200 0.999700 0.000000
+vn -0.032900 0.999500 0.000000
+vn -0.039800 0.999200 0.000000
+vn -0.046700 0.998900 0.000000
+vn -0.970800 0.239800 0.000000
+vn -0.979100 0.203200 0.000000
+vn -0.960200 0.279200 0.000000
+vn -0.985600 0.169100 0.000000
+vn -0.947000 0.321200 0.000000
+vn -0.990500 0.137400 0.000000
+vn -0.930600 0.365900 0.000000
+vn -0.994100 0.108100 0.000000
+vn -0.994100 0.108000 0.000000
+vn -0.910000 0.414700 0.000000
+vn -0.996700 0.080800 0.000000
+vn -0.885200 0.465200 0.000000
+vn -0.998500 0.055500 0.000000
+vn -0.855600 0.517600 0.000000
+vn -0.999500 0.032100 0.000000
+vn -0.820700 0.571300 0.000000
+vn -0.999900 0.010300 0.000000
+vn -0.780100 0.625700 0.000000
+vn -0.999900 -0.012900 -0.000000
+vn -0.733600 0.679600 0.000000
+vn -0.999200 -0.040200 -0.000000
+vn -0.681300 0.732000 0.000000
+vn -0.997600 -0.070000 -0.000000
+vn -0.623800 0.781600 0.000000
+vn -0.994800 -0.102300 -0.000000
+vn -0.561500 0.827500 0.000000
+vn -0.990500 -0.137400 -0.000000
+vn -0.495700 0.868500 0.000000
+vn -0.984500 -0.175600 -0.000000
+vn -0.427500 0.904000 0.000000
+vn -0.976200 -0.216900 -0.000000
+vn -0.358300 0.933600 0.000000
+vn -0.965200 -0.261500 -0.000000
+vn -0.978800 -0.204700 0.000000
+vn -0.950900 -0.309500 -0.000000
+vn -0.972500 -0.233000 0.000000
+vn -0.932700 -0.360700 -0.000000
+vn -0.964500 -0.264100 0.000000
+vn -0.909800 -0.415100 -0.000000
+vn -0.954500 -0.298200 0.000000
+vn -0.881600 -0.472000 -0.000000
+vn -0.941900 -0.335900 0.000000
+vn -0.848000 -0.530000 -0.000000
+vn -0.926100 -0.377300 0.000000
+vn -0.806700 -0.591000 0.000000
+vn -0.906200 -0.422900 0.000000
+vn -0.758500 -0.651700 0.000000
+vn -0.881300 -0.472600 0.000000
+vn -0.703400 -0.710800 0.000000
+vn -0.850100 -0.526600 0.000000
+vn -0.642000 -0.766700 0.000000
+vn -0.811200 -0.584800 0.000000
+vn -0.575300 -0.817900 0.000000
+vn -0.763300 -0.646100 0.000000
+vn -0.504600 -0.863400 0.000000
+vn -0.704700 -0.709500 0.000000
+vn -0.431400 -0.902100 0.000000
+vn -0.641700 -0.766900 0.000000
+vn -0.357600 -0.933900 0.000000
+vn -0.591700 -0.806100 0.000000
+vn -0.284700 -0.958600 0.000000
+vn -0.541500 -0.840700 0.000000
+vn -0.213900 -0.976900 0.000000
+vn -0.491700 -0.870800 0.000000
+vn -0.146500 -0.989200 0.000000
+vn -0.442800 -0.896600 0.000000
+vn -0.111600 -0.993800 0.000000
+vn -0.395500 -0.918400 0.000000
+vn -0.102400 -0.994700 0.000000
+vn -0.350100 -0.936700 0.000000
+vn -0.093100 -0.995700 0.000000
+vn -0.306700 -0.951800 0.000000
+vn -0.083800 -0.996500 0.000000
+vn -0.265700 -0.964100 0.000000
+vn -0.074300 -0.997200 0.000000
+vn -0.227100 -0.973900 0.000000
+vn -0.064800 -0.997900 0.000000
+vn -0.190700 -0.981700 0.000000
+vn -0.055000 -0.998500 0.000000
+vn -0.156800 -0.987600 0.000000
+vn -0.045300 -0.999000 0.000000
+vn -0.131500 -0.991300 0.000000
+vn -0.035400 -0.999400 0.000000
+vn -0.042200 -0.999100 -0.000000
+vn -0.025300 -0.999700 0.000000
+vn -0.025600 -0.999700 0.000000
+vn 0.029300 -0.999600 0.000000
+vn 0.028300 -0.999600 0.000000
+vn -0.015300 -0.999900 0.000000
+vn 0.080200 -0.996800 0.000000
+vn 0.079700 -0.996800 0.000000
+vn 0.078300 -0.996900 -0.000000
+vn -0.005100 -1.000000 0.000000
+vn 0.117200 -0.993100 0.000000
+vn 0.116100 -0.993200 -0.000000
+vn 0.033100 -0.999500 0.000000
+vn 0.132600 -0.991200 0.000000
+vn 0.131700 -0.991300 -0.000000
+vn 0.132200 -0.991200 -0.000000
+vn 0.102600 -0.994700 0.000000
+vn 0.132400 -0.991200 0.000000
+vn 0.175900 -0.984400 0.000000
+vn 0.113400 -0.993600 -0.000000
+vn 0.252000 -0.967700 0.000000
+vn 0.077300 -0.997000 0.000000
+vn 0.078200 -0.996900 -0.000000
+vn 0.329800 -0.944000 0.000000
+vn 0.024500 -0.999700 -0.000000
+vn 0.407700 -0.913100 0.000000
+vn -0.040400 -0.999200 0.000000
+vn -0.039500 -0.999200 0.000000
+vn 0.483900 -0.875100 0.000000
+vn -0.119400 -0.992800 0.000000
+vn -0.119000 -0.992900 0.000000
+vn -0.121100 -0.992600 -0.000000
+vn 0.556800 -0.830600 0.000000
+vn -0.091600 -0.995800 0.000000
+vn -0.091900 -0.995800 -0.000000
+vn -0.091400 -0.995800 0.000000
+vn 0.624900 -0.780700 0.000000
+vn -0.013600 -0.999900 0.000000
+vn -0.014200 -0.999900 0.000000
+vn 0.687100 -0.726600 0.000000
+vn 0.048300 -0.998800 0.000000
+vn 0.048600 -0.998800 0.000000
+vn 0.742600 -0.669800 0.000000
+vn 0.093400 -0.995600 0.000000
+vn 0.093200 -0.995600 0.000000
+vn 0.093000 -0.995700 -0.000000
+vn 0.791100 -0.611700 0.000000
+vn 0.123300 -0.992400 0.000000
+vn 0.123100 -0.992400 0.000000
+vn 0.835900 -0.548800 -0.000000
+vn 0.138600 -0.990300 0.000000
+vn 0.138400 -0.990400 -0.000000
+vn 0.876200 -0.481900 -0.000000
+vn 0.141400 -0.990000 0.000000
+vn 0.141700 -0.989900 -0.000000
+vn 0.908600 -0.417800 -0.000000
+vn 0.131000 -0.991400 0.000000
+vn 0.131200 -0.991400 -0.000000
+vn 0.131400 -0.991300 0.000000
+vn 0.934000 -0.357300 -0.000000
+vn 0.106100 -0.994400 0.000000
+vn 0.106300 -0.994300 0.000000
+vn 0.106000 -0.994400 -0.000000
+vn 0.953700 -0.300900 -0.000000
+vn 0.067200 -0.997700 0.000000
+vn 0.067100 -0.997700 -0.000000
+vn 0.066800 -0.997800 0.000000
+vn 0.968600 -0.248700 -0.000000
+vn 0.011700 -0.999900 0.000000
+vn 0.012000 -0.999900 0.000000
+vn 0.012100 -0.999900 -0.000000
+vn 0.979700 -0.200700 -0.000000
+vn -0.060700 -0.998200 0.000000
+vn -0.060300 -0.998200 -0.000000
+vn 0.987700 -0.156600 -0.000000
+vn -0.091500 -0.995800 0.000000
+vn 0.993200 -0.116300 -0.000000
+vn -0.061700 -0.998100 0.000000
+vn 0.996800 -0.079300 -0.000000
+vn -0.035800 -0.999400 0.000000
+vn 0.999000 -0.045500 -0.000000
+vn -0.015000 -0.999900 0.000000
+vn 0.999900 -0.014500 -0.000000
+vn 0.001600 -1.000000 0.000000
+vn 0.999900 0.011400 0.000000
+vn 0.014100 -0.999900 0.000000
+vn 0.999400 0.035600 0.000000
+vn 0.022500 -0.999700 0.000000
+vn 0.998100 0.061800 0.000000
+vn 0.026900 -0.999600 0.000000
+vn 0.027100 -0.999600 0.000000
+vn 0.995900 0.090200 0.000000
+vn 0.027000 -0.999600 -0.000000
+vn 0.027300 -0.999600 0.000000
+vn 0.992700 0.120900 0.000000
+vn 0.023800 -0.999700 0.000000
+vn 0.988000 0.154300 0.000000
+vn 0.016900 -0.999900 0.000000
+vn 0.981700 0.190600 0.000000
+vn 0.006800 -1.000000 0.000000
+vn 0.006400 -1.000000 0.000000
+vn 0.973200 0.230000 0.000000
+vn 0.000000 -1.000000 0.000000
+vn 0.962100 0.272900 0.000000
+vn 0.947700 0.319200 0.000000
+vn 0.929400 0.369200 0.000000
+vn 0.906200 0.422900 0.000000
+vn 0.878800 0.477200 0.000000
+vn 0.848000 0.530000 0.000000
+vn 0.811600 0.584200 0.000000
+vn 0.769100 0.639100 0.000000
+vn 0.720400 0.693600 0.000000
+vn 0.665400 0.746500 0.000000
+vn 0.604400 0.796700 0.000000
+vn 0.538200 0.842800 0.000000
+vn -0.013700 -0.999900 0.000000
+vn 0.467900 0.883800 0.000000
+vn -0.039300 -0.999200 0.000000
+vn 0.394700 0.918800 0.000000
+vn -0.059200 -0.998200 0.000000
+vn 0.320100 0.947400 0.000000
+vn -0.071000 -0.997500 0.000000
+vn 0.245500 0.969400 0.000000
+vn -0.073400 -0.997300 0.000000
+vn 0.976200 0.216900 0.000000
+vn -0.066000 -0.997800 0.000000
+vn 0.968700 0.248200 0.000000
+vn -0.050700 -0.998700 0.000000
+vn 0.959300 0.282400 0.000000
+vn -0.029600 -0.999600 0.000000
+vn 0.947400 0.319900 0.000000
+vn -0.005600 -1.000000 0.000000
+vn 0.932600 0.361000 0.000000
+vn 0.019600 -0.999800 0.000000
+vn 0.913900 0.405900 0.000000
+vn 0.044100 -0.999000 0.000000
+vn 0.890600 0.454800 0.000000
+vn 0.861500 0.507800 0.000000
+vn 0.825400 0.564500 0.000000
+vn -0.129800 0.991500 0.000000
+vn 0.781100 0.624400 0.000000
+vn 0.727200 0.686400 0.000000
+vn 0.662700 0.748900 0.000000
+vn 0.599700 0.800300 0.000000
+vn 0.544600 0.838700 0.000000
+vn 0.488100 0.872800 0.000000
+vn 0.430900 0.902400 0.000000
+vn -0.129900 0.991500 0.000000
+vn 0.373600 0.927600 0.000000
+vn 0.317200 0.948300 0.000000
+vn 0.262200 0.965000 0.000000
+vn 0.209000 0.977900 0.000000
+vn 0.158100 0.987400 0.000000
+vn -0.123800 0.992300 0.000000
+vn 0.109700 0.994000 0.000000
+vn -0.114200 0.993500 0.000000
+vn 0.063800 0.998000 0.000000
+vn -0.104500 0.994500 0.000000
+vn 0.020600 0.999800 0.000000
+vn -0.094500 0.995500 0.000000
+vn -0.006100 1.000000 0.000000
+vn -0.084300 0.996400 0.000000
+vn -0.018100 0.999800 0.000000
+vn -0.073800 0.997300 0.000000
+vn -0.029800 0.999600 0.000000
+vn -0.063300 0.998000 0.000000
+vn -0.041200 0.999200 0.000000
+vn -0.052300 0.998600 0.000000
+vn -0.260200 0.965600 0.000000
+vn -0.153200 0.988200 0.000000
+vn -0.366600 0.930400 0.000000
+vn -0.049500 0.998800 0.000000
+vn -0.468700 0.883400 0.000000
+vn 0.004100 1.000000 0.000000
+vn -0.562500 0.826800 0.000000
+vn 0.012700 0.999900 0.000000
+vn -0.645800 0.763500 0.000000
+vn 0.020700 0.999800 0.000000
+vn -0.717200 0.696800 0.000000
+vn 0.028000 0.999600 0.000000
+vn 0.028400 0.999600 0.000000
+vn -0.776900 0.629600 0.000000
+vn 0.036500 0.999300 0.000000
+vn -0.825700 0.564200 0.000000
+vn 0.044100 0.999000 0.000000
+vn -0.864900 0.501900 0.000000
+vn 0.051300 0.998700 0.000000
+vn -0.896100 0.443900 0.000000
+vn 0.059100 0.998300 0.000000
+vn -0.928600 0.371100 0.000000
+vn -0.928600 0.371200 0.000000
+vn 0.066400 0.997800 0.000000
+vn 0.066700 0.997800 0.000000
+vn -0.954100 0.299400 0.000000
+vn -0.954100 0.299500 0.000000
+vn 0.073600 0.997300 0.000000
+vn 0.073200 0.997300 0.000000
+vn -0.970300 0.241800 0.000000
+vn 0.080800 0.996700 0.000000
+vn -0.980800 0.194900 0.000000
+vn 0.088000 0.996100 0.000000
+vn -0.987700 0.156200 0.000000
+vn 0.139900 0.990200 0.000000
+vn -0.992300 0.123900 0.000000
+vn 0.247400 0.968900 0.000000
+vn -0.995300 0.096600 0.000000
+vn 0.355100 0.934800 0.000000
+vn -0.997300 0.073200 0.000000
+vn 0.458800 0.888500 0.000000
+vn -0.998600 0.053000 0.000000
+vn 0.554800 0.832000 0.000000
+vn -0.999400 0.035500 0.000000
+vn 0.640100 0.768300 0.000000
+vn -0.999800 0.020000 0.000000
+vn 0.713500 0.700700 0.000000
+vn -1.000000 0.006300 0.000000
+vn 0.774800 0.632200 0.000000
+vn -1.000000 -0.006300 -0.000000
+vn 0.824900 0.565300 0.000000
+vn -0.999800 -0.019900 -0.000000
+vn 0.865100 0.501700 0.000000
+vn -0.999400 -0.035000 -0.000000
+vn 0.896900 0.442200 0.000000
+vn -0.998700 -0.051800 -0.000000
+vn 0.921900 0.387400 0.000000
+vn -0.997500 -0.070700 -0.000000
+vn 0.944100 0.329700 0.000000
+vn -0.995800 -0.092100 -0.000000
+vn 0.962400 0.271500 0.000000
+vn -0.993200 -0.116300 -0.000000
+vn 0.974800 0.223100 0.000000
+vn -0.989600 -0.144000 -0.000000
+vn 0.983200 0.182400 0.000000
+vn -0.984400 -0.176000 -0.000000
+vn 0.989000 0.147900 0.000000
+vn -0.977000 -0.213000 -0.000000
+vn 0.993000 0.118400 0.000000
+vn -0.966600 -0.256300 -0.000000
+vn 0.995700 0.093000 0.000000
+vn -0.951700 -0.307200 -0.000000
+vn 0.997500 0.071000 0.000000
+vn -0.933800 -0.357900 -0.000000
+vn 0.998700 0.051700 0.000000
+vn -0.910700 -0.413100 -0.000000
+vn 0.999400 0.034700 0.000000
+vn -0.880500 -0.474100 -0.000000
+vn 0.999800 0.019600 0.000000
+vn -0.841100 -0.540900 -0.000000
+vn 1.000000 0.006200 0.000000
+vn -0.790200 -0.612800 -0.000000
+vn -0.790200 -0.612900 -0.000000
+vn 1.000000 -0.005600 -0.000000
+vn -0.725500 -0.688200 -0.000000
+vn 0.999800 -0.017900 -0.000000
+vn -0.645200 -0.764000 -0.000000
+vn 0.999500 -0.031700 -0.000000
+vn -0.548500 -0.836100 -0.000000
+vn 0.998900 -0.047400 -0.000000
+vn -0.437100 -0.899400 -0.000000
+vn 0.997900 -0.065400 -0.000000
+vn -0.314500 -0.949300 -0.000000
+vn 0.996300 -0.086200 -0.000000
+vn -0.186800 -0.982400 -0.000000
+vn 0.993900 -0.110500 -0.000000
+vn 0.990300 -0.139000 -0.000000
+vn 0.003900 -1.000000 -0.000000
+vn 0.984900 -0.173000 -0.000000
+vn 0.010700 -0.999900 -0.000000
+vn 0.976800 -0.214000 -0.000000
+vn 0.017900 -0.999800 -0.000000
+vn 0.017600 -0.999800 -0.000000
+vn 0.964500 -0.264000 -0.000000
+vn 0.945400 -0.325900 -0.000000
+vn 0.030300 -0.999500 -0.000000
+vn 0.922000 -0.387100 -0.000000
+vn 0.035700 -0.999400 -0.000000
+vn 0.035500 -0.999400 -0.000000
+vn 0.897100 -0.441800 -0.000000
+vn 0.040600 -0.999200 -0.000000
+vn 0.041000 -0.999200 -0.000000
+vn 0.040700 -0.999200 -0.000000
+vn 0.865200 -0.501400 -0.000000
+vn 0.045500 -0.999000 -0.000000
+vn 0.045800 -0.998900 -0.000000
+vn 0.824700 -0.565600 -0.000000
+vn 0.049700 -0.998800 -0.000000
+vn 0.773900 -0.633300 -0.000000
+vn 0.053100 -0.998600 -0.000000
+vn 0.053400 -0.998600 -0.000000
+vn 0.711300 -0.702900 -0.000000
+vn 0.056500 -0.998400 -0.000000
+vn 0.635900 -0.771800 -0.000000
+vn 0.059300 -0.998200 -0.000000
+vn 0.059100 -0.998200 -0.000000
+vn 0.547500 -0.836800 -0.000000
+vn 0.116600 -0.993200 -0.000000
+vn 0.448000 -0.894100 -0.000000
+vn 0.228000 -0.973700 -0.000000
+vn 0.340000 -0.940400 -0.000000
+vn -0.000000 0.000300 -1.000000
+vn -0.000000 0.006400 -1.000000
+vn -0.000000 -0.003500 -1.000000
+vn 0.000000 -0.001100 -1.000000
+vn 0.000000 -0.006200 -1.000000
+vn -0.000000 0.000600 -1.000000
+vn 0.000000 -0.007100 -1.000000
+vn 0.000000 0.014200 -0.999900
+vn 0.000100 0.004100 -1.000000
+vn 0.000000 -0.007600 -1.000000
+vn 0.000000 -0.000300 -1.000000
+vn -0.000100 0.000700 -1.000000
+vn 0.000000 -0.000500 -1.000000
+vn 0.000000 0.000700 -1.000000
+vn 0.000000 0.000500 -1.000000
+vn 0.000100 -0.000000 1.000000
+vn 0.045600 -0.999000 -0.000000
+vn 0.039900 -0.999200 -0.000000
+vn 0.003400 -1.000000 -0.000000
+vn 0.056100 -0.998400 -0.000000
+vn -0.078000 0.997000 0.000000
+vn -0.130700 -0.991400 0.000000
+vn -0.045100 -0.999000 -0.000000
+vn 0.028400 -0.999600 -0.000000
+vn 0.078700 -0.996900 0.000000
+vn 0.131100 -0.991400 0.000000
+vn 0.114300 -0.993400 -0.000000
+vn 0.026200 -0.999700 -0.000000
+vn -0.121600 -0.992600 0.000000
+vn -0.090900 -0.995900 0.000000
+vn -0.013400 -0.999900 0.000000
+vn 0.123400 -0.992400 0.000000
+vn 0.138500 -0.990400 -0.000000
+vn 0.141800 -0.989900 0.000000
+vn 0.131500 -0.991300 -0.000000
+vn 0.105600 -0.994400 0.000000
+vn 0.011600 -0.999900 0.000000
+vn -0.060000 -0.998200 0.000000
+vn 0.000000 -0.001700 -1.000000
+vn 0.000100 0.000000 -1.000000
+vn 0.000000 0.004600 -1.000000
+vn 0.000000 0.000600 1.000000
+vn 0.000200 0.000000 1.000000
+vn -0.000000 -0.004400 1.000000
+vn -0.000100 0.003800 1.000000
+vn 0.036100 0.999300 0.000000
+vn 0.024000 -0.999700 -0.000000
+vn 0.035800 -0.999400 -0.000000
+usemtl SVGMat.002
+s 1
+f 1//1 2//1 3//1
+f 4//2 3//2 5//2
+f 6//3 7//3 8//3
+f 9//3 10//3 11//3
+f 12//4 13//4 2//4
+f 14//5 15//5 16//5
+f 17//5 18//5 19//5
+f 20//6 5//6 15//6
+f 21//7 22//7 23//7
+f 24//8 21//9 25//9
+f 26//10 24//11 27//11
+f 28//12 26//13 29//14
+f 30//15 28//16 31//15
+f 32//17 30//18 33//17
+f 34//19 32//20 35//19
+f 36//21 34//22 37//22
+f 38//23 36//23 39//23
+f 40//24 38//24 41//24
+f 42//25 40//25 43//25
+f 44//26 42//26 45//26
+f 46//27 44//27 47//27
+f 48//28 46//28 49//28
+f 50//29 48//29 51//29
+f 52//30 50//30 53//30
+f 54//31 52//31 55//31
+f 56//32 54//32 57//32
+f 58//33 56//33 59//34
+f 60//35 58//35 61//35
+f 62//36 60//36 63//37
+f 64//38 62//38 65//38
+f 66//39 64//39 67//39
+f 68//40 66//40 69//40
+f 70//41 68//41 71//41
+f 72//42 70//42 73//42
+f 74//43 72//43 75//43
+f 76//44 74//44 77//44
+f 78//45 76//45 79//45
+f 80//46 78//46 81//46
+f 82//47 80//47 83//47
+f 84//48 82//48 85//48
+f 86//49 84//49 87//49
+f 88//49 86//49 89//49
+f 90//49 88//49 91//49
+f 92//49 90//49 93//49
+f 94//49 92//49 95//49
+f 96//49 94//49 97//49
+f 98//49 96//49 99//49
+f 100//49 98//49 101//49
+f 102//49 100//49 103//49
+f 104//49 102//49 105//49
+f 106//49 104//49 107//49
+f 108//49 106//49 109//49
+f 110//50 108//50 111//50
+f 112//49 110//49 113//49
+f 114//51 112//51 115//51
+f 116//49 114//49 117//49
+f 118//52 116//52 119//52
+f 120//53 118//53 121//53
+f 122//54 120//54 123//54
+f 124//55 122//55 125//55
+f 126//56 124//56 127//56
+f 128//55 126//55 129//55
+f 130//57 128//57 131//57
+f 132//58 130//58 133//58
+f 134//59 132//59 135//59
+f 136//60 134//60 137//60
+f 138//61 136//61 139//61
+f 140//62 138//62 141//62
+f 142//63 140//63 143//63
+f 144//64 142//64 145//64
+f 146//65 144//65 147//65
+f 11//66 146//66 148//66
+f 9//67 11//67 149//67
+f 150//68 9//68 151//68
+f 152//69 150//69 153//69
+f 154//70 152//70 155//70
+f 156//71 154//71 157//71
+f 158//72 156//72 159//72
+f 160//73 158//73 161//73
+f 162//74 160//74 163//74
+f 164//75 162//75 165//75
+f 166//76 164//76 167//76
+f 168//77 166//77 169//77
+f 170//78 168//78 171//78
+f 172//79 170//79 173//79
+f 174//80 172//80 175//80
+f 176//3 177//3 178//3
+f 179//55 180//55 181//55
+f 182//55 183//55 184//55
+f 185//81 184//81 186//81
+f 187//82 186//82 13//82
+f 188//83 15//83 189//83
+f 190//84 189//84 191//84
+f 192//85 191//85 193//85
+f 194//86 193//86 195//86
+f 196//87 195//87 197//87
+f 198//88 197//88 14//88
+f 199//89 14//89 200//89
+f 201//49 202//49 203//49
+f 204//49 205//49 206//49
+f 207//90 206//90 208//90
+f 209//91 208//91 210//91
+f 211//92 210//92 212//92
+f 213//93 212//93 214//93
+f 215//94 214//94 216//94
+f 217//95 216//95 218//95
+f 219//96 218//96 220//96
+f 221//97 220//97 222//97
+f 223//98 222//98 224//98
+f 225//99 224//99 226//99
+f 227//100 226//100 228//100
+f 229//101 228//101 230//101
+f 231//102 230//102 232//102
+f 233//102 232//102 234//102
+f 235//102 236//102 237//102
+f 238//49 239//49 240//49
+f 241//49 238//49 242//49
+f 243//103 241//103 244//103
+f 245//104 243//104 246//105
+f 247//106 245//106 248//106
+f 249//107 247//107 250//107
+f 251//108 249//108 252//108
+f 253//109 251//109 254//109
+f 255//110 253//110 256//110
+f 257//111 255//111 258//111
+f 259//112 257//112 260//112
+f 261//113 259//113 262//113
+f 263//114 261//114 264//114
+f 265//115 263//115 266//115
+f 267//116 265//117 268//118
+f 269//119 267//116 270//116
+f 271//120 269//119 272//119
+f 22//121 271//121 273//122
+f 274//5 275//5 276//5
+f 277//123 174//123 16//123
+f 278//124 279//124 280//124
+f 281//125 278//125 282//125
+f 283//126 281//126 284//126
+f 285//127 283//127 286//127
+f 287//128 285//128 288//128
+f 289//129 287//129 290//129
+f 291//130 289//130 292//130
+f 293//131 291//131 294//131
+f 295//132 293//132 296//132
+f 297//133 295//133 298//133
+f 299//134 297//134 300//134
+f 301//135 299//135 302//135
+f 303//136 301//136 304//136
+f 176//137 303//137 305//137
+f 177//138 176//138 306//138
+f 307//139 177//139 308//139
+f 309//140 307//140 310//140
+f 311//49 309//49 276//49
+f 312//49 311//49 313//49
+f 314//49 312//49 315//49
+f 316//49 314//49 317//49
+f 318//49 316//49 319//49
+f 320//49 318//49 321//49
+f 322//49 320//49 323//49
+f 324//49 322//49 325//49
+f 326//49 324//49 327//49
+f 239//49 326//49 328//49
+f 329//141 277//141 330//141
+f 331//142 329//142 332//142
+f 333//143 331//143 334//143
+f 335//144 333//144 336//144
+f 337//145 335//145 338//145
+f 279//146 337//146 339//146
+f 340//147 341//147 342//147
+f 343//148 340//148 344//148
+f 341//149 345//149 346//149
+f 347//150 343//150 348//150
+f 345//151 349//151 350//151
+f 351//152 347//152 352//152
+f 349//153 353//153 354//153
+f 355//154 351//154 356//155
+f 353//156 357//156 358//156
+f 359//157 355//157 360//157
+f 357//158 361//158 362//158
+f 363//159 359//159 364//159
+f 361//160 365//160 366//160
+f 367//161 363//161 368//161
+f 365//162 10//162 369//162
+f 370//163 367//163 371//163
+f 10//164 372//164 373//164
+f 374//165 370//165 375//165
+f 372//166 376//166 377//166
+f 378//167 374//167 379//167
+f 376//168 380//168 381//168
+f 382//169 378//169 383//169
+f 380//170 384//170 385//170
+f 386//171 382//171 387//171
+f 384//172 388//172 389//172
+f 390//173 386//173 391//173
+f 388//174 392//174 393//174
+f 394//175 390//175 395//175
+f 392//176 396//176 397//176
+f 398//177 394//177 399//177
+f 396//178 400//178 401//178
+f 402//179 398//179 403//179
+f 400//180 404//180 405//180
+f 406//181 402//181 407//181
+f 404//182 408//182 409//182
+f 410//183 406//183 411//183
+f 408//184 412//184 413//184
+f 414//185 410//185 415//185
+f 412//186 416//186 417//186
+f 418//187 414//187 419//187
+f 416//188 420//188 421//188
+f 422//189 418//189 423//189
+f 420//190 424//190 425//190
+f 426//191 422//191 427//191
+f 424//192 428//192 429//192
+f 430//193 426//193 431//193
+f 428//194 432//194 433//194
+f 434//195 430//195 435//195
+f 432//196 436//196 437//196
+f 438//197 434//197 439//197
+f 436//198 440//198 441//198
+f 442//199 438//199 443//199
+f 440//200 444//200 445//200
+f 446//201 442//201 447//201
+f 444//202 448//202 449//202
+f 450//203 446//203 451//203
+f 448//204 452//204 453//204
+f 454//205 450//205 455//205
+f 452//206 456//206 457//206
+f 458//207 454//207 459//207
+f 456//208 460//208 461//208
+f 462//209 458//209 463//209
+f 460//210 464//210 465//210
+f 466//211 462//211 467//211
+f 464//212 468//212 469//212
+f 470//213 466//213 471//213
+f 468//214 472//214 473//214
+f 474//215 470//215 475//215
+f 472//216 476//216 477//216
+f 478//217 474//217 479//217
+f 476//218 480//218 481//218
+f 482//219 478//219 483//219
+f 480//220 484//220 485//220
+f 486//221 482//221 487//221
+f 484//222 488//222 489//222
+f 490//223 486//223 491//223
+f 488//224 492//224 493//224
+f 494//225 490//225 495//225
+f 492//226 496//226 497//226
+f 498//227 494//227 499//227
+f 496//228 500//228 501//228
+f 502//229 498//229 503//229
+f 500//230 504//230 505//230
+f 506//231 502//231 507//232
+f 504//233 508//233 509//234
+f 510//235 506//235 511//235
+f 508//236 512//237 513//238
+f 514//239 510//239 515//239
+f 512//240 516//240 517//241
+f 518//242 514//242 519//242
+f 516//243 520//244 521//245
+f 522//246 518//246 523//246
+f 520//247 524//247 525//247
+f 526//248 522//248 527//248
+f 524//249 528//249 529//249
+f 530//250 526//250 531//250
+f 528//251 532//251 533//252
+f 534//253 530//253 535//253
+f 532//254 536//254 537//254
+f 538//255 534//255 539//255
+f 536//256 540//256 541//257
+f 542//258 538//258 543//258
+f 540//259 544//260 545//261
+f 546//262 542//262 547//262
+f 544//263 548//264 549//265
+f 550//266 546//266 551//266
+f 548//267 552//268 553//267
+f 554//269 550//269 555//269
+f 552//270 556//270 557//271
+f 558//272 554//272 559//272
+f 556//273 560//274 561//275
+f 562//276 558//276 563//276
+f 560//277 564//278 565//277
+f 566//279 562//279 567//279
+f 564//280 568//281 569//281
+f 570//282 566//282 571//282
+f 568//283 572//283 573//284
+f 574//285 570//285 575//285
+f 572//286 576//287 577//288
+f 578//289 574//289 579//289
+f 576//290 580//291 581//292
+f 582//293 578//293 583//293
+f 580//294 584//295 585//296
+f 586//297 582//297 587//297
+f 584//298 588//299 589//300
+f 590//301 586//301 591//301
+f 588//302 592//302 593//303
+f 594//304 590//304 595//304
+f 592//305 596//305 597//305
+f 598//306 594//306 599//306
+f 596//307 600//307 601//307
+f 602//308 598//308 603//308
+f 600//309 604//309 605//309
+f 606//310 602//310 607//310
+f 604//311 608//311 609//311
+f 610//312 606//312 611//312
+f 608//313 612//313 613//313
+f 614//314 610//314 19//314
+f 612//315 615//315 616//315
+f 617//316 614//316 18//316
+f 615//317 618//317 619//317
+f 620//318 617//318 621//318
+f 618//319 622//320 623//320
+f 6//321 620//321 624//321
+f 622//320 625//322 626//323
+f 7//324 6//324 627//324
+f 625//325 628//325 629//325
+f 630//326 7//326 631//326
+f 628//327 632//327 633//327
+f 634//328 630//328 635//328
+f 632//329 636//330 637//330
+f 638//331 634//331 639//331
+f 636//332 640//332 641//332
+f 642//333 638//333 643//333
+f 640//332 644//332 645//332
+f 646//334 642//334 647//334
+f 644//332 648//332 649//332
+f 650//335 646//335 651//335
+f 648//332 652//332 653//332
+f 654//336 650//336 655//336
+f 652//332 656//332 657//332
+f 658//337 654//337 659//337
+f 656//332 660//332 661//332
+f 662//338 658//338 663//338
+f 660//332 664//332 665//332
+f 666//339 662//339 667//339
+f 664//332 668//332 669//332
+f 670//340 666//340 671//340
+f 668//332 672//332 673//332
+f 674//341 670//341 675//341
+f 672//332 676//332 677//332
+f 678//342 674//342 679//342
+f 676//332 680//332 681//332
+f 682//343 678//343 683//343
+f 680//332 684//332 685//332
+f 686//344 682//344 687//344
+f 684//345 688//345 689//345
+f 690//346 686//346 691//346
+f 688//347 692//347 693//347
+f 694//348 690//348 695//348
+f 692//349 696//349 697//349
+f 698//350 694//350 699//350
+f 696//351 700//351 701//351
+f 702//352 698//352 703//352
+f 700//353 704//353 705//353
+f 706//354 702//354 707//354
+f 704//355 708//355 709//355
+f 710//356 706//356 711//356
+f 708//357 712//357 713//357
+f 714//358 710//358 715//358
+f 712//359 716//359 717//359
+f 718//360 714//360 719//360
+f 716//361 720//361 721//361
+f 722//362 718//362 723//362
+f 720//363 724//363 725//363
+f 726//364 722//364 727//364
+f 724//365 728//365 729//365
+f 730//366 726//366 731//366
+f 728//296 732//296 733//296
+f 734//367 730//367 735//367
+f 732//49 736//49 737//49
+f 738//368 734//368 739//368
+f 736//369 740//369 741//369
+f 742//370 738//370 743//370
+f 740//369 744//369 745//369
+f 746//371 742//371 747//371
+f 744//369 748//369 749//369
+f 750//372 746//372 751//372
+f 748//369 752//369 753//369
+f 754//373 750//373 755//373
+f 752//369 756//369 757//369
+f 758//374 754//374 759//374
+f 756//369 760//369 761//369
+f 762//375 758//375 763//375
+f 760//369 764//369 765//369
+f 766//376 762//376 767//376
+f 764//369 768//377 769//377
+f 770//378 766//378 771//378
+f 768//377 772//369 773//369
+f 774//379 770//379 775//379
+f 772//369 776//369 777//369
+f 778//380 774//380 779//380
+f 776//369 780//377 781//377
+f 782//381 778//381 783//381
+f 780//377 784//369 785//369
+f 786//382 782//382 787//382
+f 784//383 788//383 789//383
+f 790//384 786//384 791//384
+f 788//385 792//385 793//385
+f 794//386 790//386 795//386
+f 792//387 796//387 797//387
+f 798//388 794//388 799//388
+f 796//389 800//389 801//389
+f 802//390 798//390 803//390
+f 800//391 804//391 805//391
+f 806//392 802//392 807//392
+f 804//393 808//393 809//393
+f 810//394 806//394 811//394
+f 808//395 812//395 813//395
+f 814//396 810//396 815//396
+f 812//397 814//397 816//397
+f 817//3 818//3 819//3
+f 820//5 821//5 822//5
+f 823//398 824//398 825//398
+f 826//399 823//399 827//399
+f 824//400 828//400 829//400
+f 830//401 826//401 831//401
+f 828//402 832//402 833//402
+f 834//403 830//403 835//403
+f 832//404 836//404 837//404
+f 838//405 834//405 839//405
+f 836//406 840//406 841//406
+f 842//407 838//407 843//407
+f 840//408 844//408 845//408
+f 846//409 842//410 847//409
+f 844//411 848//411 849//411
+f 850//412 846//412 851//412
+f 848//413 852//413 853//413
+f 854//414 850//414 855//414
+f 852//415 856//415 857//415
+f 858//416 854//416 859//416
+f 856//417 860//417 861//417
+f 862//418 858//418 863//418
+f 860//419 864//419 865//420
+f 866//421 862//422 867//421
+f 864//423 868//423 869//424
+f 870//425 866//426 871//425
+f 868//427 872//427 873//427
+f 874//428 870//428 875//428
+f 872//429 876//429 877//429
+f 878//430 874//430 879//430
+f 876//431 880//431 881//431
+f 882//432 878//432 883//432
+f 880//433 884//433 885//433
+f 886//434 882//434 887//434
+f 884//435 888//435 889//435
+f 890//436 886//436 891//436
+f 888//437 892//437 893//437
+f 894//438 890//438 895//438
+f 892//439 896//439 897//439
+f 898//440 894//440 899//440
+f 896//441 900//441 901//441
+f 902//442 898//442 903//442
+f 900//443 904//443 905//443
+f 906//444 902//444 907//444
+f 904//445 819//445 908//445
+f 909//446 906//446 910//446
+f 819//447 818//447 911//447
+f 912//448 909//448 913//448
+f 818//449 914//449 915//449
+f 916//450 912//450 917//450
+f 914//451 918//451 919//451
+f 920//452 916//452 921//452
+f 918//453 922//453 923//453
+f 924//454 920//454 925//454
+f 922//455 926//455 927//455
+f 928//456 924//456 929//456
+f 926//457 930//457 931//457
+f 932//458 928//458 933//458
+f 930//459 934//459 935//459
+f 936//460 932//460 937//460
+f 934//461 938//461 939//461
+f 940//462 936//462 941//462
+f 938//463 942//463 821//463
+f 943//464 940//464 944//464
+f 942//465 945//465 822//465
+f 946//466 943//466 947//466
+f 945//467 948//467 949//467
+f 950//468 946//468 951//468
+f 948//469 952//469 953//469
+f 954//470 950//470 955//470
+f 952//471 956//471 957//471
+f 958//472 954//472 959//472
+f 956//473 960//473 961//473
+f 962//474 958//474 963//474
+f 960//475 964//475 965//475
+f 966//476 962//476 967//476
+f 964//477 968//477 969//477
+f 817//478 966//478 970//478
+f 968//479 971//479 972//480
+f 973//481 817//481 974//481
+f 971//482 975//482 976//482
+f 977//483 973//483 978//483
+f 975//484 979//484 980//484
+f 981//485 977//485 982//485
+f 979//486 983//486 984//486
+f 985//487 981//487 986//487
+f 983//488 987//488 988//488
+f 989//489 985//489 990//489
+f 987//490 991//490 992//490
+f 993//491 989//491 994//491
+f 991//492 995//492 996//492
+f 997//493 993//493 998//493
+f 995//302 999//302 1000//302
+f 1001//494 997//494 1002//494
+f 999//495 1003//495 1004//495
+f 1005//496 1001//496 1006//496
+f 1003//497 1007//497 1008//497
+f 1009//498 1005//498 820//498
+f 1007//499 1010//500 1011//499
+f 1012//501 1009//501 1013//501
+f 1010//254 1014//254 1015//254
+f 1016//502 1012//502 1017//502
+f 1014//503 1018//503 1019//503
+f 1020//504 1016//504 1021//504
+f 1018//505 1022//506 1023//505
+f 1024//507 1020//507 1025//507
+f 1022//508 1026//509 1027//510
+f 1028//511 1024//511 1029//511
+f 1026//512 1030//513 1031//513
+f 1032//514 1028//514 1033//514
+f 1030//515 1034//515 1035//515
+f 1036//516 1032//516 1037//516
+f 1034//517 1038//517 1039//518
+f 1040//519 1036//519 1041//519
+f 1038//520 1042//520 1043//520
+f 1044//521 1040//521 1045//521
+f 1042//522 1046//523 1047//522
+f 1048//524 1044//524 1049//524
+f 1046//525 1050//525 1051//525
+f 1052//526 1048//526 1053//526
+f 1050//527 1054//527 1055//527
+f 1054//528 1052//528 1056//528
+f 4//1 1//1 3//1
+f 20//2 4//2 5//2
+f 1057//3 454//3 458//3
+f 698//3 702//3 706//3
+f 1057//3 458//3 462//3
+f 710//3 698//3 706//3
+f 1057//3 462//3 466//3
+f 710//3 694//3 698//3
+f 1057//3 466//3 470//3
+f 710//3 714//3 694//3
+f 1057//3 470//3 474//3
+f 714//3 690//3 694//3
+f 1057//3 474//3 478//3
+f 714//3 718//3 690//3
+f 1057//3 478//3 482//3
+f 690//3 718//3 686//3
+f 1057//3 482//3 486//3
+f 718//3 722//3 686//3
+f 1057//3 486//3 490//3
+f 686//3 722//3 1058//3
+f 1057//3 490//3 494//3
+f 686//3 1058//3 682//3
+f 1057//3 494//3 498//3
+f 1058//3 678//3 682//3
+f 1057//3 498//3 502//3
+f 1058//3 674//3 678//3
+f 1057//3 502//3 506//3
+f 1058//3 722//3 726//3
+f 1057//3 506//3 510//3
+f 1059//3 726//3 730//3
+f 1057//3 510//3 514//3
+f 1059//3 730//3 734//3
+f 1057//3 514//3 518//3
+f 742//3 1059//3 738//3
+f 1057//3 518//3 522//3
+f 746//3 1059//3 742//3
+f 1057//3 522//3 526//3
+f 1060//3 798//3 199//3
+f 1057//3 526//3 530//3
+f 1060//3 794//3 798//3
+f 1057//3 530//3 534//3
+f 790//3 794//3 1060//3
+f 1057//3 534//3 538//3
+f 786//3 790//3 1060//3
+f 1057//3 538//3 542//3
+f 782//3 786//3 1060//3
+f 1057//3 542//3 546//3
+f 778//3 782//3 1060//3
+f 233//3 546//3 550//3
+f 774//3 778//3 1060//3
+f 204//3 550//3 554//3
+f 770//3 774//3 1060//3
+f 1061//3 554//3 558//3
+f 766//3 770//3 1060//3
+f 1061//3 558//3 562//3
+f 762//3 766//3 1060//3
+f 1062//3 562//3 566//3
+f 758//3 762//3 1060//3
+f 1062//3 566//3 570//3
+f 754//3 758//3 1060//3
+f 1062//3 570//3 574//3
+f 750//3 754//3 1060//3
+f 1063//3 574//3 578//3
+f 746//3 750//3 1060//3
+f 1063//3 578//3 582//3
+f 1059//3 746//3 1060//3
+f 1063//3 582//3 586//3
+f 1059//3 734//3 738//3
+f 1063//3 586//3 590//3
+f 1059//3 1058//3 726//3
+f 1064//3 590//3 594//3
+f 674//3 1058//3 670//3
+f 1064//3 594//3 598//3
+f 670//3 1058//3 202//3
+f 1061//3 204//3 554//3
+f 666//3 670//3 202//3
+f 1064//3 598//3 602//3
+f 662//3 666//3 202//3
+f 1065//3 602//3 606//3
+f 658//3 662//3 202//3
+f 546//3 233//3 1057//3
+f 654//3 658//3 202//3
+f 550//3 204//3 207//3
+f 650//3 654//3 202//3
+f 1065//3 606//3 610//3
+f 201//3 650//3 202//3
+f 1065//3 610//3 614//3
+f 201//3 646//3 650//3
+f 233//3 550//3 207//3
+f 201//3 642//3 646//3
+f 1065//3 614//3 617//3
+f 201//3 638//3 642//3
+f 209//3 233//3 207//3
+f 201//3 634//3 638//3
+f 8//3 617//3 620//3
+f 221//3 223//3 225//3
+f 225//3 219//3 221//3
+f 225//3 227//3 217//3
+f 215//3 227//3 229//3
+f 231//3 213//3 229//3
+f 574//3 1063//3 1062//3
+f 229//3 213//3 215//3
+f 562//3 1062//3 1061//3
+f 617//3 8//3 1065//3
+f 590//3 1064//3 1063//3
+f 215//3 217//3 227//3
+f 225//3 217//3 219//3
+f 209//3 231//3 233//3
+f 630//3 634//3 201//3
+f 213//3 231//3 211//3
+f 630//3 201//3 8//3
+f 602//3 1065//3 1064//3
+f 630//3 8//3 7//3
+f 620//3 6//3 8//3
+f 209//3 211//3 231//3
+f 396//3 408//3 404//3
+f 396//3 416//3 412//3
+f 392//3 424//3 420//3
+f 392//3 432//3 428//3
+f 480//3 440//3 436//3
+f 460//3 456//3 444//3
+f 448//3 456//3 452//3
+f 444//3 464//3 460//3
+f 444//3 472//3 468//3
+f 440//3 480//3 476//3
+f 588//3 488//3 484//3
+f 500//529 496//530 492//3
+f 508//3 504//531 500//532
+f 516//533 512//533 508//533
+f 548//534 544//3 540//3
+f 520//535 516//535 508//535
+f 552//3 548//534 540//3
+f 524//536 520//536 508//536
+f 556//3 552//3 540//3
+f 524//3 508//3 500//532
+f 556//537 540//537 536//537
+f 528//538 524//538 500//538
+f 560//3 556//3 536//3
+f 528//539 500//529 492//3
+f 564//3 560//3 536//3
+f 532//540 528//539 492//3
+f 568//541 564//3 536//3
+f 536//3 532//540 492//3
+f 436//3 484//3 480//3
+f 444//3 468//3 464//3
+f 444//3 456//3 448//3
+f 392//3 436//3 432//3
+f 392//3 420//3 416//3
+f 396//3 404//3 400//3
+f 1066//3 454//3 1057//3
+f 412//3 408//3 396//3
+f 1066//3 1067//3 454//3
+f 416//3 396//3 392//3
+f 454//3 1067//3 1068//3
+f 436//3 392//3 388//3
+f 1069//3 454//3 1068//3
+f 696//3 388//3 384//3
+f 1069//3 1070//3 454//3
+f 732//3 384//3 380//3
+f 1070//3 450//3 454//3
+f 732//3 380//3 376//3
+f 1070//3 446//3 450//3
+f 428//3 424//3 392//3
+f 442//3 446//3 1070//3
+f 732//3 376//3 372//3
+f 438//3 442//3 1070//3
+f 150//3 372//3 10//3
+f 438//3 1070//3 236//3
+f 484//3 436//3 388//3
+f 434//3 438//3 236//3
+f 11//3 10//3 365//3
+f 118//3 434//3 236//3
+f 146//3 365//3 361//3
+f 430//3 434//3 118//3
+f 476//3 472//3 440//3
+f 426//3 430//3 118//3
+f 142//3 361//3 357//3
+f 422//3 426//3 118//3
+f 440//3 472//3 444//3
+f 418//3 422//3 118//3
+f 138//3 357//3 353//3
+f 418//3 118//3 414//3
+f 588//3 484//3 388//3
+f 414//3 118//3 122//3
+f 136//3 353//3 349//3
+f 410//3 414//3 122//3
+f 584//542 492//3 488//3
+f 406//3 122//3 402//3
+f 576//3 536//3 492//3
+f 402//3 122//3 398//3
+f 572//543 568//541 536//3
+f 398//3 122//3 394//3
+f 576//3 572//543 536//3
+f 122//3 124//3 394//3
+f 580//3 576//3 492//3
+f 394//3 124//3 390//3
+f 584//542 580//3 492//3
+f 390//3 124//3 386//3
+f 588//3 584//542 488//3
+f 386//3 124//3 382//3
+f 592//3 588//3 388//3
+f 382//3 124//3 126//3
+f 612//3 592//3 388//3
+f 378//3 382//3 126//3
+f 600//3 596//3 592//3
+f 374//3 378//3 126//3
+f 604//3 600//3 592//3
+f 370//3 374//3 126//3
+f 608//3 604//3 592//3
+f 116//3 235//3 1071//3
+f 612//3 608//3 592//3
+f 116//3 1071//3 1072//3
+f 132//3 349//3 345//3
+f 1073//3 1072//3 1074//3
+f 615//3 612//3 388//3
+f 116//3 1072//3 1073//3
+f 618//3 615//3 388//3
+f 116//3 1073//3 1075//3
+f 622//3 618//3 388//3
+f 1075//3 239//3 238//3
+f 625//3 622//3 388//3
+f 1075//3 238//3 241//3
+f 628//3 625//3 388//3
+f 86//3 241//3 243//3
+f 632//3 628//3 388//3
+f 86//3 243//3 245//3
+f 636//3 632//3 388//3
+f 84//3 245//3 247//3
+f 640//3 636//3 388//3
+f 84//3 247//3 249//3
+f 644//3 640//3 388//3
+f 82//3 249//3 251//3
+f 648//3 644//3 388//3
+f 80//3 251//3 253//3
+f 652//3 648//3 388//3
+f 80//3 253//3 255//3
+f 656//3 652//3 388//3
+f 78//3 255//3 257//3
+f 660//3 656//3 388//3
+f 76//3 257//3 259//3
+f 664//3 660//3 388//3
+f 74//3 259//3 261//3
+f 668//3 664//3 388//3
+f 74//3 261//3 263//3
+f 672//3 668//3 388//3
+f 70//3 263//3 265//3
+f 676//3 672//3 388//3
+f 70//3 265//3 267//3
+f 680//3 676//3 388//3
+f 70//3 267//3 269//3
+f 684//3 680//3 388//3
+f 70//3 269//3 271//3
+f 688//3 684//3 388//3
+f 70//3 271//3 22//3
+f 692//3 688//3 388//3
+f 68//3 22//3 21//3
+f 696//3 692//3 388//3
+f 68//3 21//3 24//3
+f 128//3 345//3 341//3
+f 68//3 24//3 26//3
+f 732//3 728//3 384//3
+f 68//3 26//3 28//3
+f 384//3 700//3 696//3
+f 68//3 28//3 30//3
+f 384//3 704//3 700//3
+f 68//3 30//3 32//3
+f 384//3 728//3 724//3
+f 68//3 32//3 34//3
+f 704//3 384//3 708//3
+f 68//3 34//3 36//3
+f 708//3 384//3 712//3
+f 68//3 36//3 38//3
+f 712//3 384//3 716//3
+f 68//3 38//3 40//3
+f 716//3 384//3 720//3
+f 66//3 40//3 42//3
+f 128//3 341//3 340//3
+f 66//3 42//3 44//3
+f 720//3 384//3 724//3
+f 56//3 44//3 46//3
+f 128//3 130//3 345//3
+f 54//3 46//3 48//3
+f 128//3 340//3 343//3
+f 52//3 48//3 50//3
+f 199//3 740//3 736//3
+f 54//3 48//3 52//3
+f 199//3 744//3 740//3
+f 56//3 46//3 54//3
+f 199//3 748//3 744//3
+f 58//3 44//3 56//3
+f 199//3 760//3 756//3
+f 64//3 44//3 58//3
+f 199//3 764//3 760//3
+f 64//3 58//3 60//3
+f 199//3 768//3 764//3
+f 64//3 60//3 62//3
+f 199//3 756//3 752//3
+f 66//3 44//3 64//3
+f 199//3 780//3 776//3
+f 68//3 40//3 66//3
+f 199//3 776//3 772//3
+f 70//3 22//3 68//3
+f 199//3 798//3 802//3
+f 72//3 263//3 70//3
+f 199//3 802//3 806//3
+f 74//3 263//3 72//3
+f 199//3 806//3 810//3
+f 76//3 259//3 74//3
+f 199//3 810//3 814//3
+f 78//3 257//3 76//3
+f 199//3 814//3 812//3
+f 80//3 255//3 78//3
+f 199//3 812//3 808//3
+f 82//3 251//3 80//3
+f 199//3 808//3 804//3
+f 84//3 249//3 82//3
+f 199//3 804//3 800//3
+f 86//3 245//3 84//3
+f 199//3 800//3 796//3
+f 88//3 241//3 86//3
+f 199//3 796//3 792//3
+f 90//3 241//3 88//3
+f 199//3 792//3 788//3
+f 92//3 241//3 90//3
+f 199//3 788//3 784//3
+f 94//3 241//3 92//3
+f 199//3 784//3 780//3
+f 96//3 241//3 94//3
+f 199//3 772//3 768//3
+f 98//3 241//3 96//3
+f 199//3 752//3 748//3
+f 110//3 241//3 98//3
+f 168//3 199//3 736//3
+f 110//3 102//3 104//3
+f 174//3 188//3 199//3
+f 110//3 100//3 102//3
+f 199//3 196//3 198//3
+f 110//3 104//3 106//3
+f 199//3 194//3 196//3
+f 110//3 106//3 108//3
+f 199//3 192//3 194//3
+f 98//3 100//3 110//3
+f 199//3 190//3 192//3
+f 1075//3 241//3 110//3
+f 199//3 188//3 190//3
+f 1075//3 110//3 112//3
+f 174//3 20//3 188//3
+f 116//3 112//3 114//3
+f 174//3 4//3 20//3
+f 1075//3 112//3 116//3
+f 174//3 1//3 4//3
+f 118//3 235//3 116//3
+f 174//3 12//3 1//3
+f 236//3 235//3 118//3
+f 174//3 187//3 12//3
+f 122//3 118//3 120//3
+f 174//3 185//3 187//3
+f 406//3 410//3 122//3
+f 174//3 182//3 185//3
+f 370//3 126//3 367//3
+f 174//3 178//3 182//3
+f 126//3 363//3 367//3
+f 172//3 174//3 199//3
+f 126//3 128//3 363//3
+f 170//3 172//3 199//3
+f 363//3 128//3 359//3
+f 168//3 170//3 199//3
+f 128//3 355//3 359//3
+f 166//3 168//3 736//3
+f 128//3 351//3 355//3
+f 164//3 166//3 736//3
+f 128//3 347//3 351//3
+f 732//3 164//3 736//3
+f 128//3 343//3 347//3
+f 732//3 162//3 164//3
+f 130//3 132//3 345//3
+f 732//3 160//3 162//3
+f 132//3 134//3 349//3
+f 732//3 158//3 160//3
+f 134//3 136//3 349//3
+f 732//3 156//3 158//3
+f 136//3 138//3 353//3
+f 732//3 154//3 156//3
+f 138//3 140//3 357//3
+f 732//3 152//3 154//3
+f 140//3 142//3 357//3
+f 732//3 150//3 152//3
+f 142//3 144//3 361//3
+f 732//3 372//3 150//3
+f 144//3 146//3 361//3
+f 150//3 10//3 9//3
+f 146//3 11//3 365//3
+f 1//4 12//4 2//4
+f 397//5 401//5 405//5
+f 1076//5 455//5 451//5
+f 409//5 397//5 405//5
+f 1076//5 451//5 447//5
+f 409//5 413//5 397//5
+f 1076//5 447//5 443//5
+f 413//5 417//5 397//5
+f 237//5 443//5 439//5
+f 397//5 417//5 393//5
+f 1077//5 234//5 455//5
+f 393//5 417//5 421//5
+f 121//5 439//5 435//5
+f 393//5 421//5 425//5
+f 1078//5 1077//5 455//5
+f 429//5 393//5 425//5
+f 121//5 435//5 431//5
+f 433//5 393//5 429//5
+f 1079//5 1078//5 455//5
+f 437//5 393//5 433//5
+f 121//5 431//5 427//5
+f 437//5 389//5 393//5
+f 121//5 427//5 423//5
+f 441//5 477//5 481//5
+f 1080//5 1079//5 455//5
+f 469//5 445//5 465//5
+f 121//5 423//5 419//5
+f 457//5 449//5 453//5
+f 125//5 419//5 415//5
+f 445//5 449//5 457//5
+f 125//5 415//5 411//5
+f 461//5 445//5 457//5
+f 1076//5 1080//5 455//5
+f 465//5 445//5 461//5
+f 125//5 411//5 407//5
+f 469//5 473//5 445//5
+f 125//5 407//5 403//5
+f 473//5 441//5 445//5
+f 125//5 403//5 399//5
+f 473//5 477//5 441//5
+f 127//5 399//5 395//5
+f 441//5 481//5 437//5
+f 127//5 395//5 391//5
+f 481//5 485//5 437//5
+f 237//5 1076//5 443//5
+f 485//5 389//5 437//5
+f 127//5 391//5 387//5
+f 485//5 489//5 389//5
+f 129//5 387//5 383//5
+f 489//5 493//5 389//5
+f 129//5 383//5 379//5
+f 493//5 497//5 389//5
+f 129//5 379//5 375//5
+f 497//5 501//5 389//5
+f 129//5 375//5 371//5
+f 501//5 505//5 389//5
+f 129//5 371//5 368//5
+f 505//5 509//5 389//5
+f 131//5 368//5 364//5
+f 389//5 509//5 513//5
+f 121//5 1081//5 237//5
+f 389//5 513//5 517//544
+f 119//5 1082//5 1081//5
+f 389//5 517//544 521//5
+f 119//5 1083//5 1082//5
+f 389//5 521//5 525//5
+f 1084//5 1085//5 1083//5
+f 389//5 525//5 529//5
+f 119//5 1084//5 1083//5
+f 533//5 389//5 529//5
+f 242//5 240//5 1086//5
+f 537//544 389//5 533//5
+f 244//5 242//5 1086//5
+f 541//544 389//5 537//544
+f 113//5 244//5 1086//5
+f 545//5 389//5 541//544
+f 113//5 101//5 244//5
+f 549//5 389//5 545//5
+f 244//5 99//5 97//5
+f 553//5 389//5 549//5
+f 95//5 244//5 97//5
+f 557//5 389//5 553//5
+f 93//5 91//5 244//5
+f 561//5 389//5 557//5
+f 244//5 91//5 89//5
+f 565//5 389//5 561//5
+f 246//5 244//5 89//5
+f 569//5 389//5 565//5
+f 248//5 246//5 89//5
+f 573//5 389//5 569//5
+f 87//5 248//5 89//5
+f 577//5 389//5 573//5
+f 87//5 250//5 248//5
+f 581//5 389//5 577//5
+f 87//5 252//5 250//5
+f 585//5 389//5 581//5
+f 87//5 85//5 252//5
+f 589//5 389//5 585//5
+f 252//5 85//5 254//5
+f 593//5 389//5 589//5
+f 254//5 85//5 83//5
+f 613//5 389//5 593//5
+f 256//5 254//5 83//5
+f 616//5 389//5 613//5
+f 258//5 256//5 83//5
+f 623//5 389//5 619//5
+f 81//5 258//5 83//5
+f 629//5 389//5 626//5
+f 81//5 260//5 258//5
+f 633//5 389//5 629//5
+f 81//5 79//5 260//5
+f 641//5 389//5 637//5
+f 260//5 79//5 262//5
+f 645//5 389//5 641//5
+f 262//5 79//5 77//5
+f 653//5 389//5 649//5
+f 264//5 262//5 77//5
+f 657//5 389//5 653//5
+f 266//5 264//5 77//5
+f 661//5 389//5 657//5
+f 75//5 266//5 77//5
+f 601//5 593//5 597//5
+f 75//5 73//5 266//5
+f 605//5 593//5 601//5
+f 266//5 73//5 268//5
+f 609//5 593//5 605//5
+f 71//5 25//5 23//5
+f 613//5 593//5 609//5
+f 71//5 27//5 25//5
+f 616//5 619//5 389//5
+f 71//5 29//5 27//5
+f 626//5 389//5 623//5
+f 71//5 31//5 29//5
+f 389//5 633//5 637//5
+f 71//5 33//5 31//5
+f 645//5 649//5 389//5
+f 37//5 35//5 71//5
+f 661//5 665//5 389//5
+f 39//5 37//5 71//5
+f 665//5 669//5 389//5
+f 41//5 39//5 71//5
+f 669//5 673//5 389//5
+f 43//5 71//5 69//5
+f 673//5 677//5 389//5
+f 45//5 69//5 47//5
+f 677//5 681//5 389//5
+f 47//5 59//5 49//5
+f 681//5 685//5 389//5
+f 55//5 53//5 51//5
+f 685//5 689//5 389//5
+f 63//5 67//5 65//5
+f 689//5 693//5 389//5
+f 63//5 61//5 67//5
+f 693//5 697//5 389//5
+f 67//5 61//5 47//5
+f 697//5 385//5 389//5
+f 47//5 61//5 59//5
+f 701//5 385//5 697//5
+f 57//5 51//5 49//5
+f 705//5 385//5 701//5
+f 57//5 55//5 51//5
+f 709//5 385//5 705//5
+f 49//5 59//5 57//5
+f 713//5 385//5 709//5
+f 47//5 69//5 67//5
+f 717//5 385//5 713//5
+f 45//5 43//5 69//5
+f 721//5 385//5 717//5
+f 43//5 41//5 71//5
+f 369//5 373//5 153//5
+f 71//5 35//5 33//5
+f 369//5 149//5 366//5
+f 73//5 71//5 23//5
+f 149//5 148//5 366//5
+f 273//5 73//5 23//5
+f 147//5 362//5 148//5
+f 273//5 272//5 73//5
+f 151//5 369//5 153//5
+f 73//5 272//5 270//5
+f 373//5 377//5 733//5
+f 268//5 73//5 270//5
+f 733//5 381//5 385//5
+f 95//5 93//5 244//5
+f 729//5 385//5 725//5
+f 113//5 107//5 105//5
+f 385//5 721//5 725//5
+f 113//5 105//5 103//5
+f 733//5 385//5 729//5
+f 113//5 109//5 107//5
+f 377//5 381//5 733//5
+f 113//5 103//5 101//5
+f 373//5 733//5 153//5
+f 113//5 111//5 109//5
+f 145//5 358//5 362//5
+f 244//5 101//5 99//5
+f 143//5 141//5 358//5
+f 115//5 113//5 1086//5
+f 139//5 354//5 141//5
+f 119//5 115//5 1086//5
+f 167//5 733//5 737//5
+f 119//5 117//5 115//5
+f 135//5 350//5 137//5
+f 119//5 1086//5 1084//5
+f 14//5 741//5 745//5
+f 121//5 119//5 1081//5
+f 14//5 745//5 749//5
+f 439//5 121//5 237//5
+f 14//5 749//5 753//5
+f 125//5 123//5 121//5
+f 14//5 761//5 765//5
+f 125//5 121//5 419//5
+f 14//5 765//5 769//5
+f 127//5 125//5 399//5
+f 14//5 769//5 773//5
+f 131//5 364//5 360//5
+f 14//5 757//5 761//5
+f 131//5 360//5 356//5
+f 14//5 781//5 785//5
+f 129//5 127//5 387//5
+f 14//5 777//5 781//5
+f 131//5 356//5 352//5
+f 807//5 803//5 14//5
+f 131//5 352//5 348//5
+f 811//5 807//5 14//5
+f 131//5 348//5 344//5
+f 815//5 811//5 14//5
+f 131//5 129//5 368//5
+f 816//5 815//5 14//5
+f 342//5 131//5 344//5
+f 813//5 816//5 14//5
+f 342//5 346//5 131//5
+f 809//5 813//5 14//5
+f 131//5 346//5 133//5
+f 805//5 809//5 14//5
+f 133//5 346//5 135//5
+f 801//5 805//5 14//5
+f 135//5 346//5 350//5
+f 797//5 801//5 14//5
+f 137//5 350//5 139//5
+f 793//5 797//5 14//5
+f 139//5 350//5 354//5
+f 789//5 793//5 14//5
+f 141//5 354//5 358//5
+f 785//5 789//5 14//5
+f 143//5 358//5 145//5
+f 773//5 777//5 14//5
+f 145//5 362//5 147//5
+f 753//5 757//5 14//5
+f 362//5 366//5 148//5
+f 737//5 741//5 14//5
+f 14//5 197//5 195//5
+f 14//5 193//5 191//5
+f 14//5 189//5 15//5
+f 16//5 5//5 3//5
+f 16//5 2//5 13//5
+f 16//5 186//5 184//5
+f 183//5 274//5 16//5
+f 16//5 184//5 183//5
+f 16//5 3//5 2//5
+f 14//5 191//5 189//5
+f 193//5 14//5 195//5
+f 369//5 151//5 149//5
+f 14//5 16//5 175//5
+f 155//5 153//5 733//5
+f 14//5 175//5 173//5
+f 157//5 155//5 733//5
+f 14//5 173//5 171//5
+f 159//5 157//5 733//5
+f 737//5 171//5 169//5
+f 161//5 159//5 733//5
+f 13//5 186//5 16//5
+f 163//5 161//5 733//5
+f 737//5 169//5 167//5
+f 165//5 163//5 733//5
+f 733//5 167//5 165//5
+f 16//5 15//5 5//5
+f 171//5 737//5 14//5
+f 711//5 707//5 703//5
+f 459//5 455//5 234//5
+f 715//5 703//5 699//5
+f 463//5 459//5 234//5
+f 719//5 699//5 695//5
+f 467//5 463//5 234//5
+f 723//5 695//5 691//5
+f 471//5 467//5 234//5
+f 715//5 711//5 703//5
+f 475//5 471//5 234//5
+f 1087//5 691//5 687//5
+f 479//5 475//5 234//5
+f 1087//5 687//5 683//5
+f 483//5 479//5 234//5
+f 719//5 715//5 699//5
+f 487//5 483//5 234//5
+f 1087//5 683//5 679//5
+f 491//5 487//5 234//5
+f 723//5 719//5 695//5
+f 495//5 491//5 234//5
+f 727//5 723//5 691//5
+f 499//5 495//5 234//5
+f 1087//5 679//5 675//5
+f 503//5 499//5 234//5
+f 1087//5 727//5 691//5
+f 507//5 503//5 234//5
+f 1087//5 731//5 727//5
+f 511//5 507//5 234//5
+f 1087//5 1088//5 731//5
+f 515//5 511//5 234//5
+f 731//5 1088//5 735//5
+f 519//5 515//5 234//5
+f 1088//5 743//5 739//5
+f 523//5 519//5 234//5
+f 200//5 803//5 799//5
+f 527//5 523//5 234//5
+f 200//5 799//5 795//5
+f 531//5 527//5 234//5
+f 200//5 14//5 803//5
+f 535//5 531//5 234//5
+f 200//5 795//5 791//5
+f 539//5 535//5 234//5
+f 200//5 791//5 787//5
+f 543//5 539//5 234//5
+f 200//5 787//5 783//5
+f 547//5 543//5 234//5
+f 200//5 783//5 779//5
+f 551//5 547//5 234//5
+f 200//5 779//5 775//5
+f 232//5 551//5 234//5
+f 200//5 775//5 771//5
+f 232//5 555//5 551//5
+f 200//5 771//5 767//5
+f 232//5 206//5 555//5
+f 200//5 767//5 763//5
+f 555//5 205//5 559//5
+f 200//5 763//5 759//5
+f 559//5 1089//5 563//5
+f 200//5 759//5 755//5
+f 1090//5 571//5 567//5
+f 200//5 755//5 751//5
+f 1090//5 575//5 571//5
+f 1088//5 751//5 747//5
+f 1090//5 579//5 575//5
+f 1088//5 747//5 743//5
+f 1090//5 1091//5 579//5
+f 203//5 675//5 671//5
+f 579//5 1091//5 583//5
+f 203//5 671//5 667//5
+f 583//5 1091//5 587//5
+f 203//5 667//5 663//5
+f 587//5 1091//5 591//5
+f 203//5 663//5 659//5
+f 591//5 1091//5 595//5
+f 203//5 659//5 655//5
+f 1089//5 567//5 563//5
+f 1092//5 655//5 651//5
+f 595//5 1091//5 1093//5
+f 1092//5 651//5 647//5
+f 599//5 595//5 1093//5
+f 1092//5 647//5 643//5
+f 208//5 232//5 230//5
+f 1092//5 643//5 639//5
+f 212//5 230//5 228//5
+f 1092//5 639//5 635//5
+f 603//5 599//5 1093//5
+f 1094//5 635//5 631//5
+f 607//5 1093//5 17//5
+f 1094//5 631//5 627//5
+f 214//5 228//5 226//5
+f 1094//5 627//5 624//5
+f 611//5 607//5 17//5
+f 1094//5 624//5 621//5
+f 675//5 203//5 1087//5
+f 1088//5 200//5 751//5
+f 655//5 1092//5 203//5
+f 735//5 1088//5 739//5
+f 216//5 226//5 224//5
+f 224//5 222//5 220//5
+f 224//5 218//5 216//5
+f 228//5 214//5 212//5
+f 230//5 210//5 208//5
+f 555//5 206//5 205//5
+f 1093//5 607//5 603//5
+f 559//5 205//5 1089//5
+f 230//5 212//5 210//5
+f 224//5 220//5 218//5
+f 208//5 206//5 232//5
+f 621//5 17//5 1094//5
+f 1094//5 1092//5 635//5
+f 226//5 216//5 214//5
+f 567//5 1089//5 1090//5
+f 621//5 18//5 17//5
+f 19//5 611//5 17//5
+f 188//6 20//6 15//6
+f 25//7 21//7 23//7
+f 27//545 24//8 25//9
+f 29//546 26//10 27//11
+f 31//14 28//12 29//14
+f 33//16 30//15 31//15
+f 35//18 32//17 33//17
+f 37//19 34//19 35//19
+f 39//547 36//21 37//22
+f 41//23 38//23 39//23
+f 43//24 40//24 41//24
+f 45//25 42//25 43//25
+f 47//26 44//26 45//26
+f 49//27 46//27 47//27
+f 51//28 48//28 49//28
+f 53//29 50//29 51//29
+f 55//30 52//30 53//30
+f 57//31 54//31 55//31
+f 59//32 56//32 57//32
+f 61//34 58//33 59//34
+f 63//35 60//35 61//35
+f 65//37 62//36 63//37
+f 67//38 64//38 65//38
+f 69//39 66//39 67//39
+f 71//40 68//40 69//40
+f 73//41 70//41 71//41
+f 75//42 72//42 73//42
+f 77//43 74//43 75//43
+f 79//44 76//44 77//44
+f 81//45 78//45 79//45
+f 83//46 80//46 81//46
+f 85//47 82//47 83//47
+f 87//48 84//48 85//48
+f 89//49 86//49 87//49
+f 91//49 88//49 89//49
+f 93//49 90//49 91//49
+f 95//49 92//49 93//49
+f 97//49 94//49 95//49
+f 99//49 96//49 97//49
+f 101//49 98//49 99//49
+f 103//49 100//49 101//49
+f 105//49 102//49 103//49
+f 107//49 104//49 105//49
+f 109//49 106//49 107//49
+f 111//49 108//49 109//49
+f 113//50 110//50 111//50
+f 115//49 112//49 113//49
+f 117//51 114//51 115//51
+f 119//49 116//49 117//49
+f 121//52 118//52 119//52
+f 123//53 120//53 121//53
+f 125//54 122//54 123//54
+f 127//55 124//55 125//55
+f 129//56 126//56 127//56
+f 131//55 128//55 129//55
+f 133//57 130//57 131//57
+f 135//58 132//58 133//58
+f 137//59 134//59 135//59
+f 139//60 136//60 137//60
+f 141//61 138//61 139//61
+f 143//62 140//62 141//62
+f 145//63 142//63 143//63
+f 147//64 144//64 145//64
+f 148//65 146//65 147//65
+f 149//66 11//66 148//66
+f 151//67 9//67 149//67
+f 153//68 150//68 151//68
+f 155//69 152//69 153//69
+f 157//70 154//70 155//70
+f 159//71 156//71 157//71
+f 161//72 158//72 159//72
+f 163//73 160//73 161//73
+f 165//74 162//74 163//74
+f 167//75 164//75 165//75
+f 169//76 166//76 167//76
+f 171//77 168//77 169//77
+f 173//78 170//78 171//78
+f 175//79 172//79 173//79
+f 16//80 174//80 175//80
+f 178//3 174//3 277//3
+f 1095//3 311//3 312//3
+f 178//3 277//3 329//3
+f 1095//3 312//3 314//3
+f 178//3 329//3 331//3
+f 1095//3 314//3 316//3
+f 178//3 331//3 333//3
+f 1095//3 318//3 320//3
+f 178//3 333//3 335//3
+f 1095//3 316//3 318//3
+f 178//3 335//3 337//3
+f 1096//3 326//3 239//3
+f 178//3 337//3 279//3
+f 1097//3 239//3 1075//3
+f 178//3 279//3 278//3
+f 1097//3 179//3 239//3
+f 178//3 278//3 281//3
+f 239//3 179//3 1098//3
+f 178//3 281//3 283//3
+f 1099//3 239//3 1098//3
+f 178//3 283//3 285//3
+f 1100//3 239//3 1099//3
+f 178//3 285//3 287//3
+f 1096//3 239//3 1100//3
+f 178//3 287//3 289//3
+f 324//3 326//3 1096//3
+f 178//3 289//3 291//3
+f 324//3 1096//3 322//3
+f 178//3 291//3 293//3
+f 1096//3 1095//3 322//3
+f 178//3 293//3 295//3
+f 1095//3 320//3 322//3
+f 178//3 295//3 297//3
+f 309//3 311//3 1095//3
+f 178//3 297//3 299//3
+f 178//3 309//3 1095//3
+f 178//3 299//3 301//3
+f 178//3 307//3 309//3
+f 178//3 301//3 303//3
+f 178//3 177//3 307//3
+f 178//3 303//3 176//3
+f 1101//55 1100//55 1099//55
+f 275//55 1095//55 1096//55
+f 183//55 182//55 178//55
+f 178//55 274//55 183//55
+f 1096//55 1102//55 275//55
+f 1098//55 1103//55 1101//55
+f 1096//55 1104//55 1102//55
+f 275//55 274//55 178//55
+f 1101//55 1104//55 1100//55
+f 1103//55 1098//55 179//55
+f 180//55 1097//55 1075//55
+f 1084//55 1073//55 1074//55
+f 1074//55 1085//55 1084//55
+f 1075//55 1086//55 180//55
+f 179//55 181//55 1103//55
+f 1095//55 275//55 178//55
+f 1101//55 1099//55 1098//55
+f 1084//55 1075//55 1073//55
+f 1075//55 1084//55 1086//55
+f 1096//55 1100//55 1104//55
+f 179//55 1097//55 180//55
+f 185//55 182//55 184//55
+f 187//81 185//81 186//81
+f 12//82 187//82 13//82
+f 190//83 188//83 189//83
+f 192//84 190//84 191//84
+f 194//85 192//85 193//85
+f 196//86 194//86 195//86
+f 198//87 196//87 197//87
+f 199//88 198//88 14//88
+f 1060//89 199//89 200//89
+f 1089//49 1061//49 1062//49
+f 1089//49 205//49 204//49
+f 1062//49 1090//49 1089//49
+f 1064//49 1093//49 1091//49
+f 8//49 1094//49 17//49
+f 201//49 203//49 1092//49
+f 1060//49 200//49 1088//49
+f 201//49 1092//49 1094//49
+f 1059//49 1088//49 1087//49
+f 1088//49 1059//49 1060//49
+f 1087//49 202//49 1058//49
+f 1094//49 8//49 201//49
+f 1093//49 1064//49 1065//49
+f 1089//49 204//49 1061//49
+f 1091//49 1063//49 1064//49
+f 1087//49 1058//49 1059//49
+f 17//49 1065//49 8//49
+f 1091//49 1090//49 1062//49
+f 1065//49 17//49 1093//49
+f 203//49 202//49 1087//49
+f 1091//49 1062//49 1063//49
+f 207//49 204//49 206//49
+f 209//90 207//90 208//90
+f 211//91 209//91 210//91
+f 213//92 211//92 212//92
+f 215//93 213//93 214//93
+f 217//94 215//94 216//94
+f 219//95 217//95 218//95
+f 221//96 219//96 220//96
+f 223//97 221//97 222//97
+f 225//98 223//98 224//98
+f 227//99 225//99 226//99
+f 229//100 227//100 228//100
+f 231//101 229//101 230//101
+f 233//102 231//102 232//102
+f 1057//102 233//102 234//102
+f 1080//102 1069//102 1068//102
+f 1076//102 236//102 1070//102
+f 1083//102 1072//102 1071//102
+f 1076//102 1070//102 1069//102
+f 1082//102 1071//102 235//102
+f 1083//102 1085//102 1074//102
+f 1071//102 1082//102 1083//102
+f 235//102 237//102 1081//102
+f 1069//102 1080//102 1076//102
+f 1067//102 1078//102 1079//102
+f 1057//102 234//102 1077//102
+f 1077//102 1066//102 1057//102
+f 1079//102 1068//102 1067//102
+f 1083//102 1074//102 1072//102
+f 235//102 1081//102 1082//102
+f 1068//102 1079//102 1080//102
+f 1067//102 1066//102 1077//102
+f 1076//102 237//102 236//102
+f 1067//102 1077//102 1078//102
+f 242//49 238//49 240//49
+f 244//49 241//49 242//49
+f 246//103 243//103 244//103
+f 248//105 245//104 246//105
+f 250//106 247//106 248//106
+f 252//107 249//107 250//107
+f 254//108 251//108 252//108
+f 256//109 253//109 254//109
+f 258//110 255//110 256//110
+f 260//111 257//111 258//111
+f 262//112 259//112 260//112
+f 264//113 261//113 262//113
+f 266//114 263//114 264//114
+f 268//115 265//115 266//115
+f 270//116 267//116 268//118
+f 272//119 269//119 270//116
+f 273//548 271//120 272//119
+f 23//122 22//121 273//122
+f 275//5 313//5 276//5
+f 330//5 16//5 274//5
+f 275//5 315//5 313//5
+f 332//5 330//5 274//5
+f 275//5 317//5 315//5
+f 334//5 332//5 274//5
+f 275//5 321//5 319//5
+f 336//5 334//5 274//5
+f 275//5 319//5 317//5
+f 338//5 336//5 274//5
+f 1102//5 328//5 327//5
+f 339//5 338//5 274//5
+f 1102//5 240//5 328//5
+f 280//5 339//5 274//5
+f 1102//5 327//5 325//5
+f 282//5 280//5 274//5
+f 275//5 325//5 323//5
+f 284//5 282//5 274//5
+f 275//5 323//5 321//5
+f 286//5 284//5 274//5
+f 180//5 1086//5 240//5
+f 288//5 286//5 274//5
+f 181//5 180//5 240//5
+f 290//5 288//5 274//5
+f 1103//5 181//5 240//5
+f 292//5 290//5 274//5
+f 1101//5 1103//5 240//5
+f 294//5 292//5 274//5
+f 1104//5 1101//5 240//5
+f 296//5 294//5 274//5
+f 1102//5 1104//5 240//5
+f 298//5 296//5 274//5
+f 275//5 1102//5 325//5
+f 300//5 298//5 274//5
+f 274//5 276//5 310//5
+f 302//5 300//5 274//5
+f 274//5 310//5 308//5
+f 304//5 302//5 274//5
+f 274//5 308//5 306//5
+f 305//5 304//5 274//5
+f 274//5 306//5 305//5
+f 330//123 277//123 16//123
+f 282//124 278//124 280//124
+f 284//125 281//125 282//125
+f 286//126 283//126 284//126
+f 288//127 285//127 286//127
+f 290//549 287//128 288//128
+f 292//129 289//129 290//129
+f 294//130 291//130 292//130
+f 296//131 293//131 294//131
+f 298//132 295//132 296//132
+f 300//133 297//133 298//133
+f 302//134 299//134 300//134
+f 304//135 301//135 302//135
+f 305//136 303//136 304//136
+f 306//137 176//137 305//137
+f 308//138 177//138 306//138
+f 310//139 307//139 308//139
+f 276//140 309//140 310//140
+f 313//49 311//49 276//49
+f 315//49 312//49 313//49
+f 317//49 314//49 315//49
+f 319//49 316//49 317//49
+f 321//49 318//49 319//49
+f 323//49 320//49 321//49
+f 325//49 322//49 323//49
+f 327//49 324//49 325//49
+f 328//49 326//49 327//49
+f 240//49 239//49 328//49
+f 332//141 329//141 330//141
+f 334//142 331//142 332//142
+f 336//143 333//143 334//143
+f 338//144 335//144 336//144
+f 339//145 337//145 338//145
+f 280//146 279//146 339//146
+f 344//147 340//147 342//147
+f 348//148 343//148 344//148
+f 342//149 341//149 346//149
+f 352//150 347//150 348//150
+f 346//151 345//151 350//151
+f 356//152 351//152 352//152
+f 350//153 349//153 354//153
+f 360//155 355//154 356//155
+f 354//156 353//156 358//156
+f 364//157 359//157 360//157
+f 358//158 357//158 362//158
+f 368//159 363//159 364//159
+f 362//160 361//160 366//160
+f 371//161 367//161 368//161
+f 366//162 365//162 369//162
+f 375//163 370//163 371//163
+f 369//164 10//164 373//164
+f 379//165 374//165 375//165
+f 373//166 372//166 377//166
+f 383//167 378//167 379//167
+f 377//168 376//168 381//168
+f 387//169 382//169 383//169
+f 381//170 380//170 385//170
+f 391//171 386//171 387//171
+f 385//172 384//172 389//172
+f 395//173 390//173 391//173
+f 389//174 388//174 393//174
+f 399//175 394//175 395//175
+f 393//176 392//176 397//176
+f 403//177 398//177 399//177
+f 397//178 396//178 401//178
+f 407//179 402//179 403//179
+f 401//180 400//180 405//180
+f 411//181 406//181 407//181
+f 405//182 404//182 409//182
+f 415//183 410//183 411//183
+f 409//184 408//184 413//184
+f 419//185 414//185 415//185
+f 413//186 412//186 417//186
+f 423//187 418//187 419//187
+f 417//188 416//188 421//188
+f 427//189 422//189 423//189
+f 421//190 420//190 425//190
+f 431//191 426//191 427//191
+f 425//192 424//192 429//192
+f 435//193 430//193 431//193
+f 429//194 428//194 433//194
+f 439//195 434//195 435//195
+f 433//196 432//196 437//196
+f 443//197 438//197 439//197
+f 437//198 436//198 441//198
+f 447//199 442//199 443//199
+f 441//200 440//200 445//200
+f 451//201 446//201 447//201
+f 445//202 444//202 449//202
+f 455//203 450//203 451//203
+f 449//204 448//204 453//204
+f 459//205 454//205 455//205
+f 453//206 452//206 457//206
+f 463//207 458//207 459//207
+f 457//208 456//208 461//208
+f 467//209 462//209 463//209
+f 461//210 460//210 465//210
+f 471//211 466//211 467//211
+f 465//212 464//212 469//212
+f 475//213 470//213 471//213
+f 469//214 468//214 473//214
+f 479//215 474//215 475//215
+f 473//216 472//216 477//216
+f 483//217 478//217 479//217
+f 477//218 476//218 481//218
+f 487//219 482//219 483//219
+f 481//220 480//220 485//220
+f 491//221 486//221 487//221
+f 485//222 484//222 489//222
+f 495//223 490//223 491//223
+f 489//224 488//224 493//224
+f 499//225 494//225 495//225
+f 493//226 492//226 497//226
+f 503//227 498//227 499//227
+f 497//550 496//550 501//550
+f 507//229 502//229 503//229
+f 501//551 500//551 505//551
+f 511//232 506//231 507//232
+f 505//552 504//233 509//234
+f 515//235 510//235 511//235
+f 509//553 508//236 513//238
+f 519//239 514//239 515//239
+f 513//241 512//240 517//241
+f 523//242 518//242 519//242
+f 517//244 516//244 521//244
+f 527//246 522//246 523//246
+f 521//245 520//244 525//554
+f 531//248 526//248 527//248
+f 525//555 524//555 529//555
+f 535//250 530//250 531//250
+f 529//252 528//251 533//252
+f 539//253 534//253 535//253
+f 533//556 532//556 537//556
+f 543//255 538//255 539//255
+f 537//257 536//256 541//257
+f 547//258 542//258 543//258
+f 541//557 540//259 545//261
+f 551//262 546//262 547//262
+f 545//558 544//263 549//265
+f 555//266 550//266 551//266
+f 549//559 548//267 553//267
+f 559//269 554//269 555//269
+f 553//271 552//270 557//271
+f 563//272 558//272 559//272
+f 557//275 556//273 561//275
+f 567//276 562//276 563//276
+f 561//560 560//277 565//277
+f 571//279 566//279 567//279
+f 565//561 564//280 569//281
+f 575//282 570//282 571//282
+f 569//562 568//283 573//284
+f 579//285 574//285 575//285
+f 573//563 572//286 577//288
+f 583//289 578//289 579//289
+f 577//564 576//290 581//292
+f 587//293 582//293 583//293
+f 581//296 580//294 585//296
+f 591//297 586//297 587//297
+f 585//565 584//298 589//300
+f 595//301 590//301 591//301
+f 589//566 588//302 593//303
+f 599//304 594//304 595//304
+f 593//305 592//305 597//305
+f 603//306 598//306 599//306
+f 597//307 596//307 601//307
+f 607//308 602//308 603//308
+f 601//309 600//309 605//309
+f 611//310 606//310 607//310
+f 605//311 604//311 609//311
+f 19//312 610//312 611//312
+f 609//313 608//313 613//313
+f 18//314 614//314 19//314
+f 613//315 612//315 616//315
+f 621//316 617//316 18//316
+f 616//317 615//317 619//317
+f 624//318 620//318 621//318
+f 619//319 618//319 623//320
+f 627//321 6//321 624//321
+f 623//320 622//320 626//323
+f 631//324 7//324 627//324
+f 626//325 625//325 629//325
+f 635//326 630//326 631//326
+f 629//327 628//327 633//327
+f 639//328 634//328 635//328
+f 633//330 632//329 637//330
+f 643//331 638//331 639//331
+f 637//332 636//332 641//332
+f 647//333 642//333 643//333
+f 641//332 640//332 645//332
+f 651//334 646//334 647//334
+f 645//332 644//332 649//332
+f 655//335 650//335 651//335
+f 649//332 648//332 653//332
+f 659//336 654//336 655//336
+f 653//332 652//332 657//332
+f 663//337 658//337 659//337
+f 657//332 656//332 661//332
+f 667//338 662//338 663//338
+f 661//332 660//332 665//332
+f 671//339 666//339 667//339
+f 665//332 664//332 669//332
+f 675//340 670//340 671//340
+f 669//332 668//332 673//332
+f 679//341 674//341 675//341
+f 673//332 672//332 677//332
+f 683//342 678//342 679//342
+f 677//332 676//332 681//332
+f 687//343 682//343 683//343
+f 681//332 680//332 685//332
+f 691//344 686//344 687//344
+f 685//345 684//345 689//345
+f 695//346 690//346 691//346
+f 689//347 688//347 693//347
+f 699//348 694//348 695//348
+f 693//349 692//349 697//349
+f 703//350 698//350 699//350
+f 697//351 696//351 701//351
+f 707//352 702//352 703//352
+f 701//353 700//353 705//353
+f 711//354 706//354 707//354
+f 705//355 704//355 709//355
+f 715//356 710//356 711//356
+f 709//357 708//357 713//357
+f 719//358 714//358 715//358
+f 713//359 712//359 717//359
+f 723//360 718//360 719//360
+f 717//361 716//361 721//361
+f 727//362 722//362 723//362
+f 721//363 720//363 725//363
+f 731//364 726//364 727//364
+f 725//365 724//365 729//365
+f 735//366 730//366 731//366
+f 729//296 728//296 733//296
+f 739//367 734//367 735//367
+f 733//49 732//49 737//49
+f 743//368 738//368 739//368
+f 737//369 736//369 741//369
+f 747//370 742//370 743//370
+f 741//369 740//369 745//369
+f 751//371 746//371 747//371
+f 745//369 744//369 749//369
+f 755//372 750//372 751//372
+f 749//369 748//369 753//369
+f 759//373 754//373 755//373
+f 753//369 752//369 757//369
+f 763//374 758//374 759//374
+f 757//369 756//369 761//369
+f 767//375 762//375 763//375
+f 761//369 760//369 765//369
+f 771//376 766//376 767//376
+f 765//369 764//369 769//377
+f 775//378 770//378 771//378
+f 769//377 768//377 773//369
+f 779//379 774//379 775//379
+f 773//369 772//369 777//369
+f 783//380 778//380 779//380
+f 777//369 776//369 781//377
+f 787//381 782//381 783//381
+f 781//377 780//377 785//369
+f 791//382 786//382 787//382
+f 785//383 784//383 789//383
+f 795//384 790//384 791//384
+f 789//385 788//385 793//385
+f 799//386 794//386 795//386
+f 793//387 792//387 797//387
+f 803//388 798//388 799//388
+f 797//389 796//389 801//389
+f 807//390 802//390 803//390
+f 801//391 800//391 805//391
+f 811//392 806//392 807//392
+f 805//393 804//393 809//393
+f 815//394 810//394 811//394
+f 809//395 808//395 813//395
+f 816//396 814//396 815//396
+f 813//397 812//397 816//397
+f 1024//3 960//3 956//3
+f 1028//3 1032//3 964//3
+f 1054//3 975//3 971//3
+f 1018//541 1003//541 979//3
+f 983//3 991//3 987//3
+f 983//3 979//3 995//3
+f 1010//567 1007//568 1003//541
+f 1018//569 1014//569 1010//569
+f 979//3 1022//3 1018//541
+f 979//3 1030//3 1026//3
+f 979//3 1038//3 1034//3
+f 975//3 1046//3 1042//3
+f 975//3 1054//3 1050//3
+f 971//3 1048//3 1052//3
+f 971//3 1040//3 1044//3
+f 1040//3 968//3 1036//3
+f 960//3 1024//3 1028//3
+f 952//3 1016//3 1020//3
+f 948//3 1009//3 1012//3
+f 942//3 1001//3 1005//3
+f 934//3 993//3 997//3
+f 926//3 985//3 989//3
+f 918//3 977//3 981//3
+f 818//3 817//3 973//3
+f 904//3 962//3 966//3
+f 896//3 954//3 958//3
+f 888//3 946//3 950//3
+f 946//3 884//3 943//3
+f 876//3 932//3 936//3
+f 868//3 924//3 928//3
+f 864//3 916//3 920//3
+f 916//3 856//3 912//3
+f 848//3 902//3 906//3
+f 882//3 894//3 898//3
+f 894//3 886//3 890//3
+f 844//3 878//3 882//3
+f 844//3 870//3 874//3
+f 844//3 862//3 866//3
+f 844//3 840//3 858//3
+f 840//3 846//3 850//3
+f 840//3 838//3 842//3
+f 840//3 830//3 834//3
+f 836//3 823//3 826//3
+f 832//3 828//3 824//3
+f 823//3 836//3 832//3
+f 842//3 846//3 840//3
+f 906//3 852//3 848//3
+f 852//3 909//3 856//3
+f 920//3 868//3 864//3
+f 932//3 876//3 872//3
+f 936//3 940//3 880//3
+f 950//3 892//3 888//3
+f 958//3 900//3 896//3
+f 966//3 819//3 904//3
+f 973//3 914//3 818//3
+f 981//3 922//3 918//3
+f 989//3 930//3 926//3
+f 997//3 938//3 934//3
+f 1005//3 945//3 942//3
+f 1012//3 952//3 948//3
+f 1028//3 964//3 960//3
+f 1042//3 979//3 975//3
+f 983//3 995//3 991//3
+f 1018//541 1010//567 1003//541
+f 979//3 1026//3 1022//3
+f 979//3 1042//3 1038//3
+f 971//3 1052//3 1054//3
+f 971//3 968//3 1040//3
+f 956//3 1020//3 1024//3
+f 945//3 1005//3 1009//3
+f 930//3 989//3 993//3
+f 914//3 973//3 977//3
+f 900//3 958//3 962//3
+f 888//3 884//3 946//3
+f 872//3 928//3 932//3
+f 864//3 860//3 916//3
+f 848//3 844//3 902//3
+f 894//3 882//3 886//3
+f 844//3 866//3 870//3
+f 858//3 840//3 854//3
+f 840//3 834//3 838//3
+f 832//3 824//3 823//3
+f 826//3 840//3 836//3
+f 906//3 909//3 852//3
+f 928//3 872//3 868//3
+f 880//3 940//3 943//3
+f 962//3 904//3 900//3
+f 977//3 918//3 914//3
+f 993//3 934//3 930//3
+f 1009//3 948//3 945//3
+f 964//3 1032//3 968//3
+f 995//3 979//3 999//3
+f 979//3 1034//3 1030//3
+f 971//3 1044//3 1048//3
+f 952//3 1012//3 1016//3
+f 926//3 922//3 985//3
+f 896//3 892//3 954//3
+f 868//3 920//3 924//3
+f 844//3 882//3 898//3
+f 844//3 858//3 862//3
+f 840//3 826//3 830//3
+f 840//3 850//3 854//3
+f 936//3 880//3 876//3
+f 966//3 817//3 819//3
+f 997//3 1001//3 938//3
+f 979//3 1003//541 999//3
+f 975//3 1050//3 1046//3
+f 942//3 938//3 1001//3
+f 954//3 892//3 950//3
+f 902//3 844//3 898//3
+f 874//3 878//3 844//3
+f 884//3 880//3 943//3
+f 1020//3 956//3 952//3
+f 1036//3 968//3 1032//3
+f 916//3 860//3 856//3
+f 856//3 909//3 912//3
+f 922//3 981//3 985//3
+f 1002//5 935//5 939//5
+f 994//5 927//5 931//5
+f 990//5 986//5 923//5
+f 982//5 978//5 915//5
+f 970//5 905//5 908//5
+f 963//5 897//5 901//5
+f 959//5 955//5 893//5
+f 951//5 947//5 885//5
+f 937//5 873//5 877//5
+f 929//5 925//5 869//5
+f 921//5 857//5 861//5
+f 910//5 849//5 853//5
+f 863//5 841//5 845//5
+f 827//5 833//5 837//5
+f 833//5 825//5 829//5
+f 837//5 831//5 827//5
+f 841//5 839//5 835//5
+f 841//5 847//5 843//5
+f 841//5 855//5 851//5
+f 841//5 863//5 859//5
+f 845//5 871//5 867//5
+f 845//5 879//5 875//5
+f 845//5 887//5 883//5
+f 899//5 895//5 891//5
+f 887//5 903//5 899//5
+f 849//5 910//5 907//5
+f 857//5 917//5 913//5
+f 861//5 865//5 921//5
+f 869//5 933//5 929//5
+f 877//5 941//5 937//5
+f 941//5 881//5 944//5
+f 885//5 889//5 951//5
+f 897//5 963//5 959//5
+f 905//5 970//5 967//5
+f 908//5 911//5 974//5
+f 915//5 919//5 982//5
+f 927//5 994//5 990//5
+f 935//5 1002//5 998//5
+f 939//5 821//5 1006//5
+f 822//5 949//5 1013//5
+f 953//5 1025//5 1021//5
+f 961//5 1033//5 1029//5
+f 969//5 1041//5 1037//5
+f 969//5 972//5 1045//5
+f 972//5 1056//5 1053//5
+f 972//5 976//5 1055//5
+f 976//5 1043//5 1047//5
+f 980//5 1035//5 1039//5
+f 980//5 1027//5 1031//5
+f 1015//570 1019//571 1023//5
+f 1008//572 1011//572 1015//572
+f 1000//573 1004//573 1008//573
+f 980//5 996//5 1000//5
+f 984//5 988//5 992//5
+f 996//5 980//5 984//5
+f 980//5 1031//5 1035//5
+f 1037//5 965//5 969//5
+f 1029//5 957//5 961//5
+f 1021//5 1017//5 953//5
+f 1013//5 820//5 822//5
+f 998//5 931//5 935//5
+f 923//5 986//5 919//5
+f 967//5 901//5 905//5
+f 893//5 955//5 889//5
+f 933//5 869//5 873//5
+f 913//5 853//5 857//5
+f 835//5 831//5 841//5
+f 833//5 827//5 825//5
+f 841//5 843//5 839//5
+f 841//5 859//5 855//5
+f 845//5 875//5 871//5
+f 899//5 891//5 887//5
+f 845//5 907//5 903//5
+f 857//5 921//5 917//5
+f 873//5 937//5 933//5
+f 944//5 881//5 947//5
+f 901//5 967//5 963//5
+f 974//5 911//5 978//5
+f 931//5 998//5 994//5
+f 1006//5 821//5 820//5
+f 957//5 1029//5 1025//5
+f 969//5 1045//5 1041//5
+f 972//5 1055//5 1056//5
+f 976//5 980//5 1043//5
+f 980//5 1023//5 1027//5
+f 1000//5 1008//5 1015//570
+f 984//5 992//5 996//5
+f 1000//5 1023//5 980//5
+f 1033//5 961//5 965//5
+f 953//5 1017//5 949//5
+f 990//5 923//5 927//5
+f 959//5 893//5 897//5
+f 869//5 925//5 865//5
+f 841//5 831//5 837//5
+f 841//5 851//5 847//5
+f 845//5 883//5 879//5
+f 853//5 913//5 910//5
+f 877//5 881//5 941//5
+f 908//5 974//5 970//5
+f 939//5 1006//5 1002//5
+f 965//5 1037//5 1033//5
+f 1055//5 976//5 1051//5
+f 1000//5 1015//570 1023//5
+f 980//5 1039//5 1043//5
+f 1025//5 953//5 957//5
+f 919//5 986//5 982//5
+f 907//5 845//5 849//5
+f 845//5 867//5 863//5
+f 921//5 865//5 925//5
+f 978//5 911//5 915//5
+f 1045//5 972//5 1049//5
+f 1047//5 1051//5 976//5
+f 949//5 1017//5 1013//5
+f 903//5 887//5 845//5
+f 947//5 881//5 885//5
+f 1049//5 972//5 1053//5
+f 889//5 955//5 951//5
+f 827//398 823//398 825//398
+f 831//399 826//399 827//399
+f 825//400 824//400 829//400
+f 835//401 830//401 831//401
+f 829//402 828//402 833//402
+f 839//403 834//403 835//403
+f 833//404 832//404 837//404
+f 843//405 838//405 839//405
+f 837//406 836//406 841//406
+f 847//407 842//407 843//407
+f 841//408 840//408 845//408
+f 851//409 846//409 847//409
+f 845//411 844//411 849//411
+f 855//574 850//412 851//412
+f 849//413 848//413 853//413
+f 859//414 854//414 855//414
+f 853//415 852//415 857//415
+f 863//416 858//416 859//416
+f 857//417 856//417 861//417
+f 867//418 862//418 863//418
+f 861//420 860//419 865//420
+f 871//421 866//421 867//421
+f 865//424 864//423 869//424
+f 875//425 870//425 871//425
+f 869//427 868//427 873//427
+f 879//428 874//428 875//428
+f 873//429 872//429 877//429
+f 883//430 878//430 879//430
+f 877//431 876//431 881//431
+f 887//432 882//432 883//432
+f 881//433 880//433 885//433
+f 891//434 886//434 887//434
+f 885//435 884//435 889//435
+f 895//436 890//436 891//436
+f 889//437 888//437 893//437
+f 899//438 894//438 895//438
+f 893//439 892//439 897//439
+f 903//440 898//440 899//440
+f 897//441 896//441 901//441
+f 907//442 902//442 903//442
+f 901//443 900//443 905//443
+f 910//444 906//444 907//444
+f 905//445 904//445 908//445
+f 913//446 909//446 910//446
+f 908//447 819//447 911//447
+f 917//448 912//448 913//448
+f 911//449 818//449 915//449
+f 921//450 916//450 917//450
+f 915//451 914//451 919//451
+f 925//452 920//452 921//452
+f 919//453 918//453 923//453
+f 929//454 924//454 925//454
+f 923//455 922//455 927//455
+f 933//456 928//456 929//456
+f 927//457 926//457 931//457
+f 937//458 932//458 933//458
+f 931//459 930//459 935//459
+f 941//460 936//460 937//460
+f 935//461 934//461 939//461
+f 944//462 940//462 941//462
+f 939//463 938//463 821//463
+f 947//464 943//464 944//464
+f 821//465 942//465 822//465
+f 951//466 946//466 947//466
+f 822//467 945//467 949//467
+f 955//468 950//468 951//468
+f 949//469 948//469 953//469
+f 959//470 954//470 955//470
+f 953//471 952//471 957//471
+f 963//472 958//472 959//472
+f 957//473 956//473 961//473
+f 967//474 962//474 963//474
+f 961//475 960//475 965//475
+f 970//476 966//476 967//476
+f 965//477 964//477 969//477
+f 974//478 817//478 970//478
+f 969//480 968//479 972//480
+f 978//481 973//481 974//481
+f 972//482 971//482 976//482
+f 982//483 977//483 978//483
+f 976//484 975//484 980//484
+f 986//485 981//485 982//485
+f 980//486 979//486 984//486
+f 990//487 985//487 986//487
+f 984//488 983//488 988//488
+f 994//489 989//489 990//489
+f 988//490 987//490 992//490
+f 998//491 993//491 994//491
+f 992//492 991//492 996//492
+f 1002//493 997//493 998//493
+f 996//302 995//302 1000//302
+f 1006//494 1001//494 1002//494
+f 1000//495 999//495 1004//495
+f 820//496 1005//496 1006//496
+f 1004//497 1003//497 1008//497
+f 1013//498 1009//498 820//498
+f 1008//500 1007//499 1011//499
+f 1017//501 1012//501 1013//501
+f 1011//575 1010//254 1015//254
+f 1021//502 1016//502 1017//502
+f 1015//503 1014//503 1019//503
+f 1025//504 1020//504 1021//504
+f 1019//576 1018//505 1023//505
+f 1029//507 1024//507 1025//507
+f 1023//509 1022//508 1027//510
+f 1033//511 1028//511 1029//511
+f 1027//513 1026//512 1031//513
+f 1037//514 1032//514 1033//514
+f 1031//515 1030//515 1035//515
+f 1041//516 1036//516 1037//516
+f 1035//518 1034//517 1039//518
+f 1045//519 1040//519 1041//519
+f 1039//520 1038//520 1043//520
+f 1049//521 1044//521 1045//521
+f 1043//523 1042//522 1047//522
+f 1053//524 1048//524 1049//524
+f 1047//525 1046//525 1051//525
+f 1056//526 1052//526 1053//526
+f 1051//527 1050//527 1055//527
+f 1055//528 1054//528 1056//528
+o Curve_path22
+v 0.133501 -0.000000 1.118326
+v 0.133501 -0.000000 1.118326
+v 0.133052 -0.000000 1.118264
+v 0.133954 -0.000000 1.118385
+v 0.133954 -0.000000 1.118385
+v 0.134409 -0.000000 1.118442
+v 0.134409 -0.000000 1.118442
+v 0.134866 -0.000000 1.118497
+v 0.134866 -0.000000 1.118497
+v 0.135325 -0.000000 1.118550
+v 0.135325 -0.000000 1.118550
+v 0.135784 -0.000000 1.118602
+v 0.135784 -0.000000 1.118602
+v 0.136243 -0.000000 1.118652
+v 0.136243 -0.000000 1.118652
+v 0.136702 -0.000000 1.118701
+v 0.136702 -0.000000 1.118701
+v 0.137159 -0.000000 1.118750
+v 0.137159 -0.000000 1.118750
+v 0.137614 -0.000000 1.118798
+v 0.137614 -0.000000 1.118798
+v 0.138067 -0.000000 1.118845
+v 0.138067 -0.000000 1.118845
+v 0.138516 -0.000000 1.118892
+vn 0.000000 0.000000 1.000000
+vn 0.000000 0.000000 -0.000000
+vn -0.000000 1.000000 -0.000000
+vn -0.000000 1.000000 -0.000100
+vn -0.000300 1.000000 0.000000
+vn 0.000000 0.000000 -0.000100
+usemtl SVGMat.001
+s 1
+f 1105//577 1106//577 1107//577
+f 1105//577 1108//577 1106//577
+f 1109//577 1108//577 1105//577
+f 1109//577 1110//577 1108//577
+f 1111//578 1110//579 1109//579
+f 1111//580 1112//581 1110//578
+f 1113//579 1112//581 1111//580
+f 1113//579 1114//581 1112//581
+f 1115//579 1114//581 1113//579
+f 1115//579 1116//579 1114//581
+f 1117//578 1116//579 1115//579
+f 1117//580 1118//579 1116//582
+f 1119//577 1118//577 1117//577
+f 1119//577 1120//577 1118//577
+f 1121//577 1120//577 1119//577
+f 1121//577 1122//577 1120//577
+f 1123//577 1122//577 1121//577
+f 1123//577 1124//577 1122//577
+f 1125//578 1124//579 1123//580
+f 1125//579 1126//579 1124//578
+f 1127//581 1126//579 1125//579
+f 1127//581 1128//579 1126//579
+o Curve.003_path34
+v 0.131158 -0.000000 1.117179
+v 0.139489 -0.000000 1.117165
+v 0.130979 -0.000000 1.117165
+v 0.148988 -0.000000 1.117165
+v 0.159145 -0.000000 1.117165
+v 0.169632 -0.000000 1.117165
+v 0.180118 -0.000000 1.117165
+v 0.190275 -0.000000 1.117165
+v 0.199774 -0.000000 1.117165
+v 0.208284 -0.000000 1.117165
+v 0.215477 -0.000000 1.117165
+v 0.221022 -0.000000 1.117165
+v 0.224591 -0.000000 1.117165
+v 0.225853 -0.000000 1.117165
+v 0.221277 -0.000000 1.117233
+v 0.131333 -0.000000 1.117217
+v 0.131506 -0.000000 1.117275
+v 0.216748 -0.000000 1.117421
+v 0.131677 -0.000000 1.117349
+v 0.131847 -0.000000 1.117434
+v 0.212268 -0.000000 1.117705
+v 0.132015 -0.000000 1.117526
+v 0.132185 -0.000000 1.117621
+v 0.132354 -0.000000 1.117714
+v 0.207836 -0.000000 1.118061
+v 0.132525 -0.000000 1.117801
+v 0.132698 -0.000000 1.117877
+v 0.132873 -0.000000 1.117939
+v 0.133052 -0.000000 1.117981
+v 0.133501 -0.000000 1.118049
+v 0.133954 -0.000000 1.118123
+v 0.203452 -0.000000 1.118464
+v 0.134409 -0.000000 1.118203
+v 0.134866 -0.000000 1.118287
+v 0.135325 -0.000000 1.118374
+v 0.135784 -0.000000 1.118460
+v 0.136243 -0.000000 1.118546
+v 0.199116 -0.000000 1.118892
+v 0.136702 -0.000000 1.118628
+v 0.137159 -0.000000 1.118706
+v 0.137614 -0.000000 1.118777
+v 0.138067 -0.000000 1.118839
+v 0.138516 -0.000000 1.118892
+v 0.141317 -0.000000 1.119183
+v 0.194828 -0.000000 1.119320
+v 0.144144 -0.000000 1.119445
+v 0.190587 -0.000000 1.119724
+v 0.146999 -0.000000 1.119678
+v 0.149884 -0.000000 1.119884
+v 0.186394 -0.000000 1.120079
+v 0.152797 -0.000000 1.120063
+v 0.155742 -0.000000 1.120215
+v 0.182248 -0.000000 1.120363
+v 0.158718 -0.000000 1.120341
+v 0.161726 -0.000000 1.120443
+v 0.178149 -0.000000 1.120551
+v 0.164767 -0.000000 1.120521
+v 0.167842 -0.000000 1.120576
+v 0.174098 -0.000000 1.120619
+v 0.170952 -0.000000 1.120608
+vn -0.000000 1.000000 0.000000
+usemtl SVGMat.004
+s 1
+f 1129//583 1130//583 1131//583
+f 1129//583 1132//583 1130//583
+f 1129//583 1133//583 1132//583
+f 1129//583 1134//583 1133//583
+f 1129//583 1135//583 1134//583
+f 1129//583 1136//583 1135//583
+f 1129//583 1137//583 1136//583
+f 1129//583 1138//583 1137//583
+f 1129//583 1139//583 1138//583
+f 1129//583 1140//583 1139//583
+f 1129//583 1141//583 1140//583
+f 1129//583 1142//583 1141//583
+f 1129//583 1143//583 1142//583
+f 1144//583 1143//583 1129//583
+f 1145//583 1143//583 1144//583
+f 1145//583 1146//583 1143//583
+f 1147//583 1146//583 1145//583
+f 1148//583 1146//583 1147//583
+f 1148//583 1149//583 1146//583
+f 1150//583 1149//583 1148//583
+f 1151//583 1149//583 1150//583
+f 1152//583 1149//583 1151//583
+f 1152//583 1153//583 1149//583
+f 1154//583 1153//583 1152//583
+f 1155//583 1153//583 1154//583
+f 1156//583 1153//583 1155//583
+f 1157//583 1153//583 1156//583
+f 1158//583 1153//583 1157//583
+f 1159//583 1153//583 1158//583
+f 1159//583 1160//583 1153//583
+f 1161//583 1160//583 1159//583
+f 1162//583 1160//583 1161//583
+f 1163//583 1160//583 1162//583
+f 1164//583 1160//583 1163//583
+f 1165//583 1160//583 1164//583
+f 1165//583 1166//583 1160//583
+f 1167//583 1166//583 1165//583
+f 1168//583 1166//583 1167//583
+f 1169//583 1166//583 1168//583
+f 1170//583 1166//583 1169//583
+f 1171//583 1166//583 1170//583
+f 1172//583 1166//583 1171//583
+f 1172//583 1173//583 1166//583
+f 1174//583 1173//583 1172//583
+f 1174//583 1175//583 1173//583
+f 1176//583 1175//583 1174//583
+f 1177//583 1175//583 1176//583
+f 1177//583 1178//583 1175//583
+f 1179//583 1178//583 1177//583
+f 1180//583 1178//583 1179//583
+f 1180//583 1181//583 1178//583
+f 1182//583 1181//583 1180//583
+f 1183//583 1181//583 1182//583
+f 1183//583 1184//583 1181//583
+f 1185//583 1184//583 1183//583
+f 1186//583 1184//583 1185//583
+f 1186//583 1187//583 1184//583
+f 1188//583 1187//583 1186//583
diff --git a/examples/qt3d/controlsunderlay/controls.qrc b/examples/qt3d/controlsunderlay/controls.qrc
new file mode 100644
index 000000000..9ff739d07
--- /dev/null
+++ b/examples/qt3d/controlsunderlay/controls.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>Logo.qml</file>
+ <file>Qt_logo.obj</file>
+ </qresource>
+</RCC>
diff --git a/examples/qt3d/controlsunderlay/controlsunderlay.pro b/examples/qt3d/controlsunderlay/controlsunderlay.pro
new file mode 100644
index 000000000..7b6500a98
--- /dev/null
+++ b/examples/qt3d/controlsunderlay/controlsunderlay.pro
@@ -0,0 +1,12 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+QT += qml quick
+
+SOURCES += main.cpp
+
+RESOURCES += controls.qrc
+
+OTHER_FILES += main.qml \
+ Logo.qml
diff --git a/examples/qt3d/controlsunderlay/main.cpp b/examples/qt3d/controlsunderlay/main.cpp
new file mode 100644
index 000000000..cb3928a51
--- /dev/null
+++ b/examples/qt3d/controlsunderlay/main.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQuickView>
+
+int main(int argc, char **argv)
+{
+ QSurfaceFormat format;
+ format.setSamples(4);
+ QSurfaceFormat::setDefaultFormat(format);
+
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ view.resize(520, 500);
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/qt3d/controlsunderlay/main.qml b/examples/qt3d/controlsunderlay/main.qml
new file mode 100644
index 000000000..8e3e996b2
--- /dev/null
+++ b/examples/qt3d/controlsunderlay/main.qml
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import QtQuick.Scene3D 2.14
+import QtQuick.Controls 1.4
+import QtQuick.Layouts 1.2
+
+Item {
+ id: main
+
+ property real rotationValue: 0
+
+ ColumnLayout {
+ id: colorLayout
+ anchors.left: parent.horizontalCenter
+ anchors.leftMargin: parent.width * 0.25
+ anchors.right: parent.right
+ anchors.rightMargin: 15
+ anchors.top: scene3D.top
+ spacing: 5
+
+ Text { text: "Appearance"; font.bold: true }
+ Text { text: "Ambient color RGB" }
+ RowLayout {
+ Text { text: "R" }
+ Slider {
+ id: color_r
+ Layout.fillWidth: true
+ minimumValue: 0
+ maximumValue: 255
+ value: 128
+ }
+ }
+ RowLayout {
+ Text { text: "G" }
+ Slider {
+ id: color_g
+ Layout.fillWidth: true
+ minimumValue: 0
+ maximumValue: 255
+ value: 195
+ }
+ }
+ RowLayout {
+ Text { text: "B" }
+ Slider {
+ id: color_b
+ Layout.fillWidth: true
+ minimumValue: 0
+ maximumValue: 255
+ value: 66
+ }
+ }
+ Text { text: "Shininess" }
+ Slider {
+ id: shining
+ Layout.fillWidth: true
+ minimumValue: 30
+ maximumValue: 90
+ value: 50
+ }
+ }
+
+ ColumnLayout {
+ id: transformLayout
+
+ anchors.left: colorLayout.left
+ anchors.right: colorLayout.right
+ anchors.top: colorLayout.bottom
+ anchors.topMargin: 10
+ spacing: 5
+
+ Text { text: "Item transform"; font.bold: true }
+ Text { text: "Rotation" }
+ RowLayout {
+ Text { text: "X" }
+ Slider {
+ id: rotation_x
+ Layout.fillWidth: true
+ minimumValue: -45
+ maximumValue: 45
+ value: rotationValue
+ }
+ }
+ RowLayout {
+ Text { text: "Y" }
+ Slider {
+ id: rotation_y
+ Layout.fillWidth: true
+ minimumValue: -45
+ maximumValue: 45
+ value: rotationValue
+ }
+ }
+ RowLayout {
+ Text { text: "Z" }
+ Slider {
+ id: rotation_z
+ Layout.fillWidth: true
+ minimumValue: -45
+ maximumValue: 45
+ value: rotationValue
+ }
+ }
+
+ RowLayout {
+ CheckBox {id: animation; text: "Animation"; checked: false}
+ }
+ }
+
+ ColumnLayout {
+ id: cameraLayout
+
+ anchors.left: colorLayout.left
+ anchors.right: colorLayout.right
+ anchors.top: transformLayout.bottom
+ anchors.topMargin: 10
+ spacing: 5
+
+ Text { text: "Camera"; font.bold: true }
+ Text { text: "View Ctr Z: " + watch.cameraZ.toFixed(2) }
+ Slider {
+ id: viewCenter_z
+ Layout.fillWidth: true
+ minimumValue: 4
+ maximumValue: 12
+ value: 7.5
+ onValueChanged: watch.setPositionZ(value)
+ }
+ Button {
+ id: viewAll
+ Layout.fillWidth: true
+ text: "View All"
+ onClicked: watch.viewLogo()
+ }
+ }
+
+ // Position in the QML file and sizing of the Scene3D
+ // have no actual effect in Underlay mode:
+ // The 3D content will be drawn before any QtQuick content
+ // and assume a FullScreen viewport
+ Scene3D {
+ id: scene3D
+ focus: true
+ aspects: "input"
+ compositingMode: Scene3D.Underlay
+
+ Logo {
+ id: watch
+ }
+ }
+
+ SequentialAnimation {
+ running: true
+ paused: !animation.checked
+ loops: Animation.Infinite
+
+ NumberAnimation {
+ target: main
+ property: "rotationValue"
+ easing.type: Easing.OutQuad
+ duration: 1000
+ from: 0
+ to: 45
+ }
+ NumberAnimation {
+ target: main
+ property: "rotationValue"
+ easing.type: Easing.InOutQuad
+ duration: 1000
+ from: 45
+ to: -45
+ }
+ NumberAnimation {
+ target: main
+ property: "rotationValue"
+ easing.type: Easing.InQuad
+ duration: 1000
+ from: -45
+ to: 0
+ }
+ }
+}
diff --git a/examples/qt3d/planets-qml/SolarSystem.qml b/examples/qt3d/planets-qml/SolarSystem.qml
index 8c0cfccd4..2b56237f5 100644
--- a/examples/qt3d/planets-qml/SolarSystem.qml
+++ b/examples/qt3d/planets-qml/SolarSystem.qml
@@ -133,8 +133,8 @@ Entity {
projectionType: CameraLens.PerspectiveProjection
fieldOfView: 45
aspectRatio: width / height
- nearPlane: 2500000.0
- farPlane: 20000000.0
+ nearPlane: 2500.0
+ farPlane: 20000.0
position: defaultCameraPosition
upVector: defaultUp
viewCenter: Qt.vector3d( xLookAtOffset, yLookAtOffset, zLookAtOffset )
@@ -211,9 +211,9 @@ Entity {
//saturnRing.makeRing()
//uranusRing.makeRing()
saturnRingOuterRadius = planetData[Planets.SATURN].radius + Planets.saturnOuterRadius
- saturnRingInnerRadius = planetData[Planets.SATURN].radius + 6.630
+ saturnRingInnerRadius = planetData[Planets.SATURN].radius + 0.006630
uranusRingOuterRadius = planetData[Planets.URANUS].radius + Planets.uranusOuterRadius
- uranusRingInnerRadius = planetData[Planets.URANUS].radius + 2
+ uranusRingInnerRadius = planetData[Planets.URANUS].radius + 0.002
ready = true
changeScale(1200)
changeSpeed(0.2)
@@ -286,7 +286,7 @@ Entity {
// Limit minimum scaling in focus mode to avoid jitter caused by rounding errors
if (actualScale <= focusedMinimumScale) {
planetScale = focusedMinimumScale
- changeScale(focusedMinimumScale, true)
+ changeScale(focusedMinimumSfocusedPlanetcale, true)
}
focusedScaling = true
} else if (focusedScaling === true) {
@@ -423,7 +423,7 @@ Entity {
return
var scaling = setScale(scale, focused)
- sun.r = planetData[Planets.SUN].radius * scaling / 100
+ sun.r = planetData[Planets.SUN].radius * scaling / 10
mercury.r = planetData[Planets.MERCURY].radius * scaling
venus.r = planetData[Planets.VENUS].radius * scaling
earth.r = planetData[Planets.EARTH].radius * scaling
@@ -511,7 +511,7 @@ Entity {
}
property Transform transformStarfield: Transform {
- scale: 8500000
+ scale: 8500
translation: Qt.vector3d(0, 0, 0)
}
diff --git a/examples/qt3d/planets-qml/android/AndroidManifest.xml b/examples/qt3d/planets-qml/android/AndroidManifest.xml
index 0252a83b8..2acbd7b0b 100644
--- a/examples/qt3d/planets-qml/android/AndroidManifest.xml
+++ b/examples/qt3d/planets-qml/android/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<manifest package="org.qtproject.planets.qml" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
- <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+ <application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:extractNativeLibs="true">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="-- %%INSERT_APP_NAME%% --" android:screenOrientation="unspecified" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
@@ -13,12 +13,10 @@
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
- <meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
- <meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
- <meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
+ <meta-data android:name="android.app.load_local_libs_resource_id" android:resource="@array/load_local_libs"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
@@ -42,7 +40,7 @@
<!-- Background running -->
</activity>
</application>
- <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
diff --git a/examples/qt3d/planets-qml/doc/src/planets-qml.qdoc b/examples/qt3d/planets-qml/doc/src/planets-qml.qdoc
index 2dae457a0..a8c89fbe2 100644
--- a/examples/qt3d/planets-qml/doc/src/planets-qml.qdoc
+++ b/examples/qt3d/planets-qml/doc/src/planets-qml.qdoc
@@ -50,14 +50,14 @@
\section1 Qt Quick 2D Implementation
- The Qt Quick Implementation \l{planets-qml/PlanetsMain.qml}{PlanetsMain.qml} of the
+ The Qt Quick Implementation in \c {planets-qml/PlanetsMain.qml} of the
example renders the 3D content using the \c Scene3D type.
\snippet planets-qml/PlanetsMain.qml 0
The planet related information is stored into a \c{ListModel}. The selection buttons for the
planets and the information sheet are created based on the model. The 2D elements, selection
- buttons and sliders, are implemented in the \l{planets-qml/PlanetsMain.qml}{PlanetsMain.qml}.
+ buttons and sliders, are implemented in \c {planets-qml/PlanetsMain.qml}.
The selection buttons change the \c{focusedPlanet} property of the \c{mainview}. As the property
changes, the planet information is updated, and the camera is animated to the new position.
@@ -65,14 +65,14 @@
\snippet planets-qml/PlanetsMain.qml 1
The camera position and the camera look at point are updated based on values that are animated
- in the \l{planets-qml/SolarSystem.qml}{SolarSystem.qml}, triggered from the
+ in \c {planets-qml/SolarSystem.qml}, triggered from the
\c{changePlanetFocus()} function.
\snippet planets-qml/SolarSystem.qml 0
The sliders are used to adjust the rotation speed, the planet size, and the viewing distance.
- When a slider value changes, a JavaScript function in \l{planets-qml/SolarSystem.qml}
- {SolarSystem.qml} is called to adjust the given property. For example, changing the value of
+ When a slider value changes, a JavaScript function in \c {planets-qml/SolarSystem.qml}
+ is called to adjust the given property. For example, changing the value of
the \e{Viewing Distance} slider calls the \c{changeCameraDistance()} method.
\snippet planets-qml/PlanetsMain.qml 2
@@ -80,7 +80,7 @@
\section1 Qt 3D Implementation
The main part of the implementation, including the movement and rotation maths for the planets,
- is done in the \l{planets-qml/SolarSystem.qml}{SolarSystem.qml}.
+ is done in \c {planets-qml/SolarSystem.qml}.
First, a \c Camera, a \c{Light}, and a \c Configuration are added, followed by \c{Effect}s for
the planet \c{Material}s, and finally the planets themselves. For example, Earth is constructed
@@ -89,7 +89,7 @@
\snippet planets-qml/SolarSystem.qml 1
Planet data, which is needed for the movement and rotation calculations, among other things, is
- constructed with JavaScript in \l{planets-qml/planets.js}{planets.js} by calling
+ constructed with JavaScript in \c {planets-qml/planets.js} by calling
\c{loadPlanetData()} as the component completes. Other initializations, such as inserting the
planets into an array for easier handling, calculating the ring radii for Saturn and Uranus
rings, and setting the default scale, speed, and camera offset, are done as well:
diff --git a/examples/qt3d/planets-qml/planets.js b/examples/qt3d/planets-qml/planets.js
index f64ec3149..b3517ac5a 100644
--- a/examples/qt3d/planets-qml/planets.js
+++ b/examples/qt3d/planets-qml/planets.js
@@ -115,11 +115,13 @@ function planetIndex(planetName) {
var planets = []; // Planet data info
-var solarDistance = 2600000;
-var saturnOuterRadius = 120.700;
-var uranusOuterRadius = 40;
+// Units are in 10^3 KM
-var auScale = 149597.870700; // AU in thousands of kilometers
+var solarDistance = 2600.000;
+var saturnOuterRadius = 0.120700;
+var uranusOuterRadius = 0.040;
+
+var auScale = 149.597870700; // 0.001 AU (in thousands of kilometers)
function loadPlanetData() {
@@ -136,11 +138,11 @@ function loadPlanetData() {
// centerOfOrbit - the planet in the center of the orbit
// (orbital elements based on http://www.stjarnhimlen.se/comp/ppcomp.html)
- var sun = { radius: 694.439, tilt: 63.87, period: 25.05, x: 0, y: 0, z: 0,
+ var sun = { radius: 0.694439, tilt: 63.87, period: 25.05, x: 0, y: 0, z: 0,
roll: 0 };
planets.push(sun);
var mercury = {
- radius: 2.433722, tilt: 0.04, N1: 48.3313, N2: 0.0000324587,
+ radius: 0.002433722, tilt: 0.04, N1: 48.3313, N2: 0.0000324587,
i1: 7.0047, i2: 0.0000000500, w1: 29.1241, w2: 0.0000101444,
a1: 0.387098, a2: 0, e1: 0.205635, e2: 0.000000000559,
M1: 168.6562, M2: 4.0923344368, period: 58.646, x: 0, y: 0, z: 0,
@@ -148,7 +150,7 @@ function loadPlanetData() {
};
planets.push(mercury);
var venus = {
- radius: 6.046079, tilt: 177.36, N1: 76.6799, N2: 0.0000246590,
+ radius: 0.006046079, tilt: 177.36, N1: 76.6799, N2: 0.0000246590,
i1: 3.3946, i2: 0.0000000275, w1: 54.8910, w2: 0.0000138374,
a1: 0.723330, a2: 0, e1: 0.006773, e2: -0.000000001302,
M1: 48.0052, M2: 1.6021302244, period: 243.0185, x: 0, y: 0, z: 0,
@@ -156,7 +158,7 @@ function loadPlanetData() {
};
planets.push(venus);
var earth = {
- radius: 6.371, tilt: 25.44, N1: 174.873, N2: 0,
+ radius: 0.006371, tilt: 25.44, N1: 174.873, N2: 0,
i1: 0.00005, i2: 0, w1: 102.94719, w2: 0,
a1: 1, a2: 0, e1: 0.01671022, e2: 0,
M1: 357.529, M2: 0.985608, period: 0.997, x: 0, y: 0, z: 0,
@@ -164,7 +166,7 @@ function loadPlanetData() {
};
planets.push(earth);
var mars = {
- radius: 3.389372, tilt: 25.19, N1: 49.5574, N2: 0.0000211081,
+ radius: 0.003389372, tilt: 25.19, N1: 49.5574, N2: 0.0000211081,
i1: 1.8497, i2: -0.0000000178, w1: 286.5016, w2: 0.0000292961,
a1: 1.523688, a2: 0, e1: 0.093405, e2: 0.000000002516,
M1: 18.6021, M2: 0.5240207766, period: 1.025957, x: 0, y: 0, z: 0,
@@ -172,7 +174,7 @@ function loadPlanetData() {
};
planets.push(mars);
var jupiter = {
- radius: 71.41254, tilt: 3.13, N1: 100.4542, N2: 0.0000276854,
+ radius: 0.07141254, tilt: 3.13, N1: 100.4542, N2: 0.0000276854,
i1: 1.3030, i2: -0.0000001557, w1: 273.8777, w2: 0.0000164505,
a1: 5.20256, a2: 0, e1: 0.048498, e2: 0.000000004469,
M1: 19.8950, M2: 0.0830853001, period: 0.4135, x: 0, y: 0, z: 0,
@@ -180,7 +182,7 @@ function loadPlanetData() {
};
planets.push(jupiter);
var saturn = {
- radius: 60.19958, tilt: 26.73, N1: 113.6634, N2: 0.0000238980,
+ radius: 0.06019958, tilt: 26.73, N1: 113.6634, N2: 0.0000238980,
i1: 2.4886, i2: -0.0000001081, w1: 339.3939, w2: 0.0000297661,
a1: 9.55475, a2: 0, e1: 0.055546, e2: -0.000000009499,
M1: 316.9670, M2: 0.0334442282, period: 0.4395, x: 0, y: 0, z: 0,
@@ -188,7 +190,7 @@ function loadPlanetData() {
};
planets.push(saturn);
var uranus = {
- radius: 25.5286, tilt: 97.77, N1: 74.0005, N2: 0.000013978,
+ radius: 0.0255286, tilt: 97.77, N1: 74.0005, N2: 0.000013978,
i1: 0.7733, i2: 0.000000019, w1: 96.6612, w2: 0.000030565,
a1: 19.18171, a2: -0.0000000155, e1: 0.047318, e2: 0.00000000745,
M1: 142.5905, M2: 0.011725806, period: 0.71833, x: 0, y: 0, z: 0,
@@ -196,7 +198,7 @@ function loadPlanetData() {
};
planets.push(uranus);
var neptune = {
- radius: 24.73859, tilt: 28.32, N1: 131.7806, N2: 0.000030173,
+ radius: 0.02473859, tilt: 28.32, N1: 131.7806, N2: 0.000030173,
i1: 1.7700, i2: -0.000000255, w1: 272.8461, w2: 0.000006027,
a1: 30.05826, a2: 0.00000003313, e1: 0.008606, e2: 0.00000000215,
M1: 260.2471, M2: 0.005995147, period: 0.6713, x: 0, y: 0, z: 0,
@@ -204,7 +206,7 @@ function loadPlanetData() {
};
planets.push(neptune);
var moon = {
- radius: 1.5424, tilt: 28.32, N1: 125.1228, N2: -0.0529538083,
+ radius: 0.0015424, tilt: 28.32, N1: 125.1228, N2: -0.0529538083,
i1: 5.1454, i2: 0, w1: 318.0634, w2: 0.1643573223,
a1: 0.273, a2: 0, e1: 0.054900, e2: 0,
M1: 115.3654, M2: 13.0649929509, period: 27.321582, x: 0, y: 0, z: 0,
@@ -224,7 +226,7 @@ function getOuterRadius(planet) {
} else if (planet === URANUS) {
outerRadius =+ uranusOuterRadius;
} else if (planet === SUN) {
- outerRadius = planets[planet]["radius"] / 100;
+ outerRadius = planets[planet]["radius"] / 10;
}
}
diff --git a/examples/qt3d/qt3d.pro b/examples/qt3d/qt3d.pro
index 776f52ced..91163a0d1 100644
--- a/examples/qt3d/qt3d.pro
+++ b/examples/qt3d/qt3d.pro
@@ -20,7 +20,9 @@ SUBDIRS += \
simplecustommaterial \
scene2d \
phong-cubes \
- pbr-materials
+ pbr-materials \
+ controlsunderlay \
+ scene3dview
qtHaveModule(multimedia): SUBDIRS += audio-visualizer-qml
diff --git a/examples/qt3d/scene3dview/AnimatedEntity.qml b/examples/qt3d/scene3dview/AnimatedEntity.qml
new file mode 100644
index 000000000..db27f3584
--- /dev/null
+++ b/examples/qt3d/scene3dview/AnimatedEntity.qml
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Input 2.14
+import Qt3D.Extras 2.14
+
+import QtQuick 2.14 as QQ2
+
+
+Entity {
+ id: sceneRoot
+ property color sceneColor
+ property bool clearColor: true
+
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 0.0, 40.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ FirstPersonCameraController { camera: camera }
+
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ camera: camera
+ clearColor: "transparent"
+ buffersToClear: sceneRoot.clearColor ? ClearBuffers.ColorDepthBuffer : ClearBuffers.DepthBuffer
+ }
+ },
+ InputSettings { }
+ ]
+
+ PhongMaterial {
+ id: material
+ diffuse: sceneColor
+ }
+
+ TorusMesh {
+ id: torusMesh
+ radius: 5
+ minorRadius: 1
+ rings: 100
+ slices: 20
+ }
+
+ Transform {
+ id: torusTransform
+ scale3D: Qt.vector3d(1.5, 1, 0.5)
+ rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45)
+ }
+
+ Entity {
+ id: torusEntity
+ components: [ torusMesh, material, torusTransform ]
+ }
+
+ SphereMesh {
+ id: sphereMesh
+ radius: 3
+ }
+
+ Transform {
+ id: sphereTransform
+ property real userAngle: 0.0
+ matrix: {
+ var m = Qt.matrix4x4();
+ m.rotate(userAngle, Qt.vector3d(0, 1, 0))
+ m.translate(Qt.vector3d(20, 0, 0));
+ return m;
+ }
+ }
+
+ QQ2.NumberAnimation {
+ target: sphereTransform
+ property: "userAngle"
+ duration: 10000
+ from: 0
+ to: 360
+
+ loops: QQ2.Animation.Infinite
+ running: true
+ }
+
+ Entity {
+ id: sphereEntity
+ components: [ sphereMesh, material, sphereTransform ]
+ }
+}
diff --git a/examples/qt3d/scene3dview/doc/images/scene3dview.png b/examples/qt3d/scene3dview/doc/images/scene3dview.png
new file mode 100644
index 000000000..d697d1850
--- /dev/null
+++ b/examples/qt3d/scene3dview/doc/images/scene3dview.png
Binary files differ
diff --git a/examples/qt3d/scene3dview/doc/src/scene3dview.qdoc b/examples/qt3d/scene3dview/doc/src/scene3dview.qdoc
new file mode 100644
index 000000000..721929350
--- /dev/null
+++ b/examples/qt3d/scene3dview/doc/src/scene3dview.qdoc
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example scene3dview
+ \title Qt 3D: Scene3DView QML Example
+ \ingroup qt3d-examples-qml
+ \brief A QML application that demonstrates visualizing multiple 3D scenes
+ using Scene3D and Scene3DView.
+
+ \image scene3dview.png
+
+ This example demonstrates visualizing multiple 3D scenes from a Qt Quick
+ application usinc Scene3D and Scene3DView. Each 3D scene contains a single
+ active camera and a single active light source. Visualized data is assumed
+ to be at a fixed location.
+
+ \include examples-run.qdocinc
+
+ \section1 Visualizing 3D Scenes
+
+ First we set up a Scene3D instance that will be required for our
+ Scene3DView instanced.
+
+ \snippet scene3dview/main.qml 0
+
+ Then we instanciate our Scene3DView instances and make them reference the
+ Scene3D. We also provide a root Entity for each Scene3DView with a \e
+ scene3dview/AnimatedEntity.qml.
+
+ \snippet scene3dview/main.qml 1
+
+ Care has to be taken that only the first Scene3DView clears the color
+ buffer. We don't want each Scene3DView to clear the screen as that would
+ erase content for all but the last Scene3DView.
+
+ \snippet scene3dview/main.qml 1.1
+*/
diff --git a/examples/qt3d/scene3dview/main.cpp b/examples/qt3d/scene3dview/main.cpp
new file mode 100644
index 000000000..8886263f4
--- /dev/null
+++ b/examples/qt3d/scene3dview/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQuickView>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ view.resize(500, 500);
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/qt3d/scene3dview/main.qml b/examples/qt3d/scene3dview/main.qml
new file mode 100644
index 000000000..d2a3fc3e0
--- /dev/null
+++ b/examples/qt3d/scene3dview/main.qml
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import QtQuick.Scene3D 2.14
+import QtQuick.Controls 2.14
+import QtQuick.Layouts 1.14
+
+Item {
+
+ //! [0]
+ Scene3D {
+ id: scene3dInstance
+ anchors.fill: parent
+ focus: true
+ aspects: ["input", "logic"]
+ cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
+ multisample: true
+ }
+ //! [0]
+
+ ColumnLayout {
+ anchors.fill: parent
+ Grid {
+ id: grid
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ columns: 2
+ rows: 2
+ spacing: 50
+
+ readonly property int cellWidth: (width - spacing ) * 0.5
+ readonly property int cellHeight: (height -spacing) * 0.5
+ readonly property var colors: ["green", "gray", "orange", "blue"]
+ readonly property int maxInstances: grid.rows * grid.columns
+
+ Repeater {
+ id: gridRepeater
+ model: grid.rows * grid.columns
+
+ //! [1]
+ Rectangle {
+ width: grid.cellWidth
+ height: grid.cellHeight
+ color: "darkRed"
+ scale: ma.pressed || ma.containsMouse ? 0.8 : 1
+ Behavior on scale { NumberAnimation { duration: 750 } }
+
+ Scene3DView {
+ onXChanged: console.log(("X (%1): %2").arg(model.index).arg(x))
+ scene3D: scene3dInstance
+ anchors.fill: parent
+ AnimatedEntity {
+ sceneColor: grid.colors[model.index]
+ //! [1.1]
+ // Only clear the color for the first Scene3DView
+ clearColor: model.index === 0
+ //! [1.1]
+ }
+ }
+ Text {
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ bottom: parent.bottom
+ }
+
+ color: "white"
+ font.bold: true
+ text: "Scene3DView " + (model.index + 1)
+ }
+
+ MouseArea {
+ id: ma
+ anchors.fill: parent
+ hoverEnabled: true
+ }
+ }
+ //! [1]
+ }
+ }
+
+ RowLayout {
+ Layout.alignment: Qt.AlignHCenter
+ Button {
+ text: "-"
+ onClicked: gridRepeater.model = Math.max(1, gridRepeater.count - 1);
+ }
+ Text { text: "Instances (%1/%2)".arg(gridRepeater.count).arg(grid.maxInstances) }
+ Button {
+ text: "+"
+ onClicked: gridRepeater.model = Math.min(grid.maxInstances, gridRepeater.count + 1);
+ }
+ }
+ }
+}
diff --git a/examples/qt3d/scene3dview/scene3dview.pro b/examples/qt3d/scene3dview/scene3dview.pro
new file mode 100644
index 000000000..4e1052b7b
--- /dev/null
+++ b/examples/qt3d/scene3dview/scene3dview.pro
@@ -0,0 +1,15 @@
+!include( ../examples.pri ) {
+ error( "Couldn't find the examples.pri file!" )
+}
+
+QT += qml quick 3dinput
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ AnimatedEntity.qml \
+ main.qml
+
+RESOURCES += \
+ scene3dview.qrc
diff --git a/examples/qt3d/scene3dview/scene3dview.qrc b/examples/qt3d/scene3dview/scene3dview.qrc
new file mode 100644
index 000000000..dff72ed5a
--- /dev/null
+++ b/examples/qt3d/scene3dview/scene3dview.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>AnimatedEntity.qml</file>
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc b/examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc
index d10927d39..7ec7c7abb 100644
--- a/examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc
+++ b/examples/qt3d/simplecustommaterial/doc/src/simplecustommaterial.qdoc
@@ -48,7 +48,7 @@
\section1 Specifying the Material
- The material is specified in \l{simplecustommaterial/SimpleMaterial.qml}{SimpleMaterial.qml}
+ The material is specified in \c {simplecustommaterial/SimpleMaterial.qml}
using \l Material type. First the material specifies parameters,
which are mapped to the corresponding uniforms in the shaders so that they can be
changed from the qml.
diff --git a/src/animation/animation.pro b/src/animation/animation.pro
index b7d08416c..9c5db68f2 100644
--- a/src/animation/animation.pro
+++ b/src/animation/animation.pro
@@ -4,9 +4,6 @@ DEFINES += QT3DANIMATION_LIBRARY
MODULE = 3danimation
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
QT += core-private 3dcore-private 3drender 3drender-private
include(frontend/frontend.pri)
diff --git a/src/animation/backend/abstractevaluateclipanimatorjob.cpp b/src/animation/backend/abstractevaluateclipanimatorjob.cpp
new file mode 100644
index 000000000..e3c8e9e40
--- /dev/null
+++ b/src/animation/backend/abstractevaluateclipanimatorjob.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractevaluateclipanimatorjob_p.h"
+#include <Qt3DCore/private/qaspectjob_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qskeleton_p.h>
+#include <Qt3DAnimation/qabstractclipanimator.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Animation {
+
+class AbstractEvaluateClipAnimatorJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ AbstractEvaluateClipAnimatorJobPrivate() { }
+ ~AbstractEvaluateClipAnimatorJobPrivate() override { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ AnimationRecord m_record;
+ QVector<AnimationCallbackAndValue> m_callbacks;
+};
+
+AbstractEvaluateClipAnimatorJob::AbstractEvaluateClipAnimatorJob()
+ : Qt3DCore::QAspectJob(*new AbstractEvaluateClipAnimatorJobPrivate)
+{
+}
+
+void AbstractEvaluateClipAnimatorJob::setPostFrameData(const AnimationRecord &record, const QVector<AnimationCallbackAndValue> &callbacks)
+{
+ auto mainThreadCB = callbacks;
+ mainThreadCB.erase(std::remove_if(mainThreadCB.begin(), mainThreadCB.end(), [](const AnimationCallbackAndValue &callback) {
+ if (callback.flags.testFlag(QAnimationCallback::OnThreadPool)) {
+ // call these now and remove them from the list
+ callback.callback->valueChanged(callback.value);
+ return true;
+ }
+ return false;
+ }), mainThreadCB.end());
+ // Should now only have callbacks to be called on main thread
+
+ Q_DJOB(AbstractEvaluateClipAnimatorJob);
+ d->m_record = record;
+ d->m_callbacks = mainThreadCB;
+}
+
+void AbstractEvaluateClipAnimatorJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ if (m_record.animatorId.isNull())
+ return;
+
+ for (auto targetData : qAsConst(m_record.targetChanges)) {
+ Qt3DCore::QNode *node = manager->lookupNode(targetData.targetId);
+ if (node)
+ node->setProperty(targetData.propertyName, targetData.value);
+ }
+
+ for (auto skeletonData : qAsConst(m_record.skeletonChanges)) {
+ Qt3DCore::QAbstractSkeleton *node = qobject_cast<Qt3DCore::QAbstractSkeleton *>(manager->lookupNode(skeletonData.first));
+ if (node) {
+ auto d = Qt3DCore::QAbstractSkeletonPrivate::get(node);
+ d->m_localPoses = skeletonData.second;
+ d->update();
+ }
+ }
+
+ QAbstractClipAnimator *animator = qobject_cast<QAbstractClipAnimator *>(manager->lookupNode(m_record.animatorId));
+ if (animator) {
+ if (isValidNormalizedTime(m_record.normalizedTime))
+ animator->setNormalizedTime(m_record.normalizedTime);
+ if (m_record.finalFrame)
+ animator->setRunning(false);
+ }
+
+ for (const AnimationCallbackAndValue &callback: qAsConst(m_callbacks)) {
+ if (callback.callback)
+ callback.callback->valueChanged(callback.value);
+ }
+
+ m_record = {};
+}
+
+} // Animation
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/backend/abstractevaluateclipanimatorjob_p.h b/src/animation/backend/abstractevaluateclipanimatorjob_p.h
new file mode 100644
index 000000000..7027a8639
--- /dev/null
+++ b/src/animation/backend/abstractevaluateclipanimatorjob_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_ANIMATION_ABSTRACTEVALUATECLIPANIMATORJOB_P_H
+#define QT3DANIMATION_ANIMATION_ABSTRACTEVALUATECLIPANIMATORJOB_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DAnimation/private/animationutils_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+namespace Animation {
+
+class AbstractEvaluateClipAnimatorJobPrivate;
+
+class AbstractEvaluateClipAnimatorJob : public Qt3DCore::QAspectJob
+{
+protected:
+ AbstractEvaluateClipAnimatorJob();
+
+ void setPostFrameData(const AnimationRecord &record, const QVector<AnimationCallbackAndValue> &callbacks);
+};
+
+} // Animation
+} // Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_ANIMATION_ABSTRACTEVALUATECLIPANIMATORJOB_P_H
diff --git a/src/animation/backend/additiveclipblend.cpp b/src/animation/backend/additiveclipblend.cpp
index ac8b849e2..b89a1bbb2 100644
--- a/src/animation/backend/additiveclipblend.cpp
+++ b/src/animation/backend/additiveclipblend.cpp
@@ -35,10 +35,8 @@
****************************************************************************/
#include "additiveclipblend_p.h"
-#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
#include <Qt3DAnimation/qadditiveclipblend.h>
#include <Qt3DAnimation/private/qadditiveclipblend_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -58,17 +56,16 @@ AdditiveClipBlend::~AdditiveClipBlend()
{
}
-void AdditiveClipBlend::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void AdditiveClipBlend::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("additiveFactor"))
- m_additiveFactor = change->value().toFloat();
- else if (change->propertyName() == QByteArrayLiteral("baseClip"))
- m_baseClipId = change->value().value<Qt3DCore::QNodeId>();
- else if (change->propertyName() == QByteArrayLiteral("additiveClip"))
- m_additiveClipId = change->value().value<Qt3DCore::QNodeId>();
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAdditiveClipBlend *node = qobject_cast<const QAdditiveClipBlend *>(frontEnd);
+ if (!node)
+ return;
+
+ m_additiveFactor = node->additiveFactor();
+ m_baseClipId = Qt3DCore::qIdForNode(node->baseClip());
+ m_additiveClipId = Qt3DCore::qIdForNode(node->additiveClip());
}
ClipResults AdditiveClipBlend::doBlend(const QVector<ClipResults> &blendData) const
@@ -84,16 +81,6 @@ ClipResults AdditiveClipBlend::doBlend(const QVector<ClipResults> &blendData) co
return blendResults;
}
-void AdditiveClipBlend::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- ClipBlendNode::initializeFromPeer(change);
- const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QAdditiveClipBlendData>>(change);
- const Qt3DAnimation::QAdditiveClipBlendData cloneData = creationChangeData->data;
- m_baseClipId = cloneData.baseClipId;
- m_additiveClipId = cloneData.additiveClipId;
- m_additiveFactor = cloneData.additiveFactor;
-}
-
} // Animation
} // Qt3DAnimation
diff --git a/src/animation/backend/additiveclipblend_p.h b/src/animation/backend/additiveclipblend_p.h
index 0cf74ad56..48e882303 100644
--- a/src/animation/backend/additiveclipblend_p.h
+++ b/src/animation/backend/additiveclipblend_p.h
@@ -71,7 +71,7 @@ public:
inline float additiveFactor() const { return m_additiveFactor; }
void setAdditiveFactor(float additiveFactor) { m_additiveFactor = additiveFactor; } // For unit tests
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final;
inline QVector<Qt3DCore::QNodeId> allDependencyIds() const override
{
@@ -94,8 +94,6 @@ protected:
ClipResults doBlend(const QVector<ClipResults> &blendData) const final;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_baseClipId;
Qt3DCore::QNodeId m_additiveClipId;
float m_additiveFactor;
diff --git a/src/animation/backend/animationclip.cpp b/src/animation/backend/animationclip.cpp
index 3e0b8ce2b..2c7e4fffb 100644
--- a/src/animation/backend/animationclip.cpp
+++ b/src/animation/backend/animationclip.cpp
@@ -43,7 +43,6 @@
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/gltfimporter_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qfile.h>
@@ -69,32 +68,10 @@ AnimationClip::AnimationClip()
, m_name()
, m_channels()
, m_duration(0.0f)
+ , m_channelComponentCount(0)
{
}
-void AnimationClip::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto loaderTypedChange = qSharedPointerDynamicCast<Qt3DCore::QNodeCreatedChange<QAnimationClipLoaderData>>(change);
- if (loaderTypedChange) {
- const auto &data = loaderTypedChange->data;
- m_dataType = File;
- m_source = data.source;
- if (!m_source.isEmpty())
- setDirty(Handler::AnimationClipDirty);
- return;
- }
-
- const auto clipTypedChange = qSharedPointerDynamicCast<Qt3DCore::QNodeCreatedChange<QAnimationClipChangeData>>(change);
- if (clipTypedChange) {
- const auto &data = clipTypedChange->data;
- m_dataType = Data;
- m_clipData = data.clipData;
- if (m_clipData.isValid())
- setDirty(Handler::AnimationClipDirty);
- return;
- }
-}
-
void AnimationClip::cleanup()
{
setEnabled(false);
@@ -105,6 +82,7 @@ void AnimationClip::cleanup()
m_dataType = Unknown;
m_channels.clear();
m_duration = 0.0f;
+ m_channelComponentCount = 0;
clearData();
}
@@ -113,36 +91,39 @@ void AnimationClip::setStatus(QAnimationClipLoader::Status status)
{
if (status != m_status) {
m_status = status;
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("status");
- e->setValue(QVariant::fromValue(m_status));
- notifyObservers(e);
}
}
-void AnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void AnimationClip::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("source")) {
- Q_ASSERT(m_dataType == File);
- m_source = change->value().toUrl();
- setDirty(Handler::AnimationClipDirty);
- } else if (change->propertyName() == QByteArrayLiteral("clipData")) {
- Q_ASSERT(m_dataType == Data);
- m_clipData = change->value().value<Qt3DAnimation::QAnimationClipData>();
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAbstractAnimationClip *node = qobject_cast<const QAbstractAnimationClip *>(frontEnd);
+ if (!node)
+ return;
+
+ const QAnimationClip *clipNode = qobject_cast<const QAnimationClip *>(frontEnd);
+ if (clipNode) {
+ if (firstTime)
+ m_dataType = Data;
+ Q_ASSERT(m_dataType == Data);
+ if (m_clipData != clipNode->clipData()) {
+ m_clipData = clipNode->clipData();
if (m_clipData.isValid())
setDirty(Handler::AnimationClipDirty);
}
- break;
}
- default:
- break;
+ const QAnimationClipLoader *loaderNode = qobject_cast<const QAnimationClipLoader *>(frontEnd);
+ if (loaderNode) {
+ if (firstTime)
+ m_dataType = File;
+ Q_ASSERT(m_dataType == File);
+ if (m_source != loaderNode->source()) {
+ m_source = loaderNode->source();
+ if (!m_source.isEmpty())
+ setDirty(Handler::AnimationClipDirty);
+ }
}
- QBackendNode::sceneChangeEvent(e);
}
/*!
@@ -332,13 +313,6 @@ void AnimationClip::setDuration(float duration)
return;
m_duration = duration;
-
- // Send a change to the frontend
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("duration");
- e->setValue(m_duration);
- notifyObservers(e);
}
int AnimationClip::channelIndex(const QString &channelName, int jointIndex) const
diff --git a/src/animation/backend/animationclip_p.h b/src/animation/backend/animationclip_p.h
index 0b8298723..22f589f72 100644
--- a/src/animation/backend/animationclip_p.h
+++ b/src/animation/backend/animationclip_p.h
@@ -72,7 +72,7 @@ public:
QUrl source() const { return m_source; }
void setStatus(QAnimationClipLoader::Status status);
QAnimationClipLoader::Status status() const { return m_status; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void addDependingClipAnimator(const Qt3DCore::QNodeId &id);
void addDependingBlendedClipAnimator(const Qt3DCore::QNodeId &id);
@@ -103,7 +103,6 @@ public:
#endif
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
void loadAnimationFromUrl();
void loadAnimationFromData();
void clearData();
diff --git a/src/animation/backend/animationutils.cpp b/src/animation/backend/animationutils.cpp
index 92e614236..80c296a89 100644
--- a/src/animation/backend/animationutils.cpp
+++ b/src/animation/backend/animationutils.cpp
@@ -40,8 +40,6 @@
#include <Qt3DAnimation/private/clipblendnode_p.h>
#include <Qt3DAnimation/private/clipblendnodevisitor_p.h>
#include <Qt3DAnimation/private/clipblendvalue_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <QtGui/qvector2d.h>
#include <QtGui/qvector3d.h>
#include <QtGui/qvector4d.h>
@@ -407,13 +405,17 @@ QVariant buildPropertyValue(const MappingData &mappingData, const QVector<float>
return QVariant();
}
-QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId animatorId,
- const QVector<MappingData> &mappingDataVec,
- const QVector<float> &channelResults,
- bool finalFrame,
- float normalizedLocalTime)
+AnimationRecord prepareAnimationRecord(Qt3DCore::QNodeId animatorId,
+ const QVector<MappingData> &mappingDataVec,
+ const QVector<float> &channelResults,
+ bool finalFrame,
+ float normalizedLocalTime)
{
- QVector<Qt3DCore::QSceneChangePtr> changes;
+ AnimationRecord record;
+ record.finalFrame = finalFrame;
+ record.animatorId = animatorId;
+ record.normalizedTime = normalizedLocalTime;
+
QVarLengthArray<Skeleton *, 4> dirtySkeletons;
// Iterate over the mappings
@@ -453,40 +455,14 @@ QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId anim
break;
}
} else {
- // Construct a property update change, set target, property and delivery options
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(mappingData.targetId);
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName(mappingData.propertyName);
- // Handle intermediate updates vs final flag properly
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isIntermediate = !finalFrame;
- // Assign new value and send
- e->setValue(v);
- changes.push_back(e);
+ record.targetChanges.push_back({mappingData.targetId, mappingData.propertyName, v});
}
}
for (const auto skeleton : dirtySkeletons)
- skeleton->sendLocalPoses();
-
- if (isValidNormalizedTime(normalizedLocalTime)) {
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId);
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("normalizedTime");
- e->setValue(normalizedLocalTime);
- Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(e.data())->m_isIntermediate = !finalFrame;
- changes.push_back(e);
- }
-
- // If it's the final frame, notify the frontend that we've stopped
- if (finalFrame) {
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId);
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("running");
- e->setValue(false);
- changes.push_back(e);
- }
+ record.skeletonChanges.push_back({skeleton->peerId(), skeleton->joints()});
- return changes;
+ return record;
}
QVector<AnimationCallbackAndValue> prepareCallbacks(const QVector<MappingData> &mappingDataVec,
diff --git a/src/animation/backend/animationutils_p.h b/src/animation/backend/animationutils_p.h
index bded12bd2..eab15f0e5 100644
--- a/src/animation/backend/animationutils_p.h
+++ b/src/animation/backend/animationutils_p.h
@@ -53,6 +53,7 @@
#include <Qt3DAnimation/qanimationcallback.h>
#include <Qt3DCore/qnodeid.h>
#include <Qt3DCore/qscenechange.h>
+#include <Qt3DCore/private/sqt_p.h>
#include <QtCore/qbitarray.h>
#include <QtCore/qdebug.h>
@@ -183,7 +184,7 @@ struct ChannelNameAndType
case Rotation:
componentCount = 4;
break;
- };
+ }
}
bool operator==(const ChannelNameAndType &rhs) const
@@ -264,6 +265,32 @@ struct AnimationCallbackAndValue
QVariant value;
};
+struct AnimationRecord {
+ struct TargetChange {
+ TargetChange(Qt3DCore::QNodeId id, const char *name, QVariant v)
+ : targetId(id), propertyName(name), value(v) {
+
+ }
+
+ Qt3DCore::QNodeId targetId;
+ const char *propertyName = nullptr;
+ QVariant value;
+ };
+
+ Qt3DCore::QNodeId animatorId;
+ QVector<TargetChange> targetChanges;
+ QVector<QPair<Qt3DCore::QNodeId, QVector<Qt3DCore::Sqt>>> skeletonChanges;
+ float normalizedTime = -1.f;
+ bool finalFrame = false;
+};
+
+Q_AUTOTEST_EXPORT
+AnimationRecord prepareAnimationRecord(Qt3DCore::QNodeId animatorId,
+ const QVector<MappingData> &mappingDataVec,
+ const QVector<float> &channelResults,
+ bool finalFrame,
+ float normalizedLocalTime);
+
inline constexpr double toSecs(qint64 nsecs) { return nsecs / 1.0e9; }
inline qint64 toNsecs(double seconds) { return qRound64(seconds * 1.0e9); }
@@ -328,12 +355,6 @@ ClipResults evaluateClipAtPhase(AnimationClip *clip,
float phase);
Q_AUTOTEST_EXPORT
-QVector<Qt3DCore::QSceneChangePtr> preparePropertyChanges(Qt3DCore::QNodeId animatorId,
- const QVector<MappingData> &mappingDataVec,
- const QVector<float> &channelResults,
- bool finalFrame, float normalizedLocalTime);
-
-Q_AUTOTEST_EXPORT
QVector<AnimationCallbackAndValue> prepareCallbacks(const QVector<MappingData> &mappingDataVec,
const QVector<float> &channelResults);
@@ -390,5 +411,7 @@ void applyComponentDefaultValues(const QVector<ComponentValue> &componentDefault
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(Qt3DAnimation::Animation::AnimationRecord) // LCOV_EXCL_LINE
+
#endif // QT3DANIMATION_ANIMATION_ANIMATIONUTILS_P_H
diff --git a/src/animation/backend/backend.pri b/src/animation/backend/backend.pri
index cc1104102..ef7da55f0 100644
--- a/src/animation/backend/backend.pri
+++ b/src/animation/backend/backend.pri
@@ -17,6 +17,7 @@ HEADERS += \
$$PWD/channelmapping_p.h \
$$PWD/channelmapper_p.h \
$$PWD/findrunningclipanimatorsjob_p.h \
+ $$PWD/abstractevaluateclipanimatorjob_p.h \
$$PWD/evaluateclipanimatorjob_p.h \
$$PWD/clipblendnode_p.h \
$$PWD/clipblendnodevisitor_p.h \
@@ -43,6 +44,7 @@ SOURCES += \
$$PWD/channelmapping.cpp \
$$PWD/channelmapper.cpp \
$$PWD/findrunningclipanimatorsjob.cpp \
+ $$PWD/abstractevaluateclipanimatorjob.cpp \
$$PWD/evaluateclipanimatorjob.cpp \
$$PWD/clipblendnode.cpp \
$$PWD/managers.cpp \
diff --git a/src/animation/backend/backendnode.cpp b/src/animation/backend/backendnode.cpp
index 6ea7f89c7..f44836a67 100644
--- a/src/animation/backend/backendnode.cpp
+++ b/src/animation/backend/backendnode.cpp
@@ -38,6 +38,8 @@
****************************************************************************/
#include "backendnode_p.h"
+#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/private/qbackendnode_p.h>
QT_BEGIN_NAMESPACE
@@ -65,6 +67,13 @@ void BackendNode::setDirty(Handler::DirtyFlag flag)
m_handler->setDirty(flag, peerId());
}
+void BackendNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
+{
+ Q_UNUSED(firstTime)
+
+ d_ptr->setEnabled(frontEnd->isEnabled());
+}
+
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/backendnode_p.h b/src/animation/backend/backendnode_p.h
index d7842517a..4e450b6ec 100644
--- a/src/animation/backend/backendnode_p.h
+++ b/src/animation/backend/backendnode_p.h
@@ -68,6 +68,8 @@ public:
void setHandler(Handler *handler);
+ virtual void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime);
+
protected:
void setDirty(Handler::DirtyFlag flag);
Handler *m_handler;
diff --git a/src/animation/backend/blendedclipanimator.cpp b/src/animation/backend/blendedclipanimator.cpp
index fe8a5d815..7d771745b 100644
--- a/src/animation/backend/blendedclipanimator.cpp
+++ b/src/animation/backend/blendedclipanimator.cpp
@@ -36,9 +36,10 @@
#include "blendedclipanimator_p.h"
#include <Qt3DAnimation/qblendedclipanimator.h>
+#include <Qt3DAnimation/qchannelmapper.h>
+#include <Qt3DAnimation/qclock.h>
+#include <Qt3DAnimation/qabstractclipblendnode.h>
#include <Qt3DAnimation/private/qblendedclipanimator_p.h>
-#include <Qt3DAnimation/private/qanimationcallbacktrigger_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -57,19 +58,6 @@ BlendedClipAnimator::BlendedClipAnimator()
{
}
-void BlendedClipAnimator::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QBlendedClipAnimatorData>>(change);
- const QBlendedClipAnimatorData &data = typedChange->data;
- m_blendTreeRootId = data.blendTreeRootId;
- m_mapperId = data.mapperId;
- m_clockId = data.clockId;
- m_running = data.running;
- m_loops = data.loops;
- m_normalizedLocalTime = data.normalizedTime;
- setDirty(Handler::BlendedClipAnimatorDirty);
-}
-
double BlendedClipAnimator::lastLocalTime() const
{
return m_lastLocalTime;
@@ -133,27 +121,6 @@ void BlendedClipAnimator::setRunning(bool running)
setDirty(Handler::BlendedClipAnimatorDirty);
}
-void BlendedClipAnimator::sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes)
-{
- for (const Qt3DCore::QSceneChangePtr &change : changes)
- notifyObservers(change);
-}
-
-void BlendedClipAnimator::sendCallbacks(const QVector<AnimationCallbackAndValue> &callbacks)
-{
- for (const AnimationCallbackAndValue &callback : callbacks) {
- if (callback.flags.testFlag(QAnimationCallback::OnThreadPool)) {
- callback.callback->valueChanged(callback.value);
- } else {
- auto e = QAnimationCallbackTriggerPtr::create(peerId());
- e->setCallback(callback.callback);
- e->setValue(callback.value);
- e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- notifyObservers(e);
- }
- }
-}
-
Qt3DCore::QNodeId BlendedClipAnimator::blendTreeRootId() const
{
@@ -167,30 +134,32 @@ void BlendedClipAnimator::setNormalizedLocalTime(float normalizedTime)
setDirty(Handler::BlendedClipAnimatorDirty);
}
-void BlendedClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void BlendedClipAnimator::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("blendTree"))
- setBlendTreeRootId(change->value().value<Qt3DCore::QNodeId>());
- else if (change->propertyName() == QByteArrayLiteral("channelMapper"))
- setMapperId(change->value().value<Qt3DCore::QNodeId>());
- else if (change->propertyName() == QByteArrayLiteral("clock"))
- setClockId(change->value().value<Qt3DCore::QNodeId>());
- else if (change->propertyName() == QByteArrayLiteral("running"))
- setRunning(change->value().toBool());
- else if (change->propertyName() == QByteArrayLiteral("loops"))
- m_loops = change->value().toInt();
- else if (change->propertyName() == QByteArrayLiteral("normalizedTime"))
- setNormalizedLocalTime(change->value().toFloat());
- break;
- }
-
- default:
- break;
- }
- BackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QBlendedClipAnimator *node = qobject_cast<const QBlendedClipAnimator *>(frontEnd);
+ if (!node)
+ return;
+
+ auto id = Qt3DCore::qIdForNode(node->blendTree());
+ if (id != m_blendTreeRootId)
+ setBlendTreeRootId(id);
+ id = Qt3DCore::qIdForNode(node->channelMapper());
+ if (m_mapperId != id)
+ setMapperId(id);
+ id = Qt3DCore::qIdForNode(node->clock());
+ if (m_clockId != id)
+ setClockId(id);
+
+ if (m_running != node->isRunning())
+ setRunning(node->isRunning());
+ if (m_loops != node->loopCount())
+ m_loops = node->loopCount();
+ if (!qFuzzyCompare(m_normalizedLocalTime, node->normalizedTime()))
+ setNormalizedLocalTime(node->normalizedTime());
+
+ if (firstTime)
+ setDirty(Handler::BlendedClipAnimatorDirty);
}
} // namespace Animation
diff --git a/src/animation/backend/blendedclipanimator_p.h b/src/animation/backend/blendedclipanimator_p.h
index 09a071c06..04f609438 100644
--- a/src/animation/backend/blendedclipanimator_p.h
+++ b/src/animation/backend/blendedclipanimator_p.h
@@ -64,7 +64,7 @@ public:
BlendedClipAnimator();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
Qt3DCore::QNodeId blendTreeRootId() const;
Qt3DCore::QNodeId mapperId() const { return m_mapperId; }
@@ -92,9 +92,6 @@ public:
void setMappingData(const QVector<MappingData> &mappingData) { m_mappingData = mappingData; }
QVector<MappingData> mappingData() const { return m_mappingData; }
- void sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes);
- void sendCallbacks(const QVector<AnimationCallbackAndValue> &callbacks);
-
void animationClipMarkedDirty() { setDirty(Handler::BlendedClipAnimatorDirty); }
qint64 nsSincePreviousFrame(qint64 currentGlobalTimeNS);
@@ -112,7 +109,6 @@ public:
}
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
Qt3DCore::QNodeId m_blendTreeRootId;
Qt3DCore::QNodeId m_mapperId;
Qt3DCore::QNodeId m_clockId;
diff --git a/src/animation/backend/buildblendtreesjob.cpp b/src/animation/backend/buildblendtreesjob.cpp
index be96889fa..b4cc04323 100644
--- a/src/animation/backend/buildblendtreesjob.cpp
+++ b/src/animation/backend/buildblendtreesjob.cpp
@@ -50,8 +50,9 @@ namespace Animation {
BuildBlendTreesJob::BuildBlendTreesJob()
: Qt3DCore::QAspectJob()
+ , m_handler(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::BuildBlendTree, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::BuildBlendTree, 0)
}
void BuildBlendTreesJob::setBlendedClipAnimators(const QVector<HBlendedClipAnimator> &blendedClipAnimatorHandles)
@@ -86,7 +87,8 @@ void BuildBlendTreesJob::run()
// Build the format for clip results that should be used by nodes in the blend
// tree when used with this animator
const ChannelMapper *mapper = m_handler->channelMapperManager()->lookupResource(blendClipAnimator->mapperId());
- Q_ASSERT(mapper);
+ if (!mapper)
+ continue;
const QVector<ChannelNameAndType> channelNamesAndTypes
= buildRequiredChannelsAndTypes(m_handler, mapper);
const QVector<ComponentIndices> channelComponentIndices
diff --git a/src/animation/backend/channelmapper.cpp b/src/animation/backend/channelmapper.cpp
index 48a1335fa..e5d4eb009 100644
--- a/src/animation/backend/channelmapper.cpp
+++ b/src/animation/backend/channelmapper.cpp
@@ -36,12 +36,12 @@
#include "channelmapper_p.h"
#include <Qt3DAnimation/qchannelmapper.h>
+#include <Qt3DAnimation/qchannelmapping.h>
#include <Qt3DAnimation/private/qchannelmapper_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DAnimation/private/managers_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
+
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -55,14 +55,6 @@ ChannelMapper::ChannelMapper()
{
}
-void ChannelMapper::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QChannelMapperData>>(change);
- const auto &data = typedChange->data;
- m_mappingIds = data.mappingIds;
- m_isDirty = true;
-}
-
void ChannelMapper::cleanup()
{
setEnabled(false);
@@ -71,33 +63,21 @@ void ChannelMapper::cleanup()
m_isDirty = true;
}
-void ChannelMapper::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void ChannelMapper::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("mappings")) {
- m_mappingIds.push_back(change->addedNodeId());
- setDirty(Handler::ChannelMappingsDirty);
- m_isDirty = true;
- }
- break;
- }
-
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("mappings")) {
- m_mappingIds.removeOne(change->removedNodeId());
- setDirty(Handler::ChannelMappingsDirty);
- m_isDirty = true;
- }
- break;
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QChannelMapper *node = qobject_cast<const QChannelMapper *>(frontEnd);
+ if (!node)
+ return;
- default:
- break;
+ auto ids = Qt3DCore::qIdsForNodes(node->mappings());
+ std::sort(std::begin(ids), std::end(ids));
+ m_isDirty = firstTime;
+ if (m_mappingIds != ids) {
+ m_mappingIds = ids;
+ setDirty(Handler::ChannelMappingsDirty);
+ m_isDirty = true;
}
- QBackendNode::sceneChangeEvent(e);
}
void ChannelMapper::updateMappings() const
diff --git a/src/animation/backend/channelmapper_p.h b/src/animation/backend/channelmapper_p.h
index fd99c8dbd..45a3e789e 100644
--- a/src/animation/backend/channelmapper_p.h
+++ b/src/animation/backend/channelmapper_p.h
@@ -69,7 +69,7 @@ public:
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void setMappingIds(const QVector<Qt3DCore::QNodeId> &mappingIds) { m_mappingIds = mappingIds; }
QVector<Qt3DCore::QNodeId> mappingIds() const { return m_mappingIds; }
@@ -82,7 +82,6 @@ public:
}
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
void updateMappings() const;
QVector<Qt3DCore::QNodeId> m_mappingIds;
diff --git a/src/animation/backend/channelmapping.cpp b/src/animation/backend/channelmapping.cpp
index 2323182c6..42942fdd3 100644
--- a/src/animation/backend/channelmapping.cpp
+++ b/src/animation/backend/channelmapping.cpp
@@ -36,13 +36,15 @@
#include "channelmapping_p.h"
#include <Qt3DAnimation/qchannelmapping.h>
+#include <Qt3DAnimation/qskeletonmapping.h>
+#include <Qt3DAnimation/qcallbackmapping.h>
#include <Qt3DAnimation/private/qcallbackmapping_p.h>
#include <Qt3DAnimation/private/qchannelmapping_p.h>
#include <Qt3DAnimation/private/qskeletonmapping_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h>
#include <Qt3DAnimation/private/managers_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qabstractskeleton.h>
QT_BEGIN_NAMESPACE
@@ -63,43 +65,6 @@ ChannelMapping::ChannelMapping()
{
}
-void ChannelMapping::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto createdChange = qSharedPointerCast<QChannelMappingCreatedChangeBase>(change);
- switch (createdChange->type()) {
- case QChannelMappingCreatedChangeBase::ChannelMapping: {
- const auto typedChange = qSharedPointerCast<QChannelMappingCreatedChange<QChannelMappingData>>(change);
- const auto &data = typedChange->data;
- m_channelName = data.channelName;
- m_targetId = data.targetId;
- m_type = data.type;
- m_componentCount = data.componentCount;
- m_propertyName = data.propertyName;
- m_mappingType = ChannelMappingType;
- break;
- }
-
- case QChannelMappingCreatedChangeBase::SkeletonMapping: {
- const auto typedChange = qSharedPointerCast<QChannelMappingCreatedChange<QSkeletonMappingData>>(change);
- const auto &data = typedChange->data;
- m_skeletonId = data.skeletonId;
- m_mappingType = SkeletonMappingType;
- break;
- }
-
- case QChannelMappingCreatedChangeBase::CallbackMapping: {
- const auto typedChange = qSharedPointerCast<QChannelMappingCreatedChange<QCallbackMappingData>>(change);
- const auto &data = typedChange->data;
- m_channelName = data.channelName;
- m_type = data.type;
- m_callback = data.callback;
- m_callbackFlags = data.callbackFlags;
- m_mappingType = ChannelMappingType;
- break;
- }
- }
-}
-
void ChannelMapping::cleanup()
{
setEnabled(false);
@@ -113,34 +78,41 @@ void ChannelMapping::cleanup()
m_skeletonId = Qt3DCore::QNodeId();
}
-void ChannelMapping::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void ChannelMapping::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("channelName"))
- m_channelName = change->value().toString();
- else if (change->propertyName() == QByteArrayLiteral("target"))
- m_targetId = change->value().value<Qt3DCore::QNodeId>();
- else if (change->propertyName() == QByteArrayLiteral("type"))
- m_type = change->value().toInt();
- else if (change->propertyName() == QByteArrayLiteral("propertyName"))
- m_propertyName = static_cast<const char *>(const_cast<const void *>(change->value().value<void *>()));
- else if (change->propertyName() == QByteArrayLiteral("componentCount"))
- m_componentCount = change->value().toInt();
- else if (change->propertyName() == QByteArrayLiteral("callback"))
- m_callback = static_cast<QAnimationCallback *>(change->value().value<void *>());
- else if (change->propertyName() == QByteArrayLiteral("callbackFlags"))
- m_callbackFlags = QAnimationCallback::Flags(change->value().toInt());
- else if (change->propertyName() == QByteArrayLiteral("skeleton"))
- m_skeletonId = change->value().value<Qt3DCore::QNodeId>();
- break;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAbstractChannelMapping *node = qobject_cast<const QAbstractChannelMapping *>(frontEnd);
+ if (!node)
+ return;
+
+ const QChannelMapping *channelMapping = qobject_cast<const QChannelMapping *>(frontEnd);
+ if (channelMapping) {
+ m_mappingType = ChannelMappingType;
+ m_channelName = channelMapping->channelName();
+ m_targetId = Qt3DCore::qIdForNode(channelMapping->target());
+
+ QChannelMappingPrivate *d = static_cast<QChannelMappingPrivate *>(Qt3DCore::QNodePrivate::get(const_cast<QChannelMapping *>(channelMapping)));
+ m_type = d->m_type;
+ m_propertyName = d->m_propertyName;
+ m_componentCount = d->m_componentCount;
}
- default:
- break;
+ const QSkeletonMapping *skeletonMapping = qobject_cast<const QSkeletonMapping *>(frontEnd);
+ if (skeletonMapping) {
+ m_mappingType = SkeletonMappingType;
+ m_skeletonId = Qt3DCore::qIdForNode(skeletonMapping->skeleton());
+ }
+
+ const QCallbackMapping *callbackMapping = qobject_cast<const QCallbackMapping *>(frontEnd);
+ if (callbackMapping) {
+ m_mappingType = ChannelMappingType;
+ m_channelName = callbackMapping->channelName();
+
+ const QCallbackMappingPrivate *d = static_cast<const QCallbackMappingPrivate *>(Qt3DCore::QNodePrivate::get(callbackMapping));
+ m_type = d->m_type;
+ m_callback = d->m_callback;
+ m_callbackFlags = d->m_callbackFlags;
}
- QBackendNode::sceneChangeEvent(e);
}
Skeleton *ChannelMapping::skeleton() const
diff --git a/src/animation/backend/channelmapping_p.h b/src/animation/backend/channelmapping_p.h
index aa30e84ee..a0ff5f1ca 100644
--- a/src/animation/backend/channelmapping_p.h
+++ b/src/animation/backend/channelmapping_p.h
@@ -76,7 +76,7 @@ public:
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void setChannelName(const QString &channelName) { m_channelName = channelName; }
QString channelName() const { return m_channelName; }
@@ -107,8 +107,6 @@ public:
MappingType mappingType() const { return m_mappingType; }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
// Properties from QChannelMapping
QString m_channelName;
Qt3DCore::QNodeId m_targetId;
diff --git a/src/animation/backend/clipanimator.cpp b/src/animation/backend/clipanimator.cpp
index acb3c8170..32b02d2bb 100644
--- a/src/animation/backend/clipanimator.cpp
+++ b/src/animation/backend/clipanimator.cpp
@@ -36,13 +36,12 @@
#include "clipanimator_p.h"
#include <Qt3DAnimation/qclipanimator.h>
+#include <Qt3DAnimation/qchannelmapper.h>
+#include <Qt3DAnimation/qclock.h>
#include <Qt3DAnimation/private/qclipanimator_p.h>
#include <Qt3DAnimation/private/animationclip_p.h>
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
-#include <Qt3DAnimation/private/qanimationcallbacktrigger_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
@@ -65,19 +64,6 @@ ClipAnimator::ClipAnimator()
{
}
-void ClipAnimator::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QClipAnimatorData>>(change);
- const auto &data = typedChange->data;
- m_clipId = data.clipId;
- m_mapperId = data.mapperId;
- m_clockId = data.clockId;
- m_running = data.running;
- m_loops = data.loops;
- m_normalizedLocalTime = data.normalizedTime;
- setDirty(Handler::ClipAnimatorDirty);
-}
-
void ClipAnimator::setClipId(Qt3DCore::QNodeId clipId)
{
m_clipId = clipId;
@@ -129,51 +115,32 @@ void ClipAnimator::cleanup()
m_normalizedLocalTime = m_lastNormalizedLocalTime = -1.0f;
}
-void ClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void ClipAnimator::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("clip"))
- setClipId(change->value().value<Qt3DCore::QNodeId>());
- else if (change->propertyName() == QByteArrayLiteral("channelMapper"))
- setMapperId(change->value().value<Qt3DCore::QNodeId>());
- else if (change->propertyName() == QByteArrayLiteral("clock"))
- setClockId(change->value().value<Qt3DCore::QNodeId>());
- else if (change->propertyName() == QByteArrayLiteral("running"))
- setRunning(change->value().toBool());
- else if (change->propertyName() == QByteArrayLiteral("loops"))
- m_loops = change->value().toInt();
- else if (change->propertyName() == QByteArrayLiteral("normalizedTime"))
- setNormalizedLocalTime(change->value().toFloat());
- break;
- }
-
- default:
- break;
- }
- QBackendNode::sceneChangeEvent(e);
-}
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QClipAnimator *node = qobject_cast<const QClipAnimator *>(frontEnd);
+ if (!node)
+ return;
-void ClipAnimator::sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes)
-{
- for (const Qt3DCore::QSceneChangePtr &change : changes)
- notifyObservers(change);
-}
+ auto id = Qt3DCore::qIdForNode(node->clip());
+ if (m_clipId != id)
+ setClipId(id);
+ id = Qt3DCore::qIdForNode(node->channelMapper());
+ if (m_mapperId != id)
+ setMapperId(id);
+ id = Qt3DCore::qIdForNode(node->clock());
+ if (m_clockId != id)
+ setClockId(id);
-void ClipAnimator::sendCallbacks(const QVector<AnimationCallbackAndValue> &callbacks)
-{
- for (const AnimationCallbackAndValue &callback : callbacks) {
- if (callback.flags.testFlag(QAnimationCallback::OnThreadPool)) {
- callback.callback->valueChanged(callback.value);
- } else {
- auto e = QAnimationCallbackTriggerPtr::create(peerId());
- e->setCallback(callback.callback);
- e->setValue(callback.value);
- e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- notifyObservers(e);
- }
- }
+ if (m_running != node->isRunning())
+ setRunning(node->isRunning());
+ if (m_loops != node->loopCount())
+ m_loops = node->loopCount();
+ if (!qFuzzyCompare(m_normalizedLocalTime, node->normalizedTime()))
+ setNormalizedLocalTime(node->normalizedTime());
+
+ if (firstTime)
+ setDirty(Handler::ClipAnimatorDirty);
}
qint64 ClipAnimator::nsSincePreviousFrame(qint64 currentGlobalTimeNS)
diff --git a/src/animation/backend/clipanimator_p.h b/src/animation/backend/clipanimator_p.h
index f4c04a4bf..d154bdab9 100644
--- a/src/animation/backend/clipanimator_p.h
+++ b/src/animation/backend/clipanimator_p.h
@@ -80,7 +80,7 @@ public:
void setNormalizedLocalTime(float normalizedLocalTime);
float normalizedLocalTime() const { return m_normalizedLocalTime; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void setHandler(Handler *handler) { m_handler = handler; }
// Called by jobs
@@ -93,9 +93,6 @@ public:
int currentLoop() const { return m_currentLoop; }
void setCurrentLoop(int currentLoop) { m_currentLoop = currentLoop; }
- void sendPropertyChanges(const QVector<Qt3DCore::QSceneChangePtr> &changes);
- void sendCallbacks(const QVector<AnimationCallbackAndValue> &callbacks);
-
void animationClipMarkedDirty() { setDirty(Handler::ClipAnimatorDirty); }
void setClipFormat(const ClipFormat &clipFormat) { m_clipFormat = clipFormat; }
@@ -116,8 +113,6 @@ public:
}
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_clipId;
Qt3DCore::QNodeId m_mapperId;
Qt3DCore::QNodeId m_clockId;
diff --git a/src/animation/backend/clipblendnode.cpp b/src/animation/backend/clipblendnode.cpp
index 81fc61910..57fbdb920 100644
--- a/src/animation/backend/clipblendnode.cpp
+++ b/src/animation/backend/clipblendnode.cpp
@@ -37,8 +37,6 @@
#include "clipblendnode_p.h"
#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
#include <Qt3DAnimation/qabstractanimationclip.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/animation/backend/clipblendvalue.cpp b/src/animation/backend/clipblendvalue.cpp
index 5685d5191..0db9544f6 100644
--- a/src/animation/backend/clipblendvalue.cpp
+++ b/src/animation/backend/clipblendvalue.cpp
@@ -38,7 +38,6 @@
#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
#include <Qt3DAnimation/qclipblendvalue.h>
#include <Qt3DAnimation/private/qclipblendvalue_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -54,22 +53,14 @@ ClipBlendValue::~ClipBlendValue()
{
}
-void ClipBlendValue::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void ClipBlendValue::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- ClipBlendNode::initializeFromPeer(change);
- const auto creationChange
- = qSharedPointerCast<QClipBlendNodeCreatedChange<QClipBlendValueData>>(change);
- const Qt3DAnimation::QClipBlendValueData data = creationChange->data;
- m_clipId = data.clipId;
-}
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QClipBlendValue *node = qobject_cast<const QClipBlendValue *>(frontEnd);
+ if (!node)
+ return;
-void ClipBlendValue::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("clip"))
- m_clipId = change->value().value<Qt3DCore::QNodeId>();
- }
+ m_clipId = Qt3DCore::qIdForNode(node->clip());
}
ClipResults ClipBlendValue::doBlend(const QVector<ClipResults> &blendData) const
diff --git a/src/animation/backend/clipblendvalue_p.h b/src/animation/backend/clipblendvalue_p.h
index 168989a89..8a0f93d3d 100644
--- a/src/animation/backend/clipblendvalue_p.h
+++ b/src/animation/backend/clipblendvalue_p.h
@@ -64,7 +64,7 @@ public:
inline Qt3DCore::QNodeId clipId() const { return m_clipId; }
void setClipId(Qt3DCore::QNodeId clipId) { m_clipId = clipId; } // For unit tests
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
inline QVector<Qt3DCore::QNodeId> allDependencyIds() const override
{
@@ -86,8 +86,6 @@ protected:
ClipResults doBlend(const QVector<ClipResults> &blendData) const override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_clipId;
QVector<Qt3DCore::QNodeId> m_animatorIds;
diff --git a/src/animation/backend/clock.cpp b/src/animation/backend/clock.cpp
index f5b2bd1d3..a9446c2d6 100644
--- a/src/animation/backend/clock.cpp
+++ b/src/animation/backend/clock.cpp
@@ -38,8 +38,6 @@
#include <Qt3DAnimation/qclock.h>
#include <Qt3DAnimation/private/qclock_p.h>
#include <Qt3DAnimation/private/animationutils_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
QT_BEGIN_NAMESPACE
@@ -52,28 +50,16 @@ Clock::Clock()
{
}
-void Clock::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Clock::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QClockData>>(change);
- const auto &data = typedChange->data;
- m_playbackRate = data.playbackRate;
-}
-
-void Clock::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("playbackRate")) {
- m_playbackRate = change.data()->value().toDouble();
- }
- break;
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QClock *node = qobject_cast<const QClock *>(frontEnd);
+ if (!node)
+ return;
- default:
- break;
+ if (!qFuzzyCompare(m_playbackRate, node->playbackRate())) {
+ m_playbackRate = node->playbackRate();
}
- QBackendNode::sceneChangeEvent(e);
}
void Clock::cleanup()
diff --git a/src/animation/backend/clock_p.h b/src/animation/backend/clock_p.h
index 10987655a..b4a60b3a7 100644
--- a/src/animation/backend/clock_p.h
+++ b/src/animation/backend/clock_p.h
@@ -61,15 +61,13 @@ class Q_AUTOTEST_EXPORT Clock : public BackendNode
public:
Clock();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e);
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void cleanup();
void setPlaybackRate(double playbackRate) { m_playbackRate = playbackRate; }
double playbackRate() const { return m_playbackRate; }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
double m_playbackRate;
};
diff --git a/src/animation/backend/evaluateblendclipanimatorjob.cpp b/src/animation/backend/evaluateblendclipanimatorjob.cpp
index e0bb8b155..765531902 100644
--- a/src/animation/backend/evaluateblendclipanimatorjob.cpp
+++ b/src/animation/backend/evaluateblendclipanimatorjob.cpp
@@ -35,6 +35,9 @@
****************************************************************************/
#include "evaluateblendclipanimatorjob_p.h"
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qskeleton_p.h>
+#include <Qt3DAnimation/qblendedclipanimator.h>
#include <Qt3DAnimation/private/handler_p.h>
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
@@ -50,9 +53,10 @@ namespace Qt3DAnimation {
namespace Animation {
EvaluateBlendClipAnimatorJob::EvaluateBlendClipAnimatorJob()
- : Qt3DCore::QAspectJob()
+ : AbstractEvaluateClipAnimatorJob()
+ , m_handler(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateBlendClipAnimator, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateBlendClipAnimator, 0)
}
void EvaluateBlendClipAnimatorJob::run()
@@ -105,7 +109,7 @@ void EvaluateBlendClipAnimatorJob::run()
AnimationClip *clip = clipLoaderManager->lookupResource(valueNode->clipId());
Q_ASSERT(clip);
- ClipResults rawClipResults = evaluateClipAtPhase(clip, phase);
+ ClipResults rawClipResults = evaluateClipAtPhase(clip, float(phase));
// Reformat the clip results into the layout used by this animator/blend tree
const ClipFormat format = valueNode->clipFormat(blendedClipAnimator->peerId());
@@ -120,24 +124,23 @@ void EvaluateBlendClipAnimatorJob::run()
const double localTime = phase * duration;
blendedClipAnimator->setLastGlobalTimeNS(globalTimeNS);
blendedClipAnimator->setLastLocalTime(localTime);
- blendedClipAnimator->setLastNormalizedLocalTime(phase);
+ blendedClipAnimator->setLastNormalizedLocalTime(float(phase));
blendedClipAnimator->setNormalizedLocalTime(-1.0f); // Re-set to something invalid.
blendedClipAnimator->setCurrentLoop(animatorData.currentLoop);
- const bool finalFrame = isFinalFrame(localTime, duration, animatorData.currentLoop, animatorData.loopCount);
- // Prepare the property change events
+ // Prepare the change record
+ const bool finalFrame = isFinalFrame(localTime, duration, animatorData.currentLoop, animatorData.loopCount);
const QVector<MappingData> mappingData = blendedClipAnimator->mappingData();
- const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(blendedClipAnimator->peerId(),
- mappingData,
- blendedResults,
- finalFrame,
- phase);
- // Send the property changes
- blendedClipAnimator->sendPropertyChanges(changes);
+ auto record = prepareAnimationRecord(blendedClipAnimator->peerId(),
+ mappingData,
+ blendedResults,
+ finalFrame,
+ float(phase));
// Trigger callbacks either on this thread or by notifying the gui thread.
- const QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(mappingData, blendedResults);
- blendedClipAnimator->sendCallbacks(callbacks);
+ auto callbacks = prepareCallbacks(mappingData, blendedResults);
+
+ setPostFrameData(record, callbacks);
}
} // Animation
diff --git a/src/animation/backend/evaluateblendclipanimatorjob_p.h b/src/animation/backend/evaluateblendclipanimatorjob_p.h
index 7548168e9..b2a5a6d17 100644
--- a/src/animation/backend/evaluateblendclipanimatorjob_p.h
+++ b/src/animation/backend/evaluateblendclipanimatorjob_p.h
@@ -48,7 +48,7 @@
// We mean it.
//
-#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DAnimation/private/abstractevaluateclipanimatorjob_p.h>
#include <Qt3DAnimation/private/handle_types_p.h>
#include <Qt3DAnimation/private/animationutils_p.h>
#include <Qt3DAnimation/private/blendedclipanimator_p.h>
@@ -60,8 +60,9 @@ namespace Animation {
class Handler;
class ClipBlendNode;
+class EvaluateBlendClipAnimatorJobPrivate;
-class EvaluateBlendClipAnimatorJob : public Qt3DCore::QAspectJob
+class EvaluateBlendClipAnimatorJob : public AbstractEvaluateClipAnimatorJob
{
public:
EvaluateBlendClipAnimatorJob();
diff --git a/src/animation/backend/evaluateclipanimatorjob.cpp b/src/animation/backend/evaluateclipanimatorjob.cpp
index 74f9012d7..914a38139 100644
--- a/src/animation/backend/evaluateclipanimatorjob.cpp
+++ b/src/animation/backend/evaluateclipanimatorjob.cpp
@@ -35,6 +35,9 @@
****************************************************************************/
#include "evaluateclipanimatorjob_p.h"
+#include <Qt3DCore/private/qaspectjob_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DAnimation/qclipanimator.h>
#include <Qt3DAnimation/private/handler_p.h>
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
@@ -46,10 +49,12 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
namespace Animation {
+
EvaluateClipAnimatorJob::EvaluateClipAnimatorJob()
- : Qt3DCore::QAspectJob()
+ : AbstractEvaluateClipAnimatorJob()
+ , m_handler(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::EvaluateClipAnimator, 0)
}
void EvaluateClipAnimatorJob::run()
@@ -98,19 +103,16 @@ void EvaluateClipAnimatorJob::run()
clipAnimator->setNormalizedLocalTime(-1.0f); // Re-set to something invalid.
// Prepare property changes (if finalFrame it also prepares the change for the running property for the frontend)
- const QVector<Qt3DCore::QSceneChangePtr> changes = preparePropertyChanges(clipAnimator->peerId(),
- clipAnimator->mappingData(),
- formattedClipResults,
- preEvaluationDataForClip.isFinalFrame,
- preEvaluationDataForClip.normalizedLocalTime);
-
- // Send the property changes
- clipAnimator->sendPropertyChanges(changes);
+ auto record = prepareAnimationRecord(clipAnimator->peerId(),
+ clipAnimator->mappingData(),
+ formattedClipResults,
+ preEvaluationDataForClip.isFinalFrame,
+ preEvaluationDataForClip.normalizedLocalTime);
// Trigger callbacks either on this thread or by notifying the gui thread.
- const QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(clipAnimator->mappingData(),
- formattedClipResults);
- clipAnimator->sendCallbacks(callbacks);
+ auto callbacks = prepareCallbacks(clipAnimator->mappingData(), formattedClipResults);
+
+ setPostFrameData(record, callbacks);
}
} // namespace Animation
diff --git a/src/animation/backend/evaluateclipanimatorjob_p.h b/src/animation/backend/evaluateclipanimatorjob_p.h
index c9b1a8f96..2e88c9579 100644
--- a/src/animation/backend/evaluateclipanimatorjob_p.h
+++ b/src/animation/backend/evaluateclipanimatorjob_p.h
@@ -48,7 +48,7 @@
// We mean it.
//
-#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DAnimation/private/abstractevaluateclipanimatorjob_p.h>
#include <Qt3DAnimation/private/handle_types_p.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +58,7 @@ namespace Animation {
class Handler;
-class EvaluateClipAnimatorJob : public Qt3DCore::QAspectJob
+class EvaluateClipAnimatorJob : public AbstractEvaluateClipAnimatorJob
{
public:
EvaluateClipAnimatorJob();
diff --git a/src/animation/backend/findrunningclipanimatorsjob.cpp b/src/animation/backend/findrunningclipanimatorsjob.cpp
index fde3f7db8..1005914c7 100644
--- a/src/animation/backend/findrunningclipanimatorsjob.cpp
+++ b/src/animation/backend/findrunningclipanimatorsjob.cpp
@@ -48,8 +48,9 @@ namespace Animation {
FindRunningClipAnimatorsJob::FindRunningClipAnimatorsJob()
: Qt3DCore::QAspectJob()
+ , m_handler(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::FindRunningClipAnimator, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::FindRunningClipAnimator, 0)
}
void FindRunningClipAnimatorsJob::setDirtyClipAnimators(const QVector<HClipAnimator> &clipAnimatorHandles)
diff --git a/src/animation/backend/gltfimporter.cpp b/src/animation/backend/gltfimporter.cpp
index ed10c3e25..718acbb79 100644
--- a/src/animation/backend/gltfimporter.cpp
+++ b/src/animation/backend/gltfimporter.cpp
@@ -342,15 +342,12 @@ GLTFImporter::Node::Node(const QJsonObject &json)
const auto rotationValue = json.value(KEY_ROTATION);
const auto translationValue = json.value(KEY_TRANSLATION);
- QVector3D s(1.0f, 1.0f, 1.0f);
if (!scaleValue.isUndefined())
jsonArrayToVector3D(scaleValue.toArray(), localTransform.scale);
- QQuaternion r;
if (!rotationValue.isUndefined())
jsonArrayToQuaternion(json.value(KEY_ROTATION).toArray(), localTransform.rotation);
- QVector3D t;
if (!translationValue.isUndefined())
jsonArrayToVector3D(json.value(KEY_TRANSLATION).toArray(), localTransform.translation);
}
diff --git a/src/animation/backend/lerpclipblend.cpp b/src/animation/backend/lerpclipblend.cpp
index eef0072f9..b2ba2ff7e 100644
--- a/src/animation/backend/lerpclipblend.cpp
+++ b/src/animation/backend/lerpclipblend.cpp
@@ -35,9 +35,8 @@
****************************************************************************/
#include "lerpclipblend_p.h"
-#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
+#include <Qt3DAnimation/qlerpclipblend.h>
#include <Qt3DAnimation/private/qlerpclipblend_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -57,17 +56,16 @@ LerpClipBlend::~LerpClipBlend()
{
}
-void LerpClipBlend::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void LerpClipBlend::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("blendFactor"))
- m_blendFactor = change->value().toFloat();
- else if (change->propertyName() == QByteArrayLiteral("startClip"))
- m_startClipId = change->value().value<Qt3DCore::QNodeId>();
- else if (change->propertyName() == QByteArrayLiteral("endClip"))
- m_endClipId = change->value().value<Qt3DCore::QNodeId>();
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QLerpClipBlend *node = qobject_cast<const QLerpClipBlend *>(frontEnd);
+ if (!node)
+ return;
+
+ m_blendFactor = node->blendFactor();
+ m_startClipId = Qt3DCore::qIdForNode(node->startClip());
+ m_endClipId = Qt3DCore::qIdForNode(node->endClip());
}
ClipResults LerpClipBlend::doBlend(const QVector<ClipResults> &blendData) const
@@ -83,16 +81,6 @@ ClipResults LerpClipBlend::doBlend(const QVector<ClipResults> &blendData) const
return blendResults;
}
-void LerpClipBlend::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- ClipBlendNode::initializeFromPeer(change);
- const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QClipBlendNodeCreatedChange<Qt3DAnimation::QLerpClipBlendData>>(change);
- const Qt3DAnimation::QLerpClipBlendData cloneData = creationChangeData->data;
- m_startClipId = cloneData.startClipId;
- m_endClipId = cloneData.endClipId;
- m_blendFactor = cloneData.blendFactor;
-}
-
double LerpClipBlend::duration() const
{
ClipBlendNode *startNode = clipBlendNodeManager()->lookupNode(m_startClipId);
@@ -101,7 +89,7 @@ double LerpClipBlend::duration() const
ClipBlendNode *endNode = clipBlendNodeManager()->lookupNode(m_endClipId);
const double endNodeDuration = endNode ? endNode->duration() : 0.0;
- return (1.0f - m_blendFactor) * startNodeDuration + m_blendFactor * endNodeDuration;
+ return (1.0 - static_cast<double>(m_blendFactor)) * startNodeDuration + static_cast<double>(m_blendFactor) * endNodeDuration;
}
} // Animation
diff --git a/src/animation/backend/lerpclipblend_p.h b/src/animation/backend/lerpclipblend_p.h
index 6120f8afa..61434af2c 100644
--- a/src/animation/backend/lerpclipblend_p.h
+++ b/src/animation/backend/lerpclipblend_p.h
@@ -71,7 +71,7 @@ public:
inline Qt3DCore::QNodeId endClipId() const { return m_endClipId; }
void setEndClipId(Qt3DCore::QNodeId endClipId) { m_endClipId = endClipId; } // For unit tests
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final;
inline QVector<Qt3DCore::QNodeId> allDependencyIds() const override
{
@@ -89,8 +89,6 @@ protected:
ClipResults doBlend(const QVector<ClipResults> &blendData) const final;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_startClipId;
Qt3DCore::QNodeId m_endClipId;
float m_blendFactor;
diff --git a/src/animation/backend/loadanimationclipjob.cpp b/src/animation/backend/loadanimationclipjob.cpp
index d3319f8e1..86d7edf87 100644
--- a/src/animation/backend/loadanimationclipjob.cpp
+++ b/src/animation/backend/loadanimationclipjob.cpp
@@ -36,7 +36,11 @@
#include "loadanimationclipjob_p.h"
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DAnimation/qanimationcliploader.h>
+#include <Qt3DAnimation/private/qanimationcliploader_p.h>
#include <Qt3DAnimation/private/animationclip_p.h>
+#include <Qt3DAnimation/private/qabstractanimationclip_p.h>
#include <Qt3DAnimation/private/handler_p.h>
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DAnimation/private/job_common_p.h>
@@ -46,16 +50,28 @@ QT_BEGIN_NAMESPACE
namespace Qt3DAnimation {
namespace Animation {
+class LoadAnimationClipJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ LoadAnimationClipJobPrivate() { }
+ ~LoadAnimationClipJobPrivate() override { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ QVector<AnimationClip *> m_updatedNodes;
+};
+
LoadAnimationClipJob::LoadAnimationClipJob()
- : Qt3DCore::QAspectJob()
+ : Qt3DCore::QAspectJob(*new LoadAnimationClipJobPrivate)
, m_animationClipHandles()
+ , m_handler(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadAnimationClip, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadAnimationClip, 0)
}
void LoadAnimationClipJob::addDirtyAnimationClips(const QVector<HAnimationClip> &animationClipHandles)
{
- for (const auto handle : animationClipHandles) {
+ for (const auto &handle : animationClipHandles) {
if (!m_animationClipHandles.contains(handle))
m_animationClipHandles.push_back(handle);
}
@@ -69,16 +85,40 @@ void LoadAnimationClipJob::clearDirtyAnimationClips()
void LoadAnimationClipJob::run()
{
Q_ASSERT(m_handler);
+ Q_DJOB(LoadAnimationClipJob);
+
+ d->m_updatedNodes.reserve(m_animationClipHandles.size());
AnimationClipLoaderManager *animationClipManager = m_handler->animationClipLoaderManager();
for (const auto &animationClipHandle : qAsConst(m_animationClipHandles)) {
AnimationClip *animationClip = animationClipManager->data(animationClipHandle);
Q_ASSERT(animationClip);
animationClip->loadAnimation();
+ d->m_updatedNodes.push_back(animationClip);
}
clearDirtyAnimationClips();
}
+void LoadAnimationClipJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ for (AnimationClip *clip: qAsConst(m_updatedNodes)) {
+ QAbstractAnimationClip *node = qobject_cast<QAbstractAnimationClip *>(manager->lookupNode(clip->peerId()));
+ if (!node)
+ continue;
+
+ QAbstractAnimationClipPrivate *dnode = static_cast<QAbstractAnimationClipPrivate *>(Qt3DCore::QNodePrivate::get(node));
+ dnode->setDuration(clip->duration());
+
+ QAnimationClipLoader *loader = qobject_cast<QAnimationClipLoader *>(node);
+ if (loader) {
+ QAnimationClipLoaderPrivate *dloader = static_cast<QAnimationClipLoaderPrivate *>(dnode);
+ dloader->setStatus(clip->status());
+ }
+ }
+
+ m_updatedNodes.clear();
+}
+
} // namespace Animation
} // namespace Qt3DAnimation
diff --git a/src/animation/backend/loadanimationclipjob_p.h b/src/animation/backend/loadanimationclipjob_p.h
index 25de2c6b6..42cf27854 100644
--- a/src/animation/backend/loadanimationclipjob_p.h
+++ b/src/animation/backend/loadanimationclipjob_p.h
@@ -59,6 +59,7 @@ namespace Animation {
class Handler;
class FindGraphJob;
+class LoadAnimationClipJobPrivate;
class LoadAnimationClipJob : public Qt3DCore::QAspectJob
{
diff --git a/src/animation/backend/skeleton.cpp b/src/animation/backend/skeleton.cpp
index dcfaf55e7..3788fd0f1 100644
--- a/src/animation/backend/skeleton.cpp
+++ b/src/animation/backend/skeleton.cpp
@@ -35,7 +35,7 @@
****************************************************************************/
#include "skeleton_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qabstractskeleton_p.h>
QT_BEGIN_NAMESPACE
@@ -62,47 +62,20 @@ void Skeleton::cleanup()
m_jointLocalPoses.clear();
}
-void Skeleton::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Skeleton::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- // Nothing to initialize from the frontend. We get all of our internal state
- // from whatever aspect loads the skeleton data - the render aspect in the
- // default case.
- Q_UNUSED(change);
-}
-
-void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- // Get the joint names and initial local poses from a change sent
- // by the render aspect when the skeleton has been loaded.
- switch (e->type()) {
- case PropertyUpdated: {
- const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("jointNamesAndLocalPoses")) {
- const auto payload = change->value().value<JointNamesAndLocalPoses>();
- m_jointNames = payload.names;
- m_jointLocalPoses = payload.localPoses;
-
- // TODO: Mark joint info as dirty so we can rebuild any indexes used
- // by the animators and channel mappings.
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
- break;
- }
+ const Qt3DCore::QAbstractSkeleton *node = qobject_cast<const Qt3DCore::QAbstractSkeleton *>(frontEnd);
+ if (!node)
+ return;
- default:
- break;
- }
+ auto dnode = Qt3DCore::QAbstractSkeletonPrivate::get(node);
- BackendNode::sceneChangeEvent(e);
-}
-
-void Skeleton::sendLocalPoses()
-{
- auto e = QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::BackendNodes);
- e->setPropertyName("localPoses");
- e->setValue(QVariant::fromValue(m_jointLocalPoses));
- notifyObservers(e);
+ // TODO: Mark joint info as dirty so we can rebuild any indexes used
+ // by the animators and channel mappings.
+ m_jointNames = dnode->m_jointNames;
+ m_jointLocalPoses = dnode->m_localPoses;
}
} // namespace Animation
diff --git a/src/animation/backend/skeleton_p.h b/src/animation/backend/skeleton_p.h
index f1ddb1e81..d44f8fc1c 100644
--- a/src/animation/backend/skeleton_p.h
+++ b/src/animation/backend/skeleton_p.h
@@ -62,8 +62,9 @@ public:
Skeleton();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+ QVector<Qt3DCore::Sqt> joints() const { return m_jointLocalPoses; }
int jointCount() const { return m_jointLocalPoses.size(); }
QString jointName(int jointIndex) const { return m_jointNames.at(jointIndex); }
@@ -97,8 +98,6 @@ public:
return m_jointLocalPoses[jointIndex].translation;
}
- void sendLocalPoses();
-
#if defined(QT_BUILD_INTERNAL)
void setJointCount(int jointCount)
{
@@ -112,8 +111,6 @@ public:
#endif
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL;
-
QVector<QString> m_jointNames;
QVector<Qt3DCore::Sqt> m_jointLocalPoses;
};
diff --git a/src/animation/frontend/qabstractanimationclip.cpp b/src/animation/frontend/qabstractanimationclip.cpp
index 7e6df4d70..08133072c 100644
--- a/src/animation/frontend/qabstractanimationclip.cpp
+++ b/src/animation/frontend/qabstractanimationclip.cpp
@@ -36,7 +36,6 @@
#include "qabstractanimationclip.h"
#include "qabstractanimationclip_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -122,7 +121,7 @@ void QAbstractAnimationClipPrivate::setDuration(float duration)
animator->setRunning(true);
\endcode
- \sa QAnimationClip, QAnimationClipLoader
+ \sa Qt3DAnimation::QAnimationClip, Qt3DAnimation::QAnimationClipLoader
*/
/*!
@@ -134,6 +133,11 @@ QAbstractAnimationClip::QAbstractAnimationClip(QAbstractAnimationClipPrivate &dd
{
}
+// TODO Unused remove in Qt6
+void QAbstractAnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
/*!
Destroys this animation clip.
*/
@@ -153,19 +157,6 @@ float QAbstractAnimationClip::duration() const
return d->m_duration;
}
-/*!
- \internal
-*/
-void QAbstractAnimationClip::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QAbstractAnimationClip);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("duration"))
- d->setDuration(e->value().toFloat());
- }
-}
-
} // namespace Qt3DAnimation
QT_END_NAMESPACE
diff --git a/src/animation/frontend/qabstractanimationclip.h b/src/animation/frontend/qabstractanimationclip.h
index 79464b13d..fddee3dec 100644
--- a/src/animation/frontend/qabstractanimationclip.h
+++ b/src/animation/frontend/qabstractanimationclip.h
@@ -62,8 +62,8 @@ Q_SIGNALS:
protected:
QAbstractAnimationClip(QAbstractAnimationClipPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
-
private:
Q_DECLARE_PRIVATE(QAbstractAnimationClip)
};
diff --git a/src/animation/frontend/qabstractchannelmapping.cpp b/src/animation/frontend/qabstractchannelmapping.cpp
index 3249e6876..599ec6ed7 100644
--- a/src/animation/frontend/qabstractchannelmapping.cpp
+++ b/src/animation/frontend/qabstractchannelmapping.cpp
@@ -46,6 +46,7 @@ namespace Qt3DAnimation {
QAbstractChannelMappingPrivate::QAbstractChannelMappingPrivate()
: Qt3DCore::QNodePrivate()
+ , m_mappingType(QChannelMappingCreatedChangeBase::ChannelMapping)
{
}
diff --git a/src/animation/frontend/qabstractclipanimator.cpp b/src/animation/frontend/qabstractclipanimator.cpp
index 2d4de676c..8c282da49 100644
--- a/src/animation/frontend/qabstractclipanimator.cpp
+++ b/src/animation/frontend/qabstractclipanimator.cpp
@@ -41,7 +41,6 @@
#include "qabstractclipanimator_p.h"
#include <Qt3DAnimation/qchannelmapper.h>
#include <Qt3DAnimation/qclock.h>
-#include <Qt3DAnimation/private/qanimationcallbacktrigger_p.h>
QT_BEGIN_NAMESPACE
@@ -123,16 +122,9 @@ QAbstractClipAnimator::QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Q
{
}
-/*! \internal */
-void QAbstractClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QAbstractClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- if (change->type() == Qt3DCore::CallbackTriggered) {
- QAnimationCallbackTriggerPtr callbackTrigger = qSharedPointerCast<Qt3DAnimation::QAnimationCallbackTrigger>(change);
- if (callbackTrigger->callback())
- callbackTrigger->callback()->valueChanged(callbackTrigger->value());
- } else {
- QComponent::sceneChangeEvent(change);
- }
}
QAbstractClipAnimator::~QAbstractClipAnimator()
diff --git a/src/animation/frontend/qabstractclipanimator.h b/src/animation/frontend/qabstractclipanimator.h
index a3bce0600..dc9dc9077 100644
--- a/src/animation/frontend/qabstractclipanimator.h
+++ b/src/animation/frontend/qabstractclipanimator.h
@@ -94,8 +94,8 @@ protected:
explicit QAbstractClipAnimator(Qt3DCore::QNode *parent = nullptr);
QAbstractClipAnimator(QAbstractClipAnimatorPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
-
private:
Q_DECLARE_PRIVATE(QAbstractClipAnimator)
};
diff --git a/src/animation/frontend/qanimationaspect.cpp b/src/animation/frontend/qanimationaspect.cpp
index a25eb533e..850132a39 100644
--- a/src/animation/frontend/qanimationaspect.cpp
+++ b/src/animation/frontend/qanimationaspect.cpp
@@ -69,6 +69,12 @@ QAnimationAspectPrivate::QAnimationAspectPrivate()
{
}
+void QAnimationAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const
+{
+ Animation::BackendNode *renderBackend = static_cast<Animation::BackendNode *>(backend);
+ renderBackend->syncFromFrontEnd(node, firstTime);
+}
+
/*!
\class Qt3DAnimation::QAnimationAspect
\inherits Qt3DCore::QAbstractAspect
@@ -98,34 +104,34 @@ QAnimationAspect::QAnimationAspect(QAnimationAspectPrivate &dd, QObject *parent)
qRegisterMetaType<QVector<Qt3DCore::Sqt>>();
qRegisterMetaType<Qt3DAnimation::QAbstractAnimationClip*>();
- registerBackendType<QAbstractAnimationClip>(
+ d->registerBackendType<QAbstractAnimationClip, true>(
QSharedPointer<Animation::NodeFunctor<Animation::AnimationClip, Animation::AnimationClipLoaderManager>>::create(d->m_handler.data(),
d->m_handler->animationClipLoaderManager()));
- registerBackendType<QClock>(
+ d->registerBackendType<QClock, true>(
QSharedPointer<Animation::NodeFunctor<Animation::Clock, Animation::ClockManager>>::create(d->m_handler.data(),
d->m_handler->clockManager()));
- registerBackendType<QClipAnimator>(
+ d->registerBackendType<QClipAnimator, true>(
QSharedPointer<Animation::NodeFunctor<Animation::ClipAnimator, Animation::ClipAnimatorManager>>::create(d->m_handler.data(),
d->m_handler->clipAnimatorManager()));
- registerBackendType<QBlendedClipAnimator>(
+ d->registerBackendType<QBlendedClipAnimator, true>(
QSharedPointer<Animation::NodeFunctor<Animation::BlendedClipAnimator, Animation::BlendedClipAnimatorManager>>::create(d->m_handler.data(),
d->m_handler->blendedClipAnimatorManager()));
- registerBackendType<QAbstractChannelMapping>(
+ d->registerBackendType<QAbstractChannelMapping, true>(
QSharedPointer<Animation::NodeFunctor<Animation::ChannelMapping, Animation::ChannelMappingManager>>::create(d->m_handler.data(),
d->m_handler->channelMappingManager()));
- registerBackendType<QChannelMapper>(
+ d->registerBackendType<QChannelMapper, true>(
QSharedPointer<Animation::NodeFunctor<Animation::ChannelMapper, Animation::ChannelMapperManager>>::create(d->m_handler.data(),
d->m_handler->channelMapperManager()));
- registerBackendType<QLerpClipBlend>(
+ d->registerBackendType<QLerpClipBlend, true>(
QSharedPointer<Animation::ClipBlendNodeFunctor<Animation::LerpClipBlend, Animation::ClipAnimatorManager>>::create(d->m_handler.data(),
d->m_handler->clipBlendNodeManager()));
- registerBackendType<QAdditiveClipBlend>(
+ d->registerBackendType<QAdditiveClipBlend, true>(
QSharedPointer<Animation::ClipBlendNodeFunctor<Animation::AdditiveClipBlend, Animation::ClipAnimatorManager>>::create(d->m_handler.data(),
d->m_handler->clipBlendNodeManager()));
- registerBackendType<QClipBlendValue>(
+ d->registerBackendType<QClipBlendValue, true>(
QSharedPointer<Animation::ClipBlendNodeFunctor<Animation::ClipBlendValue, Animation::ClipAnimatorManager>>::create(d->m_handler.data(),
d->m_handler->clipBlendNodeManager()));
- registerBackendType<Qt3DCore::QAbstractSkeleton>(
+ d->registerBackendType<Qt3DCore::QAbstractSkeleton, true>(
QSharedPointer<Animation::NodeFunctor<Animation::Skeleton, Animation::SkeletonManager>>::create(d->m_handler.data(),
d->m_handler->skeletonManager()));
}
diff --git a/src/animation/frontend/qanimationaspect_p.h b/src/animation/frontend/qanimationaspect_p.h
index 2ecc8fdb8..203acd386 100644
--- a/src/animation/frontend/qanimationaspect_p.h
+++ b/src/animation/frontend/qanimationaspect_p.h
@@ -70,6 +70,8 @@ public:
Q_DECLARE_PUBLIC(QAnimationAspect)
+ void syncDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QBackendNode *backend, bool firstTime) const override;
+
QScopedPointer<Animation::Handler> m_handler;
};
diff --git a/src/animation/frontend/qanimationcallback.qdoc b/src/animation/frontend/qanimationcallback.qdoc
new file mode 100644
index 000000000..5c6e8e212
--- /dev/null
+++ b/src/animation/frontend/qanimationcallback.qdoc
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class Qt3DAnimation::QAnimationCallback
+ \inmodule Qt3DAnimation
+ \brief Represents an animation callback object.
+*/
+
+/*!
+ \enum Qt3DAnimation::QAnimationCallback::Flag
+
+ Flags to indicate how the valueChanged() function is called.
+
+ \value OnOwningThread
+ Callback function is called on the owning (GUI or main) thread.
+ \value OnThreadPool
+ Callback function is called on the thread pool's worker thread.
+*/
+
+/*!
+ \fn Qt3DAnimation::QAnimationCallback::valueChanged(const QVariant &value)
+
+ Callback function that is triggered for changes in the animated \a value.
+
+ \sa QCallbackMapping::setCallback()
+*/
diff --git a/src/animation/frontend/qanimationclip.cpp b/src/animation/frontend/qanimationclip.cpp
index d624a246a..74a9b8371 100644
--- a/src/animation/frontend/qanimationclip.cpp
+++ b/src/animation/frontend/qanimationclip.cpp
@@ -51,8 +51,8 @@ QAnimationClipPrivate::QAnimationClipPrivate()
}
/*!
- \class QAnimationClip
- \inherits QAbstractAnimationClip
+ \class Qt3DAnimation::QAnimationClip
+ \inherits Qt3dAnimation::QAbstractAnimationClip
\inmodule Qt3DAnimation
\brief Specifies key frame animation data.
*/
diff --git a/src/animation/frontend/qanimationclipdata.cpp b/src/animation/frontend/qanimationclipdata.cpp
index 49de71e79..e105b7b43 100644
--- a/src/animation/frontend/qanimationclipdata.cpp
+++ b/src/animation/frontend/qanimationclipdata.cpp
@@ -53,7 +53,7 @@ public:
};
/*!
- \class QAnimationClipData
+ \class Qt3DAnimation::QAnimationClipData
\inmodule Qt3DAnimation
\brief Class containing the animation data.
*/
diff --git a/src/animation/frontend/qanimationcliploader.cpp b/src/animation/frontend/qanimationcliploader.cpp
index d31f9bd5d..bf901e54f 100644
--- a/src/animation/frontend/qanimationcliploader.cpp
+++ b/src/animation/frontend/qanimationcliploader.cpp
@@ -36,7 +36,6 @@
#include "qanimationcliploader.h"
#include "qanimationcliploader_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -113,6 +112,11 @@ QAnimationClipLoader::QAnimationClipLoader(QAnimationClipLoaderPrivate &dd, Qt3D
{
}
+// TODO Unused remove in Qt6
+void QAnimationClipLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
QAnimationClipLoader::~QAnimationClipLoader()
{
}
@@ -142,19 +146,6 @@ void QAnimationClipLoader::setSource(const QUrl &source)
emit sourceChanged(source);
}
-/*!
- \internal
-*/
-void QAnimationClipLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QAnimationClipLoader);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("status"))
- d->setStatus(static_cast<QAnimationClipLoader::Status>(e->value().toInt()));
- }
-}
-
Qt3DCore::QNodeCreatedChangeBasePtr QAnimationClipLoader::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAnimationClipLoaderData>::create(this);
diff --git a/src/animation/frontend/qanimationcliploader.h b/src/animation/frontend/qanimationcliploader.h
index bf82f742e..1b68e852f 100644
--- a/src/animation/frontend/qanimationcliploader.h
+++ b/src/animation/frontend/qanimationcliploader.h
@@ -78,6 +78,7 @@ Q_SIGNALS:
protected:
explicit QAnimationClipLoader(QAnimationClipLoaderPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/animation/frontend/qcallbackmapping.cpp b/src/animation/frontend/qcallbackmapping.cpp
index c0163da80..24b5d2e6e 100644
--- a/src/animation/frontend/qcallbackmapping.cpp
+++ b/src/animation/frontend/qcallbackmapping.cpp
@@ -38,7 +38,6 @@
#include "qcallbackmapping_p.h"
#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/QMetaProperty>
@@ -58,7 +57,7 @@ QCallbackMappingPrivate::QCallbackMappingPrivate()
}
/*!
- \class QCallbackMapping
+ \class Qt3DAnimation::QCallbackMapping
\inherits Qt3DCore::QAbstractChannelMapping
\inmodule Qt3DAnimation
\brief Allows to map the channels within the clip onto an invocation
@@ -130,24 +129,15 @@ void QCallbackMapping::setCallback(int type, QAnimationCallback *callback, QAnim
Q_D(QCallbackMapping);
if (d->m_type != type) {
d->m_type = type;
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
- e->setPropertyName("type");
- e->setValue(QVariant(d->m_type));
- notifyObservers(e);
+ d->update();
}
if (d->m_callback != callback) {
d->m_callback = callback;
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
- e->setPropertyName("callback");
- e->setValue(QVariant::fromValue(static_cast<void *>(d->m_callback)));
- notifyObservers(e);
+ d->update();
}
if (d->m_callbackFlags != flags) {
d->m_callbackFlags = flags;
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
- e->setPropertyName("callbackFlags");
- e->setValue(QVariant::fromValue(int(d->m_callbackFlags)));
- notifyObservers(e);
+ d->update();
}
}
diff --git a/src/animation/frontend/qchannel.cpp b/src/animation/frontend/qchannel.cpp
index eab7f0df4..1e0da3c3f 100644
--- a/src/animation/frontend/qchannel.cpp
+++ b/src/animation/frontend/qchannel.cpp
@@ -54,7 +54,7 @@ public:
};
/*!
- \class QChannel
+ \class Qt3DAnimation::QChannel
\inmodule Qt3DAnimation
\brief Defines a channel for a QAnimationClipData.
The animation system interpolates each channel component independently
diff --git a/src/animation/frontend/qchannelmapper.cpp b/src/animation/frontend/qchannelmapper.cpp
index 82ce5ebbe..c5909adbc 100644
--- a/src/animation/frontend/qchannelmapper.cpp
+++ b/src/animation/frontend/qchannelmapper.cpp
@@ -36,9 +36,8 @@
#include "qchannelmapper.h"
#include "qchannelmapper_p.h"
+#include <Qt3DCore/qscenechange.h>
#include <Qt3DAnimation/qchannelmapping.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -50,7 +49,7 @@ QChannelMapperPrivate::QChannelMapperPrivate()
}
/*!
- \class QChannelMapper
+ \class Qt3DAnimation::QChannelMapper
\inmodule Qt3DAnimation
\brief Allows to map the channels within the clip onto properties of
objects in the application.
@@ -87,11 +86,7 @@ void QChannelMapper::addMapping(QAbstractChannelMapping *mapping)
if (!mapping->parent())
mapping->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), mapping);
- change->setPropertyName("mappings");
- d->notifyObservers(change);
- }
+ d->updateNode(mapping, "mappings", Qt3DCore::PropertyValueAdded);
}
}
@@ -99,12 +94,8 @@ void QChannelMapper::removeMapping(QAbstractChannelMapping *mapping)
{
Q_ASSERT(mapping);
Q_D(QChannelMapper);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), mapping);
- change->setPropertyName("mappings");
- d->notifyObservers(change);
- }
d->m_mappings.removeOne(mapping);
+ d->updateNode(mapping, "mappings", Qt3DCore::PropertyValueRemoved);
// Remove bookkeeping connection
d->unregisterDestructionHelper(mapping);
}
diff --git a/src/animation/frontend/qchannelmapping.cpp b/src/animation/frontend/qchannelmapping.cpp
index 8f6ebe9ab..16651afe6 100644
--- a/src/animation/frontend/qchannelmapping.cpp
+++ b/src/animation/frontend/qchannelmapping.cpp
@@ -38,7 +38,6 @@
#include "qchannelmapping_p.h"
#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/QMetaProperty>
@@ -147,39 +146,22 @@ void QChannelMappingPrivate::updatePropertyNameTypeAndComponentCount()
if (m_type != type) {
m_type = type;
-
- // Send update to the backend
- Q_Q(QChannelMapping);
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(q->id());
- e->setPropertyName("type");
- e->setValue(QVariant(m_type));
- notifyObservers(e);
+ update();
}
if (m_componentCount != componentCount) {
m_componentCount = componentCount;
-
- // Send update to the backend
- Q_Q(QChannelMapping);
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(q->id());
- e->setPropertyName("componentCount");
- e->setValue(QVariant(m_componentCount));
- notifyObservers(e);
+ update();
}
if (qstrcmp(m_propertyName, propertyName) != 0) {
m_propertyName = propertyName;
-
- // Send update to the backend
- Q_Q(QChannelMapping);
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(q->id());
- e->setPropertyName("propertyName");
- e->setValue(QVariant::fromValue(const_cast<void *>(static_cast<const void *>(m_propertyName))));
- notifyObservers(e);
+ update();
}
}
+
/*!
- \class QChannelMapping
+ \class Qt3DAnimation::QChannelMapping
\inherits Qt3DCore::QNode
\inmodule Qt3DAnimation
\brief Allows to map the channels within the clip onto properties of
diff --git a/src/animation/frontend/qclipanimator.cpp b/src/animation/frontend/qclipanimator.cpp
index 03510aa93..ffad588c1 100644
--- a/src/animation/frontend/qclipanimator.cpp
+++ b/src/animation/frontend/qclipanimator.cpp
@@ -107,7 +107,8 @@ bool QClipAnimatorPrivate::canPlay() const
The properties for controlling the animator are provided by the QAbstractClipAnimator base
class.
- \sa QAbstractClipAnimator, QAbstractAnimationClip, QChannelMapper, QBlendedClipAnimator
+ \sa Qt3DAnimation::QAbstractClipAnimator, Qt3DAnimation::QAbstractAnimationClip,
+ Qt3DAnimation::QChannelMapper, Qt3DAnimation::QBlendedClipAnimator
*/
QClipAnimator::QClipAnimator(Qt3DCore::QNode *parent)
diff --git a/src/animation/frontend/qclipblendvalue.cpp b/src/animation/frontend/qclipblendvalue.cpp
index 72a7dd796..053453e33 100644
--- a/src/animation/frontend/qclipblendvalue.cpp
+++ b/src/animation/frontend/qclipblendvalue.cpp
@@ -53,14 +53,14 @@ QClipBlendValuePrivate::QClipBlendValuePrivate()
}
/*!
- \class QClipBlendValue
+ \class Qt3DAnimation::QClipBlendValue
\inherits Qt3DAnimation::QAbstractClipBlendNode
\inmodule Qt3DAnimation
\brief Class used for including a clip in a blend tree.
*/
/*!
\qmltype ClipBlendValue
- \instantiates QClipBlendValue
+ \instantiates Qt3DAnimation::QClipBlendValue
\inqmlmodule Qt3D.Animation
\brief Type used for including a clip in a blend tree.
*/
diff --git a/src/animation/frontend/qclock.cpp b/src/animation/frontend/qclock.cpp
index 717982902..f38c21807 100644
--- a/src/animation/frontend/qclock.cpp
+++ b/src/animation/frontend/qclock.cpp
@@ -36,7 +36,6 @@
#include "qclock.h"
#include "qclock_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/animation/frontend/qmorphtarget.cpp b/src/animation/frontend/qmorphtarget.cpp
index 76b1a598e..da068d477 100644
--- a/src/animation/frontend/qmorphtarget.cpp
+++ b/src/animation/frontend/qmorphtarget.cpp
@@ -86,8 +86,8 @@ namespace Qt3DAnimation {
*/
/*!
\qmlmethod MorphTarget Qt3D.Animation::MorphTarget::fromGeometry(geometry, stringList)
- Returns a morph target based on the attributes defined by the given stringList from
- the given geometry.
+ Returns a morph target based on the attributes defined by the given \a stringList from
+ the given \a geometry.
*/
QMorphTargetPrivate::QMorphTargetPrivate()
diff --git a/src/animation/frontend/qvertexblendanimation.cpp b/src/animation/frontend/qvertexblendanimation.cpp
index 25468d4a7..143b9553a 100644
--- a/src/animation/frontend/qvertexblendanimation.cpp
+++ b/src/animation/frontend/qvertexblendanimation.cpp
@@ -192,8 +192,8 @@ void QVertexBlendAnimationPrivate::updateAnimation(float position)
Qt3DRender::QGeometry *geometry = m_target->geometry();
// remove attributes from previous frame
- if ((m_currentBase && (base != m_currentBase))
- || (m_currentTarget && (target != m_currentTarget))) {
+ if (m_currentBase && m_currentTarget &&
+ (base != m_currentBase || target != m_currentTarget)) {
const QVector<Qt3DRender::QAttribute *> baseAttributes = m_currentBase->attributeList();
const QVector<Qt3DRender::QAttribute *> targetAttributes = m_currentTarget->attributeList();
for (int i = 0; i < baseAttributes.size(); ++i) {
diff --git a/src/core/aspects/aspects.pri b/src/core/aspects/aspects.pri
index ced33f310..5e8327192 100644
--- a/src/core/aspects/aspects.pri
+++ b/src/core/aspects/aspects.pri
@@ -4,8 +4,7 @@ SOURCES += \
$$PWD/qabstractaspect.cpp \
$$PWD/qaspectengine.cpp \
$$PWD/qaspectfactory.cpp \
- $$PWD/qaspectmanager.cpp \
- $$PWD/qaspectthread.cpp
+ $$PWD/qaspectmanager.cpp
HEADERS += \
$$PWD/qabstractaspect.h \
@@ -13,8 +12,7 @@ HEADERS += \
$$PWD/qabstractaspect_p.h \
$$PWD/qaspectengine_p.h \
$$PWD/qaspectfactory_p.h \
- $$PWD/qaspectmanager_p.h \
- $$PWD/qaspectthread_p.h
+ $$PWD/qaspectmanager_p.h
INCLUDEPATH += $$PWD
diff --git a/src/core/aspects/qabstractaspect.cpp b/src/core/aspects/qabstractaspect.cpp
index 7b08dec81..19b6f70c1 100644
--- a/src/core/aspects/qabstractaspect.cpp
+++ b/src/core/aspects/qabstractaspect.cpp
@@ -40,15 +40,25 @@
#include "qabstractaspect.h"
#include "qabstractaspect_p.h"
+#include <QMetaObject>
+#include <QMetaProperty>
+
+#include <Qt3DCore/qcomponent.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qpropertyvalueaddedchange.h>
+#include <Qt3DCore/qpropertyvalueremovedchange.h>
+#include <Qt3DCore/qcomponentaddedchange.h>
+#include <Qt3DCore/qcomponentremovedchange.h>
#include <Qt3DCore/private/corelogging_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
@@ -82,6 +92,13 @@ void QAbstractAspectPrivate::onEngineAboutToShutdown()
}
/*! \internal */
+void QAbstractAspectPrivate::registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor, bool supportsSyncing)
+{
+ const auto f = supportsSyncing ? QAbstractAspectPrivate::SupportsSyncing : QAbstractAspectPrivate::DefaultMapper;
+ m_backendCreatorFunctors.insert(&obj, {functor, f});
+}
+
+/*! \internal */
void QAbstractAspectPrivate::unregisterBackendType(const QMetaObject &mo)
{
m_backendCreatorFunctors.remove(&mo);
@@ -170,7 +187,7 @@ QNodeId QAbstractAspect::rootEntityId() const Q_DECL_NOEXCEPT
void QAbstractAspect::registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor)
{
Q_D(QAbstractAspect);
- d->m_backendCreatorFunctors.insert(&obj, functor);
+ d->m_backendCreatorFunctors.insert(&obj, {functor, QAbstractAspectPrivate::DefaultMapper});
}
void QAbstractAspect::unregisterBackendType(const QMetaObject &obj)
@@ -179,108 +196,281 @@ void QAbstractAspect::unregisterBackendType(const QMetaObject &obj)
d->m_backendCreatorFunctors.remove(&obj);
}
-void QAbstractAspectPrivate::sceneNodeAdded(QSceneChangePtr &change)
+QVariant QAbstractAspect::executeCommand(const QStringList &args)
{
- QNodeCreatedChangeBasePtr creationChange = qSharedPointerCast<QNodeCreatedChangeBase>(change);
- createBackendNode(creationChange);
+ Q_UNUSED(args)
+ return QVariant();
}
-void QAbstractAspectPrivate::sceneNodeRemoved(QSceneChangePtr &change)
+QVector<QAspectJobPtr> QAbstractAspect::jobsToExecute(qint64 time)
{
- QNodeDestroyedChangePtr destructionChange = qSharedPointerCast<QNodeDestroyedChange>(change);
- clearBackendNode(destructionChange);
+ Q_UNUSED(time)
+ return QVector<QAspectJobPtr>();
}
-QVariant QAbstractAspect::executeCommand(const QStringList &args)
+QAbstractAspectPrivate::BackendNodeMapperAndInfo QAbstractAspectPrivate::mapperForNode(const QMetaObject *metaObj) const
{
- Q_UNUSED(args);
- return QVariant();
+ Q_ASSERT(metaObj);
+ BackendNodeMapperAndInfo info;
+
+ while (metaObj != nullptr && info.first.isNull()) {
+ info = m_backendCreatorFunctors.value(metaObj);
+ metaObj = metaObj->superClass();
+ }
+ return info;
}
-QVector<QAspectJobPtr> QAbstractAspect::jobsToExecute(qint64 time)
+void QAbstractAspectPrivate::syncDirtyFrontEndNodes(const QVector<QNode *> &nodes)
{
- Q_UNUSED(time);
- return QVector<QAspectJobPtr>();
+ for (auto node: qAsConst(nodes)) {
+ const QMetaObject *metaObj = QNodePrivate::get(node)->m_typeInfo;
+ const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj);
+ const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first;
+
+ if (!backendNodeMapper)
+ continue;
+
+ QBackendNode *backend = backendNodeMapper->get(node->id());
+ if (!backend)
+ continue;
+
+ const bool supportsSyncing = backendNodeMapperInfo.second & SupportsSyncing;
+ if (supportsSyncing)
+ syncDirtyFrontEndNode(node, backend, false);
+ else
+ sendPropertyMessages(node, backend);
+ }
}
-QBackendNode *QAbstractAspectPrivate::createBackendNode(const QNodeCreatedChangeBasePtr &change) const
+void QAbstractAspectPrivate::syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes)
{
- const QMetaObject *metaObj = change->metaObject();
- QBackendNodeMapperPtr backendNodeMapper;
- while (metaObj != nullptr && backendNodeMapper.isNull()) {
- backendNodeMapper = m_backendCreatorFunctors.value(metaObj);
- metaObj = metaObj->superClass();
+ for (const auto &nodeChange: qAsConst(nodes)) {
+ auto getBackend = [this](QNode *node) -> std::tuple<QBackendNode *, bool> {
+ const QMetaObject *metaObj = QNodePrivate::get(node)->m_typeInfo;
+ const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj);
+ const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first;
+
+ if (!backendNodeMapper)
+ return {};
+
+ QBackendNode *backend = backendNodeMapper->get(node->id());
+ if (!backend)
+ return {};
+
+ const bool supportsSyncing = backendNodeMapperInfo.second & SupportsSyncing;
+
+ return std::tuple<QBackendNode *, bool>(backend, supportsSyncing);
+ };
+
+ auto nodeInfo = getBackend(nodeChange.node);
+ if (!std::get<0>(nodeInfo))
+ continue;
+
+ auto subNodeInfo = getBackend(nodeChange.subNode);
+ if (!std::get<0>(subNodeInfo))
+ continue;
+
+ switch (nodeChange.change) {
+ case PropertyValueAdded: {
+ if (std::get<1>(nodeInfo))
+ break; // do nothing as the node will be dirty anyway
+
+ QPropertyValueAddedChange change(nodeChange.node->id());
+ change.setPropertyName(nodeChange.property);
+ change.setAddedValue(QVariant::fromValue(nodeChange.subNode->id()));
+ QPropertyValueAddedChangePtr pChange(&change, [](QPropertyValueAddedChange *) { });
+ std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
+ }
+ break;
+ case PropertyValueRemoved: {
+ if (std::get<1>(nodeInfo))
+ break; // do nothing as the node will be dirty anyway
+
+ QPropertyValueRemovedChange change(nodeChange.node->id());
+ change.setPropertyName(nodeChange.property);
+ change.setRemovedValue(QVariant::fromValue(nodeChange.subNode->id()));
+ QPropertyValueRemovedChangePtr pChange(&change, [](QPropertyValueRemovedChange *) { });
+ std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
+ }
+ break;
+ case ComponentAdded: {
+ // let the entity know it has a new component
+ if (std::get<1>(nodeInfo)) {
+ QBackendNodePrivate::get(std::get<0>(nodeInfo))->componentAdded(nodeChange.subNode);
+ } else {
+ QComponentAddedChange change(qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode), qobject_cast<Qt3DCore::QEntity *>(nodeChange.node));
+ QComponentAddedChangePtr pChange(&change, [](QComponentAddedChange *) { });
+ std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
+ }
+
+ // let the component know it was added to an entity
+ if (std::get<1>(subNodeInfo)) {
+ QBackendNodePrivate::get(std::get<0>(subNodeInfo))->addedToEntity(nodeChange.node);
+ } else {
+ QComponentAddedChange change(qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode), qobject_cast<Qt3DCore::QEntity *>(nodeChange.node));
+ QComponentAddedChangePtr pChange(&change, [](QComponentAddedChange *) { });
+ std::get<0>(subNodeInfo)->sceneChangeEvent(pChange);
+ }
+ }
+ break;
+ case ComponentRemoved: {
+ // let the entity know a component was removed
+ if (std::get<1>(nodeInfo)) {
+ QBackendNodePrivate::get(std::get<0>(nodeInfo))->componentRemoved(nodeChange.subNode);
+ } else {
+ QComponentRemovedChange change(qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode), qobject_cast<Qt3DCore::QEntity *>(nodeChange.node));
+ QComponentRemovedChangePtr pChange(&change, [](QComponentRemovedChange *) { });
+ std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
+ }
+
+ // let the component know it was removed from an entity
+ if (std::get<1>(subNodeInfo)) {
+ QBackendNodePrivate::get(std::get<0>(subNodeInfo))->removedFromEntity(nodeChange.node);
+ } else {
+ QComponentRemovedChange change(qobject_cast<Qt3DCore::QEntity *>(nodeChange.node), qobject_cast<Qt3DCore::QComponent *>(nodeChange.subNode));
+ QComponentRemovedChangePtr pChange(&change, [](QComponentRemovedChange *) { });
+ std::get<0>(nodeInfo)->sceneChangeEvent(pChange);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void QAbstractAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const
+{
+ Q_ASSERT(false); // overload in derived class
+ if (!firstTime)
+ sendPropertyMessages(node, backend);
+}
+
+void QAbstractAspectPrivate::sendPropertyMessages(QNode *node, QBackendNode *backend) const
+{
+ const int offset = QNode::staticMetaObject.propertyOffset();
+ const auto metaObj = node->metaObject();
+ const int count = metaObj->propertyCount();
+
+ const auto toBackendValue = [](const QVariant &data) -> QVariant
+ {
+ if (data.canConvert<QNode*>()) {
+ QNode *node = data.value<QNode*>();
+
+ // Ensure the node and all ancestors have issued their node creation changes.
+ // We can end up here if a newly created node with a parent is immediately set
+ // as a property on another node. In this case the deferred call to
+ // _q_postConstructorInit() will not have happened yet as the event
+ // loop will still be blocked. We need to do this for all ancestors,
+ // since the subtree of this node otherwise can end up on the backend
+ // with a reference to a non-existent parent.
+ if (node)
+ QNodePrivate::get(node)->_q_ensureBackendNodeCreated();
+
+ const QNodeId id = node ? node->id() : QNodeId();
+ return QVariant::fromValue(id);
+ }
+
+ return data;
+ };
+
+ QPropertyUpdatedChange change(node->id());
+ QPropertyUpdatedChangePtr pchange(&change, [](QPropertyUpdatedChange *) { });
+ for (int index = offset; index < count; index++) {
+ const QMetaProperty pro = metaObj->property(index);
+ change.setPropertyName(pro.name());
+ change.setValue(toBackendValue(pro.read(node)));
+ backend->sceneChangeEvent(pchange);
}
+ auto const dynamicProperties = node->dynamicPropertyNames();
+ for (const QByteArray &name: dynamicProperties) {
+ change.setPropertyName(name.data());
+ change.setValue(toBackendValue(node->property(name.data())));
+ backend->sceneChangeEvent(pchange);
+ }
+}
+
+QBackendNode *QAbstractAspectPrivate::createBackendNode(const NodeTreeChange &change) const
+{
+ const QMetaObject *metaObj = change.metaObj;
+ const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj);
+ const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first;
+
if (!backendNodeMapper)
return nullptr;
- QBackendNode *backend = backendNodeMapper->get(change->subjectId());
+ QBackendNode *backend = backendNodeMapper->get(change.id);
if (backend != nullptr)
return backend;
- backend = backendNodeMapper->create(change);
+
+ QNode *node = change.node;
+ QNodeCreatedChangeBasePtr creationChange;
+ const bool supportsSyncing = backendNodeMapperInfo.second & SupportsSyncing;
+ if (supportsSyncing) {
+ // All objects modified to use syncing should only use the id in the creation functor
+ QNodeCreatedChangeBase changeObj(node);
+ creationChange = QNodeCreatedChangeBasePtr(&changeObj, [](QNodeCreatedChangeBase *) {});
+ backend = backendNodeMapper->create(creationChange);
+ } else {
+ creationChange = node->createNodeCreationChange();
+ backend = backendNodeMapper->create(creationChange);
+ }
if (!backend)
return nullptr;
// TODO: Find some place else to do all of this function from the arbiter
- backend->setPeerId(change->subjectId());
+ backend->setPeerId(change.id);
// Backend could be null if the user decides that his functor should only
// perform some action when encountering a given type of item but doesn't need to
// return a QBackendNode pointer.
QBackendNodePrivate *backendPriv = QBackendNodePrivate::get(backend);
- backendPriv->setEnabled(change->isNodeEnabled());
+ backendPriv->setEnabled(node->isEnabled());
// TO DO: Find a way to specify the changes to observe
// Register backendNode with QChangeArbiter
if (m_arbiter != nullptr) { // Unit tests may not have the arbiter registered
qCDebug(Nodes) << q_func()->objectName() << "Creating backend node for node id"
- << change->subjectId() << "of type" << change->metaObject()->className();
+ << node->id() << "of type" << QNodePrivate::get(node)->m_typeInfo->className();
m_arbiter->registerObserver(backendPriv, backend->peerId(), AllChanges);
if (backend->mode() == QBackendNode::ReadWrite)
m_arbiter->scene()->addObservable(backendPriv, backend->peerId());
}
- backend->initializeFromPeer(change);
+ if (supportsSyncing)
+ syncDirtyFrontEndNode(node, backend, true);
+ else
+ backend->initializeFromPeer(creationChange);
return backend;
}
-void QAbstractAspectPrivate::clearBackendNode(const QNodeDestroyedChangePtr &change) const
+void QAbstractAspectPrivate::clearBackendNode(const NodeTreeChange &change) const
{
- // Each QNodeDestroyedChange may contain info about a whole sub-tree of nodes that
- // are being destroyed. Iterate over them and process each in turn
- const auto subTree = change->subtreeIdsAndTypes();
- for (const auto &idAndType : subTree) {
- const QMetaObject *metaObj = idAndType.type;
- QBackendNodeMapperPtr backendNodeMapper;
-
- // Find backend node mapper for this type
- while (metaObj != nullptr && backendNodeMapper.isNull()) {
- backendNodeMapper = m_backendCreatorFunctors.value(metaObj);
- metaObj = metaObj->superClass();
- }
+ const QMetaObject *metaObj = change.metaObj;
+ const BackendNodeMapperAndInfo backendNodeMapperInfo = mapperForNode(metaObj);
+ const QBackendNodeMapperPtr backendNodeMapper = backendNodeMapperInfo.first;
- if (!backendNodeMapper)
- continue;
+ if (!backendNodeMapper)
+ return;
- // Request the mapper to destroy the corresponding backend node
- QBackendNode *backend = backendNodeMapper->get(idAndType.id);
- if (backend) {
- qCDebug(Nodes) << q_func()->objectName() << "Deleting backend node for node id"
- << idAndType.id << "of type" << idAndType.type->className();
- QBackendNodePrivate *backendPriv = QBackendNodePrivate::get(backend);
- m_arbiter->unregisterObserver(backendPriv, backend->peerId());
- if (backend->mode() == QBackendNode::ReadWrite)
- m_arbiter->scene()->removeObservable(backendPriv, backend->peerId());
- backendNodeMapper->destroy(idAndType.id);
- }
+ // Request the mapper to destroy the corresponding backend node
+ QBackendNode *backend = backendNodeMapper->get(change.id);
+ if (backend) {
+ qCDebug(Nodes) << "Deleting backend node for node id"
+ << change.id << "of type" << metaObj->className();
+ QBackendNodePrivate *backendPriv = QBackendNodePrivate::get(backend);
+ m_arbiter->unregisterObserver(backendPriv, backend->peerId());
+ if (backend->mode() == QBackendNode::ReadWrite)
+ m_arbiter->scene()->removeObservable(backendPriv, backend->peerId());
+ backendNodeMapper->destroy(change.id);
}
}
-void QAbstractAspectPrivate::setRootAndCreateNodes(QEntity *rootObject, const QVector<QNodeCreatedChangeBasePtr> &changes)
+void QAbstractAspectPrivate::setRootAndCreateNodes(QEntity *rootObject, const QVector<NodeTreeChange> &nodesChanges)
{
qCDebug(Aspects) << Q_FUNC_INFO << "rootObject =" << rootObject;
if (rootObject == m_root)
@@ -289,10 +479,11 @@ void QAbstractAspectPrivate::setRootAndCreateNodes(QEntity *rootObject, const QV
m_root = rootObject;
m_rootId = rootObject->id();
- for (const auto &change : changes)
+ for (const NodeTreeChange &change : nodesChanges)
createBackendNode(change);
}
+
QServiceLocator *QAbstractAspectPrivate::services() const
{
return m_aspectManager ? m_aspectManager->serviceLocator() : nullptr;
diff --git a/src/core/aspects/qabstractaspect.h b/src/core/aspects/qabstractaspect.h
index 1ae85e4e6..cb3d02089 100644
--- a/src/core/aspects/qabstractaspect.h
+++ b/src/core/aspects/qabstractaspect.h
@@ -42,6 +42,7 @@
#include <Qt3DCore/qt3dcore_global.h>
#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/qscenechange.h>
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
@@ -77,7 +78,7 @@ protected:
template<class Frontend>
void registerBackendType(const QBackendNodeMapperPtr &functor);
- void registerBackendType(const QMetaObject &, const QBackendNodeMapperPtr &functor);
+ void registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor);
template<class Frontend>
void unregisterBackendType();
void unregisterBackendType(const QMetaObject &);
diff --git a/src/core/aspects/qabstractaspect_p.h b/src/core/aspects/qabstractaspect_p.h
index e743dc63a..325fca678 100644
--- a/src/core/aspects/qabstractaspect_p.h
+++ b/src/core/aspects/qabstractaspect_p.h
@@ -56,9 +56,8 @@
#include <Qt3DCore/private/qaspectjobproviderinterface_p.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/private/qbackendnodefactory_p.h>
-#include <Qt3DCore/private/qsceneobserverinterface_p.h>
#include <Qt3DCore/private/qt3dcore_global_p.h>
+#include <Qt3DCore/private/qscenechange_p.h>
#include <QtCore/private/qobject_p.h>
#include <QMutex>
@@ -102,50 +101,77 @@ private:
} // Debug
+struct NodeTreeChange
+{
+ enum NodeTreeChangeType {
+ Added = 0,
+ Removed = 1
+ };
+ Qt3DCore::QNodeId id;
+ const QMetaObject *metaObj;
+ NodeTreeChangeType type;
+ Qt3DCore::QNode *node;
+};
+
class Q_3DCORE_PRIVATE_EXPORT QAbstractAspectPrivate
: public QObjectPrivate
- , public QBackendNodeFactory
- , public QSceneObserverInterface
, public QAspectJobProviderInterface
{
public:
QAbstractAspectPrivate();
~QAbstractAspectPrivate();
- void setRootAndCreateNodes(QEntity *rootObject, const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> &changes);
+ void setRootAndCreateNodes(QEntity *rootObject, const QVector<NodeTreeChange> &nodesTreeChanges);
QServiceLocator *services() const;
QAbstractAspectJobManager *jobManager() const;
QVector<QAspectJobPtr> jobsToExecute(qint64 time) override;
- QBackendNode *createBackendNode(const QNodeCreatedChangeBasePtr &change) const override;
- void clearBackendNode(const QNodeDestroyedChangePtr &change) const;
-
- void sceneNodeAdded(Qt3DCore::QSceneChangePtr &e) override;
- void sceneNodeRemoved(Qt3DCore::QSceneChangePtr &e) override;
+ QBackendNode *createBackendNode(const NodeTreeChange &change) const;
+ void clearBackendNode(const NodeTreeChange &change) const;
+ void syncDirtyFrontEndNodes(const QVector<QNode *> &nodes);
+ void syncDirtyFrontEndSubNodes(const QVector<NodeRelationshipChange> &nodes);
+ virtual void syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const;
+ void sendPropertyMessages(QNode *node, QBackendNode *backend) const;
virtual void onEngineAboutToShutdown();
- // TODO: Make these public in 5.8
+ // TODO: Make public at some point
+ template<class Frontend, bool supportsSyncing>
+ void registerBackendType(const QBackendNodeMapperPtr &functor);
+ void registerBackendType(const QMetaObject &obj, const QBackendNodeMapperPtr &functor, bool supportsSyncing);
template<class Frontend>
void unregisterBackendType();
void unregisterBackendType(const QMetaObject &mo);
Q_DECLARE_PUBLIC(QAbstractAspect)
+ enum NodeMapperInfo {
+ DefaultMapper = 0,
+ SupportsSyncing = 1 << 0
+ };
+ using BackendNodeMapperAndInfo = QPair<QBackendNodeMapperPtr, NodeMapperInfo>;
+ BackendNodeMapperAndInfo mapperForNode(const QMetaObject *metaObj) const;
+
QEntity *m_root;
QNodeId m_rootId;
QAspectManager *m_aspectManager;
QAbstractAspectJobManager *m_jobManager;
QChangeArbiter *m_arbiter;
- QHash<const QMetaObject*, QBackendNodeMapperPtr> m_backendCreatorFunctors;
+ QHash<const QMetaObject*, BackendNodeMapperAndInfo> m_backendCreatorFunctors;
QMutex m_singleShotMutex;
QVector<QAspectJobPtr> m_singleShotJobs;
static QAbstractAspectPrivate *get(QAbstractAspect *aspect);
};
+template<class Frontend, bool supportsSyncing>
+void QAbstractAspectPrivate::registerBackendType(const QBackendNodeMapperPtr &functor)
+{
+ registerBackendType(Frontend::staticMetaObject, functor, supportsSyncing);
+}
+
template<class Frontend>
void QAbstractAspectPrivate::unregisterBackendType()
{
diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp
index 3f219597e..426741a61 100644
--- a/src/core/aspects/qaspectengine.cpp
+++ b/src/core/aspects/qaspectengine.cpp
@@ -47,13 +47,11 @@
#include <QtCore/QMetaObject>
#include <Qt3DCore/private/corelogging_p.h>
-#include <Qt3DCore/private/qaspectthread_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qnodevisitor_p.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qpostman_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
@@ -65,6 +63,51 @@
QT_BEGIN_NAMESPACE
+namespace{
+
+QVector<Qt3DCore::QNode *> getNodesForCreation(Qt3DCore::QNode *root)
+{
+ using namespace Qt3DCore;
+
+ QVector<QNode *> nodes;
+ QNodeVisitor visitor;
+ visitor.traverse(root, [&nodes](QNode *node) {
+ nodes.append(node);
+
+ // Store the metaobject of the node in the QNode so that we have it available
+ // to us during destruction in the QNode destructor. This allows us to send
+ // the QNodeId and the metaobject as typeinfo to the backend aspects so they
+ // in turn can find the correct QBackendNodeMapper object to handle the destruction
+ // of the corresponding backend nodes.
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(QNodePrivate::findStaticMetaObject(node->metaObject()));
+
+ // Mark this node as having been handled for creation so that it is picked up
+ d->m_hasBackendNode = true;
+ });
+
+ return nodes;
+}
+
+QVector<Qt3DCore::QNode *> getNodesForRemoval(Qt3DCore::QNode *root)
+{
+ using namespace Qt3DCore;
+
+ QVector<QNode *> nodes;
+ QNodeVisitor visitor;
+ visitor.traverse(root, [&nodes](QNode *node) {
+ nodes.append(node);
+
+ // Mark this node as having been handled for destruction so we don't
+ // repeat it unnecessarily in an O(n^2) manner
+ QNodePrivate::get(node)->m_hasBackendNode = false;
+ });
+
+ return nodes;
+}
+
+}
+
namespace Qt3DCore {
QAspectEnginePrivate *QAspectEnginePrivate::get(QAspectEngine *q)
@@ -74,9 +117,11 @@ QAspectEnginePrivate *QAspectEnginePrivate::get(QAspectEngine *q)
QAspectEnginePrivate::QAspectEnginePrivate()
: QObjectPrivate()
+ , m_aspectManager(nullptr)
, m_postman(nullptr)
, m_scene(nullptr)
, m_initialized(false)
+ , m_runMode(QAspectEngine::Automatic)
#if QT_CONFIG(qt3d_profile_jobs)
, m_commandDebugger(new Debug::AspectCommandDebugger(q_func()))
#endif
@@ -119,10 +164,14 @@ void QAspectEnginePrivate::initEntity(QEntity *entity)
}
}
-void QAspectEnginePrivate::generateCreationChanges(QNode *root)
+void QAspectEnginePrivate::addNode(QNode *node)
+{
+ m_aspectManager->addNodes(getNodesForCreation(node));
+}
+
+void QAspectEnginePrivate::removeNode(QNode *node)
{
- const QNodeCreatedChangeGenerator generator(root);
- m_creationChanges = generator.creationChanges();
+ m_aspectManager->removeNodes(getNodesForRemoval(node));
}
/*!
@@ -185,8 +234,7 @@ QAspectEngine::QAspectEngine(QObject *parent)
d->m_scene = new QScene(this);
d->m_postman = new QPostman(this);
d->m_postman->setScene(d->m_scene);
- d->m_aspectThread = new QAspectThread(this);
- d->m_aspectThread->waitForStart(QThread::HighestPriority);
+ d->m_aspectManager = new QAspectManager(this);
}
/*!
@@ -206,11 +254,6 @@ QAspectEngine::~QAspectEngine()
for (auto aspect : aspects)
unregisterAspect(aspect);
- // Wait for thread to have completed it's final loop of execution
- d->m_aspectThread->aspectManager()->quit();
- d->m_aspectThread->wait();
-
- delete d->m_aspectThread;
delete d->m_postman;
delete d->m_scene;
}
@@ -225,16 +268,14 @@ void QAspectEnginePrivate::initNodeTree(QNode *node)
void QAspectEnginePrivate::initialize()
{
- QChangeArbiter *arbiter = m_aspectThread->aspectManager()->changeArbiter();
+ m_aspectManager->initialize();
+ QChangeArbiter *arbiter = m_aspectManager->changeArbiter();
m_scene->setArbiter(arbiter);
QChangeArbiter::createUnmanagedThreadLocalChangeQueue(arbiter);
- QMetaObject::invokeMethod(arbiter,
- "setPostman",
- Q_ARG(Qt3DCore::QAbstractPostman*, m_postman));
- QMetaObject::invokeMethod(arbiter,
- "setScene",
- Q_ARG(Qt3DCore::QScene*, m_scene));
+ arbiter->setPostman(m_postman);
+ arbiter->setScene(m_scene);
m_initialized = true;
+ m_aspectManager->setPostConstructorInit(m_scene->postConstructorInit());
#if QT_CONFIG(qt3d_profile_jobs)
m_commandDebugger->setAspectEngine(q_func());
m_commandDebugger->initialize();
@@ -263,14 +304,14 @@ void QAspectEnginePrivate::shutdown()
// Cleanup the scene before quitting the backend
m_scene->setArbiter(nullptr);
- QChangeArbiter *arbiter = m_aspectThread->aspectManager()->changeArbiter();
+ QChangeArbiter *arbiter = m_aspectManager->changeArbiter();
QChangeArbiter::destroyUnmanagedThreadLocalChangeQueue(arbiter);
m_initialized = false;
}
void QAspectEnginePrivate::exitSimulationLoop()
{
- m_aspectThread->aspectManager()->exitSimulationLoop();
+ m_aspectManager->exitSimulationLoop();
}
/*!
@@ -285,12 +326,8 @@ void QAspectEngine::registerAspect(QAbstractAspect *aspect)
// AspectManager::registerAspect is called in the context
// of the AspectThread. This is turns call aspect->onInitialize
// still in the same AspectThread context
- aspect->moveToThread(d->m_aspectThread);
d->m_aspects << aspect;
- QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(),
- "registerAspect",
- Qt::BlockingQueuedConnection,
- Q_ARG(Qt3DCore::QAbstractAspect*, aspect));
+ d->m_aspectManager->registerAspect(aspect);
}
/*!
@@ -327,10 +364,7 @@ void QAspectEngine::unregisterAspect(QAbstractAspect *aspect)
// Tell the aspect manager to give the aspect a chance to do some cleanup
// in its QAbstractAspect::onUnregistered() virtual
- QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(),
- "unregisterAspect",
- Qt::BlockingQueuedConnection,
- Q_ARG(Qt3DCore::QAbstractAspect*, aspect));
+ d->m_aspectManager->unregisterAspect(aspect);
// Remove from our collection of named aspects (if present)
const auto it = std::find_if(d->m_namedAspects.begin(), d->m_namedAspects.end(),
@@ -381,9 +415,9 @@ QVariant QAspectEngine::executeCommand(const QString &command)
{
Q_D(QAspectEngine);
- if (command == QLatin1Literal("list aspects")) {
+ if (command == QLatin1String("list aspects")) {
if (d->m_aspects.isEmpty())
- return QLatin1Literal("No loaded aspect");
+ return QLatin1String("No loaded aspect");
QString reply;
reply += QLatin1String("Loaded aspects:");
@@ -409,6 +443,19 @@ QVariant QAspectEngine::executeCommand(const QString &command)
}
/*!
+ * If using the manual run mode, this function executes the jobs for each aspect.
+ * It is blocking and won't return until all jobs have been completed.
+ *
+ * If you are using the QRenderAspect,
+ */
+void QAspectEngine::processFrame()
+{
+ Q_D(QAspectEngine);
+ Q_ASSERT(d->m_runMode == QAspectEngine::Manual);
+ d->m_aspectManager->processFrame();
+}
+
+/*!
* Sets the \a root entity for the aspect engine.
*/
void QAspectEngine::setRootEntity(QEntityPtr root)
@@ -445,8 +492,10 @@ void QAspectEngine::setRootEntity(QEntityPtr root)
// deregister the nodes from the scene
d->initNodeTree(root.data());
- // Traverse tree to generate a vector of creation changes
- d->generateCreationChanges(root.data());
+ const QVector<QNode *> nodes = getNodesForCreation(root.data());
+
+ // Specify if the AspectManager should be driving the simulation loop or not
+ d->m_aspectManager->setRunMode(d->m_runMode);
// Finally, tell the aspects about the new scene object tree. This is done
// in a blocking manner to allow the aspects to get synchronized before the
@@ -455,14 +504,9 @@ void QAspectEngine::setRootEntity(QEntityPtr root)
// TODO: Pass the creation changes via the arbiter rather than relying upon
// an invokeMethod call.
qCDebug(Aspects) << "Begin setting scene root on aspect manager";
- QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(),
- "setRootEntity",
- Qt::BlockingQueuedConnection,
- Q_ARG(Qt3DCore::QEntity*, root.data()),
- Q_ARG(QVector<Qt3DCore::QNodeCreatedChangeBasePtr>, d->m_creationChanges));
+ d->m_aspectManager->setRootEntity(root.data(), nodes);
qCDebug(Aspects) << "Done setting scene root on aspect manager";
-
- d->m_aspectThread->aspectManager()->enterSimulationLoop();
+ d->m_aspectManager->enterSimulationLoop();
}
/*!
@@ -474,6 +518,20 @@ QEntityPtr QAspectEngine::rootEntity() const
return d->m_root;
}
+void QAspectEngine::setRunMode(QAspectEngine::RunMode mode)
+{
+ Q_D(QAspectEngine);
+ d->m_runMode = mode;
+ if (d->m_aspectManager)
+ d->m_aspectManager->setRunMode(mode);
+}
+
+QAspectEngine::RunMode QAspectEngine::runMode() const
+{
+ Q_D(const QAspectEngine);
+ return d->m_runMode;
+}
+
} // namespace Qt3DCore
QT_END_NAMESPACE
diff --git a/src/core/aspects/qaspectengine.h b/src/core/aspects/qaspectengine.h
index 7f900ad52..1d5d7e220 100644
--- a/src/core/aspects/qaspectengine.h
+++ b/src/core/aspects/qaspectengine.h
@@ -60,12 +60,21 @@ class Q_3DCORESHARED_EXPORT QAspectEngine : public QObject
{
Q_OBJECT
public:
+ enum RunMode {
+ Manual = 0,
+ Automatic
+ };
+ Q_ENUM(RunMode)
+
explicit QAspectEngine(QObject *parent = nullptr);
~QAspectEngine();
void setRootEntity(QEntityPtr root);
QEntityPtr rootEntity() const;
+ void setRunMode(RunMode mode);
+ RunMode runMode() const;
+
void registerAspect(QAbstractAspect *aspect);
void registerAspect(const QString &name);
void unregisterAspect(QAbstractAspect *aspect);
@@ -75,6 +84,8 @@ public:
QVariant executeCommand(const QString &command);
+ void processFrame();
+
private:
Q_DECLARE_PRIVATE(QAspectEngine)
};
diff --git a/src/core/aspects/qaspectengine_p.h b/src/core/aspects/qaspectengine_p.h
index 2d7d0fe93..c83940435 100644
--- a/src/core/aspects/qaspectengine_p.h
+++ b/src/core/aspects/qaspectengine_p.h
@@ -56,6 +56,7 @@
#include <QtCore/qsharedpointer.h>
#include <Qt3DCore/private/qaspectfactory_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
#include <QtCore/private/qobject_p.h>
QT_BEGIN_NAMESPACE
@@ -64,8 +65,7 @@ namespace Qt3DCore {
class QEntity;
class QNode;
-class QAspectEngine;
-class QAspectThread;
+class QAspectManager;
class QPostman;
class QScene;
@@ -84,13 +84,14 @@ public:
Q_DECLARE_PUBLIC(QAspectEngine)
QAspectFactory m_factory;
- QAspectThread *m_aspectThread;
+ QAspectManager *m_aspectManager;
QPostman *m_postman;
QScene *m_scene;
QSharedPointer<QEntity> m_root;
QVector<QAbstractAspect*> m_aspects;
QHash<QString, QAbstractAspect *> m_namedAspects;
bool m_initialized;
+ QAspectEngine::RunMode m_runMode;
#if QT_CONFIG(qt3d_profile_jobs)
Debug::AspectCommandDebugger *m_commandDebugger;
@@ -104,9 +105,8 @@ public:
void initNodeTree(QNode *node);
void initNode(QNode *node);
void initEntity(QEntity *entity);
-
- void generateCreationChanges(QNode *rootNode);
- QVector<QNodeCreatedChangeBasePtr> m_creationChanges;
+ void addNode(QNode *node);
+ void removeNode(QNode *node);
static QAspectEnginePrivate *get(QAspectEngine *engine);
};
diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp
index e9642116a..f24248399 100644
--- a/src/core/aspects/qaspectmanager.cpp
+++ b/src/core/aspects/qaspectmanager.cpp
@@ -60,6 +60,11 @@
#include <Qt3DCore/private/qthreadpooler_p.h>
#include <Qt3DCore/private/qtickclock_p.h>
#include <Qt3DCore/private/qtickclockservice_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DCore/private/qscene_p.h>
+
+#include <QtCore/QCoreApplication>
#if defined(QT3D_CORE_JOB_TIMING)
#include <QElapsedTimer>
@@ -69,6 +74,26 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
+namespace {
+
+class RequestFrameEvent : public QEvent
+{
+public:
+ RequestFrameEvent()
+ : QEvent(static_cast<QEvent::Type>(RequestFrameEvent::requestEventType))
+ {}
+
+ static int eventType() { return RequestFrameEvent::requestEventType; }
+
+private:
+ static int requestEventType;
+};
+
+int RequestFrameEvent::requestEventType = QEvent::registerEventType();
+
+} // anonymous
+
+
/*!
\class Qt3DCore::QAspectManager
\internal
@@ -80,14 +105,11 @@ QAspectManager::QAspectManager(QObject *parent)
, m_jobManager(new QAspectJobManager(this))
, m_changeArbiter(new QChangeArbiter(this))
, m_serviceLocator(new QServiceLocator())
- , m_waitForEndOfSimulationLoop(0)
- , m_waitForStartOfSimulationLoop(0)
- , m_waitForEndOfExecLoop(0)
- , m_waitForQuit(0)
+ , m_simulationLoopRunning(false)
+ , m_driveMode(QAspectEngine::Automatic)
+ , m_postConstructorInit(nullptr)
{
qRegisterMetaType<QSurface *>("QSurface*");
- m_runSimulationLoop.fetchAndStoreOrdered(0);
- m_runMainLoop.fetchAndStoreOrdered(1);
qCDebug(Aspects) << Q_FUNC_INFO;
}
@@ -98,19 +120,37 @@ QAspectManager::~QAspectManager()
delete m_scheduler;
}
+void QAspectManager::setRunMode(QAspectEngine::RunMode mode)
+{
+ qCDebug(Aspects) << Q_FUNC_INFO << "Running Loop Drive Mode set to" << mode;
+ m_driveMode = mode;
+}
+
// Main thread (called by QAspectEngine)
void QAspectManager::enterSimulationLoop()
{
qCDebug(Aspects) << Q_FUNC_INFO;
- m_runSimulationLoop.fetchAndStoreOrdered(1);
+ m_simulationLoopRunning = true;
+
+ // Retrieve the frame advance service. Defaults to timer based if there is no renderer.
+ QAbstractFrameAdvanceService *frameAdvanceService =
+ m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService);
- // Wake up QAspectThread's event loop
- thread()->eventDispatcher()->wakeUp();
+ // Start the frameAdvanceService
+ frameAdvanceService->start();
- // We wait for the setRootEntity on the aspectManager to have completed
- // This ensures we cannot shutdown before the aspects have had a chance
- // to be initialized
- m_waitForStartOfSimulationLoop.acquire(1);
+ // We are about to enter the simulation loop. Give aspects a chance to do any last
+ // pieces of initialization
+ qCDebug(Aspects) << "Calling onEngineStartup() for each aspect";
+ for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
+ qCDebug(Aspects) << "\t" << aspect->objectName();
+ aspect->onEngineStartup();
+ }
+ qCDebug(Aspects) << "Done calling onEngineStartup() for each aspect";
+
+ // Start running loop if Qt3D is in charge of driving it
+ if (m_driveMode == QAspectEngine::Automatic)
+ requestNextFrame();
}
// Main thread (called by QAspectEngine)
@@ -119,7 +159,7 @@ void QAspectManager::exitSimulationLoop()
qCDebug(Aspects) << Q_FUNC_INFO;
// If this fails, simulation loop is already exited so nothing to do
- if (!m_runSimulationLoop.testAndSetOrdered(1, 0)) {
+ if (!m_simulationLoopRunning) {
qCDebug(Aspects) << "Simulation loop was not running. Nothing to do";
return;
}
@@ -141,17 +181,26 @@ void QAspectManager::exitSimulationLoop()
for (QAbstractAspect *aspect : qAsConst(m_aspects))
aspect->d_func()->onEngineAboutToShutdown();
+ // Process any pending changes from the frontend before we shut the aspects down
+ m_changeArbiter->syncChanges();
+
+ // Give aspects a chance to perform any shutdown actions. This may include unqueuing
+ // any blocking work on the main thread that could potentially deadlock during shutdown.
+ qCDebug(Aspects) << "Calling onEngineShutdown() for each aspect";
+ for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
+ qCDebug(Aspects) << "\t" << aspect->objectName();
+ aspect->onEngineShutdown();
+ }
+ qCDebug(Aspects) << "Done calling onEngineShutdown() for each aspect";
- qCDebug(Aspects) << "exitSimulationLoop waiting for exec loop to terminate";
- // Wait until the simulation loop is fully exited and the aspects are done
- // processing any final changes and have had onEngineShutdown() called on them
- m_waitForEndOfSimulationLoop.acquire(1);
+
+ m_simulationLoopRunning = false;
qCDebug(Aspects) << "exitSimulationLoop completed";
}
bool QAspectManager::isShuttingDown() const
{
- return !m_runSimulationLoop.load();
+ return !m_simulationLoopRunning;
}
/*!
@@ -178,14 +227,11 @@ void QAspectManager::shutdown()
{
qCDebug(Aspects) << Q_FUNC_INFO;
- for (QAbstractAspect *aspect : qAsConst(m_aspects))
- m_changeArbiter->unregisterSceneObserver(aspect->d_func());
-
// Aspects must be deleted in the Thread they were created in
}
-// QAspectThread:: queued invoked by QAspectEngine::setRootEntity
-void QAspectManager::setRootEntity(Qt3DCore::QEntity *root, const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> &changes)
+// MainThread called by QAspectEngine::setRootEntity
+void QAspectManager::setRootEntity(Qt3DCore::QEntity *root, const QVector<QNode *> &nodes)
{
qCDebug(Aspects) << Q_FUNC_INFO;
@@ -200,8 +246,70 @@ void QAspectManager::setRootEntity(Qt3DCore::QEntity *root, const QVector<Qt3DCo
m_root = root;
if (m_root) {
+
+ QVector<NodeTreeChange> nodeTreeChanges;
+ nodeTreeChanges.reserve(nodes.size());
+
+ for (QNode *n : nodes) {
+ nodeTreeChanges.push_back({
+ n->id(),
+ QNodePrivate::get(n)->m_typeInfo,
+ NodeTreeChange::Added,
+ n
+ });
+ }
+
for (QAbstractAspect *aspect : qAsConst(m_aspects))
- aspect->d_func()->setRootAndCreateNodes(m_root, changes);
+ aspect->d_func()->setRootAndCreateNodes(m_root, nodeTreeChanges);
+ }
+}
+
+
+// Main Thread -> immediately following node insertion
+void QAspectManager::addNodes(const QVector<QNode *> &nodes)
+{
+ // We record the nodes added information, which we will actually use when
+ // processFrame is called (later but within the same loop of the even loop
+ // as this call) The idea is we want to avoid modifying the backend tree if
+ // the Renderer hasn't allowed processFrame to continue yet
+
+ QVector<NodeTreeChange> treeChanges;
+ treeChanges.reserve(nodes.size());
+
+ for (QNode *node : nodes) {
+ treeChanges.push_back({ node->id(),
+ QNodePrivate::get(node)->m_typeInfo,
+ NodeTreeChange::Added,
+ node });
+ }
+
+ m_nodeTreeChanges += treeChanges;
+}
+
+// Main Thread -> immediately following node destruction (call from QNode dtor)
+void QAspectManager::removeNodes(const QVector<QNode *> &nodes)
+{
+ // We record the nodes removed information, which we will actually use when
+ // processFrame is called (later but within the same loop of the even loop
+ // as this call) The idea is we want to avoid modifying the backend tree if
+ // the Renderer hasn't allowed processFrame to continue yet The drawback is
+ // that when processFrame is processed, the QNode* pointer might be invalid by
+ // that point. Therefore we record all we need to remove the object.
+
+ for (QNode *node : nodes) {
+ // In addition, we check if we contain an Added change for a given node
+ // that is now about to be destroyed. If so we remove the Added change
+ // entirely
+
+ m_nodeTreeChanges.erase(std::remove_if(m_nodeTreeChanges.begin(),
+ m_nodeTreeChanges.end(),
+ [&node] (const NodeTreeChange &change) { return change.id == node->id(); }),
+ m_nodeTreeChanges.end());
+
+ m_nodeTreeChanges.push_back({ node->id(),
+ QNodePrivate::get(node)->m_typeInfo,
+ NodeTreeChange::Removed,
+ nullptr });
}
}
@@ -219,8 +327,6 @@ void QAspectManager::registerAspect(QAbstractAspect *aspect)
QAbstractAspectPrivate::get(aspect)->m_aspectManager = this;
QAbstractAspectPrivate::get(aspect)->m_jobManager = m_jobManager;
QAbstractAspectPrivate::get(aspect)->m_arbiter = m_changeArbiter;
- // Register sceneObserver with the QChangeArbiter
- m_changeArbiter->registerSceneObserver(aspect->d_func());
// Allow the aspect to do some work now that it is registered
aspect->onRegistered();
@@ -243,7 +349,6 @@ void QAspectManager::unregisterAspect(Qt3DCore::QAbstractAspect *aspect)
qCDebug(Aspects) << "Unregistering aspect";
Q_ASSERT(aspect);
aspect->onUnregistered();
- m_changeArbiter->unregisterSceneObserver(aspect->d_func());
QAbstractAspectPrivate::get(aspect)->m_arbiter = nullptr;
QAbstractAspectPrivate::get(aspect)->m_jobManager = nullptr;
QAbstractAspectPrivate::get(aspect)->m_aspectManager = nullptr;
@@ -251,139 +356,166 @@ void QAspectManager::unregisterAspect(Qt3DCore::QAbstractAspect *aspect)
qCDebug(Aspects) << "Completed unregistering aspect";
}
-void QAspectManager::exec()
+const QVector<QAbstractAspect *> &QAspectManager::aspects() const
{
- // Gentlemen, start your engines
- QEventLoop eventLoop;
-
- // Enter the engine loop
- qCDebug(Aspects) << Q_FUNC_INFO << "***** Entering main loop *****";
- while (m_runMainLoop.load()) {
- // Process events until we're told to start the simulation loop
- while (m_runMainLoop.load() && !m_runSimulationLoop.load())
- eventLoop.processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents);
-
- if (!m_runSimulationLoop.load())
- break;
-
- // Retrieve the frame advance service. Defaults to timer based if there is no renderer.
- QAbstractFrameAdvanceService *frameAdvanceService =
- m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService);
+ return m_aspects;
+}
- // Start the frameAdvanceService
- frameAdvanceService->start();
+QAbstractAspectJobManager *QAspectManager::jobManager() const
+{
+ return m_jobManager;
+}
- // We are about to enter the simulation loop. Give aspects a chance to do any last
- // pieces of initialization
- qCDebug(Aspects) << "Calling onEngineStartup() for each aspect";
- for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
- qCDebug(Aspects) << "\t" << aspect->objectName();
- aspect->onEngineStartup();
- }
- qCDebug(Aspects) << "Done calling onEngineStartup() for each aspect";
- m_waitForStartOfSimulationLoop.release(1);
-
- // Only enter main simulation loop once the renderer and other aspects are initialized
- while (m_runSimulationLoop.load()) {
- qint64 t = frameAdvanceService->waitForNextFrame();
-
- // Distribute accumulated changes. This includes changes sent from the frontend
- // to the backend nodes. We call this before the call to m_scheduler->update() to ensure
- // that any property changes do not set dirty flags in a data race with the renderer's
- // submission thread which may be looking for dirty flags, acting upon them and then
- // clearing the dirty flags.
- //
- // Doing this as the first call in the new frame ensures the lock free approach works
- // without any such data race.
-#if QT_CONFIG(qt3d_profile_jobs)
- const quint32 arbiterId = 4096;
- JobRunStats changeArbiterStats;
- changeArbiterStats.jobId.typeAndInstance[0] = arbiterId;
- changeArbiterStats.jobId.typeAndInstance[1] = 0;
- changeArbiterStats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
- changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
-#endif
- m_changeArbiter->syncChanges();
-#if QT_CONFIG(qt3d_profile_jobs)
- changeArbiterStats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- QThreadPooler::addJobLogStatsEntry(changeArbiterStats);
-#endif
+QChangeArbiter *QAspectManager::changeArbiter() const
+{
+ return m_changeArbiter;
+}
- // For each Aspect
- // Ask them to launch set of jobs for the current frame
- // Updates matrices, bounding volumes, render bins ...
-#if defined(QT3D_CORE_JOB_TIMING)
- QElapsedTimer timer;
- timer.start();
-#endif
- m_scheduler->scheduleAndWaitForFrameAspectJobs(t);
-#if defined(QT3D_CORE_JOB_TIMING)
- qDebug() << "Jobs took" << timer.nsecsElapsed() / 1.0e6;
-#endif
+QServiceLocator *QAspectManager::serviceLocator() const
+{
+ return m_serviceLocator.data();
+}
- // Process any pending events
- eventLoop.processEvents();
- } // End of simulation loop
+void QAspectManager::setPostConstructorInit(NodePostConstructorInit *postConstructorInit)
+{
+ m_postConstructorInit = postConstructorInit;
+}
- // Process any pending changes from the frontend before we shut the aspects down
- m_changeArbiter->syncChanges();
+QNode *QAspectManager::lookupNode(QNodeId id) const
+{
+ if (!m_root)
+ return nullptr;
- // Give aspects a chance to perform any shutdown actions. This may include unqueuing
- // any blocking work on the main thread that could potentially deadlock during shutdown.
- qCDebug(Aspects) << "Calling onEngineShutdown() for each aspect";
- for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
- qCDebug(Aspects) << "\t" << aspect->objectName();
- aspect->onEngineShutdown();
- }
- qCDebug(Aspects) << "Done calling onEngineShutdown() for each aspect";
+ QNodePrivate *d = QNodePrivate::get(m_root);
+ return d->m_scene ? d->m_scene->lookupNode(id) : nullptr;
+}
- // Wake up the main thread which is waiting for us inside of exitSimulationLoop()
- m_waitForEndOfSimulationLoop.release(1);
- } // End of main loop
- qCDebug(Aspects) << Q_FUNC_INFO << "***** Exited main loop *****";
+QVector<QNode *> QAspectManager::lookupNodes(const QVector<QNodeId> &ids) const
+{
+ if (!m_root)
+ return {};
- m_waitForEndOfExecLoop.release(1);
- m_waitForQuit.acquire(1);
+ QNodePrivate *d = QNodePrivate::get(m_root);
+ return d->m_scene ? d->m_scene->lookupNodes(ids) : QVector<QNode *>{};
}
-void QAspectManager::quit()
+/*!
+ \internal
+ \brief Drives the Qt3D simulation loop in the main thread
+ */
+bool QAspectManager::event(QEvent *e)
{
- qCDebug(Aspects) << Q_FUNC_INFO;
+ if (e->type() == RequestFrameEvent::eventType()) {
- Q_ASSERT_X(m_runSimulationLoop.load() == 0, "QAspectManagr::quit()", "Inner loop is still running");
- m_runMainLoop.fetchAndStoreOrdered(0);
+ // Process current frame
+ processFrame();
- // Wake up QAspectThread's event loop if needed
- thread()->eventDispatcher()->wakeUp();
+ // Request next frame if we are still running and if Qt3D is driving
+ // the loop
+ if (m_simulationLoopRunning && m_driveMode == QAspectEngine::Automatic)
+ requestNextFrame();
- // We need to wait for the QAspectManager exec loop to terminate
- m_waitForEndOfExecLoop.acquire(1);
- m_waitForQuit.release(1);
+ return true;
+ }
- qCDebug(Aspects) << Q_FUNC_INFO << "Exiting";
+ return QObject::event(e);
}
-const QVector<QAbstractAspect *> &QAspectManager::aspects() const
+void QAspectManager::requestNextFrame()
{
- return m_aspects;
+ qCDebug(Aspects) << "Requesting new Frame";
+ // Post event in the event loop to force
+ // next frame to be processed
+ QCoreApplication::postEvent(this, new RequestFrameEvent());
}
-QAbstractAspectJobManager *QAspectManager::jobManager() const
+void QAspectManager::processFrame()
{
- return m_jobManager;
-}
+ qCDebug(Aspects) << "Processing Frame";
-QChangeArbiter *QAspectManager::changeArbiter() const
-{
- return m_changeArbiter;
-}
+ // Retrieve the frame advance service. Defaults to timer based if there is no renderer.
+ QAbstractFrameAdvanceService *frameAdvanceService =
+ m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService);
-QServiceLocator *QAspectManager::serviceLocator() const
-{
- return m_serviceLocator.data();
+ const qint64 t = frameAdvanceService->waitForNextFrame();
+ if (t < 0)
+ return;
+
+ // Distribute accumulated changes. This includes changes sent from the frontend
+ // to the backend nodes. We call this before the call to m_scheduler->update() to ensure
+ // that any property changes do not set dirty flags in a data race with the renderer's
+ // submission thread which may be looking for dirty flags, acting upon them and then
+ // clearing the dirty flags.
+ //
+ // Doing this as the first call in the new frame ensures the lock free approach works
+ // without any such data race.
+#if QT_CONFIG(qt3d_profile_jobs)
+ const quint32 arbiterId = 4096;
+ JobRunStats changeArbiterStats;
+ changeArbiterStats.jobId.typeAndInstance[0] = arbiterId;
+ changeArbiterStats.jobId.typeAndInstance[1] = 0;
+ changeArbiterStats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
+ changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
+#endif
+
+ // Tell the NodePostConstructorInit to process any pending nodes which will add them to our list of
+ // tree changes
+ m_postConstructorInit->processNodes();
+
+ // Add and Remove Nodes
+ const QVector<NodeTreeChange> nodeTreeChanges = std::move(m_nodeTreeChanges);
+ for (const NodeTreeChange &change : nodeTreeChanges) {
+ // Buckets ensure that even if we have intermingled node added / removed
+ // buckets, we preserve the order of the sequences
+
+ for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
+ switch (change.type) {
+ case NodeTreeChange::Added:
+ aspect->d_func()->createBackendNode(change);
+ break;
+ case NodeTreeChange::Removed:
+ aspect->d_func()->clearBackendNode(change);
+ break;
+ }
+ }
+ }
+
+ // Sync node / subnode relationship changes
+ const auto dirtySubNodes = m_changeArbiter->takeDirtyFrontEndSubNodes();
+ if (dirtySubNodes.size())
+ for (QAbstractAspect *aspect : qAsConst(m_aspects))
+ QAbstractAspectPrivate::get(aspect)->syncDirtyFrontEndSubNodes(dirtySubNodes);
+
+ // Sync property updates
+ const auto dirtyFrontEndNodes = m_changeArbiter->takeDirtyFrontEndNodes();
+ if (dirtyFrontEndNodes.size())
+ for (QAbstractAspect *aspect : qAsConst(m_aspects))
+ QAbstractAspectPrivate::get(aspect)->syncDirtyFrontEndNodes(dirtyFrontEndNodes);
+
+ // TO DO: Having this done in the main thread actually means aspects could just
+ // as simply read info out of the Frontend classes without risk of introducing
+ // races. This could therefore be removed for Qt 6.
+ m_changeArbiter->syncChanges();
+#if QT_CONFIG(qt3d_profile_jobs)
+ changeArbiterStats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
+ QThreadPooler::addJobLogStatsEntry(changeArbiterStats);
+#endif
+
+ // For each Aspect
+ // Ask them to launch set of jobs for the current frame
+ // Updates matrices, bounding volumes, render bins ...
+#if defined(QT3D_CORE_JOB_TIMING)
+ QElapsedTimer timer;
+ timer.start();
+#endif
+ m_scheduler->scheduleAndWaitForFrameAspectJobs(t);
+#if defined(QT3D_CORE_JOB_TIMING)
+ qDebug() << "Jobs took" << timer.nsecsElapsed() / 1.0e6;
+#endif
+
+ // TODO sync backend changes to frontend
}
} // namespace Qt3DCore
QT_END_NAMESPACE
-
diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h
index de978b8e9..ebc148324 100644
--- a/src/core/aspects/qaspectmanager_p.h
+++ b/src/core/aspects/qaspectmanager_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qnodecreatedchange.h>
+#include <Qt3DCore/qaspectengine.h>
#include <QtCore/QObject>
#include <QtCore/QScopedPointer>
#include <QtCore/QSemaphore>
@@ -72,16 +73,18 @@ class QScheduler;
class QChangeArbiter;
class QAbstractAspect;
class QAbstractAspectJobManager;
-class QSceneObserverInterface;
class QServiceLocator;
+class NodePostConstructorInit;
+struct NodeTreeChange;
class Q_3DCORE_PRIVATE_EXPORT QAspectManager : public QObject
{
Q_OBJECT
public:
- explicit QAspectManager(QObject *parent = 0);
+ explicit QAspectManager(QObject *parent = nullptr);
~QAspectManager();
+ void setRunMode(QAspectEngine::RunMode mode);
void enterSimulationLoop();
void exitSimulationLoop();
@@ -90,34 +93,40 @@ public:
public Q_SLOTS:
void initialize();
void shutdown();
+ void processFrame();
- void setRootEntity(Qt3DCore::QEntity *root, const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> &changes);
+ void setRootEntity(Qt3DCore::QEntity *root, const QVector<QNode *> &nodes);
+ void addNodes(const QVector<QNode *> &nodes);
+ void removeNodes(const QVector<QNode *> &nodes);
void registerAspect(Qt3DCore::QAbstractAspect *aspect);
void unregisterAspect(Qt3DCore::QAbstractAspect *aspect);
- void exec();
- void quit();
-
public:
const QVector<QAbstractAspect *> &aspects() const;
QAbstractAspectJobManager *jobManager() const;
QChangeArbiter *changeArbiter() const;
QServiceLocator *serviceLocator() const;
+ void setPostConstructorInit(NodePostConstructorInit *postConstructorInit);
+
+ QNode *lookupNode(QNodeId id) const;
+ QVector<QNode *> lookupNodes(const QVector<QNodeId> &ids) const;
private:
+ bool event(QEvent *event) override;
+ void requestNextFrame();
+
QVector<QAbstractAspect *> m_aspects;
QEntity *m_root;
QVariantMap m_data;
QScheduler *m_scheduler;
QAbstractAspectJobManager *m_jobManager;
QChangeArbiter *m_changeArbiter;
- QAtomicInt m_runSimulationLoop;
- QAtomicInt m_runMainLoop;
QScopedPointer<QServiceLocator> m_serviceLocator;
- QSemaphore m_waitForEndOfSimulationLoop;
- QSemaphore m_waitForStartOfSimulationLoop;
- QSemaphore m_waitForEndOfExecLoop;
- QSemaphore m_waitForQuit;
+ bool m_simulationLoopRunning;
+ QAspectEngine::RunMode m_driveMode;
+ QVector<NodeTreeChange> m_nodeTreeChanges;
+ NodePostConstructorInit* m_postConstructorInit;
+
};
} // namespace Qt3DCore
diff --git a/src/core/aspects/qaspectthread.cpp b/src/core/aspects/qaspectthread.cpp
deleted file mode 100644
index 31715b04e..000000000
--- a/src/core/aspects/qaspectthread.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qaspectthread_p.h"
-
-#include <QtCore/QMutexLocker>
-
-#include <Qt3DCore/private/qaspectmanager_p.h>
-#include <Qt3DCore/private/corelogging_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DCore {
-
-QAspectThread::QAspectThread(QObject *parent)
- : QThread(parent),
- m_aspectManager(nullptr),
- m_semaphore(0)
-{
- qCDebug(Aspects) << Q_FUNC_INFO;
-}
-
-QAspectThread::~QAspectThread()
-{
-}
-
-void QAspectThread::waitForStart(Priority priority)
-{
- qCDebug(Aspects) << "Starting QAspectThread and going to sleep until it is ready for us...";
- start(priority);
- m_semaphore.acquire();
- qCDebug(Aspects) << "QAspectThead is now ready & calling thread is now awake again";
-}
-
-void QAspectThread::run()
-{
- qCDebug(Aspects) << "Entering void QAspectThread::run()";
-
- m_aspectManager = new QAspectManager;
-
- // Load and initialize the aspects and any other core services
- // Done before releasing condition to make sure that Qml Components
- // Are exposed prior to Qml Engine source being set
- m_aspectManager->initialize();
-
- // Wake up the calling thread now that our worker objects are ready for action
- m_semaphore.release();
-
- // Enter the main loop
- m_aspectManager->exec();
-
- // Clean up
- m_aspectManager->shutdown();
-
- // Delete the aspect manager while we're still in the thread
- delete m_aspectManager;
-
- qCDebug(Aspects) << "Exiting void QAspectThread::run()";
-}
-
-} // namespace Qt3DCore
-
-QT_END_NAMESPACE
diff --git a/src/core/changes/qscenechange.h b/src/core/changes/qscenechange.h
index 7d88d334f..4a0740819 100644
--- a/src/core/changes/qscenechange.h
+++ b/src/core/changes/qscenechange.h
@@ -63,6 +63,7 @@ enum ChangeFlag {
Q_DECLARE_FLAGS(ChangeFlags, ChangeFlag)
Q_DECLARE_OPERATORS_FOR_FLAGS(ChangeFlags)
+class QNode;
class QSceneChangePrivate;
class Q_3DCORESHARED_EXPORT QSceneChange
diff --git a/src/core/changes/qscenechange_p.h b/src/core/changes/qscenechange_p.h
index d32f6eec3..358beab49 100644
--- a/src/core/changes/qscenechange_p.h
+++ b/src/core/changes/qscenechange_p.h
@@ -60,6 +60,14 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
+//! internal
+struct NodeRelationshipChange {
+ QNode *node;
+ QNode *subNode;
+ ChangeFlag change;
+ const char *property;
+};
+
class QSceneChange;
class QNodeId;
diff --git a/src/core/core.pri b/src/core/core.pri
index 458a0328d..ea95ab10d 100644
--- a/src/core/core.pri
+++ b/src/core/core.pri
@@ -5,13 +5,11 @@ HEADERS += \
$$PWD/qtickclock_p.h \
$$PWD/qscheduler_p.h \
$$PWD/corelogging_p.h \
- $$PWD/qsceneobserverinterface_p.h \
$$PWD/qpostman_p.h \
$$PWD/qobservableinterface_p.h \
$$PWD/qobserverinterface_p.h \
$$PWD/qlockableobserverinterface_p.h \
$$PWD/qchangearbiter_p.h \
- $$PWD/qbackendnodefactory_p.h \
$$PWD/qt3dcore_global_p.h \
$$PWD/qscene_p.h \
$$PWD/qpostman_p_p.h
@@ -24,7 +22,5 @@ SOURCES += \
$$PWD/qobservableinterface.cpp \
$$PWD/qobserverinterface.cpp \
$$PWD/qlockableobserverinterface.cpp \
- $$PWD/qsceneobserverinterface.cpp \
$$PWD/qpostman.cpp \
- $$PWD/qscene.cpp \
- $$PWD/qbackendnodefactory.cpp
+ $$PWD/qscene.cpp
diff --git a/src/core/core.pro b/src/core/core.pro
index 8e65fafab..b1ba54be2 100644
--- a/src/core/core.pro
+++ b/src/core/core.pro
@@ -3,9 +3,6 @@ MODULE = 3dcore
QT = core-private gui-private network
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/core/jobs/qaspectjob.cpp b/src/core/jobs/qaspectjob.cpp
index ccb9c3a0e..bdb2063ba 100644
--- a/src/core/jobs/qaspectjob.cpp
+++ b/src/core/jobs/qaspectjob.cpp
@@ -59,11 +59,23 @@ QAspectJobPrivate::QAspectJobPrivate()
{
}
+QAspectJobPrivate::~QAspectJobPrivate() = default;
+
QAspectJobPrivate *QAspectJobPrivate::get(QAspectJob *job)
{
return job->d_func();
}
+const QAspectJobPrivate *QAspectJobPrivate::get(const QAspectJob *job)
+{
+ return job->d_func();
+}
+
+void QAspectJobPrivate::postFrame(QAspectManager *aspectManager)
+{
+ Q_UNUSED(aspectManager)
+}
+
QAspectJob::QAspectJob()
: d_ptr(new QAspectJobPrivate)
{
diff --git a/src/core/jobs/qaspectjob.h b/src/core/jobs/qaspectjob.h
index 5c088fd1a..bd86a61e1 100644
--- a/src/core/jobs/qaspectjob.h
+++ b/src/core/jobs/qaspectjob.h
@@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
class QAspectJobPrivate;
+class QAspectManager;
class Q_3DCORESHARED_EXPORT QAspectJob
{
diff --git a/src/core/jobs/qaspectjob_p.h b/src/core/jobs/qaspectjob_p.h
index 7aa3151a0..5504bd936 100644
--- a/src/core/jobs/qaspectjob_p.h
+++ b/src/core/jobs/qaspectjob_p.h
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
class QAspectJob;
+class QAspectManager;
#if QT_CONFIG(qt3d_profile_jobs)
struct FrameHeader
@@ -107,8 +108,12 @@ class Q_3DCORE_PRIVATE_EXPORT QAspectJobPrivate
{
public:
QAspectJobPrivate();
+ virtual ~QAspectJobPrivate();
static QAspectJobPrivate *get(QAspectJob *job);
+ static const QAspectJobPrivate *get(const QAspectJob *job);
+
+ virtual void postFrame(QAspectManager *aspectManager);
QVector<QWeakPointer<QAspectJob> > m_dependencies;
#if QT_CONFIG(qt3d_profile_jobs)
@@ -118,6 +123,9 @@ public:
} // Qt3D
+#define Q_DJOB(Class) \
+ Class##Private *d = static_cast<Class##Private *>(Qt3DCore::QAspectJobPrivate::get(this))
+
#if QT_CONFIG(qt3d_profile_jobs)
#include <Qt3DCore/private/qaspectjob_p.h>
diff --git a/src/core/jobs/qaspectjobmanager.cpp b/src/core/jobs/qaspectjobmanager.cpp
index 328899433..91394924f 100644
--- a/src/core/jobs/qaspectjobmanager.cpp
+++ b/src/core/jobs/qaspectjobmanager.cpp
@@ -87,7 +87,7 @@ void QAspectJobManager::enqueueJobs(const QVector<QAspectJobPtr> &jobQueue)
int dependerCount = 0;
for (const QWeakPointer<QAspectJob> &dep : deps) {
- AspectTaskRunnable *taskDependee = tasksMap.value(dep.data());
+ AspectTaskRunnable *taskDependee = tasksMap.value(dep.toStrongRef().data());
// The dependencies here are not hard requirements, i.e., the dependencies
// not in the jobQueue should already have their data ready.
if (taskDependee) {
diff --git a/src/core/jobs/qthreadpooler.cpp b/src/core/jobs/qthreadpooler.cpp
index ca123ddad..a9f4e7a31 100644
--- a/src/core/jobs/qthreadpooler.cpp
+++ b/src/core/jobs/qthreadpooler.cpp
@@ -183,7 +183,7 @@ int QThreadPooler::currentCount() const
{
// The caller have to set the mutex
- return m_taskCount.load();
+ return m_taskCount.loadRelaxed();
}
int QThreadPooler::maxThreadCount() const
@@ -212,7 +212,7 @@ void QThreadPooler::addJobLogStatsEntry(JobRunStats &stats)
jobStatsCached.localData()->push_back(stats);
}
-// Called after jobs have been executed (AspectThread QAspectJobManager::enqueueJobs)
+// Called after jobs have been executed (MainThread QAspectJobManager::enqueueJobs)
void QThreadPooler::writeFrameJobLogStats()
{
static QScopedPointer<QFile> traceFile;
@@ -268,7 +268,7 @@ void QThreadPooler::writeFrameJobLogStats()
++frameId;
}
-// Called from Submission thread
+// Called from Submission thread (which can be main thread in Manual drive mode)
void QThreadPooler::addSubmissionLogStatsEntry(JobRunStats &stats)
{
QMutexLocker lock(&localStoragesMutex);
@@ -276,6 +276,12 @@ void QThreadPooler::addSubmissionLogStatsEntry(JobRunStats &stats)
submissionStorage = new QVector<JobRunStats>;
jobStatsCached.setLocalData(submissionStorage);
}
+
+ // Handle the case where submission thread is also the main thread (Scene/Manual drive modes with no RenderThread)
+ if (submissionStorage == nullptr && jobStatsCached.hasLocalData())
+ submissionStorage = new QVector<JobRunStats>;
+
+ // When having no submission thread this can be null
submissionStorage->push_back(stats);
}
diff --git a/src/core/jobs/task.cpp b/src/core/jobs/task.cpp
index 4291a4779..7c3ebf6eb 100644
--- a/src/core/jobs/task.cpp
+++ b/src/core/jobs/task.cpp
@@ -57,6 +57,7 @@ RunnableInterface::~RunnableInterface()
AspectTaskRunnable::AspectTaskRunnable()
: m_pooler(nullptr)
+ , m_id(0)
, m_reserved(false)
{
}
@@ -118,7 +119,7 @@ void SyncTaskRunnable::run()
m_atomicCount->deref();
// Wait for the other worker threads to be done
- while (m_atomicCount->load() > 0)
+ while (m_atomicCount->loadRelaxed() > 0)
QThread::currentThread()->yieldCurrentThread();
if (m_pooler)
diff --git a/src/core/nodes/qbackendnode.cpp b/src/core/nodes/qbackendnode.cpp
index f10bf5769..e5f93e96f 100644
--- a/src/core/nodes/qbackendnode.cpp
+++ b/src/core/nodes/qbackendnode.cpp
@@ -95,6 +95,26 @@ QBackendNodePrivate *QBackendNodePrivate::get(QBackendNode *n)
return n->d_func();
}
+void QBackendNodePrivate::addedToEntity(QNode *frontend)
+{
+ Q_UNUSED(frontend)
+}
+
+void QBackendNodePrivate::removedFromEntity(QNode *frontend)
+{
+ Q_UNUSED(frontend)
+}
+
+void QBackendNodePrivate::componentAdded(QNode *frontend)
+{
+ Q_UNUSED(frontend)
+}
+
+void QBackendNodePrivate::componentRemoved(QNode *frontend)
+{
+ Q_UNUSED(frontend)
+}
+
/*!
* \class Qt3DCore::QBackendNodeMapper
* \inheaderfile Qt3DCore/QBackendNodeMapper
@@ -256,16 +276,16 @@ void QBackendNode::setEnabled(bool enabled) Q_DECL_NOTHROW
void QBackendNode::sceneChangeEvent(const QSceneChangePtr &e)
{
Q_D(QBackendNode);
- auto propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
switch (e->type()) {
- case PropertyUpdated: {
- if (propertyChange->propertyName() == QByteArrayLiteral("enabled"))
- d->m_enabled = propertyChange->value().toBool();
- break;
- }
- default:
- break;
+ case PropertyUpdated: {
+ auto propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
+ if (propertyChange->propertyName() == QByteArrayLiteral("enabled"))
+ d->m_enabled = propertyChange->value().toBool();
+ break;
+ }
+ default:
+ break;
}
}
diff --git a/src/core/nodes/qbackendnode.h b/src/core/nodes/qbackendnode.h
index 21485cd5f..550ced04f 100644
--- a/src/core/nodes/qbackendnode.h
+++ b/src/core/nodes/qbackendnode.h
@@ -62,7 +62,7 @@ class Q_3DCORESHARED_EXPORT QBackendNodeMapper
{
public:
virtual ~QBackendNodeMapper();
- virtual QBackendNode *create(const QNodeCreatedChangeBasePtr &change) const = 0;
+ virtual QBackendNode *create(const QNodeCreatedChangeBasePtr &change) const = 0; // TODO QT6 change to only take a NodeId
virtual QBackendNode *get(QNodeId id) const = 0;
virtual void destroy(QNodeId id) const = 0;
};
diff --git a/src/core/nodes/qbackendnode_p.h b/src/core/nodes/qbackendnode_p.h
index dde86fa48..260eef087 100644
--- a/src/core/nodes/qbackendnode_p.h
+++ b/src/core/nodes/qbackendnode_p.h
@@ -63,6 +63,8 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
+class QNode;
+
class Q_3DCORE_PRIVATE_EXPORT QBackendNodePrivate
: public QObserverInterface
, public QObservableInterface
@@ -85,6 +87,11 @@ public:
QNodeId m_peerId;
bool m_enabled;
+ virtual void addedToEntity(QNode *frontend);
+ virtual void removedFromEntity(QNode *frontend);
+ virtual void componentAdded(QNode *frontend);
+ virtual void componentRemoved(QNode *frontend);
+
private:
Q_DISABLE_COPY(QBackendNodePrivate)
};
diff --git a/src/core/nodes/qcomponent.cpp b/src/core/nodes/qcomponent.cpp
index f67989b1e..79bba229d 100644
--- a/src/core/nodes/qcomponent.cpp
+++ b/src/core/nodes/qcomponent.cpp
@@ -40,9 +40,6 @@
#include "qcomponent.h"
#include "qcomponent_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qcomponentaddedchange.h>
-#include <Qt3DCore/qcomponentremovedchange.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/private/qentity_p.h>
@@ -73,8 +70,6 @@ void QComponentPrivate::addEntity(QEntity *entity)
m_scene->addEntityForComponent(m_id, entity->id());
}
- const auto componentAddedChange = QComponentAddedChangePtr::create(q, entity);
- notifyObservers(componentAddedChange);
Q_EMIT q->addedToEntity(entity);
}
@@ -86,8 +81,6 @@ void QComponentPrivate::removeEntity(QEntity *entity)
m_entities.removeAll(entity);
- const auto componentRemovedChange = QComponentRemovedChangePtr::create(q, entity);
- notifyObservers(componentRemovedChange);
Q_EMIT q->removedFromEntity(entity);
}
diff --git a/src/core/nodes/qentity.cpp b/src/core/nodes/qentity.cpp
index 1d16e828e..93601901f 100644
--- a/src/core/nodes/qentity.cpp
+++ b/src/core/nodes/qentity.cpp
@@ -41,10 +41,7 @@
#include "qentity_p.h"
#include <Qt3DCore/qcomponent.h>
-#include <Qt3DCore/qcomponentaddedchange.h>
-#include <Qt3DCore/qcomponentremovedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/QMetaObject>
#include <QtCore/QMetaProperty>
@@ -78,7 +75,7 @@ namespace Qt3DCore {
*/
/*!
- \fn template<typename T> QVector<T *> QEntity::componentsOfType() const
+ \fn template<typename T> QVector<T *> Qt3DCore::QEntity::componentsOfType() const
Returns all the components added to this entity that can be cast to
type T or an empty vector if there are no such components.
@@ -102,13 +99,8 @@ void QEntityPrivate::removeDestroyedComponent(QComponent *comp)
Q_CHECK_PTR(comp);
qCDebug(Nodes) << Q_FUNC_INFO << comp;
- Q_Q(QEntity);
-
- if (m_changeArbiter) {
- const auto componentRemovedChange = QComponentRemovedChangePtr::create(q, comp);
- notifyObservers(componentRemovedChange);
- }
+ updateNode(comp, nullptr, ComponentRemoved);
m_components.removeOne(comp);
// Remove bookkeeping connection
@@ -125,6 +117,7 @@ QEntity::QEntity(QNode *parent)
QEntity::QEntity(QEntityPrivate &dd, QNode *parent)
: QNode(dd, parent)
{
+ connect(this, &QNode::parentChanged, this, &QEntity::onParentChanged);
}
QEntity::~QEntity()
@@ -186,10 +179,7 @@ void QEntity::addComponent(QComponent *comp)
// Ensures proper bookkeeping
d->registerPrivateDestructionHelper(comp, &QEntityPrivate::removeDestroyedComponent);
- if (d->m_changeArbiter) {
- const auto componentAddedChange = QComponentAddedChangePtr::create(this, comp);
- d->notifyObservers(componentAddedChange);
- }
+ d->updateNode(comp, nullptr, ComponentAdded);
static_cast<QComponentPrivate *>(QComponentPrivate::get(comp))->addEntity(this);
}
@@ -204,10 +194,7 @@ void QEntity::removeComponent(QComponent *comp)
static_cast<QComponentPrivate *>(QComponentPrivate::get(comp))->removeEntity(this);
- if (d->m_changeArbiter) {
- const auto componentRemovedChange = QComponentRemovedChangePtr::create(this, comp);
- d->notifyObservers(componentRemovedChange);
- }
+ d->updateNode(comp, nullptr, ComponentRemoved);
d->m_components.removeOne(comp);
@@ -259,10 +246,6 @@ QNodeId QEntityPrivate::parentEntityId() const
QNodeCreatedChangeBasePtr QEntity::createNodeCreationChange() const
{
- // connect to the parentChanged signal here rather than constructor because
- // until now there's no backend node to notify when parent changes
- connect(this, &QNode::parentChanged, this, &QEntity::onParentChanged);
-
auto creationChange = QNodeCreatedChangePtr<QEntityData>::create(this);
auto &data = creationChange->data;
@@ -294,13 +277,11 @@ QNodeCreatedChangeBasePtr QEntity::createNodeCreationChange() const
void QEntity::onParentChanged(QObject *)
{
- const auto parentID = parentEntity() ? parentEntity()->id() : Qt3DCore::QNodeId();
- auto parentChange = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
- parentChange->setPropertyName("parentEntityUpdated");
- parentChange->setValue(QVariant::fromValue(parentID));
- const bool blocked = blockNotifications(false);
- notifyObservers(parentChange);
- blockNotifications(blocked);
+ Q_D(QEntity);
+ if (!d->m_hasBackendNode)
+ return;
+
+ d->update();
}
} // namespace Qt3DCore
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp
index c418e03d5..af16eaa21 100644
--- a/src/core/nodes/qnode.cpp
+++ b/src/core/nodes/qnode.cpp
@@ -39,6 +39,7 @@
#include "qnode.h"
#include "qnode_p.h"
+#include "qscene_p.h"
#include <Qt3DCore/QComponent>
#include <Qt3DCore/qaspectengine.h>
@@ -55,10 +56,11 @@
#include <Qt3DCore/private/corelogging_p.h>
#include <Qt3DCore/private/qdestructionidandtypecollector_p.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qnodevisitor_p.h>
#include <Qt3DCore/private/qpostman_p.h>
#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
#include <QtCore/private/qmetaobject_p.h>
QT_BEGIN_NAMESPACE
@@ -110,17 +112,15 @@ void QNodePrivate::init(QNode *parent)
*
* Sends QNodeCreatedChange events to the aspects.
*/
-void QNodePrivate::notifyCreationChange()
+void QNodePrivate::createBackendNode()
{
- Q_Q(QNode);
// Do nothing if we already have already sent a node creation change
// and not a subsequent node destroyed change.
- if (m_hasBackendNode || !m_scene)
+ if (m_hasBackendNode || !m_scene || !m_scene->engine())
return;
- QNodeCreatedChangeGenerator generator(q);
- const auto creationChanges = generator.creationChanges();
- for (const auto &change : creationChanges)
- notifyObservers(change);
+
+ Q_Q(QNode);
+ QAspectEnginePrivate::get(m_scene->engine())->addNode(q);
}
/*!
@@ -149,11 +149,8 @@ void QNodePrivate::notifyDestructionChangesAndRemoveFromScene()
}
// Tell the backend we are about to be destroyed
- if (m_hasBackendNode) {
- const QDestructionIdAndTypeCollector collector(q);
- const auto destroyedChange = QNodeDestroyedChangePtr::create(q, collector.subtreeIdsAndTypes());
- notifyObservers(destroyedChange);
- }
+ if (m_hasBackendNode && m_scene && m_scene->engine())
+ QAspectEnginePrivate::get(m_scene->engine())->removeNode(q);
// We unset the scene from the node as its backend node was/is about to be destroyed
QNodeVisitor visitor;
@@ -189,7 +186,7 @@ void QNodePrivate::_q_postConstructorInit()
return;
// Set the scene on this node and all children it references so that all
- // children have a scene set since notifyCreationChanges will set
+ // children have a scene set since createBackendNode will set
// m_hasBackendNode to true for all children, which would prevent them from
// ever having their scene set
if (m_scene) {
@@ -198,7 +195,7 @@ void QNodePrivate::_q_postConstructorInit()
}
// Let the backend know we have been added to the scene
- notifyCreationChange();
+ createBackendNode();
// Let the backend parent know that they have a new child
Q_ASSERT(parentNode);
@@ -247,7 +244,7 @@ void QNodePrivate::_q_addChild(QNode *childNode)
}
// Update the scene
- // TODO: Fold this into the QNodeCreatedChangeGenerator so we don't have to
+ // TODO: Fold this into the QAspectEnginePrivate::addNode so we don't have to
// traverse the sub tree three times!
QNodeVisitor visitor;
visitor.traverse(childNode, this, &QNodePrivate::addEntityComponentToScene);
@@ -340,13 +337,13 @@ void QNodePrivate::_q_setParentHelper(QNode *parent)
// child->setParent(subTreeRoot)
// We need to take into account that subTreeRoot needs to be
// created in the backend before the child.
- // Therefore we only call notifyCreationChanges if the parent
+ // Therefore we only call createBackendNode if the parent
// hasn't been created yet as we know that when the parent will be
// fully created, it will also send the changes for all of its
// children
if (newParentPrivate->m_hasBackendNode)
- notifyCreationChange();
+ createBackendNode();
// If we have a valid new parent, we let him know that we are its child
QNodePrivate::get(parent)->_q_addChild(q);
@@ -385,48 +382,13 @@ void QNodePrivate::unregisterNotifiedProperties()
void QNodePrivate::propertyChanged(int propertyIndex)
{
+ Q_UNUSED(propertyIndex);
+
// Bail out early if we can to avoid the cost below
if (m_blockNotifications)
return;
- const auto toBackendValue = [](const QVariant &data) -> QVariant
- {
- if (data.canConvert<QNode*>()) {
- QNode *node = data.value<QNode*>();
-
- // Ensure the node and all ancestors have issued their node creation changes.
- // We can end up here if a newly created node with a parent is immediately set
- // as a property on another node. In this case the deferred call to
- // _q_postConstructorInit() will not have happened yet as the event
- // loop will still be blocked. We need to do this for all ancestors,
- // since the subtree of this node otherwise can end up on the backend
- // with a reference to a non-existent parent.
- if (node)
- QNodePrivate::get(node)->_q_ensureBackendNodeCreated();
-
- const QNodeId id = node ? node->id() : QNodeId();
- return QVariant::fromValue(id);
- }
-
- return data;
- };
-
- Q_Q(QNode);
-
- const QMetaProperty property = q->metaObject()->property(propertyIndex);
-
- const QVariant data = property.read(q);
-
- if (data.type() == QVariant::List) {
- QSequentialIterable iterable = data.value<QSequentialIterable>();
- QVariantList variants;
- variants.reserve(iterable.size());
- for (const auto &v : iterable)
- variants.append(toBackendValue(v));
- notifyPropertyChange(property.name(), variants);
- } else {
- notifyPropertyChange(property.name(), toBackendValue(data));
- }
+ update();
}
/*!
@@ -498,8 +460,13 @@ void QNodePrivate::addEntityComponentToScene(QNode *root)
// Called in the main thread by QScene -> following QEvent::childAdded / addChild
void QNodePrivate::setArbiter(QLockableObserverInterface *arbiter)
{
- if (m_changeArbiter && m_changeArbiter != arbiter)
+ if (m_changeArbiter && m_changeArbiter != arbiter) {
unregisterNotifiedProperties();
+
+ // Remove node from dirtyFrontendNodeList on old arbiter
+ Q_Q(QNode);
+ m_changeArbiter->removeDirtyFrontEndNode(q);
+ }
m_changeArbiter = static_cast<QAbstractArbiter *>(arbiter);
if (m_changeArbiter)
registerNotifiedProperties();
@@ -559,10 +526,11 @@ void QNodePrivate::_q_ensureBackendNodeCreated()
* Sends the \a change QSceneChangePtr to any QBackendNodes in the registered
* aspects that correspond to this QNode.
*
- * For the common case of a QObject property change, QNode handles this for you
- * automatically by sending a QPropertyUpdatedChange event to the backend nodes.
* You only need to call this function if you wish to send a specific type of
* change in place of the automatic handling.
+ *
+ * Note: as of Qt 5.14, change messages are deprecated and should not be used,
+ * in particular for properties.
*/
void QNode::notifyObservers(const QSceneChangePtr &change)
{
@@ -626,26 +594,26 @@ QScene *QNodePrivate::scene() const
*/
void QNodePrivate::notifyPropertyChange(const char *name, const QVariant &value)
{
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+
// Bail out early if we can to avoid operator new
if (m_blockNotifications)
return;
- auto e = QPropertyUpdatedChangePtr::create(m_id);
- e->setPropertyName(name);
- e->setValue(value);
- notifyObservers(e);
+ update();
}
void QNodePrivate::notifyDynamicPropertyChange(const QByteArray &name, const QVariant &value)
{
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+
// Bail out early if we can to avoid operator new
if (m_blockNotifications)
return;
- auto e = QDynamicPropertyUpdatedChangePtr::create(m_id);
- e->setPropertyName(name);
- e->setValue(value);
- notifyObservers(e);
+ update();
}
/*!
@@ -704,6 +672,27 @@ void QNodePrivate::updatePropertyTrackMode()
}
}
+void QNodePrivate::update()
+{
+ if (m_changeArbiter) {
+ Q_Q(QNode);
+ m_changeArbiter->addDirtyFrontEndNode(q);
+ }
+}
+
+void QNodePrivate::updateNode(QNode *node, const char *property, ChangeFlag change)
+{
+ if (m_changeArbiter) {
+ // Ensure node has its postConstructorInit called if we reach this
+ // point, we could otherwise endup referencing a node that has yet
+ // to be created in the backend
+ QNodePrivate::get(node)->_q_ensureBackendNodeCreated();
+
+ Q_Q(QNode);
+ m_changeArbiter->addDirtyFrontEndNode(q, node, property, change);
+ }
+}
+
/*!
\internal
*/
@@ -715,6 +704,14 @@ QNodePrivate *QNodePrivate::get(QNode *q)
/*!
\internal
*/
+const QNodePrivate *QNodePrivate::get(const QNode *q)
+{
+ return q->d_func();
+}
+
+/*!
+ \internal
+ */
void QNodePrivate::nodePtrDeleter(QNode *q)
{
QObject *p = q->parent();
diff --git a/src/core/nodes/qnode.h b/src/core/nodes/qnode.h
index d4e4ff088..9ca817fb6 100644
--- a/src/core/nodes/qnode.h
+++ b/src/core/nodes/qnode.h
@@ -134,6 +134,7 @@ private:
friend class QAspectEngine;
friend class QAspectEnginePrivate;
+ friend class QAbstractAspectPrivate;
friend class QNodeCreatedChangeGenerator;
friend class QPostman;
friend class QScene;
diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h
index 86bfab85a..208474802 100644
--- a/src/core/nodes/qnode_p.h
+++ b/src/core/nodes/qnode_p.h
@@ -89,6 +89,9 @@ public:
void insertTree(QNode *treeRoot, int depth = 0);
void updatePropertyTrackMode();
+ void update();
+ void updateNode(QNode *node, const char* property, ChangeFlag change);
+
Q_DECLARE_PUBLIC(QNode)
// For now this just protects access to the m_changeArbiter.
@@ -106,6 +109,7 @@ public:
QHash<QString, QNode::PropertyTrackingMode> m_trackedPropertiesOverrides;
static QNodePrivate *get(QNode *q);
+ static const QNodePrivate *get(const QNode *q);
static void nodePtrDeleter(QNode *q);
template<typename Caller, typename NodeType>
@@ -173,7 +177,7 @@ public:
void _q_ensureBackendNodeCreated();
private:
- void notifyCreationChange();
+ void createBackendNode();
void notifyDestructionChangesAndRemoveFromScene();
void _q_addChild(QNode *childNode);
void _q_removeChild(QNode *childNode);
@@ -201,7 +205,7 @@ public:
void removeNode(QNode *node);
void addNode(QNode *node);
-private Q_SLOTS:
+public Q_SLOTS:
void processNodes();
private:
diff --git a/src/core/qchangearbiter.cpp b/src/core/qchangearbiter.cpp
index 2e32d6722..e5745b017 100644
--- a/src/core/qchangearbiter.cpp
+++ b/src/core/qchangearbiter.cpp
@@ -49,7 +49,8 @@
#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
#include <Qt3DCore/private/qpostman_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/private/qsceneobserverinterface_p.h>
+
+#include <mutex>
QT_BEGIN_NAMESPACE
@@ -76,7 +77,6 @@ namespace Qt3DCore {
*/
QChangeArbiter::QChangeArbiter(QObject *parent)
: QObject(parent)
- , m_mutex(QMutex::Recursive)
, m_jobManager(nullptr)
, m_postman(nullptr)
, m_scene(nullptr)
@@ -116,12 +116,8 @@ void QChangeArbiter::distributeQueueChanges(QChangeQueue *changeQueue)
if (change.isNull())
continue;
- if (change->type() == NodeCreated) {
- for (QSceneObserverInterface *observer : qAsConst(m_sceneObservers))
- observer->sceneNodeAdded(change);
- } else if (change->type() == NodeDeleted) {
- for (QSceneObserverInterface *observer : qAsConst(m_sceneObservers))
- observer->sceneNodeRemoved(change);
+ if (change->type() == NodeCreated || change->type() == NodeDeleted) {
+ Q_ASSERT(false); // messages no longer used
}
const QNodeId nodeId = change->subjectId();
@@ -151,31 +147,31 @@ QThreadStorage<QChangeArbiter::QChangeQueue *> *QChangeArbiter::tlsChangeQueue()
void QChangeArbiter::appendChangeQueue(QChangeArbiter::QChangeQueue *queue)
{
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);;
m_changeQueues.append(queue);
}
void QChangeArbiter::removeChangeQueue(QChangeArbiter::QChangeQueue *queue)
{
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);;
m_changeQueues.removeOne(queue);
}
void QChangeArbiter::appendLockingChangeQueue(QChangeArbiter::QChangeQueue *queue)
{
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);;
m_lockingChangeQueues.append(queue);
}
void QChangeArbiter::removeLockingChangeQueue(QChangeArbiter::QChangeQueue *queue)
{
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);;
m_lockingChangeQueues.removeOne(queue);
}
void QChangeArbiter::syncChanges()
{
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);;
for (QChangeArbiter::QChangeQueue *changeQueue : qAsConst(m_changeQueues))
distributeQueueChanges(changeQueue);
@@ -202,21 +198,14 @@ void QChangeArbiter::registerObserver(QObserverInterface *observer,
QNodeId nodeId,
ChangeFlags changeFlags)
{
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);;
QObserverList &observerList = m_nodeObservations[nodeId];
observerList.append(QObserverPair(changeFlags, observer));
}
-// Called from the QAspectThread context, no need to lock
-void QChangeArbiter::registerSceneObserver(QSceneObserverInterface *observer)
-{
- if (!m_sceneObservers.contains(observer))
- m_sceneObservers << observer;
-}
-
void QChangeArbiter::unregisterObserver(QObserverInterface *observer, QNodeId nodeId)
{
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);;
const auto it = m_nodeObservations.find(nodeId);
if (it != m_nodeObservations.end()) {
QObserverList &observers = it.value();
@@ -229,13 +218,6 @@ void QChangeArbiter::unregisterObserver(QObserverInterface *observer, QNodeId no
}
}
-// Called from the QAspectThread context, no need to lock
-void QChangeArbiter::unregisterSceneObserver(QSceneObserverInterface *observer)
-{
- if (observer != nullptr)
- m_sceneObservers.removeOne(observer);
-}
-
void QChangeArbiter::sceneChangeEvent(const QSceneChangePtr &e)
{
// qCDebug(ChangeArbiter) << Q_FUNC_INFO << QThread::currentThread();
@@ -244,21 +226,57 @@ void QChangeArbiter::sceneChangeEvent(const QSceneChangePtr &e)
QChangeQueue *localChangeQueue = m_tlsChangeQueue.localData();
localChangeQueue->push_back(e);
+ emit receivedChange();
+
// qCDebug(ChangeArbiter) << "Change queue for thread" << QThread::currentThread() << "now contains" << localChangeQueue->count() << "items";
}
void QChangeArbiter::sceneChangeEventWithLock(const QSceneChangePtr &e)
{
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);;
sceneChangeEvent(e);
}
void QChangeArbiter::sceneChangeEventWithLock(const QSceneChangeList &e)
{
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);;
QChangeQueue *localChangeQueue = m_tlsChangeQueue.localData();
qCDebug(ChangeArbiter) << Q_FUNC_INFO << "Handles " << e.size() << " changes at once";
localChangeQueue->insert(localChangeQueue->end(), e.begin(), e.end());
+
+ emit receivedChange();
+}
+
+void QChangeArbiter::addDirtyFrontEndNode(QNode *node)
+{
+ if (!m_dirtyFrontEndNodes.contains(node)) {
+ m_dirtyFrontEndNodes += node;
+ emit receivedChange();
+ }
+}
+
+void QChangeArbiter::addDirtyFrontEndNode(QNode *node, QNode *subNode, const char *property, ChangeFlag change)
+{
+ addDirtyFrontEndNode(node);
+ m_dirtySubNodeChanges.push_back({node, subNode, change, property});
+}
+
+void QChangeArbiter::removeDirtyFrontEndNode(QNode *node)
+{
+ m_dirtyFrontEndNodes.removeOne(node);
+ m_dirtySubNodeChanges.erase(std::remove_if(m_dirtySubNodeChanges.begin(), m_dirtySubNodeChanges.end(), [node](const NodeRelationshipChange &elt) {
+ return elt.node == node || elt.subNode == node;
+ }), m_dirtySubNodeChanges.end());
+}
+
+QVector<QNode *> QChangeArbiter::takeDirtyFrontEndNodes()
+{
+ return std::move(m_dirtyFrontEndNodes);
+}
+
+QVector<NodeRelationshipChange> QChangeArbiter::takeDirtyFrontEndSubNodes()
+{
+ return std::move(m_dirtySubNodeChanges);
}
// Either we have the postman or we could make the QChangeArbiter agnostic to the postman
diff --git a/src/core/qchangearbiter_p.h b/src/core/qchangearbiter_p.h
index 4a82061ed..81f33f625 100644
--- a/src/core/qchangearbiter_p.h
+++ b/src/core/qchangearbiter_p.h
@@ -53,6 +53,7 @@
#include <Qt3DCore/qnodeid.h>
#include <Qt3DCore/qscenechange.h>
+#include <Qt3DCore/private/qscenechange_p.h>
#include <QtCore/QFlags>
#include <QtCore/QMutex>
#include <QtCore/QObject>
@@ -81,6 +82,9 @@ class Q_3DCORE_PRIVATE_EXPORT QAbstractArbiter : public QLockableObserverInterfa
{
public:
virtual QAbstractPostman *postman() const = 0;
+ virtual void addDirtyFrontEndNode(QNode *node) = 0;
+ virtual void removeDirtyFrontEndNode(QNode *node) = 0;
+ virtual void addDirtyFrontEndNode(QNode *node, QNode *subNode, const char *property, ChangeFlag change) = 0;
};
class Q_3DCORE_PRIVATE_EXPORT QChangeArbiter final
@@ -89,7 +93,7 @@ class Q_3DCORE_PRIVATE_EXPORT QChangeArbiter final
{
Q_OBJECT
public:
- explicit QChangeArbiter(QObject *parent = 0);
+ explicit QChangeArbiter(QObject *parent = nullptr);
~QChangeArbiter();
void initialize(Qt3DCore::QAbstractAspectJobManager *jobManager);
@@ -102,15 +106,18 @@ public:
void unregisterObserver(QObserverInterface *observer,
QNodeId nodeId);
- void registerSceneObserver(QSceneObserverInterface *observer);
- void unregisterSceneObserver(QSceneObserverInterface *observer);
-
void sceneChangeEvent(const QSceneChangePtr &e) override; // QLockableObserverInterface impl
void sceneChangeEventWithLock(const QSceneChangePtr &e) override; // QLockableObserverInterface impl
void sceneChangeEventWithLock(const QSceneChangeList &e) override; // QLockableObserverInterface impl
- Q_INVOKABLE void setPostman(Qt3DCore::QAbstractPostman *postman);
- Q_INVOKABLE void setScene(Qt3DCore::QScene *scene);
+ void addDirtyFrontEndNode(QNode *node) override;
+ void addDirtyFrontEndNode(QNode *node, QNode *subNode, const char *property, ChangeFlag change) override;
+ void removeDirtyFrontEndNode(QNode *node) override;
+ QVector<QNode *> takeDirtyFrontEndNodes();
+ QVector<NodeRelationshipChange> takeDirtyFrontEndSubNodes();
+
+ void setPostman(Qt3DCore::QAbstractPostman *postman);
+ void setScene(Qt3DCore::QScene *scene);
QAbstractPostman *postman() const final;
QScene *scene() const;
@@ -120,6 +127,9 @@ public:
static void createThreadLocalChangeQueue(void *changeArbiter);
static void destroyThreadLocalChangeQueue(void *changeArbiter);
+Q_SIGNALS:
+ void receivedChange();
+
protected:
typedef std::vector<QSceneChangePtr> QChangeQueue;
typedef QPair<ChangeFlags, QObserverInterface *> QObserverPair;
@@ -134,13 +144,12 @@ protected:
void removeLockingChangeQueue(QChangeQueue *queue);
private:
- QMutex m_mutex;
+ mutable QRecursiveMutex m_mutex;
QAbstractAspectJobManager *m_jobManager;
// The lists of observers indexed by observable (QNodeId).
// m_nodeObservations is for observables in the main thread's object tree
QHash<QNodeId, QObserverList> m_nodeObservations;
- QList<QSceneObserverInterface *> m_sceneObservers;
// Each thread has a TLS ChangeQueue so we never need to lock whilst
// receiving a QSceneChange.
@@ -152,6 +161,9 @@ private:
QList<QChangeQueue *> m_lockingChangeQueues;
QAbstractPostman *m_postman;
QScene *m_scene;
+
+ QVector<QNode *> m_dirtyFrontEndNodes;
+ QVector<NodeRelationshipChange> m_dirtySubNodeChanges;
};
} // namespace Qt3DCore
diff --git a/src/core/qscene.cpp b/src/core/qscene.cpp
index c94272e90..1b8996e8d 100644
--- a/src/core/qscene.cpp
+++ b/src/core/qscene.cpp
@@ -68,7 +68,7 @@ public:
QMultiHash<QNodeId, QObservableInterface *> m_observablesLookupTable;
QHash<QObservableInterface *, QNodeId> m_observableToUuid;
QHash<QNodeId, QScene::NodePropertyTrackData> m_nodePropertyTrackModeLookupTable;
- QLockableObserverInterface *m_arbiter;
+ QAbstractArbiter *m_arbiter;
QScopedPointer<NodePostConstructorInit> m_postConstructorInit;
mutable QReadWriteLock m_lock;
mutable QReadWriteLock m_nodePropertyTrackModeLock;
@@ -183,13 +183,13 @@ QNode *QScene::rootNode() const
return d->m_rootNode;
}
-void QScene::setArbiter(QLockableObserverInterface *arbiter)
+void QScene::setArbiter(QAbstractArbiter *arbiter)
{
Q_D(QScene);
d->m_arbiter = arbiter;
}
-QLockableObserverInterface *QScene::arbiter() const
+QAbstractArbiter *QScene::arbiter() const
{
Q_D(const QScene);
return d->m_arbiter;
diff --git a/src/core/qscene_p.h b/src/core/qscene_p.h
index afcfb9b40..cdb85ebe6 100644
--- a/src/core/qscene_p.h
+++ b/src/core/qscene_p.h
@@ -65,6 +65,7 @@ namespace Qt3DCore {
class QScenePrivate;
class QAspectEngine;
class NodePostConstructorInit;
+class QAbstractArbiter;
typedef QList<QObservableInterface *> QObservableList;
@@ -88,8 +89,8 @@ public:
QNode *rootNode() const;
- void setArbiter(Qt3DCore::QLockableObserverInterface *arbiter);
- Qt3DCore::QLockableObserverInterface *arbiter() const;
+ void setArbiter(QAbstractArbiter *arbiter);
+ QAbstractArbiter *arbiter() const;
// Component -> Entities
QVector<QNodeId> entitiesForComponent(QNodeId id) const;
diff --git a/src/core/qscheduler.cpp b/src/core/qscheduler.cpp
index cc2f9081e..e714e477d 100644
--- a/src/core/qscheduler.cpp
+++ b/src/core/qscheduler.cpp
@@ -40,7 +40,7 @@
#include "qscheduler_p.h"
#include <Qt3DCore/qabstractaspect.h>
-
+#include <Qt3DCore/private/qaspectjob_p.h>
#include <Qt3DCore/private/qabstractaspect_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
@@ -91,6 +91,9 @@ void QScheduler::scheduleAndWaitForFrameAspectJobs(qint64 time)
// whilst the threadpool works its way through the jobs
m_aspectManager->jobManager()->waitForAllJobs();
+
+ for (auto &job : qAsConst(jobQueue))
+ QAspectJobPrivate::get(job.data())->postFrame(m_aspectManager);
}
} // namespace Qt3DCore
diff --git a/src/core/resources/qframeallocator.cpp b/src/core/resources/qframeallocator.cpp
index 61a82a2b4..e85ae4057 100644
--- a/src/core/resources/qframeallocator.cpp
+++ b/src/core/resources/qframeallocator.cpp
@@ -57,6 +57,8 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
QFrameAllocatorPrivate::QFrameAllocatorPrivate()
+ : m_maxObjectSize(0U)
+ , m_alignment(0U)
{
}
diff --git a/src/core/services/qdownloadhelperservice.cpp b/src/core/services/qdownloadhelperservice.cpp
index 4cd89c5d0..deddf3ae0 100644
--- a/src/core/services/qdownloadhelperservice.cpp
+++ b/src/core/services/qdownloadhelperservice.cpp
@@ -39,10 +39,10 @@
#include "qdownloadhelperservice_p.h"
#include "qdownloadnetworkworker_p.h"
+#include <QtCore/QThread>
#include <Qt3DCore/QAspectEngine>
#include <Qt3DCore/private/qabstractserviceprovider_p.h>
#include <Qt3DCore/private/qaspectengine_p.h>
-#include <Qt3DCore/private/qaspectthread_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
@@ -196,7 +196,7 @@ QString QDownloadHelperService::urlToLocalFileOrQrc(const QUrl &url)
QDownloadHelperService *QDownloadHelperService::getService(QAspectEngine *engine)
{
auto enginePrivate = Qt3DCore::QAspectEnginePrivate::get(engine);
- return enginePrivate->m_aspectThread->aspectManager()->serviceLocator()->downloadHelperService();
+ return enginePrivate->m_aspectManager->serviceLocator()->downloadHelperService();
}
bool QDownloadHelperService::isLocal(const QUrl &url)
diff --git a/src/core/services/qeventfilterservice.cpp b/src/core/services/qeventfilterservice.cpp
index c4ec79a13..036bcd7b4 100644
--- a/src/core/services/qeventfilterservice.cpp
+++ b/src/core/services/qeventfilterservice.cpp
@@ -39,12 +39,13 @@
#include "qeventfilterservice_p.h"
-#include <QtCore/QMap>
#include <QtCore/QObject>
-#include <QtCore/QVector>
#include <Qt3DCore/private/qabstractserviceprovider_p.h>
+#include <algorithm>
+#include <vector>
+
QT_BEGIN_NAMESPACE
namespace {
@@ -54,10 +55,10 @@ namespace {
int priority;
};
- bool operator <(const FilterPriorityPair &a, const FilterPriorityPair &b)
+ const auto byPriority = [](const FilterPriorityPair &a, const FilterPriorityPair &b) noexcept
{
return a.priority < b.priority;
- }
+ };
}
Q_DECLARE_TYPEINFO(FilterPriorityPair, Q_PRIMITIVE_TYPE);
@@ -89,32 +90,26 @@ public:
void registerEventFilter(QObject *eventFilter, int priority)
{
- for (int i = 0, m = m_eventFilters.size(); i < m; ++i)
- if (m_eventFilters.at(i).priority == priority)
- return;
-
FilterPriorityPair fpPair;
fpPair.filter = eventFilter;
fpPair.priority = priority;
- m_eventFilters.push_back(fpPair);
- std::sort(m_eventFilters.begin(), m_eventFilters.end());
+ const auto it = std::lower_bound(m_eventFilters.begin(), m_eventFilters.end(), fpPair, byPriority);
+ if (it == m_eventFilters.end() || it->priority != priority)
+ m_eventFilters.insert(it, std::move(fpPair));
}
void unregisterEventFilter(QObject *eventFilter)
{
- QVector<FilterPriorityPair>::iterator it = m_eventFilters.begin();
- const QVector<FilterPriorityPair>::iterator end = m_eventFilters.end();
- while (it != end) {
+ for (auto it = m_eventFilters.begin(), end = m_eventFilters.end(); it != end; ++it) {
if (it->filter == eventFilter) {
m_eventFilters.erase(it);
return;
}
- ++it;
}
}
QScopedPointer<InternalEventListener> m_eventDispatcher;
- QVector<FilterPriorityPair> m_eventFilters;
+ std::vector<FilterPriorityPair> m_eventFilters;
};
/* !\internal
@@ -179,8 +174,8 @@ InternalEventListener::InternalEventListener(QEventFilterServicePrivate *filterS
bool InternalEventListener::eventFilter(QObject *obj, QEvent *e)
{
- for (int i = m_filterService->m_eventFilters.size() - 1; i >= 0; --i) {
- const FilterPriorityPair &fPPair = m_filterService->m_eventFilters.at(i);
+ for (auto i = m_filterService->m_eventFilters.size(); i > 0; --i) {
+ const FilterPriorityPair &fPPair = m_filterService->m_eventFilters[i - 1];
if (fPPair.filter->eventFilter(obj, e))
return true;
}
diff --git a/src/core/transforms/qabstractskeleton.cpp b/src/core/transforms/qabstractskeleton.cpp
index 1bc7247a7..4a30d0710 100644
--- a/src/core/transforms/qabstractskeleton.cpp
+++ b/src/core/transforms/qabstractskeleton.cpp
@@ -39,7 +39,6 @@
#include "qabstractskeleton.h"
#include "qabstractskeleton_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -47,6 +46,7 @@ namespace Qt3DCore {
QAbstractSkeletonPrivate::QAbstractSkeletonPrivate()
: Qt3DCore::QNodePrivate()
+ , m_type(QSkeletonCreatedChangeBase::Skeleton)
, m_jointCount(0)
{
}
@@ -60,6 +60,14 @@ const QAbstractSkeletonPrivate *QAbstractSkeletonPrivate::get(const QAbstractSke
}
/*!
+ \internal
+ */
+QAbstractSkeletonPrivate *QAbstractSkeletonPrivate::get(QAbstractSkeleton *q)
+{
+ return q->d_func();
+}
+
+/*!
\qmltype AbstractSkeleton
\inqmlmodule Qt3D.Core
\inherits Node
@@ -97,6 +105,13 @@ QAbstractSkeleton::~QAbstractSkeleton()
{
}
+/*! \internal */
+void QAbstractSkeleton::sceneChangeEvent(const QSceneChangePtr &change)
+{
+ // TODO Unused remove in Qt6
+ Q_UNUSED(change)
+}
+
/*!
\property Qt3DCore::QAbstractSkeleton::jointCount
@@ -119,16 +134,6 @@ void QAbstractSkeletonPrivate::setJointCount(int jointCount)
q->blockNotifications(block);
}
-void QAbstractSkeleton::sceneChangeEvent(const QSceneChangePtr &change)
-{
- Q_D(QAbstractSkeleton);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("jointCount"))
- d->setJointCount(e->value().toInt());
- }
-}
-
} // namespace Qt3DCore
QT_END_NAMESPACE
diff --git a/src/core/transforms/qabstractskeleton.h b/src/core/transforms/qabstractskeleton.h
index 902def9f8..1c2eba08f 100644
--- a/src/core/transforms/qabstractskeleton.h
+++ b/src/core/transforms/qabstractskeleton.h
@@ -64,7 +64,8 @@ Q_SIGNALS:
protected:
QAbstractSkeleton(QAbstractSkeletonPrivate &dd, Qt3DCore::QNode *parent = nullptr);
- void sceneChangeEvent(const QSceneChangePtr &change) override;
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QAbstractSkeleton)
diff --git a/src/core/transforms/qabstractskeleton_p.h b/src/core/transforms/qabstractskeleton_p.h
index 51d57f8c4..35d0df755 100644
--- a/src/core/transforms/qabstractskeleton_p.h
+++ b/src/core/transforms/qabstractskeleton_p.h
@@ -53,12 +53,13 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qskeletoncreatedchange_p.h>
+#include <Qt3DCore/private/sqt_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class QAbstractSkeletonPrivate : public Qt3DCore::QNodePrivate
+class Q_3DCORE_PRIVATE_EXPORT QAbstractSkeletonPrivate : public Qt3DCore::QNodePrivate
{
public:
QAbstractSkeletonPrivate();
@@ -67,10 +68,13 @@ public:
Q_DECLARE_PUBLIC(QAbstractSkeleton)
static const QAbstractSkeletonPrivate *get(const QAbstractSkeleton *q);
+ static QAbstractSkeletonPrivate *get(QAbstractSkeleton *q);
QSkeletonCreatedChangeBase::SkeletonType m_type;
int m_jointCount;
+ QVector<Sqt> m_localPoses;
+ QVector<QString> m_jointNames;
};
} // namespace Qt3DCore
diff --git a/src/core/transforms/qarmature_p.h b/src/core/transforms/qarmature_p.h
index 1fc241dc2..3474349a6 100644
--- a/src/core/transforms/qarmature_p.h
+++ b/src/core/transforms/qarmature_p.h
@@ -60,7 +60,7 @@ namespace Qt3DCore {
class QAbstractSkeleton;
-class QArmaturePrivate : public Qt3DCore::QComponentPrivate
+class Q_3DCORE_PRIVATE_EXPORT QArmaturePrivate : public Qt3DCore::QComponentPrivate
{
public:
QArmaturePrivate();
diff --git a/src/core/transforms/qjoint.cpp b/src/core/transforms/qjoint.cpp
index 017773ff6..408d42f6d 100644
--- a/src/core/transforms/qjoint.cpp
+++ b/src/core/transforms/qjoint.cpp
@@ -41,9 +41,6 @@
#include "qjoint_p.h"
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -352,11 +349,8 @@ void QJoint::addChildJoint(QJoint *joint)
// Ensures proper bookkeeping
d->registerDestructionHelper(joint, &QJoint::removeChildJoint, d->m_childJoints);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), joint);
- change->setPropertyName("childJoint");
- d->notifyObservers(change);
- }
+ if (d->m_changeArbiter != nullptr)
+ d->updateNode(joint, "childJoint", PropertyValueAdded);
}
}
@@ -368,12 +362,8 @@ void QJoint::removeChildJoint(QJoint *joint)
{
Q_D(QJoint);
if (d->m_childJoints.contains(joint)) {
-
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), joint);
- change->setPropertyName("childJoint");
- d->notifyObservers(change);
- }
+ if (d->m_changeArbiter != nullptr)
+ d->updateNode(joint, "childJoint", PropertyValueRemoved);
d->m_childJoints.removeOne(joint);
diff --git a/src/core/transforms/qjoint_p.h b/src/core/transforms/qjoint_p.h
index 82439d55a..cb0bfe847 100644
--- a/src/core/transforms/qjoint_p.h
+++ b/src/core/transforms/qjoint_p.h
@@ -60,7 +60,7 @@ namespace Qt3DCore {
class QJoint;
-class QJointPrivate : public QNodePrivate
+class Q_3DCORE_PRIVATE_EXPORT QJointPrivate : public QNodePrivate
{
public:
QJointPrivate();
diff --git a/src/core/transforms/qskeleton_p.h b/src/core/transforms/qskeleton_p.h
index c8b6554f9..2ce5fce07 100644
--- a/src/core/transforms/qskeleton_p.h
+++ b/src/core/transforms/qskeleton_p.h
@@ -60,7 +60,7 @@ namespace Qt3DCore {
class QJoint;
-class QSkeletonPrivate : public QAbstractSkeletonPrivate
+class Q_3DCORE_PRIVATE_EXPORT QSkeletonPrivate : public QAbstractSkeletonPrivate
{
public:
QSkeletonPrivate();
diff --git a/src/core/transforms/qskeletonloader.cpp b/src/core/transforms/qskeletonloader.cpp
index d5296ecc9..b1a311a0c 100644
--- a/src/core/transforms/qskeletonloader.cpp
+++ b/src/core/transforms/qskeletonloader.cpp
@@ -68,6 +68,27 @@ void QSkeletonLoaderPrivate::setStatus(QSkeletonLoader::Status status)
}
}
+void QSkeletonLoaderPrivate::setRootJoint(QJoint *rootJoint)
+{
+ Q_Q(QSkeletonLoader);
+ if (rootJoint == m_rootJoint)
+ return;
+
+ if (m_rootJoint)
+ unregisterDestructionHelper(m_rootJoint);
+
+ if (rootJoint && !rootJoint->parent())
+ rootJoint->setParent(q);
+
+ m_rootJoint = rootJoint;
+
+ // Ensures proper bookkeeping
+ if (m_rootJoint)
+ registerPrivateDestructionHelper(m_rootJoint, &QSkeletonLoaderPrivate::setRootJoint);
+
+ emit q->rootJointChanged(m_rootJoint);
+}
+
/*!
\qmltype SkeletonLoader
\inqmlmodule Qt3D.Core
@@ -217,39 +238,12 @@ void QSkeletonLoader::setCreateJointsEnabled(bool createJoints)
void QSkeletonLoader::setRootJoint(QJoint *rootJoint)
{
Q_D(QSkeletonLoader);
- if (rootJoint == d->m_rootJoint)
- return;
-
- if (d->m_rootJoint)
- d->unregisterDestructionHelper(d->m_rootJoint);
-
- if (rootJoint && !rootJoint->parent())
- rootJoint->setParent(this);
-
- d->m_rootJoint = rootJoint;
-
- // Ensures proper bookkeeping
- if (d->m_rootJoint)
- d->registerDestructionHelper(d->m_rootJoint, &QSkeletonLoader::setRootJoint, d->m_rootJoint);
-
- emit rootJointChanged(d->m_rootJoint);
+ d->setRootJoint(rootJoint);
}
/*! \internal */
void QSkeletonLoader::sceneChangeEvent(const QSceneChangePtr &change)
{
- Q_D(QSkeletonLoader);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- auto propertyChange = qSharedPointerCast<QStaticPropertyUpdatedChangeBase>(change);
- if (propertyChange->propertyName() == QByteArrayLiteral("status")) {
- const auto e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- d->setStatus(static_cast<QSkeletonLoader::Status>(e->value().toInt()));
- } else if (propertyChange->propertyName() == QByteArrayLiteral("rootJoint")) {
- auto typedChange = qSharedPointerCast<QJointChange>(propertyChange);
- auto rootJoint = std::move(typedChange->data);
- setRootJoint(rootJoint.release());
- }
- }
QAbstractSkeleton::sceneChangeEvent(change);
}
diff --git a/src/core/transforms/qskeletonloader_p.h b/src/core/transforms/qskeletonloader_p.h
index ab0babe00..6bd4e1eef 100644
--- a/src/core/transforms/qskeletonloader_p.h
+++ b/src/core/transforms/qskeletonloader_p.h
@@ -64,12 +64,13 @@ namespace Qt3DCore {
class QJoint;
-class QSkeletonLoaderPrivate : public QAbstractSkeletonPrivate
+class Q_3DCORE_PRIVATE_EXPORT QSkeletonLoaderPrivate : public QAbstractSkeletonPrivate
{
public:
QSkeletonLoaderPrivate();
void setStatus(QSkeletonLoader::Status status);
+ void setRootJoint(QJoint *rootJoint);
Q_DECLARE_PUBLIC(QSkeletonLoader)
diff --git a/src/core/transforms/qtransform.cpp b/src/core/transforms/qtransform.cpp
index d0e2628f7..d41b87f79 100644
--- a/src/core/transforms/qtransform.cpp
+++ b/src/core/transforms/qtransform.cpp
@@ -135,6 +135,18 @@ QTransformPrivate::~QTransformPrivate()
*/
/*!
+ \qmlproperty matrix4x4 QTransform::worldMatrix
+
+ Holds the world transformation matrix for the transform. This assumes the
+ Transform component is being referenced by an Entity. This makes it more
+ convenient to identify when an Entity part of a subtree has been
+ transformed in the world even though its local transformation might not
+ have changed.
+
+ \since 5.14
+ */
+
+/*!
\qmlmethod quaternion Transform::fromAxisAndAngle(vector3d axis, real angle)
Creates a quaternion from \a axis and \a angle.
Returns the resulting quaternion.
@@ -222,6 +234,37 @@ QTransform::QTransform(QTransformPrivate &dd, QNode *parent)
{
}
+/*!
+ \internal
+ */
+// TODO Unused remove in Qt6
+void QTransform::sceneChangeEvent(const QSceneChangePtr &change)
+{
+ Q_D(QTransform);
+ switch (change->type()) {
+ case PropertyUpdated: {
+ Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
+ if (propertyChange->propertyName() == QByteArrayLiteral("worldMatrix")) {
+ const bool blocked = blockNotifications(true);
+ d->setWorldMatrix(propertyChange->value().value<QMatrix4x4>());
+ blockNotifications(blocked);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void QTransformPrivate::setWorldMatrix(const QMatrix4x4 &worldMatrix)
+{
+ Q_Q(QTransform);
+ if (m_worldMatrix == worldMatrix)
+ return;
+ m_worldMatrix = worldMatrix;
+ emit q->worldMatrixChanged(worldMatrix);
+}
+
void QTransform::setMatrix(const QMatrix4x4 &m)
{
Q_D(QTransform);
@@ -240,7 +283,6 @@ void QTransform::setMatrix(const QMatrix4x4 &m)
emit scale3DChanged(s);
emit rotationChanged(r);
emit translationChanged(t);
-
const bool wasBlocked = blockNotifications(true);
emit matrixChanged();
emit scaleChanged(d->m_scale.x());
@@ -330,6 +372,30 @@ QMatrix4x4 QTransform::matrix() const
}
/*!
+ \property QTransform::worldMatrix
+
+ Holds the world transformation matrix for the transform. This assumes the
+ QTransform component is being referenced by a QEntity. This makes it more
+ convenient to identify when a QEntity part of a subtree has been
+ transformed in the world even though its local transformation might not
+ have changed.
+
+ \since 5.14
+ */
+
+/*!
+ Returns the world transformation matrix associated to the QTransform when
+ referenced by a QEntity which may be part of a QEntity hierarchy.
+
+ \since 5.14
+ */
+QMatrix4x4 QTransform::worldMatrix() const
+{
+ Q_D(const QTransform);
+ return d->m_worldMatrix;
+}
+
+/*!
\property Qt3DCore::QTransform::rotationX
Holds the x rotation of the transform as Euler angle.
diff --git a/src/core/transforms/qtransform.h b/src/core/transforms/qtransform.h
index a80385a1b..ce6bf42fa 100644
--- a/src/core/transforms/qtransform.h
+++ b/src/core/transforms/qtransform.h
@@ -61,6 +61,7 @@ class Q_3DCORESHARED_EXPORT QTransform : public QComponent
Q_PROPERTY(float rotationX READ rotationX WRITE setRotationX NOTIFY rotationXChanged)
Q_PROPERTY(float rotationY READ rotationY WRITE setRotationY NOTIFY rotationYChanged)
Q_PROPERTY(float rotationZ READ rotationZ WRITE setRotationZ NOTIFY rotationZChanged)
+ Q_PROPERTY(QMatrix4x4 worldMatrix READ worldMatrix NOTIFY worldMatrixChanged REVISION 14)
public:
explicit QTransform(QNode *parent = nullptr);
@@ -88,6 +89,7 @@ public:
Q_INVOKABLE static QMatrix4x4 rotateFromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis);
QMatrix4x4 matrix() const;
+ QMatrix4x4 worldMatrix() const;
float rotationX() const;
float rotationY() const;
@@ -113,9 +115,12 @@ Q_SIGNALS:
void rotationXChanged(float rotationX);
void rotationYChanged(float rotationY);
void rotationZChanged(float rotationZ);
+ void worldMatrixChanged(const QMatrix4x4 &worldMatrix);
protected:
explicit QTransform(QTransformPrivate &dd, QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
Q_DECLARE_PRIVATE(QTransform)
diff --git a/src/core/transforms/qtransform_p.h b/src/core/transforms/qtransform_p.h
index 89bc55491..56053309e 100644
--- a/src/core/transforms/qtransform_p.h
+++ b/src/core/transforms/qtransform_p.h
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
-class QTransformPrivate : public QComponentPrivate
+class Q_3DCORE_PRIVATE_EXPORT QTransformPrivate : public QComponentPrivate
{
Q_DECLARE_PUBLIC(QTransform)
@@ -75,6 +75,10 @@ public:
mutable QMatrix4x4 m_matrix;
mutable bool m_matrixDirty;
+
+ QMatrix4x4 m_worldMatrix;
+
+ void setWorldMatrix(const QMatrix4x4 &worldMatrix);
};
struct QTransformData
diff --git a/src/core/transforms/sqt_p.h b/src/core/transforms/sqt_p.h
index 5fdefccc8..e602cc71e 100644
--- a/src/core/transforms/sqt_p.h
+++ b/src/core/transforms/sqt_p.h
@@ -71,7 +71,9 @@ struct Sqt
Sqt()
: rotation()
, scale(1.0f, 1.0f, 1.0f)
+ , pad1(0.f)
, translation()
+ , pad2(0.f)
{}
inline QMatrix4x4 toMatrix() const
diff --git a/src/extras/defaults/qabstractspritesheet.cpp b/src/extras/defaults/qabstractspritesheet.cpp
index 640e600c7..2cf134f7c 100644
--- a/src/extras/defaults/qabstractspritesheet.cpp
+++ b/src/extras/defaults/qabstractspritesheet.cpp
@@ -100,7 +100,7 @@ QAbstractSpriteSheet::~QAbstractSpriteSheet()
}
/*!
- \property QAbstractSpriteSheet::texture
+ \property Qt3DExtras::QAbstractSpriteSheet::texture
Holds the current texture used by the material.
*/
diff --git a/src/extras/defaults/qforwardrenderer.cpp b/src/extras/defaults/qforwardrenderer.cpp
index 5bf206ede..f1306e787 100644
--- a/src/extras/defaults/qforwardrenderer.cpp
+++ b/src/extras/defaults/qforwardrenderer.cpp
@@ -139,6 +139,7 @@ QForwardRenderer::QForwardRenderer(QNode *parent)
{
Q_D(QForwardRenderer);
QObject::connect(d->m_clearBuffer, &QClearBuffers::clearColorChanged, this, &QForwardRenderer::clearColorChanged);
+ QObject::connect(d->m_clearBuffer, &QClearBuffers::buffersChanged, this, &QForwardRenderer::buffersToClearChanged);
QObject::connect(d->m_viewport, &QViewport::normalizedRectChanged, this, &QForwardRenderer::viewportRectChanged);
QObject::connect(d->m_cameraSelector, &QCameraSelector::cameraChanged, this, &QForwardRenderer::cameraChanged);
QObject::connect(d->m_surfaceSelector, &QRenderSurfaceSelector::surfaceChanged, this, &QForwardRenderer::surfaceChanged);
@@ -164,6 +165,12 @@ void QForwardRenderer::setClearColor(const QColor &clearColor)
d->m_clearBuffer->setClearColor(clearColor);
}
+void QForwardRenderer::setBuffersToClear(QClearBuffers::BufferType buffers)
+{
+ Q_D(QForwardRenderer);
+ d->m_clearBuffer->setBuffers(buffers);
+}
+
void QForwardRenderer::setCamera(Qt3DCore::QEntity *camera)
{
Q_D(QForwardRenderer);
@@ -229,6 +236,24 @@ QColor QForwardRenderer::clearColor() const
}
/*!
+ \qmlproperty color ForwardRenderer::buffersToClear
+
+ Holds the current buffers to be cleared. Default value is ColorDepthBuffer
+ \since 5.14
+*/
+/*!
+ \property QForwardRenderer::buffersToClear
+
+ Holds the current buffers to be cleared. Default value is ColorDepthBuffer
+ \since 5.14
+*/
+QClearBuffers::BufferType QForwardRenderer::buffersToClear() const
+{
+ Q_D(const QForwardRenderer);
+ return d->m_clearBuffer->buffers();
+}
+
+/*!
\qmlproperty Entity ForwardRenderer::camera
Holds the current camera entity used to render the scene.
diff --git a/src/extras/defaults/qforwardrenderer.h b/src/extras/defaults/qforwardrenderer.h
index e41cbd3df..a34d39560 100644
--- a/src/extras/defaults/qforwardrenderer.h
+++ b/src/extras/defaults/qforwardrenderer.h
@@ -44,7 +44,7 @@
#include <Qt3DRender/qtechniquefilter.h>
#include <QtCore/QRectF>
#include <QtGui/QColor>
-
+#include <Qt3DRender/QClearBuffers>
QT_BEGIN_NAMESPACE
@@ -61,6 +61,7 @@ class Q_3DEXTRASSHARED_EXPORT QForwardRenderer : public Qt3DRender::QTechniqueFi
Q_PROPERTY(QObject *window READ surface WRITE setSurface NOTIFY surfaceChanged)
Q_PROPERTY(QRectF viewportRect READ viewportRect WRITE setViewportRect NOTIFY viewportRectChanged)
Q_PROPERTY(QColor clearColor READ clearColor WRITE setClearColor NOTIFY clearColorChanged)
+ Q_PROPERTY(Qt3DRender::QClearBuffers::BufferType buffersToClear READ buffersToClear WRITE setBuffersToClear NOTIFY buffersToClearChanged REVISION 14)
Q_PROPERTY(Qt3DCore::QEntity *camera READ camera WRITE setCamera NOTIFY cameraChanged)
Q_PROPERTY(QSize externalRenderTargetSize READ externalRenderTargetSize WRITE setExternalRenderTargetSize NOTIFY externalRenderTargetSizeChanged)
Q_PROPERTY(bool frustumCulling READ isFrustumCullingEnabled WRITE setFrustumCullingEnabled NOTIFY frustumCullingEnabledChanged)
@@ -71,6 +72,7 @@ public:
QRectF viewportRect() const;
QColor clearColor() const;
+ Qt3DRender::QClearBuffers::BufferType buffersToClear() const;
Qt3DCore::QEntity *camera() const;
QObject *surface() const;
QSize externalRenderTargetSize() const;
@@ -80,6 +82,7 @@ public:
public Q_SLOTS:
void setViewportRect(const QRectF &viewportRect);
void setClearColor(const QColor &clearColor);
+ void setBuffersToClear(Qt3DRender::QClearBuffers::BufferType);
void setCamera(Qt3DCore::QEntity *camera);
void setSurface(QObject * surface);
void setExternalRenderTargetSize(const QSize &size);
@@ -89,6 +92,7 @@ public Q_SLOTS:
Q_SIGNALS:
void viewportRectChanged(const QRectF &viewportRect);
void clearColorChanged(const QColor &clearColor);
+ void buffersToClearChanged(Qt3DRender::QClearBuffers::BufferType);
void cameraChanged(Qt3DCore::QEntity *camera);
void surfaceChanged(QObject *surface);
void externalRenderTargetSizeChanged(const QSize &size);
diff --git a/src/extras/defaults/qt3dwindow.cpp b/src/extras/defaults/qt3dwindow.cpp
index 2df4716dd..ace40c3c1 100644
--- a/src/extras/defaults/qt3dwindow.cpp
+++ b/src/extras/defaults/qt3dwindow.cpp
@@ -61,6 +61,7 @@
#include <Qt3DLogic/qlogicaspect.h>
#include <Qt3DRender/qcamera.h>
#include <QtGui/qopenglcontext.h>
+#include <private/qrendersettings_p.h>
#include <QEvent>
@@ -248,8 +249,11 @@ bool Qt3DWindow::event(QEvent *e)
{
Q_D(Qt3DWindow);
const bool needsRedraw = (e->type() == QEvent::Expose || e->type() == QEvent::UpdateRequest);
- if (needsRedraw && d->m_renderSettings->renderPolicy() == Qt3DRender::QRenderSettings::OnDemand)
- d->m_renderSettings->sendCommand(QLatin1Literal("InvalidateFrame"));
+ if (needsRedraw && d->m_renderSettings->renderPolicy() == Qt3DRender::QRenderSettings::OnDemand) {
+ Qt3DRender::QRenderSettingsPrivate *p = static_cast<Qt3DRender::QRenderSettingsPrivate *>(
+ Qt3DCore::QNodePrivate::get(d->m_renderSettings));
+ p->invalidateFrame();
+ }
return QWindow::event(e);
}
diff --git a/src/extras/defaults/qtexturematerial.cpp b/src/extras/defaults/qtexturematerial.cpp
index 5545f2018..dca45fded 100644
--- a/src/extras/defaults/qtexturematerial.cpp
+++ b/src/extras/defaults/qtexturematerial.cpp
@@ -63,7 +63,7 @@ QTextureMaterialPrivate::QTextureMaterialPrivate()
: QMaterialPrivate()
, m_textureEffect(new QEffect)
, m_textureParameter(new QParameter(QStringLiteral("diffuseTexture"), new QTexture2D))
- , m_textureTransformParameter(new QParameter(QStringLiteral("texCoordTransform"), qVariantFromValue(QMatrix3x3())))
+ , m_textureTransformParameter(new QParameter(QStringLiteral("texCoordTransform"), QVariant::fromValue(QMatrix3x3())))
, m_textureGL3Technique(new QTechnique)
, m_textureGL2Technique(new QTechnique)
, m_textureES2Technique(new QTechnique)
@@ -247,13 +247,13 @@ void QTextureMaterial::setTextureOffset(QVector2D textureOffset)
QMatrix3x3 matrix = d->m_textureTransformParameter->value().value<QMatrix3x3>();
matrix(0, 2) = textureOffset.x();
matrix(1, 2) = textureOffset.y();
- d->m_textureTransformParameter->setValue(qVariantFromValue(matrix));
+ d->m_textureTransformParameter->setValue(QVariant::fromValue(matrix));
}
void QTextureMaterial::setTextureTransform(const QMatrix3x3 &matrix)
{
Q_D(QTextureMaterial);
- d->m_textureTransformParameter->setValue(qVariantFromValue(matrix));
+ d->m_textureTransformParameter->setValue(QVariant::fromValue(matrix));
}
/*!
diff --git a/src/extras/extras.pro b/src/extras/extras.pro
index 22c9fcb93..396c9aa91 100644
--- a/src/extras/extras.pro
+++ b/src/extras/extras.pro
@@ -4,9 +4,6 @@ QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dinput
DEFINES += QT3DEXTRAS_LIBRARY
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
load(qt_module)
include (geometries/geometries.pri)
diff --git a/src/extras/text/qdistancefieldglyphcache.cpp b/src/extras/text/qdistancefieldglyphcache.cpp
index 30db3ff4e..a3819b8fe 100644
--- a/src/extras/text/qdistancefieldglyphcache.cpp
+++ b/src/extras/text/qdistancefieldglyphcache.cpp
@@ -284,7 +284,9 @@ DistanceFieldFont* QDistanceFieldGlyphCache::getOrCreateDistanceFieldFont(const
actualFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(useDoubleRes) * QT_DISTANCEFIELD_SCALE(useDoubleRes));
// create new font cache
- DistanceFieldFont *dff = new DistanceFieldFont(actualFont, useDoubleRes, m_rootNode);
+ // we set the parent node to nullptr, since the parent node of QTextureAtlasses
+ // will be set when we pass them to QText2DMaterial later
+ DistanceFieldFont *dff = new DistanceFieldFont(actualFont, useDoubleRes, nullptr);
m_fonts.insert(key, dff);
return dff;
}
diff --git a/src/extras/text/qtextureatlas.cpp b/src/extras/text/qtextureatlas.cpp
index 1f4b22d83..4ab992224 100644
--- a/src/extras/text/qtextureatlas.cpp
+++ b/src/extras/text/qtextureatlas.cpp
@@ -41,9 +41,6 @@
#include "qtextureatlas_p_p.h"
#include <Qt3DRender/qtexturedata.h>
#include <Qt3DRender/qabstracttextureimage.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/input/backend/abstractactioninput.cpp b/src/input/backend/abstractactioninput.cpp
index 1d4366554..ec469204e 100644
--- a/src/input/backend/abstractactioninput.cpp
+++ b/src/input/backend/abstractactioninput.cpp
@@ -46,7 +46,7 @@ namespace Qt3DInput {
namespace Input {
AbstractActionInput::AbstractActionInput()
- : Qt3DCore::QBackendNode()
+ : BackendNode()
{
}
diff --git a/src/input/backend/abstractactioninput_p.h b/src/input/backend/abstractactioninput_p.h
index 267d276c7..e200990e7 100644
--- a/src/input/backend/abstractactioninput_p.h
+++ b/src/input/backend/abstractactioninput_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -62,7 +62,7 @@ namespace Input {
class InputHandler;
-class Q_AUTOTEST_EXPORT AbstractActionInput : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT AbstractActionInput : public BackendNode
{
public:
AbstractActionInput();
diff --git a/src/input/backend/abstractaxisinput.cpp b/src/input/backend/abstractaxisinput.cpp
index aae165a7e..f69c046b3 100644
--- a/src/input/backend/abstractaxisinput.cpp
+++ b/src/input/backend/abstractaxisinput.cpp
@@ -41,7 +41,6 @@
#include "qabstractaxisinput_p.h"
#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/abstractaxisinput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
@@ -54,32 +53,24 @@ namespace Qt3DInput {
namespace Input {
AbstractAxisInput::AbstractAxisInput()
- : Qt3DCore::QBackendNode()
+ : BackendNode()
{
}
-void AbstractAxisInput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractAxisInputData>>(change);
- const auto &data = typedChange->data;
- m_sourceDevice = data.sourceDeviceId;
-}
-
void AbstractAxisInput::cleanup()
{
QBackendNode::setEnabled(false);
m_sourceDevice = Qt3DCore::QNodeId();
}
-void AbstractAxisInput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void AbstractAxisInput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("sourceDevice")) {
- m_sourceDevice = propertyChange->value().value<Qt3DCore::QNodeId>();
- }
- }
- QBackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAbstractAxisInput *node = qobject_cast<const QAbstractAxisInput *>(frontEnd);
+ if (!node)
+ return;
+
+ m_sourceDevice = Qt3DCore::qIdForNode(node->sourceDevice());
}
} // Input
diff --git a/src/input/backend/abstractaxisinput_p.h b/src/input/backend/abstractaxisinput_p.h
index 765e2214f..07a063908 100644
--- a/src/input/backend/abstractaxisinput_p.h
+++ b/src/input/backend/abstractaxisinput_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -64,19 +64,18 @@ namespace Input {
class InputHandler;
-class Q_AUTOTEST_EXPORT AbstractAxisInput : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT AbstractAxisInput : public BackendNode
{
public:
virtual void cleanup();
inline Qt3DCore::QNodeId sourceDevice() const { return m_sourceDevice; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
virtual float process(InputHandler *inputHandler, qint64 currentTime) = 0;
protected:
AbstractAxisInput();
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
Qt3DCore::QNodeId m_sourceDevice;
};
diff --git a/src/input/backend/action.cpp b/src/input/backend/action.cpp
index 601961dd9..a34ff164f 100644
--- a/src/input/backend/action.cpp
+++ b/src/input/backend/action.cpp
@@ -41,9 +41,6 @@
#include <Qt3DInput/qaction.h>
#include <Qt3DInput/qabstractactioninput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DInput/private/qaction_p.h>
@@ -54,18 +51,11 @@ namespace Qt3DInput {
namespace Input {
Action::Action()
- : Qt3DCore::QBackendNode(ReadWrite)
+ : BackendNode(ReadWrite)
, m_actionTriggered(false)
{
}
-void Action::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QActionData>>(change);
- const auto &data = typedChange->data;
- m_inputs = data.inputIds;
-}
-
void Action::cleanup()
{
QBackendNode::setEnabled(false);
@@ -75,38 +65,19 @@ void Action::cleanup()
void Action::setActionTriggered(bool actionTriggered)
{
- if (isEnabled() && (actionTriggered != m_actionTriggered)) {
+ if (isEnabled() && (actionTriggered != m_actionTriggered))
m_actionTriggered = actionTriggered;
-
- // Send change to the frontend
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("active");
- e->setValue(m_actionTriggered);
- notifyObservers(e);
- }
}
-void Action::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void Action::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("input"))
- m_inputs.push_back(change->addedNodeId());
- break;
- }
-
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("input"))
- m_inputs.removeOne(change->removedNodeId());
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const Qt3DInput::QAction *node = qobject_cast<const Qt3DInput::QAction *>(frontEnd);
+ if (!node)
+ return;
- default:
- break;
- }
- QBackendNode::sceneChangeEvent(e);
+ auto ids = Qt3DCore::qIdsForNodes(node->inputs());
+ m_inputs = ids;
}
} // Input
diff --git a/src/input/backend/action_p.h b/src/input/backend/action_p.h
index 8fe2759fd..7036f04b9 100644
--- a/src/input/backend/action_p.h
+++ b/src/input/backend/action_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +60,7 @@ namespace Qt3DInput {
namespace Input {
-class Q_AUTOTEST_EXPORT Action : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT Action : public BackendNode
{
public:
Action();
@@ -68,11 +68,9 @@ public:
inline QVector<Qt3DCore::QNodeId> inputs() const { return m_inputs; }
inline bool actionTriggered() const { return m_actionTriggered; }
void setActionTriggered(bool actionTriggered);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DCore::QNodeId> m_inputs;
bool m_actionTriggered;
};
diff --git a/src/input/backend/actioninput.cpp b/src/input/backend/actioninput.cpp
index 46dc7f584..b02da0a4d 100644
--- a/src/input/backend/actioninput.cpp
+++ b/src/input/backend/actioninput.cpp
@@ -40,8 +40,7 @@
#include "actioninput_p.h"
#include <Qt3DInput/qactioninput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-
+#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DInput/private/qactioninput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/utils_p.h>
@@ -58,14 +57,6 @@ ActionInput::ActionInput()
{
}
-void ActionInput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QActionInputData>>(change);
- const auto &data = typedChange->data;
- m_buttons = data.buttons;
- m_sourceDevice = data.sourceDeviceId;
-}
-
void ActionInput::cleanup()
{
setEnabled(false);
@@ -73,21 +64,20 @@ void ActionInput::cleanup()
m_buttons.clear();
}
-void ActionInput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void ActionInput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("sourceDevice"))
- m_sourceDevice = propertyChange->value().value<Qt3DCore::QNodeId>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("buttons"))
- m_buttons = propertyChange->value().value<QVector<int>>();
- }
- AbstractActionInput::sceneChangeEvent(e);
+ AbstractActionInput::syncFromFrontEnd(frontEnd, firstTime);
+ const QActionInput *node = qobject_cast<const QActionInput *>(frontEnd);
+ if (!node)
+ return;
+
+ m_sourceDevice = Qt3DCore::qIdForNode(node->sourceDevice());
+ m_buttons = node->buttons();
}
bool ActionInput::process(InputHandler *inputHandler, qint64 currentTime)
{
- Q_UNUSED(currentTime);
+ Q_UNUSED(currentTime)
if (!isEnabled())
return false;
diff --git a/src/input/backend/actioninput_p.h b/src/input/backend/actioninput_p.h
index 00fb0475c..eecf1d10e 100644
--- a/src/input/backend/actioninput_p.h
+++ b/src/input/backend/actioninput_p.h
@@ -69,13 +69,11 @@ public:
inline QVector<int> buttons() const { return m_buttons; }
inline Qt3DCore::QNodeId sourceDevice() const { return m_sourceDevice; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
bool process(InputHandler *inputHandler, qint64 currentTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<int> m_buttons;
Qt3DCore::QNodeId m_sourceDevice;
};
diff --git a/src/input/backend/analogaxisinput.cpp b/src/input/backend/analogaxisinput.cpp
index 4a801baec..9dece6b9b 100644
--- a/src/input/backend/analogaxisinput.cpp
+++ b/src/input/backend/analogaxisinput.cpp
@@ -41,7 +41,6 @@
#include <Qt3DInput/qanalogaxisinput.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
#include <Qt3DInput/private/qanalogaxisinput_p.h>
@@ -59,29 +58,20 @@ AnalogAxisInput::AnalogAxisInput()
{
}
-void AnalogAxisInput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAnalogAxisInputData>>(change);
- const auto &data = typedChange->data;
- m_axis = data.axis;
- AbstractAxisInput::initializeFromPeer(change);
-}
-
void AnalogAxisInput::cleanup()
{
m_axis = 0;
AbstractAxisInput::cleanup();
}
-void AnalogAxisInput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void AnalogAxisInput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("axis")) {
- m_axis = propertyChange->value().toInt();
- }
- }
- AbstractAxisInput::sceneChangeEvent(e);
+ AbstractAxisInput::syncFromFrontEnd(frontEnd, firstTime);
+ const QAnalogAxisInput *node = qobject_cast<const QAnalogAxisInput *>(frontEnd);
+ if (!node)
+ return;
+
+ m_axis = node->axis();
}
float AnalogAxisInput::process(InputHandler *inputHandler, qint64 currentTime)
diff --git a/src/input/backend/analogaxisinput_p.h b/src/input/backend/analogaxisinput_p.h
index cd43e7d23..f13a2a2e1 100644
--- a/src/input/backend/analogaxisinput_p.h
+++ b/src/input/backend/analogaxisinput_p.h
@@ -66,13 +66,11 @@ public:
void cleanup() final;
inline int axis() const { return m_axis; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final;
float process(InputHandler *inputHandler, qint64 currentTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
int m_axis;
};
diff --git a/src/input/backend/assignkeyboardfocusjob.cpp b/src/input/backend/assignkeyboardfocusjob.cpp
index 385074812..d5947f9c9 100644
--- a/src/input/backend/assignkeyboardfocusjob.cpp
+++ b/src/input/backend/assignkeyboardfocusjob.cpp
@@ -38,7 +38,8 @@
****************************************************************************/
#include "assignkeyboardfocusjob_p.h"
-
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DInput/qkeyboardhandler.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/job_common_p.h>
@@ -50,12 +51,23 @@ QT_BEGIN_NAMESPACE
namespace Qt3DInput {
namespace Input {
+class AssignKeyboardFocusJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ AssignKeyboardFocusJobPrivate() { }
+ ~AssignKeyboardFocusJobPrivate() override { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ QVector<QPair<Qt3DCore::QNodeId, bool>> updates;
+};
+
AssignKeyboardFocusJob::AssignKeyboardFocusJob(Qt3DCore::QNodeId keyboardDevice)
- : QAspectJob()
+ : QAspectJob(*new AssignKeyboardFocusJobPrivate())
, m_inputHandler(nullptr)
, m_keyboardDevice(keyboardDevice)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::AssignKeyboardFocus, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::AssignKeyboardFocus, 0)
}
void AssignKeyboardFocusJob::setInputHandler(InputHandler *handler)
@@ -65,20 +77,40 @@ void AssignKeyboardFocusJob::setInputHandler(InputHandler *handler)
void AssignKeyboardFocusJob::run()
{
+ Q_DJOB(AssignKeyboardFocusJob);
+
KeyboardDevice *keyboardDevice = m_inputHandler->keyboardDeviceManager()->lookupResource(m_keyboardDevice);
const auto handles = m_inputHandler->keyboardInputManager()->activeHandles();
+ d->updates.reserve(handles.size());
+
for (const HKeyboardHandler &handle : handles) {
KeyboardHandler *input = m_inputHandler->keyboardInputManager()->data(handle);
Q_ASSERT(input);
if (input->keyboardDevice() == m_keyboardDevice) {
bool hasFocus = input->peerId() == keyboardDevice->lastKeyboardInputRequester();
input->setFocus(hasFocus);
+ d->updates.push_back({input->peerId(), hasFocus});
if (hasFocus)
keyboardDevice->setCurrentFocusItem(input->peerId());
}
}
}
+void AssignKeyboardFocusJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ for (const auto &data: qAsConst(updates)) {
+ QKeyboardHandler *node = qobject_cast<QKeyboardHandler *>(manager->lookupNode(data.first));
+ if (!node)
+ continue;
+
+ const bool b = node->blockNotifications(true);
+ node->setFocus(data.second);
+ node->blockNotifications(b);
+ }
+
+ updates.clear();
+}
+
} // namespace Input
} // namespace Qt3DInput
diff --git a/src/input/backend/assignkeyboardfocusjob_p.h b/src/input/backend/assignkeyboardfocusjob_p.h
index 8a74de85f..87cc2fbda 100644
--- a/src/input/backend/assignkeyboardfocusjob_p.h
+++ b/src/input/backend/assignkeyboardfocusjob_p.h
@@ -60,6 +60,7 @@ namespace Qt3DInput {
namespace Input {
class InputHandler;
+class AssignKeyboardFocusJobPrivate;
class AssignKeyboardFocusJob : public Qt3DCore::QAspectJob
{
diff --git a/src/input/backend/axis.cpp b/src/input/backend/axis.cpp
index 6ba4e2b34..6c04d8fac 100644
--- a/src/input/backend/axis.cpp
+++ b/src/input/backend/axis.cpp
@@ -41,11 +41,9 @@
#include <Qt3DInput/qaxis.h>
#include <Qt3DInput/qabstractaxisinput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DInput/private/qaxis_p.h>
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -54,18 +52,11 @@ namespace Qt3DInput {
namespace Input {
Axis::Axis()
- : Qt3DCore::QBackendNode(ReadWrite)
+ : BackendNode(ReadWrite)
, m_axisValue(0.0f)
{
}
-void Axis::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAxisData>>(change);
- const auto &data = typedChange->data;
- m_inputs = data.inputIds;
-}
-
void Axis::cleanup()
{
QBackendNode::setEnabled(false);
@@ -75,38 +66,19 @@ void Axis::cleanup()
void Axis::setAxisValue(float axisValue)
{
- if (isEnabled() && (axisValue != m_axisValue)) {
+ if (isEnabled() && (!qFuzzyCompare(axisValue, m_axisValue)))
m_axisValue = axisValue;
-
- // Send a change to the frontend
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("value");
- e->setValue(m_axisValue);
- notifyObservers(e);
- }
}
-void Axis::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void Axis::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("input"))
- m_inputs.push_back(change->addedNodeId());
- break;
- }
-
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("input"))
- m_inputs.removeOne(change->removedNodeId());
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const Qt3DInput::QAxis *node = qobject_cast<const Qt3DInput::QAxis *>(frontEnd);
+ if (!node)
+ return;
- default:
- break;
- }
- QBackendNode::sceneChangeEvent(e);
+ auto ids = Qt3DCore::qIdsForNodes(node->inputs());
+ m_inputs = ids;
}
} // namespace Input
diff --git a/src/input/backend/axis_p.h b/src/input/backend/axis_p.h
index b83405060..da4ec9ac6 100644
--- a/src/input/backend/axis_p.h
+++ b/src/input/backend/axis_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -60,7 +60,7 @@ namespace Qt3DInput {
namespace Input {
-class Q_AUTOTEST_EXPORT Axis : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT Axis : public BackendNode
{
public:
Axis();
@@ -68,11 +68,9 @@ public:
inline QVector<Qt3DCore::QNodeId> inputs() const { return m_inputs; }
inline float axisValue() const { return m_axisValue; }
void setAxisValue(float axisValue);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DCore::QNodeId> m_inputs;
float m_axisValue;
};
diff --git a/src/input/backend/axisaccumulator.cpp b/src/input/backend/axisaccumulator.cpp
index edc282bec..8e93c120e 100644
--- a/src/input/backend/axisaccumulator.cpp
+++ b/src/input/backend/axisaccumulator.cpp
@@ -39,8 +39,7 @@
#include "axisaccumulator_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
-
+#include <Qt3DInput/qaxis.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/qaxisaccumulator_p.h>
@@ -50,7 +49,7 @@ namespace Qt3DInput {
namespace Input {
AxisAccumulator::AxisAccumulator()
- : Qt3DCore::QBackendNode(ReadWrite)
+ : BackendNode(ReadWrite)
, m_sourceAxisId()
, m_sourceAxisType(QAxisAccumulator::Velocity)
, m_scale(1.0f)
@@ -59,17 +58,6 @@ AxisAccumulator::AxisAccumulator()
{
}
-void AxisAccumulator::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAxisAccumulatorData>>(change);
- const auto &data = typedChange->data;
- m_sourceAxisId = data.sourceAxisId;
- m_sourceAxisType = data.sourceAxisType;
- m_scale = data.scale;
- m_value = 0.0f;
- m_velocity = 0.0f;
-}
-
void AxisAccumulator::cleanup()
{
QBackendNode::setEnabled(false);
@@ -81,50 +69,31 @@ void AxisAccumulator::cleanup()
void AxisAccumulator::setValue(float value)
{
- if (isEnabled() && value != m_value) {
+ if (isEnabled() && value != m_value)
m_value = value;
-
- // Send a change to the frontend
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("value");
- e->setValue(m_value);
- notifyObservers(e);
- }
}
void AxisAccumulator::setVelocity(float velocity)
{
- if (isEnabled() && velocity != m_velocity) {
+ if (isEnabled() && velocity != m_velocity)
m_velocity = velocity;
-
- // Send a change to the frontend
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("velocity");
- e->setValue(m_velocity);
- notifyObservers(e);
- }
}
-void AxisAccumulator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void AxisAccumulator::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("sourceAxis"))
- m_sourceAxisId = change->value().value<Qt3DCore::QNodeId>();
- else if (change->propertyName() == QByteArrayLiteral("sourceAxisType"))
- m_sourceAxisType = change->value().value<QAxisAccumulator::SourceAxisType>();
- else if (change->propertyName() == QByteArrayLiteral("scale"))
- m_scale = change->value().toFloat();
- break;
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAxisAccumulator *node = qobject_cast<const QAxisAccumulator *>(frontEnd);
+ if (!node)
+ return;
- default:
- break;
+ m_sourceAxisId = Qt3DCore::qIdForNode(node->sourceAxis());
+ m_sourceAxisType = node->sourceAxisType();
+ m_scale = node->scale();
+
+ if (firstTime) {
+ m_value = 0.f;
+ m_velocity = 0.f;
}
- QBackendNode::sceneChangeEvent(e);
}
void AxisAccumulator::stepIntegration(AxisManager *axisManager, float dt)
diff --git a/src/input/backend/axisaccumulator_p.h b/src/input/backend/axisaccumulator_p.h
index bb1a35812..2f5a7de63 100644
--- a/src/input/backend/axisaccumulator_p.h
+++ b/src/input/backend/axisaccumulator_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DInput/qaxisaccumulator.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DCore/qbackendnode.h>
#include <Qt3DCore/qnodeid.h>
@@ -62,7 +63,7 @@ namespace Input {
class AxisManager;
-class Q_AUTOTEST_EXPORT AxisAccumulator : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT AxisAccumulator : public BackendNode
{
public:
AxisAccumulator();
@@ -78,13 +79,11 @@ public:
float velocity() const Q_DECL_NOTHROW { return m_velocity; }
void setVelocity(float velocity);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void stepIntegration(AxisManager *axisManager, float dt);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_sourceAxisId;
QAxisAccumulator::SourceAxisType m_sourceAxisType;
float m_scale;
diff --git a/src/input/backend/axisaccumulatorjob.cpp b/src/input/backend/axisaccumulatorjob.cpp
index cda8a5e26..b6c1c8482 100644
--- a/src/input/backend/axisaccumulatorjob.cpp
+++ b/src/input/backend/axisaccumulatorjob.cpp
@@ -38,7 +38,9 @@
****************************************************************************/
#include "axisaccumulatorjob_p.h"
-
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DInput/qaxisaccumulator.h>
+#include <Qt3DInput/private/qaxisaccumulator_p.h>
#include <Qt3DInput/private/axisaccumulator_p.h>
#include <Qt3DInput/private/job_common_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
@@ -48,24 +50,53 @@ QT_BEGIN_NAMESPACE
namespace Qt3DInput {
namespace Input {
+class AxisAccumulatorJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ AxisAccumulatorJobPrivate() { }
+ ~AxisAccumulatorJobPrivate() override { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ QVector<AxisAccumulator *> updates;
+};
+
AxisAccumulatorJob::AxisAccumulatorJob(AxisAccumulatorManager *axisAccumulatormanager,
AxisManager *axisManager)
- : Qt3DCore::QAspectJob()
+ : Qt3DCore::QAspectJob(*new AxisAccumulatorJobPrivate)
, m_axisAccumulatorManager(axisAccumulatormanager)
, m_axisManager(axisManager)
, m_dt(0.0f)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::AxisAccumulatorIntegration, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::AxisAccumulatorIntegration, 0)
}
void AxisAccumulatorJob::run()
{
+ Q_DJOB(AxisAccumulatorJob);
// Iterate over the accumulators and ask each to step the integrations
const auto activeHandles = m_axisAccumulatorManager->activeHandles();
+ d->updates.reserve(activeHandles.size());
+
for (const auto &accumulatorHandle : activeHandles) {
AxisAccumulator *accumulator = m_axisAccumulatorManager->data(accumulatorHandle);
- if (accumulator->isEnabled())
+ if (accumulator->isEnabled()) {
accumulator->stepIntegration(m_axisManager, m_dt);
+ d->updates.push_back(accumulator);
+ }
+ }
+}
+
+void AxisAccumulatorJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ for (auto backend: qAsConst(updates)) {
+ QAxisAccumulator *node = qobject_cast<QAxisAccumulator *>(manager->lookupNode(backend->peerId()));
+ if (!node)
+ continue;
+
+ QAxisAccumulatorPrivate *dnode = static_cast<QAxisAccumulatorPrivate *>(QAxisAccumulatorPrivate::get(node));
+ dnode->setValue(backend->value());
+ dnode->setVelocity(backend->velocity());
}
}
diff --git a/src/input/backend/axisaccumulatorjob_p.h b/src/input/backend/axisaccumulatorjob_p.h
index 4d38fd70f..3e8122287 100644
--- a/src/input/backend/axisaccumulatorjob_p.h
+++ b/src/input/backend/axisaccumulatorjob_p.h
@@ -62,6 +62,7 @@ namespace Input {
class AxisAccumulatorManager;
class AxisManager;
+class AxisAccumulatorJobPrivate;
class Q_AUTOTEST_EXPORT AxisAccumulatorJob : public Qt3DCore::QAspectJob
{
diff --git a/src/input/backend/axissetting.cpp b/src/input/backend/axissetting.cpp
index b3c81f84d..53e645c4d 100644
--- a/src/input/backend/axissetting.cpp
+++ b/src/input/backend/axissetting.cpp
@@ -40,7 +40,6 @@
#include "axissetting_p.h"
#include <Qt3DInput/qaxissetting.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/qaxissetting_p.h>
@@ -50,22 +49,13 @@ namespace Qt3DInput {
namespace Input {
AxisSetting::AxisSetting()
- : Qt3DCore::QBackendNode()
+ : BackendNode()
, m_deadZoneRadius(0.0f)
, m_axes(0)
, m_smooth(false)
{
}
-void AxisSetting::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAxisSettingData>>(change);
- const auto &data = typedChange->data;
- m_deadZoneRadius = data.deadZoneRadius;
- m_axes = data.axes;
- m_smooth = data.smooth;
-}
-
void AxisSetting::cleanup()
{
QBackendNode::setEnabled(false);
@@ -74,19 +64,16 @@ void AxisSetting::cleanup()
m_smooth = false;
}
-void AxisSetting::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void AxisSetting::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("deadZoneRadius")) {
- m_deadZoneRadius = propertyChange->value().toFloat();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("axes")) {
- m_axes = propertyChange->value().value<QVector<int>>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("smooth")) {
- m_smooth = propertyChange->value().toBool();
- }
- }
- QBackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAxisSetting *node = qobject_cast<const QAxisSetting *>(frontEnd);
+ if (!node)
+ return;
+
+ m_deadZoneRadius = node->deadZoneRadius();
+ m_axes = node->axes();
+ m_smooth = node->isSmoothEnabled();
}
} // namespace Input
diff --git a/src/input/backend/axissetting_p.h b/src/input/backend/axissetting_p.h
index 42e1010d5..7d1e6ed4c 100644
--- a/src/input/backend/axissetting_p.h
+++ b/src/input/backend/axissetting_p.h
@@ -51,14 +51,14 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DInput {
namespace Input {
-class Q_AUTOTEST_EXPORT AxisSetting : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT AxisSetting : public BackendNode
{
public:
AxisSetting();
@@ -68,11 +68,9 @@ public:
inline QVector<int> axes() const { return m_axes; }
inline bool isSmoothEnabled() const { return m_smooth; }
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
float m_deadZoneRadius;
QVector<int> m_axes;
diff --git a/src/input/backend/backend.pri b/src/input/backend/backend.pri
index 71c1a9a1c..e1ddee9c7 100644
--- a/src/input/backend/backend.pri
+++ b/src/input/backend/backend.pri
@@ -1,4 +1,5 @@
HEADERS += \
+ $$PWD/backendnode_p.h \
$$PWD/keyboarddevice_p.h \
$$PWD/keyboardhandler_p.h \
$$PWD/inputhandler_p.h \
@@ -39,6 +40,7 @@ HEADERS += \
$$PWD/axisaccumulatorjob_p.h
SOURCES += \
+ $$PWD/backendnode.cpp \
$$PWD/keyboarddevice.cpp \
$$PWD/keyboardhandler.cpp \
$$PWD/inputhandler.cpp \
diff --git a/src/render/renderers/opengl/renderer/glcommands.cpp b/src/input/backend/backendnode.cpp
index fd7ee9fe8..aa440ed51 100644
--- a/src/render/renderers/opengl/renderer/glcommands.cpp
+++ b/src/input/backend/backendnode.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,31 +37,38 @@
**
****************************************************************************/
-#include "glcommands_p.h"
-#include <Qt3DRender/private/renderer_p.h>
-#include <Qt3DRender/private/graphicscontext_p.h>
-#include <Qt3DRender/private/nodemanagers_p.h>
+#include "backendnode_p.h"
+#include <Qt3DCore/qnode.h>
+#include <Qt3DCore/private/qbackendnode_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DRender {
+namespace Qt3DInput {
+namespace Input {
-namespace Render {
+BackendNode::BackendNode(Mode mode)
+ : Qt3DCore::QBackendNode(mode)
+{
+}
-LoadShaderCommand::LoadShaderCommand(Shader *shader)
- : m_shader(shader)
+BackendNode::BackendNode(Qt3DCore::QBackendNodePrivate &dd)
+ : Qt3DCore::QBackendNode(dd)
{
- Q_ASSERT(m_shader);
+
}
-void LoadShaderCommand::execute(Renderer *renderer, GraphicsContext *ctx)
+BackendNode::~BackendNode()
{
- NodeManagers *nodeManagers = renderer->nodeManagers();
- ctx->loadShader(m_shader, nodeManagers->shaderManager());
}
-} // Render
+void BackendNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
+{
+ Q_UNUSED(firstTime)
+
+ d_ptr->setEnabled(frontEnd->isEnabled());
+}
-} // Qt3DRender
+} // namespace Input
+} // namespace Qt3DInput
QT_END_NAMESPACE
diff --git a/src/core/aspects/qaspectthread_p.h b/src/input/backend/backendnode_p.h
index 8ae9ff86d..a7749852b 100644
--- a/src/core/aspects/qaspectthread_p.h
+++ b/src/input/backend/backendnode_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DCORE_QASPECTTHREAD_P_H
-#define QT3DCORE_QASPECTTHREAD_P_H
+#ifndef QT3DINPUT_INPUT_BACKENDNODE_H
+#define QT3DINPUT_INPUT_BACKENDNODE_H
//
// W A R N I N G
@@ -51,38 +51,29 @@
// We mean it.
//
-#include <Qt3DCore/qt3dcore_global.h>
-#include <QtCore/QSemaphore>
-#include <QtCore/QThread>
-
+#include <Qt3DInput/private/qt3dinput_global_p.h>
+#include <Qt3DCore/qbackendnode.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DCore {
-
-class QAspectManager;
+namespace Qt3DInput {
+namespace Input {
-class QAspectThread : public QThread
+class Q_3DINPUTSHARED_PRIVATE_EXPORT BackendNode : public Qt3DCore::QBackendNode
{
- Q_OBJECT
public:
- explicit QAspectThread(QObject *parent = 0);
- ~QAspectThread();
+ BackendNode(Qt3DCore::QBackendNode::Mode mode = ReadOnly);
+ ~BackendNode();
- void waitForStart(Priority priority);
-
- QAspectManager *aspectManager() const { return m_aspectManager; }
+ virtual void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime);
protected:
- void run() override;
-
-private:
- QAspectManager *m_aspectManager;
- QSemaphore m_semaphore;
+ explicit BackendNode(Qt3DCore::QBackendNodePrivate &dd);
};
-} // namespace Qt3DCore
+} // namespace Input
+} // namespace Qt3DInput
QT_END_NAMESPACE
-#endif // QT3DCORE_QASPECTTHREAD_P_H
+#endif // QT3DINPUT_INPUT_BACKENDNODE_H
diff --git a/src/input/backend/buttonaxisinput.cpp b/src/input/backend/buttonaxisinput.cpp
index fef8f6d41..011d7df56 100644
--- a/src/input/backend/buttonaxisinput.cpp
+++ b/src/input/backend/buttonaxisinput.cpp
@@ -41,7 +41,6 @@
#include <Qt3DInput/qbuttonaxisinput.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/qabstractphysicaldevicebackendnode_p.h>
#include <Qt3DInput/private/qbuttonaxisinput_p.h>
@@ -63,17 +62,6 @@ ButtonAxisInput::ButtonAxisInput()
{
}
-void ButtonAxisInput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QButtonAxisInputData>>(change);
- const auto &data = typedChange->data;
- m_buttons = data.buttons;
- m_scale = data.scale;
- m_acceleration = data.acceleration;
- m_deceleration = data.deceleration;
- AbstractAxisInput::initializeFromPeer(change);
-}
-
void ButtonAxisInput::cleanup()
{
m_scale = 0.0f;
@@ -101,21 +89,17 @@ void ButtonAxisInput::updateSpeedRatio(qint64 currentTime, ButtonAxisInput::Upda
m_lastUpdateTime = currentTime;
}
-void ButtonAxisInput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void ButtonAxisInput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("scale")) {
- m_scale = propertyChange->value().toFloat();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("buttons")) {
- m_buttons = propertyChange->value().value<QVector<int>>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("acceleration")) {
- m_acceleration = propertyChange->value().toFloat();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("deceleration")) {
- m_deceleration = propertyChange->value().toFloat();
- }
- }
- AbstractAxisInput::sceneChangeEvent(e);
+ AbstractAxisInput::syncFromFrontEnd(frontEnd, firstTime);
+ const QButtonAxisInput *node = qobject_cast<const QButtonAxisInput *>(frontEnd);
+ if (!node)
+ return;
+
+ m_scale = node->scale();
+ m_buttons = node->buttons();
+ m_acceleration = node->acceleration();
+ m_deceleration = node->deceleration();
}
namespace {
diff --git a/src/input/backend/buttonaxisinput_p.h b/src/input/backend/buttonaxisinput_p.h
index f47a9b5cc..761b9e92a 100644
--- a/src/input/backend/buttonaxisinput_p.h
+++ b/src/input/backend/buttonaxisinput_p.h
@@ -78,13 +78,12 @@ public:
inline float speedRatio() const { return m_speedRatio; }
inline qint64 lastUpdateTime() const { return m_lastUpdateTime; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final;
float process(InputHandler *inputHandler, qint64 currentTime) override;
private:
void updateSpeedRatio(qint64 currentTime, UpdateType type);
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
QVector<int> m_buttons;
float m_scale;
diff --git a/src/input/backend/eventsourcesetterhelper.cpp b/src/input/backend/eventsourcesetterhelper.cpp
index bbc7ea54c..fe800a1a4 100644
--- a/src/input/backend/eventsourcesetterhelper.cpp
+++ b/src/input/backend/eventsourcesetterhelper.cpp
@@ -56,21 +56,21 @@ EventSourceSetterHelper::EventSourceSetterHelper(InputHandler *inputHandler)
{
}
-// Aspect thread
+// Main thread
void EventSourceSetterHelper::setEventFilterService(Qt3DCore::QEventFilterService *service)
{
- QMutexLocker lock(&m_mutex);
m_service = service;
}
-// Any thread
+// Main thread
void EventSourceSetterHelper::setEventSource(QObject *eventSource)
{
if (eventSource && m_lastEventSource != eventSource) {
- QMetaObject::invokeMethod(this,
- "setEventSourceHelper",
- Qt::BlockingQueuedConnection,
- Q_ARG(QObject*, eventSource));
+ if (m_service) {
+ m_service->initialize(eventSource);
+ m_inputHandler->registerEventFilters(m_service);
+ m_lastEventSource = eventSource;
+ }
}
}
@@ -83,17 +83,6 @@ void EventSourceSetterHelper::unsetEventSource(QObject *eventSource)
}
}
-// Main Thread
-void EventSourceSetterHelper::setEventSourceHelper(QObject *eventSource)
-{
- QMutexLocker lock(&m_mutex);
- if (m_service) {
- m_service->initialize(eventSource);
- m_inputHandler->registerEventFilters(m_service);
- m_lastEventSource = eventSource;
- }
-}
-
} // Input
} // Qt3DInput
diff --git a/src/input/backend/eventsourcesetterhelper_p.h b/src/input/backend/eventsourcesetterhelper_p.h
index 48418f1b9..b8800d8a6 100644
--- a/src/input/backend/eventsourcesetterhelper_p.h
+++ b/src/input/backend/eventsourcesetterhelper_p.h
@@ -75,14 +75,10 @@ public:
// Called from aspect thread
void setEventFilterService(Qt3DCore::QEventFilterService *service);
- // Called from any thread
+ // Called from main thread
void setEventSource(QObject *eventSource);
void unsetEventSource(QObject *eventSource);
-private Q_SLOTS:
- // Called in main thread
- void setEventSourceHelper(QObject *);
-
private:
Qt3DCore::QEventFilterService *m_service;
InputHandler *m_inputHandler;
diff --git a/src/input/backend/genericdevicebackendnode.cpp b/src/input/backend/genericdevicebackendnode.cpp
index 40202b4a5..d56a674fc 100644
--- a/src/input/backend/genericdevicebackendnode.cpp
+++ b/src/input/backend/genericdevicebackendnode.cpp
@@ -40,10 +40,11 @@
#include "genericdevicebackendnode_p.h"
#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/qgenericinputdevice_p.h>
+#include <Qt3DInput/private/qabstractphysicaldevice_p.h>
QT_BEGIN_NAMESPACE
@@ -60,19 +61,24 @@ GenericDeviceBackendNode::~GenericDeviceBackendNode()
{
}
-void GenericDeviceBackendNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void GenericDeviceBackendNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (e->type() == Qt3DCore::PropertyUpdated) {
- if (propertyChange->propertyName() == QByteArrayLiteral("axisEvent")) {
- QPair<int, qreal> val = propertyChange->value().value<QPair<int, qreal>>();
- const QMutexLocker lock(&m_mutex);
+ QAbstractPhysicalDeviceBackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const Qt3DInput::QGenericInputDevice *node = qobject_cast<const Qt3DInput::QGenericInputDevice *>(frontEnd);
+ if (!node)
+ return;
+
+ auto *d = static_cast<Qt3DInput::QAbstractPhysicalDevicePrivate *>( Qt3DCore::QNodePrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd)) );
+
+ {
+ const QMutexLocker lock(&m_mutex);
+ for (const auto &val: qAsConst(d->m_pendingAxisEvents))
m_axesValues[val.first] = val.second;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("buttonEvent")) {
- QPair<int, qreal> val = propertyChange->value().value<QPair<int, qreal>>();
- const QMutexLocker lock(&m_mutex);
+ for (const auto &val: qAsConst(d->m_pendingButtonsEvents))
m_buttonsValues[val.first] = val.second;
- }
+
+ d->m_pendingAxisEvents.clear();
+ d->m_pendingButtonsEvents.clear();
}
}
diff --git a/src/input/backend/genericdevicebackendnode_p.h b/src/input/backend/genericdevicebackendnode_p.h
index c3ee1e467..3ae712115 100644
--- a/src/input/backend/genericdevicebackendnode_p.h
+++ b/src/input/backend/genericdevicebackendnode_p.h
@@ -73,7 +73,7 @@ public:
void updateEvents();
// QAbstractPhysicalDeviceBackendNode interface
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void cleanup() override;
float axisValue(int axisIdentifier) const override;
bool isButtonPressed(int buttonIdentifier) const override;
diff --git a/src/input/backend/inputchord.cpp b/src/input/backend/inputchord.cpp
index 731fd91e3..fa8112e6d 100644
--- a/src/input/backend/inputchord.cpp
+++ b/src/input/backend/inputchord.cpp
@@ -40,9 +40,6 @@
#include "inputchord_p.h"
#include <Qt3DInput/qinputchord.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DInput/private/qinputchord_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
@@ -62,15 +59,6 @@ InputChord::InputChord()
{
}
-void InputChord::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QInputChordData>>(change);
- const QInputChordData &data = typedChange->data;
- m_chords = data.chordIds;
- m_timeout = milliToNano(data.timeout);
- m_inputsToTrigger = m_chords;
-}
-
void InputChord::cleanup()
{
setEnabled(false);
@@ -102,38 +90,16 @@ void InputChord::setStartTime(qint64 time)
m_startTime = time;
}
-void InputChord::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void InputChord::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("timeout"))
- m_timeout = milliToNano(change->value().toInt());
- break;
- }
+ AbstractActionInput::syncFromFrontEnd(frontEnd, firstTime);
+ const QInputChord *node = qobject_cast<const QInputChord *>(frontEnd);
+ if (!node)
+ return;
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("chord")) {
- m_chords.push_back(change->addedNodeId());
- m_inputsToTrigger.push_back(change->addedNodeId());
- }
- break;
- }
-
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("chord")) {
- m_chords.removeOne(change->removedNodeId());
- m_inputsToTrigger.removeOne(change->removedNodeId());
- }
- break;
- }
-
- default:
- break;
- }
- AbstractActionInput::sceneChangeEvent(e);
+ m_timeout = milliToNano(node->timeout());
+ m_chords = Qt3DCore::qIdsForNodes(node->chords());
+ m_inputsToTrigger = m_chords;
}
bool InputChord::process(InputHandler *inputHandler, qint64 currentTime)
diff --git a/src/input/backend/inputchord_p.h b/src/input/backend/inputchord_p.h
index efad2c4af..0a654aa87 100644
--- a/src/input/backend/inputchord_p.h
+++ b/src/input/backend/inputchord_p.h
@@ -73,13 +73,11 @@ public:
void setStartTime(qint64 time);
void reset();
bool actionTriggered(Qt3DCore::QNodeId input);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
bool process(InputHandler *inputHandler, qint64 currentTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DCore::QNodeId> m_chords;
QVector<Qt3DCore::QNodeId> m_inputsToTrigger;
qint64 m_timeout;
diff --git a/src/input/backend/inputhandler.cpp b/src/input/backend/inputhandler.cpp
index 18559e9d4..9484909ab 100644
--- a/src/input/backend/inputhandler.cpp
+++ b/src/input/backend/inputhandler.cpp
@@ -127,58 +127,55 @@ void InputHandler::unregisterEventFilters(Qt3DCore::QEventFilterService *service
// Called by the keyboardEventFilter in the main thread
void InputHandler::appendKeyEvent(const QT_PREPEND_NAMESPACE(QKeyEvent) &event)
{
- QMutexLocker lock(&m_mutex);
m_pendingKeyEvents.append(event);
}
-// Called by QInputASpect::jobsToExecute (aspectThread)
+// Called by QInputASpect::jobsToExecute (Main Thread)
QList<QT_PREPEND_NAMESPACE(QKeyEvent)> InputHandler::pendingKeyEvents()
{
- QMutexLocker lock(&m_mutex);
return std::move(m_pendingKeyEvents);
}
-// Called by QInputASpect::jobsToExecute (aspectThread)
+// Called by QInputASpect::jobsToExecute (Main Thread)
void InputHandler::clearPendingKeyEvents()
{
- QMutexLocker lock(&m_mutex);
m_pendingKeyEvents.clear();
}
+// Main Thread
void InputHandler::appendMouseEvent(const QT_PREPEND_NAMESPACE(QMouseEvent) &event)
{
- QMutexLocker lock(&m_mutex);
m_pendingMouseEvents.append(event);
}
+// Main Thread
QList<QT_PREPEND_NAMESPACE(QMouseEvent)> InputHandler::pendingMouseEvents()
{
- QMutexLocker lock(&m_mutex);
return std::move(m_pendingMouseEvents);
}
+// Main Thread
void InputHandler::clearPendingMouseEvents()
{
- QMutexLocker lock(&m_mutex);
m_pendingMouseEvents.clear();
}
#if QT_CONFIG(wheelevent)
+// Main Thread
void InputHandler::appendWheelEvent(const QT_PREPEND_NAMESPACE(QWheelEvent) &event)
{
- QMutexLocker lock(&m_mutex);
m_pendingWheelEvents.append(event);
}
+// Main Thread
QList<QT_PREPEND_NAMESPACE (QWheelEvent)> Qt3DInput::Input::InputHandler::pendingWheelEvents()
{
- QMutexLocker lock(&m_mutex);
return std::move(m_pendingWheelEvents);
}
+// Main Thread
void InputHandler::clearPendingWheelEvents()
{
- QMutexLocker lock(&m_mutex);
m_pendingWheelEvents.clear();
}
#endif
@@ -253,7 +250,6 @@ QVector<Qt3DCore::QAspectJobPtr> InputHandler::mouseJobs()
#if QT_CONFIG(wheelevent)
const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> wheelEvents = pendingWheelEvents();
#endif
-
for (const HMouseDevice &cHandle : qAsConst(m_activeMouseDevices)) {
MouseDevice *controller = m_mouseDeviceManager->data(cHandle);
diff --git a/src/input/backend/inputsequence.cpp b/src/input/backend/inputsequence.cpp
index e45fae364..690a7f0d1 100644
--- a/src/input/backend/inputsequence.cpp
+++ b/src/input/backend/inputsequence.cpp
@@ -41,9 +41,6 @@
#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DInput/qinputsequence.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/QDateTime>
#include <Qt3DInput/private/inputhandler_p.h>
@@ -66,16 +63,6 @@ InputSequence::InputSequence()
{
}
-void InputSequence::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QInputSequenceData>>(change);
- const QInputSequenceData &data = typedChange->data;
- m_sequences = data.sequenceIds;
- m_timeout = milliToNano(data.timeout);
- m_buttonInterval = milliToNano(data.buttonInterval);
- m_inputsToTrigger = m_sequences;
-}
-
void InputSequence::cleanup()
{
setEnabled(false);
@@ -127,41 +114,17 @@ bool InputSequence::actionTriggered(Qt3DCore::QNodeId input, const qint64 curren
return false;
}
-void InputSequence::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void InputSequence::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("timeout")) {
- m_timeout = milliToNano(change->value().toInt());
- } else if (change->propertyName() == QByteArrayLiteral("buttonInterval")) {
- m_buttonInterval = milliToNano(change->value().toInt());
- }
- break;
- }
-
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("sequence")) {
- m_sequences.push_back(change->addedNodeId());
- m_inputsToTrigger.push_back(change->addedNodeId());
- }
- break;
- }
-
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("sequence")) {
- m_sequences.removeOne(change->removedNodeId());
- m_inputsToTrigger.removeOne(change->removedNodeId());
- }
- break;
- }
-
- default:
- break;
- }
- AbstractActionInput::sceneChangeEvent(e);
+ AbstractActionInput::syncFromFrontEnd(frontEnd, firstTime);
+ const QInputSequence *node = qobject_cast<const QInputSequence *>(frontEnd);
+ if (!node)
+ return;
+
+ m_timeout = milliToNano(node->timeout());
+ m_buttonInterval = milliToNano(node->buttonInterval());
+ m_sequences = Qt3DCore::qIdsForNodes(node->sequences());
+ m_inputsToTrigger = m_sequences;
}
bool InputSequence::process(InputHandler *inputHandler, qint64 currentTime)
diff --git a/src/input/backend/inputsequence_p.h b/src/input/backend/inputsequence_p.h
index 395021035..53407bd1d 100644
--- a/src/input/backend/inputsequence_p.h
+++ b/src/input/backend/inputsequence_p.h
@@ -75,13 +75,11 @@ public:
bool sequenceTriggered() const;
void reset();
bool actionTriggered(Qt3DCore::QNodeId input, const qint64 currentTime);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
bool process(InputHandler *inputHandler, qint64 currentTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DCore::QNodeId> m_sequences;
QVector<Qt3DCore::QNodeId> m_inputsToTrigger;
qint64 m_timeout;
diff --git a/src/input/backend/inputsettings.cpp b/src/input/backend/inputsettings.cpp
index b695ed600..4fdd61a1b 100644
--- a/src/input/backend/inputsettings.cpp
+++ b/src/input/backend/inputsettings.cpp
@@ -40,7 +40,6 @@
#include "inputsettings_p.h"
#include <Qt3DInput/qinputsettings.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/qinputsettings_p.h>
@@ -52,26 +51,19 @@ namespace Qt3DInput {
namespace Input {
InputSettings::InputSettings()
- : QBackendNode(QBackendNode::ReadOnly)
+ : BackendNode(QBackendNode::ReadOnly)
, m_eventSource(nullptr)
{
}
-void InputSettings::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void InputSettings::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QInputSettingsData>>(change);
- const auto &data = typedChange->data;
- m_eventSource = data.eventSource;
-}
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QInputSettings *node = qobject_cast<const QInputSettings *>(frontEnd);
+ if (!node)
+ return;
-void InputSettings::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("eventSource"))
- m_eventSource = propertyChange->value().value<QObject *>();
- }
- QBackendNode::sceneChangeEvent(e);
+ m_eventSource = node->eventSource();
}
InputSettingsFunctor::InputSettingsFunctor(InputHandler *handler)
diff --git a/src/input/backend/inputsettings_p.h b/src/input/backend/inputsettings_p.h
index 87cb4debf..33f56cc0b 100644
--- a/src/input/backend/inputsettings_p.h
+++ b/src/input/backend/inputsettings_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <QtCore/QPointer>
QT_BEGIN_NAMESPACE
@@ -62,18 +62,15 @@ namespace Input {
class InputHandler;
-class InputSettings : public Qt3DCore::QBackendNode
+class InputSettings : public BackendNode
{
public:
InputSettings();
inline QObject *eventSource() const { return m_eventSource; }
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QPointer<QObject> m_eventSource;
};
diff --git a/src/input/backend/keyboarddevice.cpp b/src/input/backend/keyboarddevice.cpp
index 33578bdad..0e45d1c84 100644
--- a/src/input/backend/keyboarddevice.cpp
+++ b/src/input/backend/keyboarddevice.cpp
@@ -427,11 +427,6 @@ void KeyboardDevice::updateKeyEvents(const QList<QT_PREPEND_NAMESPACE(QKeyEvent)
setButtonValue(e.key(), e.type() == QT_PREPEND_NAMESPACE(QKeyEvent)::KeyPress ? true : false);
}
-
-void KeyboardDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
-{
-}
-
KeyboardDeviceFunctor::KeyboardDeviceFunctor(QInputAspect *inputaspect, InputHandler *handler)
: m_inputAspect(inputaspect)
, m_handler(handler)
diff --git a/src/input/backend/keyboarddevice_p.h b/src/input/backend/keyboarddevice_p.h
index 781e8ead5..2df5eb64d 100644
--- a/src/input/backend/keyboarddevice_p.h
+++ b/src/input/backend/keyboarddevice_p.h
@@ -86,9 +86,6 @@ public:
inline Qt3DCore::QNodeId currentFocusItem() const { return m_currentFocusItem; }
inline Qt3DCore::QNodeId lastKeyboardInputRequester() const { return m_lastRequester; }
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) override;
-
private:
void setButtonValue(int key, bool value);
diff --git a/src/input/backend/keyboardeventfilter.cpp b/src/input/backend/keyboardeventfilter.cpp
index bd3bac5a7..e4f47f08e 100644
--- a/src/input/backend/keyboardeventfilter.cpp
+++ b/src/input/backend/keyboardeventfilter.cpp
@@ -53,6 +53,7 @@ namespace Input {
KeyboardEventFilter::KeyboardEventFilter(QObject *parent)
: QObject(parent)
+ , m_inputHandler(nullptr)
{
}
diff --git a/src/input/backend/keyboardhandler.cpp b/src/input/backend/keyboardhandler.cpp
index ae1e6d03c..026012e52 100644
--- a/src/input/backend/keyboardhandler.cpp
+++ b/src/input/backend/keyboardhandler.cpp
@@ -41,7 +41,6 @@
#include <Qt3DInput/qkeyboarddevice.h>
#include <Qt3DInput/qkeyboardhandler.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/QVariant>
#include <Qt3DInput/private/inputhandler_p.h>
@@ -56,22 +55,12 @@ namespace Qt3DInput {
namespace Input {
KeyboardHandler::KeyboardHandler()
- : QBackendNode(QBackendNode::ReadWrite)
+ : BackendNode(QBackendNode::ReadWrite)
, m_inputHandler(nullptr)
, m_focus(false)
{
}
-void KeyboardHandler::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QKeyboardHandlerData>>(change);
- const auto &data = typedChange->data;
- setSourcerDevice(data.keyboardDeviceId);
- m_focus = false;
- if (data.focus)
- requestFocus();
-}
-
Qt3DCore::QNodeId KeyboardHandler::keyboardDevice() const
{
return m_keyboardDevice;
@@ -86,43 +75,32 @@ void KeyboardHandler::setInputHandler(InputHandler *handler)
// Sends a change notification so that the frontend can update itself
void KeyboardHandler::setFocus(bool focus)
{
- if (focus != m_focus) {
+ if (focus != m_focus)
m_focus = focus;
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("focus");
- e->setValue(m_focus);
- notifyObservers(e);
- }
}
-void KeyboardHandler::keyEvent(const QKeyEventPtr &event)
+void KeyboardHandler::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("event");
- e->setValue(QVariant::fromValue(event));
- notifyObservers(e);
-}
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const Qt3DInput::QKeyboardHandler *node = qobject_cast<const Qt3DInput::QKeyboardHandler *>(frontEnd);
+ if (!node)
+ return;
+
+ if (firstTime)
+ m_focus = false;
-void KeyboardHandler::sceneChangeEvent(const QSceneChangePtr &e)
-{
bool focusRequest = false;
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("sourceDevice")) {
- const QNodeId newId = propertyChange->value().value<QNodeId>();
- if (m_keyboardDevice != newId) {
- setSourcerDevice(newId);
- focusRequest = m_focus;
- }
- } else if (propertyChange->propertyName() == QByteArrayLiteral("focus")) {
- focusRequest = propertyChange->value().toBool();
- }
+ auto id = Qt3DCore::qIdForNode(node->sourceDevice());
+ if (m_keyboardDevice != id) {
+ setSourcerDevice(id);
+ focusRequest = m_focus;
}
+
+ if (m_focus != node->focus())
+ focusRequest = node->focus();
+
if (focusRequest)
requestFocus();
- QBackendNode::sceneChangeEvent(e);
}
void KeyboardHandler::requestFocus()
diff --git a/src/input/backend/keyboardhandler_p.h b/src/input/backend/keyboardhandler_p.h
index 317c33792..a5c13efbf 100644
--- a/src/input/backend/keyboardhandler_p.h
+++ b/src/input/backend/keyboardhandler_p.h
@@ -52,7 +52,7 @@
//
#include <Qt3DInput/qkeyevent.h>
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -63,7 +63,7 @@ namespace Input {
class InputHandler;
-class Q_AUTOTEST_EXPORT KeyboardHandler : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT KeyboardHandler : public BackendNode
{
public:
KeyboardHandler();
@@ -71,19 +71,16 @@ public:
Qt3DCore::QNodeId keyboardDevice() const;
void setInputHandler(InputHandler *handler);
void setFocus(bool focus);
- void keyEvent(const QKeyEventPtr &event);
inline bool focus() const { return m_focus; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
protected:
void requestFocus();
void setSourcerDevice(Qt3DCore::QNodeId device);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
InputHandler *m_inputHandler;
Qt3DCore::QNodeId m_keyboardDevice;
bool m_focus;
diff --git a/src/input/backend/keyeventdispatcherjob.cpp b/src/input/backend/keyeventdispatcherjob.cpp
index 6201453fc..31db01e53 100644
--- a/src/input/backend/keyeventdispatcherjob.cpp
+++ b/src/input/backend/keyeventdispatcherjob.cpp
@@ -38,7 +38,9 @@
****************************************************************************/
#include "keyeventdispatcherjob_p.h"
-
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DInput/qkeyboardhandler.h>
+#include <Qt3DInput/private/qkeyboardhandler_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/job_common_p.h>
@@ -49,13 +51,26 @@ QT_BEGIN_NAMESPACE
namespace Qt3DInput {
namespace Input {
+class KeyEventDispatcherJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ KeyEventDispatcherJobPrivate() { }
+ ~KeyEventDispatcherJobPrivate() override { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ Qt3DCore::QNodeId m_keyboardHandler;
+ QList<QT_PREPEND_NAMESPACE(QKeyEvent)> m_events;
+};
+
KeyEventDispatcherJob::KeyEventDispatcherJob(Qt3DCore::QNodeId input, const QList<QT_PREPEND_NAMESPACE(QKeyEvent)> &events)
- : QAspectJob()
+ : QAspectJob(*new KeyEventDispatcherJobPrivate)
, m_inputHandler(nullptr)
- , m_keyboardHandler(input)
- , m_events(events)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::KeyEventDispatcher, 0);
+ Q_DJOB(KeyEventDispatcherJob);
+ d->m_keyboardHandler = input;
+ d->m_events = events;
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::KeyEventDispatcher, 0)
}
void KeyEventDispatcherJob::setInputHandler(InputHandler *handler)
@@ -65,12 +80,22 @@ void KeyEventDispatcherJob::setInputHandler(InputHandler *handler)
void KeyEventDispatcherJob::run()
{
- KeyboardHandler *input = m_inputHandler->keyboardInputManager()->lookupResource(m_keyboardHandler);
- if (input)
- for (const QT_PREPEND_NAMESPACE(QKeyEvent) &e : qAsConst(m_events)) {
- // Send events to frontend
- input->keyEvent(QKeyEventPtr::create(e));
- }
+ // NOP
+}
+
+void KeyEventDispatcherJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ QKeyboardHandler *node = qobject_cast<QKeyboardHandler *>(manager->lookupNode(m_keyboardHandler));
+ if (!node)
+ return;
+
+ QKeyboardHandlerPrivate *dnode = static_cast<QKeyboardHandlerPrivate *>(QKeyboardHandlerPrivate::get(node));
+ for (const auto &e: qAsConst(m_events)) {
+ QKeyEvent ke(e);
+ dnode->keyEvent(&ke);
+ }
+
+ m_events.clear();
}
} // namespace Input
diff --git a/src/input/backend/keyeventdispatcherjob_p.h b/src/input/backend/keyeventdispatcherjob_p.h
index be2364ac9..975dc3d31 100644
--- a/src/input/backend/keyeventdispatcherjob_p.h
+++ b/src/input/backend/keyeventdispatcherjob_p.h
@@ -61,6 +61,7 @@ namespace Qt3DInput {
namespace Input {
class InputHandler;
+class KeyEventDispatcherJobPrivate;
class KeyEventDispatcherJob : public Qt3DCore::QAspectJob
{
@@ -71,8 +72,6 @@ public:
private:
InputHandler *m_inputHandler;
- const Qt3DCore::QNodeId m_keyboardHandler;
- const QList<QT_PREPEND_NAMESPACE(QKeyEvent)> m_events;
};
} // namespace Input
diff --git a/src/input/backend/loadproxydevicejob.cpp b/src/input/backend/loadproxydevicejob.cpp
index 2ea29b4a9..059d14bc0 100644
--- a/src/input/backend/loadproxydevicejob.cpp
+++ b/src/input/backend/loadproxydevicejob.cpp
@@ -38,7 +38,9 @@
****************************************************************************/
#include "loadproxydevicejob_p.h"
-
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p.h>
+#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/job_common_p.h>
@@ -48,12 +50,22 @@ QT_BEGIN_NAMESPACE
namespace Qt3DInput {
namespace Input {
+class LoadProxyDeviceJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ LoadProxyDeviceJobPrivate() { }
+ ~LoadProxyDeviceJobPrivate() override { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ QVector<QPair<Qt3DCore::QNodeId, QAbstractPhysicalDevice *>> updates;
+};
+
LoadProxyDeviceJob::LoadProxyDeviceJob()
- : Qt3DCore::QAspectJob()
+ : Qt3DCore::QAspectJob(*new LoadProxyDeviceJobPrivate)
, m_inputHandler(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::DeviceProxyLoading, 0);
-
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::DeviceProxyLoading, 0)
}
LoadProxyDeviceJob::~LoadProxyDeviceJob()
@@ -82,6 +94,9 @@ QVector<Qt3DCore::QNodeId> LoadProxyDeviceJob::proxies() const
void LoadProxyDeviceJob::run()
{
+ Q_DJOB(LoadProxyDeviceJob);
+ d->updates.reserve(m_proxies.size());
+
Q_ASSERT(m_inputHandler);
for (const Qt3DCore::QNodeId id : qAsConst(m_proxies)) {
PhysicalDeviceProxy *proxy = m_inputHandler->physicalDeviceProxyManager()->lookupResource(id);
@@ -89,9 +104,27 @@ void LoadProxyDeviceJob::run()
if (device != nullptr)
proxy->setDevice(device);
}
- m_proxies.clear();
}
+void LoadProxyDeviceJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ for (const auto &res : qAsConst(updates)) {
+ QAbstractPhysicalDeviceProxy *node = qobject_cast<QAbstractPhysicalDeviceProxy *>(manager->lookupNode(res.first));
+ if (!node)
+ continue;
+
+ auto *device = res.second;
+ QAbstractPhysicalDeviceProxyPrivate *dnode = static_cast<QAbstractPhysicalDeviceProxyPrivate *>(QAbstractPhysicalDeviceProxyPrivate::get(node));
+ QAbstractPhysicalDevice *oldDevice = dnode->m_device;
+ dnode->setDevice(device);
+ // Delete the old device if it existed
+ delete oldDevice;
+ }
+
+ updates.clear();
+}
+
+
} // namespace Input
} // namespace Qt3DInput
diff --git a/src/input/backend/loadproxydevicejob_p.h b/src/input/backend/loadproxydevicejob_p.h
index f9b343b2e..0a425f3a5 100644
--- a/src/input/backend/loadproxydevicejob_p.h
+++ b/src/input/backend/loadproxydevicejob_p.h
@@ -60,6 +60,7 @@ namespace Qt3DInput {
namespace Input {
class InputHandler;
+class LoadProxyDeviceJobPrivate;
class Q_AUTOTEST_EXPORT LoadProxyDeviceJob : public Qt3DCore::QAspectJob
{
diff --git a/src/input/backend/logicaldevice.cpp b/src/input/backend/logicaldevice.cpp
index 5fcfb07bb..17426922f 100644
--- a/src/input/backend/logicaldevice.cpp
+++ b/src/input/backend/logicaldevice.cpp
@@ -42,9 +42,6 @@
#include <Qt3DInput/qaction.h>
#include <Qt3DInput/qaxis.h>
#include <Qt3DInput/qlogicaldevice.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/qlogicaldevice_p.h>
@@ -56,18 +53,10 @@ namespace Qt3DInput {
namespace Input {
LogicalDevice::LogicalDevice()
- : QBackendNode()
+ : BackendNode()
{
}
-void LogicalDevice::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLogicalDeviceData>>(change);
- const auto &data = typedChange->data;
- m_actions = data.actionIds;
- m_axes = data.axisIds;
-}
-
void LogicalDevice::cleanup()
{
QBackendNode::setEnabled(false);
@@ -75,31 +64,15 @@ void LogicalDevice::cleanup()
m_axes.clear();
}
-void LogicalDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void LogicalDevice::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("axis"))
- m_axes.push_back(change->addedNodeId());
- else if (change->propertyName() == QByteArrayLiteral("action"))
- m_actions.push_back(change->addedNodeId());
- break;
- }
-
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("axis"))
- m_axes.removeOne(change->removedNodeId());
- else if (change->propertyName() == QByteArrayLiteral("action"))
- m_actions.removeOne(change->removedNodeId());
- break;
- }
-
- default:
- break;
- }
- QBackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QLogicalDevice *node = qobject_cast<const QLogicalDevice *>(frontEnd);
+ if (!node)
+ return;
+
+ m_actions = Qt3DCore::qIdsForNodes(node->actions());
+ m_axes = Qt3DCore::qIdsForNodes(node->axes());
}
LogicalDeviceNodeFunctor::LogicalDeviceNodeFunctor(LogicalDeviceManager *manager)
diff --git a/src/input/backend/logicaldevice_p.h b/src/input/backend/logicaldevice_p.h
index 138a54777..292f2a5c3 100644
--- a/src/input/backend/logicaldevice_p.h
+++ b/src/input/backend/logicaldevice_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -62,7 +62,7 @@ namespace Input {
class LogicalDeviceManager;
-class Q_AUTOTEST_EXPORT LogicalDevice : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT LogicalDevice : public BackendNode
{
public:
LogicalDevice();
@@ -71,11 +71,9 @@ public:
inline QVector<Qt3DCore::QNodeId> axes() const { return m_axes; }
inline QVector<Qt3DCore::QNodeId> actions() const { return m_actions; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DCore::QNodeId> m_axes;
QVector<Qt3DCore::QNodeId> m_actions;
};
diff --git a/src/input/backend/mousedevice.cpp b/src/input/backend/mousedevice.cpp
index 128988637..47045a1a1 100644
--- a/src/input/backend/mousedevice.cpp
+++ b/src/input/backend/mousedevice.cpp
@@ -42,7 +42,6 @@
#include <Qt3DInput/qmousedevice.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qnode.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
@@ -65,14 +64,6 @@ MouseDevice::~MouseDevice()
{
}
-void MouseDevice::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMouseDeviceData>>(change);
- const auto &data = typedChange->data;
- m_sensitivity = data.sensitivity;
- QAbstractPhysicalDeviceBackendNode::initializeFromPeer(change);
-}
-
void MouseDevice::setInputHandler(InputHandler *handler)
{
m_inputHandler = handler;
@@ -150,6 +141,7 @@ void MouseDevice::updateWheelEvents(const QList<QT_PREPEND_NAMESPACE (QWheelEven
}
#endif
+// Main Thread
void MouseDevice::updateMouseEvents(const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> &events)
{
// Reset axis values before we accumulate new values for this frame
@@ -172,13 +164,14 @@ void MouseDevice::updateMouseEvents(const QList<QT_PREPEND_NAMESPACE(QMouseEvent
}
}
-void MouseDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void MouseDevice::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("sensitivity"))
- m_sensitivity = propertyChange->value().toFloat();
- }
+ QAbstractPhysicalDeviceBackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const Qt3DInput::QMouseDevice *node = qobject_cast<const Qt3DInput::QMouseDevice *>(frontEnd);
+ if (!node)
+ return;
+
+ m_sensitivity = node->sensitivity();
}
MouseDeviceFunctor::MouseDeviceFunctor(QInputAspect *inputAspect, InputHandler *handler)
diff --git a/src/input/backend/mousedevice_p.h b/src/input/backend/mousedevice_p.h
index d49ea2502..283eeaeaf 100644
--- a/src/input/backend/mousedevice_p.h
+++ b/src/input/backend/mousedevice_p.h
@@ -108,11 +108,9 @@ public:
bool wasPressed() const;
float sensitivity() const;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
InputHandler *m_inputHandler;
MouseState m_mouseState;
diff --git a/src/input/backend/mouseeventdispatcherjob.cpp b/src/input/backend/mouseeventdispatcherjob.cpp
index 4bd3e93c3..b91a7b638 100644
--- a/src/input/backend/mouseeventdispatcherjob.cpp
+++ b/src/input/backend/mouseeventdispatcherjob.cpp
@@ -38,7 +38,9 @@
****************************************************************************/
#include "mouseeventdispatcherjob_p.h"
-
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DInput/qmousehandler.h>
+#include <Qt3DInput/private/qmousehandler_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/job_common_p.h>
@@ -49,21 +51,37 @@ QT_BEGIN_NAMESPACE
namespace Qt3DInput {
namespace Input {
+class MouseEventDispatcherJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ MouseEventDispatcherJobPrivate() { }
+ ~MouseEventDispatcherJobPrivate() override { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ Qt3DCore::QNodeId m_mouseInput;
+ QList<QT_PREPEND_NAMESPACE(QMouseEvent)> m_mouseEvents;
+#if QT_CONFIG(wheelevent)
+ QList<QT_PREPEND_NAMESPACE(QWheelEvent)> m_wheelEvents;
+#endif
+};
+
MouseEventDispatcherJob::MouseEventDispatcherJob(Qt3DCore::QNodeId input,
const QList<QT_PREPEND_NAMESPACE (QMouseEvent)> &mouseEvents
#if QT_CONFIG(wheelevent)
, const QList<QT_PREPEND_NAMESPACE (QWheelEvent)> &wheelEvents
#endif
)
- : QAspectJob()
+ : QAspectJob(*new MouseEventDispatcherJobPrivate)
, m_inputHandler(nullptr)
- , m_mouseInput(input)
- , m_mouseEvents(mouseEvents)
+{
+ Q_DJOB(MouseEventDispatcherJob);
+ d->m_mouseInput = input;
+ d->m_mouseEvents = mouseEvents;
#if QT_CONFIG(wheelevent)
- , m_wheelEvents(wheelEvents)
+ d->m_wheelEvents = wheelEvents;
#endif
-{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::MouseEventDispatcher, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::MouseEventDispatcher, 0)
}
void MouseEventDispatcherJob::setInputHandler(InputHandler *handler)
@@ -73,16 +91,25 @@ void MouseEventDispatcherJob::setInputHandler(InputHandler *handler)
void MouseEventDispatcherJob::run()
{
- MouseHandler *input = m_inputHandler->mouseInputManager()->lookupResource(m_mouseInput);
- if (input) {
- // Send mouse and wheel events to frontend
- for (const QT_PREPEND_NAMESPACE(QMouseEvent) &e : m_mouseEvents)
- input->mouseEvent(QMouseEventPtr::create(e));
+ // NOP
+}
+
+void MouseEventDispatcherJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ QMouseHandler *node = qobject_cast<QMouseHandler *>(manager->lookupNode(m_mouseInput));
+ if (!node)
+ return;
+
+ QMouseHandlerPrivate *dnode = static_cast<QMouseHandlerPrivate *>(QMouseHandlerPrivate::get(node));
+
+ for (const QT_PREPEND_NAMESPACE(QMouseEvent) &e : m_mouseEvents)
+ dnode->mouseEvent(QMouseEventPtr::create(e));
#if QT_CONFIG(wheelevent)
- for (const QT_PREPEND_NAMESPACE(QWheelEvent) &e : m_wheelEvents)
- input->wheelEvent(QWheelEventPtr::create(e));
-#endif
+ for (const QT_PREPEND_NAMESPACE(QWheelEvent) &e : m_wheelEvents) {
+ QWheelEvent we(e);
+ emit node->wheel(&we);
}
+#endif
}
} // namespace Input
diff --git a/src/input/backend/mouseeventdispatcherjob_p.h b/src/input/backend/mouseeventdispatcherjob_p.h
index 8abeccfb4..983837446 100644
--- a/src/input/backend/mouseeventdispatcherjob_p.h
+++ b/src/input/backend/mouseeventdispatcherjob_p.h
@@ -61,6 +61,7 @@ namespace Qt3DInput {
namespace Input {
class InputHandler;
+class MouseEventDispatcherJobPrivate;
class MouseEventDispatcherJob : public Qt3DCore::QAspectJob
{
@@ -76,11 +77,6 @@ public:
private:
InputHandler *m_inputHandler;
- const Qt3DCore::QNodeId m_mouseInput;
- const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> m_mouseEvents;
-#if QT_CONFIG(wheelevent)
- const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> m_wheelEvents;
-#endif
};
} // namespace Input
diff --git a/src/input/backend/mouseeventfilter.cpp b/src/input/backend/mouseeventfilter.cpp
index 618a64b15..48b30725a 100644
--- a/src/input/backend/mouseeventfilter.cpp
+++ b/src/input/backend/mouseeventfilter.cpp
@@ -53,6 +53,7 @@ namespace Input {
MouseEventFilter::MouseEventFilter(QObject *parent)
: QObject(parent)
+ , m_inputHandler(nullptr)
{
}
diff --git a/src/input/backend/mousehandler.cpp b/src/input/backend/mousehandler.cpp
index c492dcf28..9c7ff9817 100644
--- a/src/input/backend/mousehandler.cpp
+++ b/src/input/backend/mousehandler.cpp
@@ -41,7 +41,6 @@
#include <Qt3DInput/qmousehandler.h>
#include <Qt3DInput/qmousedevice.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
@@ -56,7 +55,7 @@ namespace Qt3DInput {
namespace Input {
MouseHandler::MouseHandler()
- : QBackendNode(ReadWrite)
+ : BackendNode(ReadWrite)
, m_inputHandler(nullptr)
{
}
@@ -65,13 +64,6 @@ MouseHandler::~MouseHandler()
{
}
-void MouseHandler::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMouseHandlerData>>(change);
- const auto &data = typedChange->data;
- setDevice(data.mouseDeviceId);
-}
-
Qt3DCore::QNodeId MouseHandler::mouseDevice() const
{
return m_mouseDevice;
@@ -82,38 +74,16 @@ void MouseHandler::setInputHandler(InputHandler *handler)
m_inputHandler = handler;
}
-void MouseHandler::mouseEvent(const QMouseEventPtr &event)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("mouse");
- e->setValue(QVariant::fromValue(event));
- notifyObservers(e);
-}
-
-#if QT_CONFIG(wheelevent)
-void MouseHandler::wheelEvent(const QWheelEventPtr &event)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("wheel");
- e->setValue(QVariant::fromValue(event));
- notifyObservers(e);
-}
-#endif
-
-void MouseHandler::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void MouseHandler::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("device")) {
- const QNodeId newId = propertyChange->value().value<QNodeId>();
- if (m_mouseDevice != newId) {
- setDevice(newId);
- }
- }
- }
- QBackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const Qt3DInput::QMouseHandler *node = qobject_cast<const Qt3DInput::QMouseHandler *>(frontEnd);
+ if (!node)
+ return;
+
+ const auto newId = Qt3DCore::qIdForNode(node->sourceDevice());
+ if (m_mouseDevice != newId)
+ setDevice(newId);
}
void MouseHandler::setDevice(Qt3DCore::QNodeId device)
diff --git a/src/input/backend/mousehandler_p.h b/src/input/backend/mousehandler_p.h
index 6d748c068..693c42471 100644
--- a/src/input/backend/mousehandler_p.h
+++ b/src/input/backend/mousehandler_p.h
@@ -52,7 +52,7 @@
//
#include <Qt3DInput/qmouseevent.h>
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
QT_BEGIN_NAMESPACE
@@ -61,7 +61,7 @@ namespace Input {
class InputHandler;
-class MouseHandler : public Qt3DCore::QBackendNode
+class MouseHandler : public BackendNode
{
public:
MouseHandler();
@@ -69,18 +69,12 @@ public:
Qt3DCore::QNodeId mouseDevice() const;
void setInputHandler(InputHandler *handler);
- void mouseEvent(const QMouseEventPtr &event);
-#if QT_CONFIG(wheelevent)
- void wheelEvent(const QWheelEventPtr &event);
-#endif
protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void setDevice(Qt3DCore::QNodeId device);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_mouseDevice;
InputHandler *m_inputHandler;
};
diff --git a/src/input/backend/physicaldeviceproxy.cpp b/src/input/backend/physicaldeviceproxy.cpp
index 9512296b8..390b525eb 100644
--- a/src/input/backend/physicaldeviceproxy.cpp
+++ b/src/input/backend/physicaldeviceproxy.cpp
@@ -40,10 +40,10 @@
#include "physicaldeviceproxy_p.h"
#include <Qt3DInput/qabstractphysicaldevice.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/QCoreApplication>
#include <Qt3DInput/private/inputmanagers_p.h>
+#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p.h>
#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p_p.h>
QT_BEGIN_NAMESPACE
@@ -53,7 +53,7 @@ namespace Qt3DInput {
namespace Input {
PhysicalDeviceProxy::PhysicalDeviceProxy()
- : QBackendNode(QBackendNode::ReadWrite)
+ : BackendNode(QBackendNode::ReadWrite)
, m_manager(nullptr)
{
}
@@ -89,12 +89,6 @@ void PhysicalDeviceProxy::setDevice(QAbstractPhysicalDevice *device)
m_physicalDeviceId = device->id();
device->moveToThread(QCoreApplication::instance()->thread());
}
-
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("device");
- e->setValue(QVariant::fromValue(device));
- notifyObservers(e);
}
Qt3DCore::QNodeId PhysicalDeviceProxy::physicalDeviceId() const
@@ -102,14 +96,20 @@ Qt3DCore::QNodeId PhysicalDeviceProxy::physicalDeviceId() const
return m_physicalDeviceId;
}
-void PhysicalDeviceProxy::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void PhysicalDeviceProxy::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractPhysicalDeviceProxyData>>(change);
- const QAbstractPhysicalDeviceProxyData &data = typedChange->data;
- m_deviceName = data.deviceName;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (firstTime) {
+ const QAbstractPhysicalDeviceProxy *node = qobject_cast<const QAbstractPhysicalDeviceProxy *>(frontEnd);
+ if (!node)
+ return;
- // Request to load the actual device
- m_manager->addPendingProxyToLoad(peerId());
+ m_deviceName = node->deviceName();
+
+ // Request to load the actual device
+ m_manager->addPendingProxyToLoad(peerId());
+ }
}
PhysicalDeviceProxyNodeFunctor::PhysicalDeviceProxyNodeFunctor(PhysicalDeviceProxyManager *manager)
diff --git a/src/input/backend/physicaldeviceproxy_p.h b/src/input/backend/physicaldeviceproxy_p.h
index 9500a4adb..6dd2a54be 100644
--- a/src/input/backend/physicaldeviceproxy_p.h
+++ b/src/input/backend/physicaldeviceproxy_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DCore/qnodeid.h>
QT_BEGIN_NAMESPACE
@@ -64,7 +64,7 @@ namespace Input {
class PhysicalDeviceProxyManager;
-class Q_AUTOTEST_EXPORT PhysicalDeviceProxy : public Qt3DCore::QBackendNode
+class Q_AUTOTEST_EXPORT PhysicalDeviceProxy : public BackendNode
{
public:
PhysicalDeviceProxy();
@@ -79,9 +79,9 @@ public:
void setDevice(QAbstractPhysicalDevice *device);
Qt3DCore::QNodeId physicalDeviceId() const;
-private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+private:
QString m_deviceName;
PhysicalDeviceProxyManager *m_manager;
Qt3DCore::QNodeId m_physicalDeviceId;
diff --git a/src/input/backend/qabstractphysicaldevicebackendnode.cpp b/src/input/backend/qabstractphysicaldevicebackendnode.cpp
index 5006d702a..6e6899e32 100644
--- a/src/input/backend/qabstractphysicaldevicebackendnode.cpp
+++ b/src/input/backend/qabstractphysicaldevicebackendnode.cpp
@@ -44,11 +44,9 @@
#include <Qt3DInput/qaxissetting.h>
#include <Qt3DInput/qinputaspect.h>
#include <Qt3DInput/qphysicaldevicecreatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <cmath>
+#include <algorithm>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
@@ -132,51 +130,14 @@ Input::AxisSetting *QAbstractPhysicalDeviceBackendNodePrivate::getAxisSetting(Qt
return axisSetting;
}
-QVector<Input::AxisIdSetting> QAbstractPhysicalDeviceBackendNodePrivate::convertToAxisIdSettingVector(Qt3DCore::QNodeId axisSettingId) const
-{
- const auto axisSetting = getAxisSetting(axisSettingId);
- const auto axisIds = axisSetting->axes();
-
- auto result = QVector<Input::AxisIdSetting>();
- result.reserve(axisIds.size());
- std::transform(axisIds.constBegin(), axisIds.constEnd(),
- std::back_inserter(result),
- [axisSettingId] (int axisId) {
- return Input::AxisIdSetting{ axisId, axisSettingId };
- });
- return result;
-}
-
-void QAbstractPhysicalDeviceBackendNodePrivate::updatePendingAxisSettings()
-{
- if (m_pendingAxisSettingIds.isEmpty())
- return;
-
- m_axisSettings = std::accumulate(
- m_pendingAxisSettingIds.constBegin(), m_pendingAxisSettingIds.constEnd(),
- QVector<Input::AxisIdSetting>(),
- [this] (const QVector<Input::AxisIdSetting> &current, Qt3DCore::QNodeId axisSettingId) {
- return current + convertToAxisIdSettingVector(axisSettingId);
- });
- m_pendingAxisSettingIds.clear();
-}
-
QAbstractPhysicalDeviceBackendNode::QAbstractPhysicalDeviceBackendNode(QBackendNode::Mode mode)
- : Qt3DCore::QBackendNode(*new QAbstractPhysicalDeviceBackendNodePrivate(mode))
+ : Input::BackendNode(*new QAbstractPhysicalDeviceBackendNodePrivate(mode))
{
}
QAbstractPhysicalDeviceBackendNode::QAbstractPhysicalDeviceBackendNode(QAbstractPhysicalDeviceBackendNodePrivate &dd)
- : Qt3DCore::QBackendNode(dd)
-{
-}
-
-void QAbstractPhysicalDeviceBackendNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+ : Input::BackendNode(dd)
{
- const auto deviceChange = qSharedPointerCast<QPhysicalDeviceCreatedChangeBase>(change);
- Q_D(QAbstractPhysicalDeviceBackendNode);
- // Store the axis setting Ids. We will update the settings themselves when needed
- d->m_pendingAxisSettingIds = deviceChange->axisSettingIds();
}
void QAbstractPhysicalDeviceBackendNode::cleanup()
@@ -188,33 +149,34 @@ void QAbstractPhysicalDeviceBackendNode::cleanup()
d->m_inputAspect = nullptr;
}
-void QAbstractPhysicalDeviceBackendNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void QAbstractPhysicalDeviceBackendNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
Q_D(QAbstractPhysicalDeviceBackendNode);
- switch (e->type()) {
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("axisSettings")) {
- const auto axisSettingId = change->addedNodeId();
- Input::AxisSetting *axisSetting = d->getAxisSetting(axisSettingId);
- const auto axisIds = axisSetting->axes();
- for (int axisId : axisIds)
- d->addAxisSetting(axisId, axisSettingId);
- }
- break;
- }
-
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("axisSettings"))
- d->removeAxisSetting(change->removedNodeId());
- break;
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const Qt3DInput::QAbstractPhysicalDevice *node = qobject_cast<const Qt3DInput::QAbstractPhysicalDevice *>(frontEnd);
+ if (!node)
+ return;
- default:
- break;
+ auto settings = Qt3DCore::qIdsForNodes(node->axisSettings());
+ std::sort(std::begin(settings), std::end(settings));
+ Qt3DCore::QNodeIdVector addedSettings;
+ Qt3DCore::QNodeIdVector removedSettings;
+ std::set_difference(std::begin(settings), std::end(settings),
+ std::begin(d->m_currentAxisSettingIds), std::end(d->m_currentAxisSettingIds),
+ std::inserter(addedSettings, addedSettings.end()));
+ std::set_difference(std::begin(d->m_currentAxisSettingIds), std::end(d->m_currentAxisSettingIds),
+ std::begin(settings), std::end(settings),
+ std::inserter(removedSettings, removedSettings.end()));
+ d->m_currentAxisSettingIds = settings;
+
+ for (const auto &axisSettingId: qAsConst(addedSettings)) {
+ Input::AxisSetting *axisSetting = d->getAxisSetting(axisSettingId);
+ const auto axisIds = axisSetting->axes();
+ for (int axisId : axisIds)
+ d->addAxisSetting(axisId, axisSettingId);
}
- QBackendNode::sceneChangeEvent(e);
+ for (const auto &axisSettingId: qAsConst(removedSettings))
+ d->removeAxisSetting(axisSettingId);
}
void QAbstractPhysicalDeviceBackendNode::setInputAspect(QInputAspect *aspect)
@@ -232,7 +194,6 @@ QInputAspect *QAbstractPhysicalDeviceBackendNode::inputAspect() const
float QAbstractPhysicalDeviceBackendNode::processedAxisValue(int axisIdentifier)
{
Q_D(QAbstractPhysicalDeviceBackendNode);
- d->updatePendingAxisSettings();
// Find axis settings for this axis (if any)
Qt3DCore::QNodeId axisSettingId;
diff --git a/src/input/backend/qabstractphysicaldevicebackendnode_p.h b/src/input/backend/qabstractphysicaldevicebackendnode_p.h
index e8e397883..ff46cf814 100644
--- a/src/input/backend/qabstractphysicaldevicebackendnode_p.h
+++ b/src/input/backend/qabstractphysicaldevicebackendnode_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DInput/private/qt3dinput_global_p.h>
@@ -66,12 +66,12 @@ namespace Qt3DInput {
class QInputAspect;
class QAbstractPhysicalDeviceBackendNodePrivate;
-class Q_3DINPUTSHARED_PRIVATE_EXPORT QAbstractPhysicalDeviceBackendNode : public Qt3DCore::QBackendNode
+class Q_3DINPUTSHARED_PRIVATE_EXPORT QAbstractPhysicalDeviceBackendNode : public Input::BackendNode
{
public:
explicit QAbstractPhysicalDeviceBackendNode(QBackendNode::Mode mode);
virtual void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void setInputAspect(QInputAspect *aspect);
QInputAspect *inputAspect() const;
@@ -83,8 +83,6 @@ public:
protected:
QAbstractPhysicalDeviceBackendNode(QAbstractPhysicalDeviceBackendNodePrivate &dd);
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
-
Q_DECLARE_PRIVATE(QAbstractPhysicalDeviceBackendNode)
};
diff --git a/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h b/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h
index 4b0c47b36..9156fc64d 100644
--- a/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h
+++ b/src/input/backend/qabstractphysicaldevicebackendnode_p_p.h
@@ -97,10 +97,7 @@ public:
Input::AxisSetting *getAxisSetting(Qt3DCore::QNodeId axisSettingId) const;
- QVector<Input::AxisIdSetting> convertToAxisIdSettingVector(Qt3DCore::QNodeId axisSettingId) const;
- void updatePendingAxisSettings();
-
- Qt3DCore::QNodeIdVector m_pendingAxisSettingIds;
+ Qt3DCore::QNodeIdVector m_currentAxisSettingIds;
QVector<Input::AxisIdSetting> m_axisSettings;
QVector<Input::AxisIdFilter> m_axisFilters;
QInputAspect *m_inputAspect;
diff --git a/src/input/backend/updateaxisactionjob.cpp b/src/input/backend/updateaxisactionjob.cpp
index 03690479a..5732c2a9b 100644
--- a/src/input/backend/updateaxisactionjob.cpp
+++ b/src/input/backend/updateaxisactionjob.cpp
@@ -38,7 +38,11 @@
****************************************************************************/
#include "updateaxisactionjob_p.h"
-
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DInput/qaction.h>
+#include <Qt3DInput/qaxis.h>
+#include <Qt3DInput/private/qaction_p.h>
+#include <Qt3DInput/private/qaxis_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/job_common_p.h>
@@ -49,13 +53,25 @@ namespace Qt3DInput {
namespace Input {
+class UpdateAxisActionJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ UpdateAxisActionJobPrivate() { }
+ ~UpdateAxisActionJobPrivate() override { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ QVector<QPair<Qt3DCore::QNodeId, bool>> m_triggeredActions;
+ QVector<QPair<Qt3DCore::QNodeId, float>> m_triggeredAxis;
+};
+
UpdateAxisActionJob::UpdateAxisActionJob(qint64 currentTime, InputHandler *handler, HLogicalDevice handle)
- : Qt3DCore::QAspectJob()
+ : Qt3DCore::QAspectJob(*new UpdateAxisActionJobPrivate())
, m_currentTime(currentTime)
, m_handler(handler)
, m_handle(handle)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateAxisAction, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateAxisAction, 0)
}
void UpdateAxisActionJob::run()
@@ -73,7 +89,10 @@ void UpdateAxisActionJob::run()
void UpdateAxisActionJob::updateAction(LogicalDevice *device)
{
+ Q_DJOB(UpdateAxisActionJob);
const auto actionIds = device->actions();
+ d->m_triggeredActions.reserve(actionIds.size());
+
for (const Qt3DCore::QNodeId actionId : actionIds) {
bool actionTriggered = false;
Action *action = m_handler->actionManager()->lookupResource(actionId);
@@ -82,7 +101,10 @@ void UpdateAxisActionJob::updateAction(LogicalDevice *device)
for (const Qt3DCore::QNodeId actionInputId : actionInputIds)
actionTriggered |= processActionInput(actionInputId);
- action->setActionTriggered(actionTriggered);
+ if (action->isEnabled() && (action->actionTriggered() != actionTriggered)) {
+ action->setActionTriggered(actionTriggered);
+ d->m_triggeredActions.push_back({actionId, actionTriggered});
+ }
}
}
@@ -95,7 +117,10 @@ bool UpdateAxisActionJob::processActionInput(const Qt3DCore::QNodeId actionInput
void UpdateAxisActionJob::updateAxis(LogicalDevice *device)
{
+ Q_DJOB(UpdateAxisActionJob);
const auto axisIds = device->axes();
+ d->m_triggeredAxis.reserve(axisIds.size());
+
for (const Qt3DCore::QNodeId axisId : axisIds) {
Axis *axis = m_handler->axisManager()->lookupResource(axisId);
float axisValue = 0.0f;
@@ -106,7 +131,11 @@ void UpdateAxisActionJob::updateAxis(LogicalDevice *device)
// Clamp the axisValue -1/1
axisValue = qMin(1.0f, qMax(axisValue, -1.0f));
- axis->setAxisValue(axisValue);
+
+ if (axis->isEnabled() && !qFuzzyCompare(axisValue, axis->axisValue())) {
+ axis->setAxisValue(axisValue);
+ d->m_triggeredAxis.push_back({axisId, axisValue});
+ }
}
}
@@ -124,6 +153,30 @@ float UpdateAxisActionJob::processAxisInput(const Qt3DCore::QNodeId axisInputId)
return 0.0f;
}
+void UpdateAxisActionJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ for (const auto &data: qAsConst(m_triggeredActions)) {
+ Qt3DInput::QAction *action = qobject_cast<Qt3DInput::QAction *>(manager->lookupNode(data.first));
+ if (!action)
+ continue;
+
+ Qt3DInput::QActionPrivate *daction = static_cast<Qt3DInput::QActionPrivate *>(Qt3DCore::QNodePrivate::get(action));
+ daction->setActive(data.second);
+ }
+
+ for (const auto &data: qAsConst(m_triggeredAxis)) {
+ Qt3DInput::QAxis *axis = qobject_cast<Qt3DInput::QAxis *>(manager->lookupNode(data.first));
+ if (!axis)
+ continue;
+
+ Qt3DInput::QAxisPrivate *daxis = static_cast<Qt3DInput::QAxisPrivate *>(Qt3DCore::QNodePrivate::get(axis));
+ daxis->setValue(data.second);
+ }
+
+ m_triggeredActions.clear();
+ m_triggeredAxis.clear();
+}
+
} // Input
} // Qt3DInput
diff --git a/src/input/backend/updateaxisactionjob_p.h b/src/input/backend/updateaxisactionjob_p.h
index 719923a50..39b5f5cf6 100644
--- a/src/input/backend/updateaxisactionjob_p.h
+++ b/src/input/backend/updateaxisactionjob_p.h
@@ -67,6 +67,7 @@ namespace Input {
class AbstractAxisInput;
class ButtonAxisInput;
class InputHandler;
+class UpdateAxisActionJobPrivate;
class UpdateAxisActionJob : public Qt3DCore::QAspectJob
{
diff --git a/src/input/frontend/qabstractphysicaldevice.cpp b/src/input/frontend/qabstractphysicaldevice.cpp
index 120ec43a2..33c86f7b8 100644
--- a/src/input/frontend/qabstractphysicaldevice.cpp
+++ b/src/input/frontend/qabstractphysicaldevice.cpp
@@ -42,9 +42,6 @@
#include <Qt3DInput/qaxissetting.h>
#include <Qt3DInput/qphysicaldevicecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnode_p.h>
@@ -168,12 +165,7 @@ void QAbstractPhysicalDevice::addAxisSetting(QAxisSetting *axisSetting)
{
Q_D(QAbstractPhysicalDevice);
if (axisSetting && !d->m_axisSettings.contains(axisSetting)) {
- if (d->m_changeArbiter) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), axisSetting);
- change->setPropertyName("axisSettings");
- d->notifyObservers(change);
- }
-
+ d->updateNode(axisSetting, "axisSettings", Qt3DCore::PropertyValueAdded);
d->m_axisSettings.push_back(axisSetting);
}
}
@@ -185,12 +177,7 @@ void QAbstractPhysicalDevice::removeAxisSetting(QAxisSetting *axisSetting)
{
Q_D(QAbstractPhysicalDevice);
if (axisSetting && d->m_axisSettings.contains(axisSetting)) {
- if (d->m_changeArbiter) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), axisSetting);
- change->setPropertyName("axisSettings");
- d->notifyObservers(change);
- }
-
+ d->updateNode(axisSetting, "axisSettings", Qt3DCore::PropertyValueRemoved);
d->m_axisSettings.removeOne(axisSetting);
}
}
@@ -209,11 +196,8 @@ QVector<QAxisSetting *> QAbstractPhysicalDevice::axisSettings() const
*/
void QAbstractPhysicalDevicePrivate::postAxisEvent(int axis, qreal value)
{
- Q_Q(QAbstractPhysicalDevice);
- Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(q->id()));
- change->setPropertyName("axisEvent");
- change->setValue(QVariant::fromValue(QPair<int, qreal>(axis, value)));
- notifyObservers(change);
+ m_pendingAxisEvents.push_back({axis, value});
+ update();
}
/*
@@ -221,11 +205,8 @@ void QAbstractPhysicalDevicePrivate::postAxisEvent(int axis, qreal value)
*/
void QAbstractPhysicalDevicePrivate::postButtonEvent(int button, qreal value)
{
- Q_Q(QAbstractPhysicalDevice);
- Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(q->id()));
- change->setPropertyName("buttonEvent");
- change->setValue(QVariant::fromValue(QPair<int, qreal>(button, value)));
- notifyObservers(change);
+ m_pendingButtonsEvents.push_back({button, value});
+ update();
}
/*!
diff --git a/src/input/frontend/qabstractphysicaldevice_p.h b/src/input/frontend/qabstractphysicaldevice_p.h
index 8fa72aa02..fc8ad561c 100644
--- a/src/input/frontend/qabstractphysicaldevice_p.h
+++ b/src/input/frontend/qabstractphysicaldevice_p.h
@@ -76,6 +76,9 @@ public:
QHash<QString, int> m_axesHash;
QHash<QString, int> m_buttonsHash;
+ QVector<QPair<int, qreal>> m_pendingAxisEvents;
+ QVector<QPair<int, qreal>> m_pendingButtonsEvents;
+
void postAxisEvent(int axis, qreal value);
void postButtonEvent(int button, qreal value);
};
diff --git a/src/input/frontend/qabstractphysicaldeviceproxy.cpp b/src/input/frontend/qabstractphysicaldeviceproxy.cpp
index 34b7db2a4..4ed116440 100644
--- a/src/input/frontend/qabstractphysicaldeviceproxy.cpp
+++ b/src/input/frontend/qabstractphysicaldeviceproxy.cpp
@@ -41,7 +41,6 @@
#include "qabstractphysicaldeviceproxy_p_p.h"
#include <Qt3DInput/qphysicaldevicecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -160,26 +159,6 @@ int QAbstractPhysicalDeviceProxy::buttonIdentifier(const QString &name) const
/*!
\internal
*/
-void QAbstractPhysicalDeviceProxy::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QAbstractPhysicalDeviceProxy);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated) {
- if (e->propertyName() == QByteArrayLiteral("device")) {
- QAbstractPhysicalDevice *device = e->value().value<Qt3DInput::QAbstractPhysicalDevice *>();
- QAbstractPhysicalDevice *oldDevice = d->m_device;
- setDevice(device);
- // Delete the old device if it existed
- if (oldDevice != nullptr)
- delete oldDevice;
- }
- }
- QAbstractPhysicalDevice::sceneChangeEvent(change);
-}
-
-/*!
- \internal
- */
QAbstractPhysicalDeviceProxy::QAbstractPhysicalDeviceProxy(QAbstractPhysicalDeviceProxyPrivate &dd, Qt3DCore::QNode *parent)
: QAbstractPhysicalDevice(dd, parent)
{
@@ -202,32 +181,45 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAbstractPhysicalDeviceProxy::createNodeCrea
/*!
\internal
*/
-void QAbstractPhysicalDeviceProxy::setDevice(QAbstractPhysicalDevice *device)
+void QAbstractPhysicalDeviceProxyPrivate::setDevice(QAbstractPhysicalDevice *device)
{
- Q_D(QAbstractPhysicalDeviceProxy);
+ Q_Q(QAbstractPhysicalDeviceProxy);
// Note: technically book keeping could be optional since we are the parent
// of the device. But who knows if someone plays with the object tree...
// Unset bookkeeper
- if (d->m_device != nullptr) {
+ if (m_device != nullptr) {
// Note: we cannot delete the device here as we don't how if we are
// called by the bookkeeper (in which case we would do a double free)
// or by the sceneChangeEvent
- d->unregisterDestructionHelper(d->m_device);
- d->setStatus(QAbstractPhysicalDeviceProxy::NotFound);
+ unregisterDestructionHelper(m_device);
+ setStatus(QAbstractPhysicalDeviceProxy::NotFound);
}
// Set parent so that node is created in the backend
if (device != nullptr && device->parent() == nullptr)
- device->setParent(this);
+ device->setParent(q);
- d->m_device = device;
+ m_device = device;
// Set bookkeeper
if (device != nullptr) {
- d->setStatus(QAbstractPhysicalDeviceProxy::Ready);
- d->registerDestructionHelper(d->m_device, &QAbstractPhysicalDeviceProxy::setDevice, d->m_device);
+ setStatus(QAbstractPhysicalDeviceProxy::Ready);
+ registerPrivateDestructionHelper(m_device, &QAbstractPhysicalDeviceProxyPrivate::resetDevice);
+ }
+}
+
+void QAbstractPhysicalDeviceProxyPrivate::resetDevice(QAbstractPhysicalDevice *device)
+{
+ if (m_device == device) {
+ // Note: we cannot delete the device here as we don't how if we are
+ // called by the bookkeeper (in which case we would do a double free)
+ // or by the sceneChangeEvent
+ unregisterDestructionHelper(m_device);
+ setStatus(QAbstractPhysicalDeviceProxy::NotFound);
+
+ m_device = nullptr;
}
}
diff --git a/src/input/frontend/qabstractphysicaldeviceproxy_p.h b/src/input/frontend/qabstractphysicaldeviceproxy_p.h
index e250b9eb9..4a7b1dfc5 100644
--- a/src/input/frontend/qabstractphysicaldeviceproxy_p.h
+++ b/src/input/frontend/qabstractphysicaldeviceproxy_p.h
@@ -88,13 +88,10 @@ Q_SIGNALS:
void statusChanged(QAbstractPhysicalDeviceProxy::DeviceStatus status);
protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
-
QAbstractPhysicalDeviceProxy(QAbstractPhysicalDeviceProxyPrivate &dd, Qt3DCore::QNode *parent = nullptr);
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
private:
- void setDevice(QAbstractPhysicalDevice *device);
Q_DECLARE_PRIVATE(QAbstractPhysicalDeviceProxy)
};
diff --git a/src/input/frontend/qabstractphysicaldeviceproxy_p_p.h b/src/input/frontend/qabstractphysicaldeviceproxy_p_p.h
index 8f8d1bea3..fc8645272 100644
--- a/src/input/frontend/qabstractphysicaldeviceproxy_p_p.h
+++ b/src/input/frontend/qabstractphysicaldeviceproxy_p_p.h
@@ -73,6 +73,8 @@ public:
QAbstractPhysicalDeviceProxy::DeviceStatus m_status;
QAbstractPhysicalDevice *m_device;
+ void setDevice(QAbstractPhysicalDevice *device);
+ void resetDevice(QAbstractPhysicalDevice *device);
void setStatus(QAbstractPhysicalDeviceProxy::DeviceStatus status);
};
diff --git a/src/input/frontend/qaction.cpp b/src/input/frontend/qaction.cpp
index 1006c0cec..8cceaab51 100644
--- a/src/input/frontend/qaction.cpp
+++ b/src/input/frontend/qaction.cpp
@@ -41,9 +41,6 @@
#include "qaction_p.h"
#include <Qt3DInput/qabstractactioninput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
@@ -121,11 +118,7 @@ void QAction::addInput(QAbstractActionInput *input)
// Ensures proper bookkeeping
d->registerDestructionHelper(input, &QAction::removeInput, d->m_inputs);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), input);
- change->setPropertyName("input");
- d->notifyObservers(change);
- }
+ d->updateNode(input, "inputs", Qt3DCore::PropertyValueAdded);
}
}
@@ -137,11 +130,7 @@ void QAction::removeInput(QAbstractActionInput *input)
Q_D(QAction);
if (d->m_inputs.contains(input)) {
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), input);
- change->setPropertyName("input");
- d->notifyObservers(change);
- }
+ d->updateNode(input, "inputs", Qt3DCore::PropertyValueRemoved);
d->m_inputs.removeOne(input);
@@ -159,14 +148,9 @@ QVector<QAbstractActionInput *> QAction::inputs() const
return d->m_inputs;
}
-/*! \internal */
-void QAction::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QAction::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- Q_D(QAction);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("active")) {
- d->setActive(e->value().toBool());
- }
}
Qt3DCore::QNodeCreatedChangeBasePtr QAction::createNodeCreationChange() const
diff --git a/src/input/frontend/qaction.h b/src/input/frontend/qaction.h
index f15159f68..ef74debe5 100644
--- a/src/input/frontend/qaction.h
+++ b/src/input/frontend/qaction.h
@@ -68,6 +68,7 @@ Q_SIGNALS:
void activeChanged(bool isActive);
protected:
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/input/frontend/qactioninput.cpp b/src/input/frontend/qactioninput.cpp
index 9f32f57cc..f013147f2 100644
--- a/src/input/frontend/qactioninput.cpp
+++ b/src/input/frontend/qactioninput.cpp
@@ -181,7 +181,7 @@ QAbstractPhysicalDevice *QActionInput::sourceDevice() const
/*!
\qmlsignal Qt3D.Input::ActionInput::buttonsChanged(const QVector<int> &buttons)
- This signal is emitted when the buttons associated with the action input is changed.
+ This signal is emitted when the \a buttons associated with the action input is changed.
The corresponding handler is \c onbuttonsChanged
*/
diff --git a/src/input/frontend/qaxis.cpp b/src/input/frontend/qaxis.cpp
index 1830c8005..d76135fd7 100644
--- a/src/input/frontend/qaxis.cpp
+++ b/src/input/frontend/qaxis.cpp
@@ -40,9 +40,6 @@
#include "qaxis_p.h"
#include <Qt3DInput/qabstractaxisinput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -117,12 +114,7 @@ void QAxis::addInput(QAbstractAxisInput *input)
// Ensures proper bookkeeping
d->registerDestructionHelper(input, &QAxis::removeInput, d->m_inputs);
-
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), input);
- change->setPropertyName("input");
- d->notifyObservers(change);
- }
+ d->updateNode(input, "input", Qt3DCore::PropertyValueAdded);
}
}
@@ -144,11 +136,7 @@ void QAxis::removeInput(QAbstractAxisInput *input)
Q_D(QAxis);
if (d->m_inputs.contains(input)) {
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), input);
- change->setPropertyName("input");
- d->notifyObservers(change);
- }
+ d->updateNode(input, "input", Qt3DCore::PropertyValueRemoved);
d->m_inputs.removeOne(input);
@@ -179,14 +167,9 @@ float QAxis::value() const
return d->m_value;
}
-/*! \internal */
-void QAxis::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QAxis::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- Q_D(QAxis);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("value")) {
- d->setValue(e->value().toFloat());
- }
}
Qt3DCore::QNodeCreatedChangeBasePtr QAxis::createNodeCreationChange() const
diff --git a/src/input/frontend/qaxis.h b/src/input/frontend/qaxis.h
index a4f7ea7d4..3dbe54a4f 100644
--- a/src/input/frontend/qaxis.h
+++ b/src/input/frontend/qaxis.h
@@ -67,6 +67,7 @@ Q_SIGNALS:
void valueChanged(float value);
protected:
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/input/frontend/qaxisaccumulator.cpp b/src/input/frontend/qaxisaccumulator.cpp
index 0c156194b..a7bb14441 100644
--- a/src/input/frontend/qaxisaccumulator.cpp
+++ b/src/input/frontend/qaxisaccumulator.cpp
@@ -42,7 +42,6 @@
#include <Qt3DInput/qaxis.h>
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -290,15 +289,9 @@ void QAxisAccumulator::setScale(float scale)
emit scaleChanged(scale);
}
-/*! \internal */
-void QAxisAccumulator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QAxisAccumulator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- Q_D(QAxisAccumulator);
- auto e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("value"))
- d->setValue(e->value().toFloat());
- else if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("velocity"))
- d->setVelocity(e->value().toFloat());
}
/*! \internal */
diff --git a/src/input/frontend/qaxisaccumulator.h b/src/input/frontend/qaxisaccumulator.h
index e5f35a32f..e711b0691 100644
--- a/src/input/frontend/qaxisaccumulator.h
+++ b/src/input/frontend/qaxisaccumulator.h
@@ -88,6 +88,7 @@ Q_SIGNALS:
void scaleChanged(float scale);
protected:
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/input/frontend/qinputaspect.cpp b/src/input/frontend/qinputaspect.cpp
index e7ff70326..31a0f8b1e 100644
--- a/src/input/frontend/qinputaspect.cpp
+++ b/src/input/frontend/qinputaspect.cpp
@@ -61,6 +61,7 @@
#include <QtCore/QLibraryInfo>
#include <QtCore/QPluginLoader>
+#include <Qt3DInput/private/backendnode_p.h>
#include <Qt3DInput/private/action_p.h>
#include <Qt3DInput/private/actioninput_p.h>
#include <Qt3DInput/private/axis_p.h>
@@ -109,6 +110,13 @@ QInputAspectPrivate::QInputAspectPrivate()
{
}
+void QInputAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const
+{
+ Input::BackendNode *renderBackend = static_cast<Input::BackendNode *>(backend);
+ renderBackend->syncFromFrontEnd(node, firstTime);
+}
+
+
/*!
\class Qt3DInput::QInputAspect
\inherits Qt3DCore::QAbstractAspect
@@ -133,33 +141,33 @@ QInputAspect::QInputAspect(QObject *parent)
QInputAspect::QInputAspect(QInputAspectPrivate &dd, QObject *parent)
: QAbstractAspect(dd, parent)
{
+ Q_D(QInputAspect);
setObjectName(QStringLiteral("Input Aspect"));
qRegisterMetaType<Qt3DInput::QAbstractPhysicalDevice*>();
- registerBackendType<QKeyboardDevice>(QBackendNodeMapperPtr(new Input::KeyboardDeviceFunctor(this, d_func()->m_inputHandler.data())));
- registerBackendType<QKeyboardHandler>(QBackendNodeMapperPtr(new Input::KeyboardHandlerFunctor(d_func()->m_inputHandler.data())));
- registerBackendType<QMouseDevice>(QBackendNodeMapperPtr(new Input::MouseDeviceFunctor(this, d_func()->m_inputHandler.data())));
- registerBackendType<QMouseHandler>(QBackendNodeMapperPtr(new Input::MouseHandlerFunctor(d_func()->m_inputHandler.data())));
- registerBackendType<QAxis>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::Axis, Input::AxisManager>(d_func()->m_inputHandler->axisManager())));
- registerBackendType<QAxisAccumulator>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AxisAccumulator, Input::AxisAccumulatorManager>(d_func()->m_inputHandler->axisAccumulatorManager())));
- registerBackendType<QAnalogAxisInput>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AnalogAxisInput, Input::AnalogAxisInputManager>(d_func()->m_inputHandler->analogAxisInputManager())));
- registerBackendType<QButtonAxisInput>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::ButtonAxisInput, Input::ButtonAxisInputManager>(d_func()->m_inputHandler->buttonAxisInputManager())));
- registerBackendType<QAxisSetting>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AxisSetting, Input::AxisSettingManager>(d_func()->m_inputHandler->axisSettingManager())));
- registerBackendType<Qt3DInput::QAction>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::Action, Input::ActionManager>(d_func()->m_inputHandler->actionManager())));
- registerBackendType<QActionInput>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::ActionInput, Input::ActionInputManager>(d_func()->m_inputHandler->actionInputManager())));
- registerBackendType<QInputChord>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::InputChord, Input::InputChordManager>(d_func()->m_inputHandler->inputChordManager())));
- registerBackendType<QInputSequence>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::InputSequence, Input::InputSequenceManager>(d_func()->m_inputHandler->inputSequenceManager())));
- registerBackendType<QLogicalDevice>(QBackendNodeMapperPtr(new Input::LogicalDeviceNodeFunctor(d_func()->m_inputHandler->logicalDeviceManager())));
- registerBackendType<QGenericInputDevice>(QBackendNodeMapperPtr(new Input::GenericDeviceBackendFunctor(this, d_func()->m_inputHandler.data())));
- registerBackendType<QInputSettings>(QBackendNodeMapperPtr(new Input::InputSettingsFunctor(d_func()->m_inputHandler.data())));
- registerBackendType<QAbstractPhysicalDeviceProxy>(QBackendNodeMapperPtr(new Input::PhysicalDeviceProxyNodeFunctor(d_func()->m_inputHandler->physicalDeviceProxyManager())));
+ d->registerBackendType<QKeyboardDevice, true>(QBackendNodeMapperPtr(new Input::KeyboardDeviceFunctor(this, d_func()->m_inputHandler.data())));
+ d->registerBackendType<QKeyboardHandler, true>(QBackendNodeMapperPtr(new Input::KeyboardHandlerFunctor(d_func()->m_inputHandler.data())));
+ d->registerBackendType<QMouseDevice, true>(QBackendNodeMapperPtr(new Input::MouseDeviceFunctor(this, d_func()->m_inputHandler.data())));
+ d->registerBackendType<QMouseHandler, true>(QBackendNodeMapperPtr(new Input::MouseHandlerFunctor(d_func()->m_inputHandler.data())));
+ d->registerBackendType<QAxis, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::Axis, Input::AxisManager>(d_func()->m_inputHandler->axisManager())));
+ d->registerBackendType<QAxisAccumulator, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AxisAccumulator, Input::AxisAccumulatorManager>(d_func()->m_inputHandler->axisAccumulatorManager())));
+ d->registerBackendType<QAnalogAxisInput, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AnalogAxisInput, Input::AnalogAxisInputManager>(d_func()->m_inputHandler->analogAxisInputManager())));
+ d->registerBackendType<QButtonAxisInput, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::ButtonAxisInput, Input::ButtonAxisInputManager>(d_func()->m_inputHandler->buttonAxisInputManager())));
+ d->registerBackendType<QAxisSetting, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AxisSetting, Input::AxisSettingManager>(d_func()->m_inputHandler->axisSettingManager())));
+ d->registerBackendType<Qt3DInput::QAction, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::Action, Input::ActionManager>(d_func()->m_inputHandler->actionManager())));
+ d->registerBackendType<QActionInput, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::ActionInput, Input::ActionInputManager>(d_func()->m_inputHandler->actionInputManager())));
+ d->registerBackendType<QInputChord, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::InputChord, Input::InputChordManager>(d_func()->m_inputHandler->inputChordManager())));
+ d->registerBackendType<QInputSequence, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::InputSequence, Input::InputSequenceManager>(d_func()->m_inputHandler->inputSequenceManager())));
+ d->registerBackendType<QLogicalDevice, true>(QBackendNodeMapperPtr(new Input::LogicalDeviceNodeFunctor(d_func()->m_inputHandler->logicalDeviceManager())));
+ d->registerBackendType<QGenericInputDevice, true>(QBackendNodeMapperPtr(new Input::GenericDeviceBackendFunctor(this, d_func()->m_inputHandler.data())));
+ d->registerBackendType<QInputSettings, true>(QBackendNodeMapperPtr(new Input::InputSettingsFunctor(d_func()->m_inputHandler.data())));
+ d->registerBackendType<QAbstractPhysicalDeviceProxy, true>(QBackendNodeMapperPtr(new Input::PhysicalDeviceProxyNodeFunctor(d_func()->m_inputHandler->physicalDeviceProxyManager())));
#ifdef HAVE_QGAMEPAD
- registerBackendType<QGamepadInput>(QBackendNodeMapperPtr(new Input::GenericDeviceBackendFunctor(this, d_func()->m_inputHandler.data())));
+ d->registerBackendType<QGamepadInput, true>(QBackendNodeMapperPtr(new Input::GenericDeviceBackendFunctor(this, d_func()->m_inputHandler.data())));
#endif
- Q_D(QInputAspect);
// Plugins are QInputDeviceIntegration instances
d->loadInputDevicePlugins();
diff --git a/src/input/frontend/qinputaspect_p.h b/src/input/frontend/qinputaspect_p.h
index bcdd8d4ed..aee7e7909 100644
--- a/src/input/frontend/qinputaspect_p.h
+++ b/src/input/frontend/qinputaspect_p.h
@@ -69,6 +69,7 @@ class QInputAspectPrivate : public Qt3DCore::QAbstractAspectPrivate
public:
QInputAspectPrivate();
void loadInputDevicePlugins();
+ void syncDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QBackendNode *backend, bool firstTime) const override;
Q_DECLARE_PUBLIC(QInputAspect)
QScopedPointer<Input::InputHandler> m_inputHandler;
diff --git a/src/input/frontend/qinputchord.cpp b/src/input/frontend/qinputchord.cpp
index 7c986f297..0c4d15190 100644
--- a/src/input/frontend/qinputchord.cpp
+++ b/src/input/frontend/qinputchord.cpp
@@ -41,9 +41,6 @@
#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -157,11 +154,7 @@ void QInputChord::addChord(QAbstractActionInput *input)
if (!input->parent())
input->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), input);
- change->setPropertyName("chord");
- d->notifyObservers(change);
- }
+ d->updateNode(input, "input", Qt3DCore::PropertyValueAdded);
}
}
@@ -174,12 +167,7 @@ void QInputChord::removeChord(QAbstractActionInput *input)
{
Q_D(QInputChord);
if (d->m_chords.contains(input)) {
-
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), input);
- change->setPropertyName("chord");
- d->notifyObservers(change);
- }
+ d->updateNode(input, "input", Qt3DCore::PropertyValueRemoved);
d->m_chords.removeOne(input);
diff --git a/src/input/frontend/qinputsequence.cpp b/src/input/frontend/qinputsequence.cpp
index 766674840..d59ebc0f3 100644
--- a/src/input/frontend/qinputsequence.cpp
+++ b/src/input/frontend/qinputsequence.cpp
@@ -42,9 +42,6 @@
#include <Qt3DInput/qabstractactioninput.h>
#include <Qt3DInput/qabstractphysicaldevice.h>
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
@@ -210,11 +207,7 @@ void QInputSequence::addSequence(QAbstractActionInput *input)
if (!input->parent())
input->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), input);
- change->setPropertyName("sequence");
- d->notifyObservers(change);
- }
+ d->updateNode(input, "input", Qt3DCore::PropertyValueAdded);
}
}
@@ -227,11 +220,7 @@ void QInputSequence::removeSequence(QAbstractActionInput *input)
{
Q_D(QInputSequence);
if (d->m_sequences.contains(input)) {
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), input);
- change->setPropertyName("sequence");
- d->notifyObservers(change);
- }
+ d->updateNode(input, "input", Qt3DCore::PropertyValueRemoved);
d->m_sequences.removeOne(input);
diff --git a/src/input/frontend/qkeyboarddevice.cpp b/src/input/frontend/qkeyboarddevice.cpp
index 257a5be8c..1ec1f8ead 100644
--- a/src/input/frontend/qkeyboarddevice.cpp
+++ b/src/input/frontend/qkeyboarddevice.cpp
@@ -41,7 +41,6 @@
#include "qkeyboarddevice_p.h"
#include <Qt3DInput/qkeyboardhandler.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qscene_p.h>
@@ -310,16 +309,11 @@ QKeyboardDevice::QKeyboardDevice(QKeyboardDevicePrivate &dd, QNode *parent)
{
}
-/*! \internal */
-void QKeyboardDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QKeyboardDevice::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- Q_D(QKeyboardDevice);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated && e->propertyName() == QByteArrayLiteral("activeInput")) {
- Qt3DCore::QNodeId activeInputId = e->value().value<Qt3DCore::QNodeId>();
- setActiveInput(qobject_cast<QKeyboardHandler *>(d->scene()->lookupNode(activeInputId)));
- }
}
+
/*!
* Set the active input to \a activeInput
*/
diff --git a/src/input/frontend/qkeyboarddevice.h b/src/input/frontend/qkeyboarddevice.h
index c3478ec27..df2f47020 100644
--- a/src/input/frontend/qkeyboarddevice.h
+++ b/src/input/frontend/qkeyboarddevice.h
@@ -71,6 +71,7 @@ public:
protected:
explicit QKeyboardDevice(QKeyboardDevicePrivate &dd, QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
Q_SIGNALS:
diff --git a/src/input/frontend/qkeyboardhandler.cpp b/src/input/frontend/qkeyboardhandler.cpp
index 485959bcd..92ce39c31 100644
--- a/src/input/frontend/qkeyboardhandler.cpp
+++ b/src/input/frontend/qkeyboardhandler.cpp
@@ -41,7 +41,6 @@
#include "qkeyboardhandler_p.h"
#include <Qt3DInput/qkeyboarddevice.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -170,23 +169,6 @@ QKeyboardHandler::~QKeyboardHandler()
{
}
-/*! \internal */
-void QKeyboardHandler::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QKeyboardHandler);
- QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change);
- if (e->type() == PropertyUpdated) {
- if (e->propertyName() == QByteArrayLiteral("focus")) {
- bool block = blockNotifications(true);
- setFocus(e->value().toBool());
- blockNotifications(block);
- } else if (e->propertyName() == QByteArrayLiteral("event")) {
- QKeyEventPtr ev = e->value().value<QKeyEventPtr>();
- d->keyEvent(ev.data());
- }
- }
-}
-
/*!
\qmlproperty KeyboardDevice Qt3D.Input::KeyboardHandler::sourceDevice
*/
@@ -255,6 +237,11 @@ void QKeyboardHandler::setFocus(bool focus)
}
}
+// TODO Unused remove in Qt6
+void QKeyboardHandler::sceneChangeEvent(const QSceneChangePtr &)
+{
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QKeyboardHandler::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QKeyboardHandlerData>::create(this);
diff --git a/src/input/frontend/qkeyboardhandler.h b/src/input/frontend/qkeyboardhandler.h
index 056d7c7a4..b4425de72 100644
--- a/src/input/frontend/qkeyboardhandler.h
+++ b/src/input/frontend/qkeyboardhandler.h
@@ -116,6 +116,7 @@ Q_SIGNALS:
void released(Qt3DInput::QKeyEvent *event);
protected:
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/input/frontend/qkeyevent.cpp b/src/input/frontend/qkeyevent.cpp
index a70a2970b..efbddc771 100644
--- a/src/input/frontend/qkeyevent.cpp
+++ b/src/input/frontend/qkeyevent.cpp
@@ -160,7 +160,7 @@ QKeyEvent::~QKeyEvent()
/*!
\qmlmethod bool Qt3D.Input::KeyEvent::matches(StandardKey key)
- Returns \c true if the key event matches the given standard key; otherwise
+ Returns \c true if the key event matches the given standard \a key; otherwise
returns \c false.
\sa QKeySequence::StandardKey
@@ -174,7 +174,7 @@ QKeyEvent::~QKeyEvent()
See \l [CPP] {Qt::Key}{Qt.Key} for the list of keyboard codes.
- \sa {QKeyEvent::key}
+ \b {See also} \l [QtGui] {QKeyEvent::key()}.
*/
/*!
@@ -194,7 +194,7 @@ QKeyEvent::~QKeyEvent()
This property holds the keyboard modifier flags that existed immediately
before the event occurred.
- \sa {QKeyEvent::modifiers}
+ \b {See also} \l [QtGui] {QKeyEvent::modifiers()}.
*/
/*!
diff --git a/src/input/frontend/qlogicaldevice.cpp b/src/input/frontend/qlogicaldevice.cpp
index 1e7033962..44e04baa8 100644
--- a/src/input/frontend/qlogicaldevice.cpp
+++ b/src/input/frontend/qlogicaldevice.cpp
@@ -41,9 +41,6 @@
#include "qlogicaldevice_p.h"
#include <Qt3DCore/qnodecreatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/qaction.h>
#include <Qt3DInput/qaxis.h>
@@ -176,11 +173,7 @@ void QLogicalDevice::addAction(QAction *action)
// Ensures proper bookkeeping
d->registerDestructionHelper(action, &QLogicalDevice::removeAction, d->m_actions);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), action);
- change->setPropertyName("action");
- d->notifyObservers(change);
- }
+ d->updateNode(action, "action", Qt3DCore::PropertyValueAdded);
}
}
@@ -191,12 +184,7 @@ void QLogicalDevice::removeAction(QAction *action)
{
Q_D(QLogicalDevice);
if (d->m_actions.contains(action)) {
-
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), action);
- change->setPropertyName("action");
- d->notifyObservers(change);
- }
+ d->updateNode(action, "action", Qt3DCore::PropertyValueRemoved);
d->m_actions.removeOne(action);
@@ -236,11 +224,7 @@ void QLogicalDevice::addAxis(QAxis *axis)
// Ensures proper bookkeeping
d->registerDestructionHelper(axis, &QLogicalDevice::removeAxis, d->m_axes);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), axis);
- change->setPropertyName("axis");
- d->notifyObservers(change);
- }
+ d->updateNode(axis, "axis", Qt3DCore::PropertyValueAdded);
}
}
@@ -251,11 +235,7 @@ void QLogicalDevice::removeAxis(QAxis *axis)
{
Q_D(QLogicalDevice);
if (d->m_axes.contains(axis)) {
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), axis);
- change->setPropertyName("axis");
- d->notifyObservers(change);
- }
+ d->updateNode(axis, "axis", Qt3DCore::PropertyValueRemoved);
d->m_axes.removeOne(axis);
diff --git a/src/input/frontend/qmouseevent.cpp b/src/input/frontend/qmouseevent.cpp
index 62f7a097e..2b06c824d 100644
--- a/src/input/frontend/qmouseevent.cpp
+++ b/src/input/frontend/qmouseevent.cpp
@@ -43,6 +43,36 @@ QT_BEGIN_NAMESPACE
namespace Qt3DInput {
+namespace {
+
+template<typename EventClass, typename QtEventClass>
+typename EventClass::Modifiers modifiersForEvent(const QtEventClass &event)
+{
+ const Qt::KeyboardModifiers eventModifiers = event.modifiers();
+ int modifiers = EventClass::NoModifier;
+
+ if (eventModifiers & Qt::ShiftModifier)
+ modifiers |= EventClass::ShiftModifier;
+
+ if (eventModifiers & Qt::ControlModifier)
+ modifiers |= EventClass::ControlModifier;
+
+ if (eventModifiers & Qt::AltModifier)
+ modifiers |= EventClass::AltModifier;
+
+ if (eventModifiers & Qt::MetaModifier)
+ modifiers |= EventClass::MetaModifier;
+
+ if (eventModifiers & Qt::KeypadModifier)
+ modifiers |= EventClass::KeypadModifier;
+
+ // Abuse the int used to store an enum to store multiple
+ // modifiers into one
+ return static_cast<typename EventClass::Modifiers>(modifiers);
+}
+
+} // anonymous
+
// Notes:
// Maybe we should provide the world pos of the intersection
// The distance t along the segment line at which the intersection occurs
@@ -270,20 +300,7 @@ int QMouseEvent::buttons() const
*/
QMouseEvent::Modifiers QMouseEvent::modifiers() const
{
- switch (m_event.modifiers()) {
- case Qt::ShiftModifier:
- return QMouseEvent::ShiftModifier;
- case Qt::ControlModifier:
- return QMouseEvent::ControlModifier;
- case Qt::AltModifier:
- return QMouseEvent::AltModifier;
- case Qt::MetaModifier:
- return QMouseEvent::MetaModifier;
- case Qt::KeypadModifier:
- return QMouseEvent::KeypadModifier;
- default:
- return QMouseEvent::NoModifier;
- }
+ return modifiersForEvent<QMouseEvent, decltype(m_event)>(m_event);
}
/*!
@@ -483,20 +500,7 @@ int QWheelEvent::buttons() const
*/
QWheelEvent::Modifiers QWheelEvent::modifiers() const
{
- switch (m_event.modifiers()) {
- case Qt::ShiftModifier:
- return QWheelEvent::ShiftModifier;
- case Qt::ControlModifier:
- return QWheelEvent::ControlModifier;
- case Qt::AltModifier:
- return QWheelEvent::AltModifier;
- case Qt::MetaModifier:
- return QWheelEvent::MetaModifier;
- case Qt::KeypadModifier:
- return QWheelEvent::KeypadModifier;
- default:
- return QWheelEvent::NoModifier;
- }
+ return modifiersForEvent<QWheelEvent, decltype(m_event)>(m_event);
}
#endif // QT_CONFIG(wheelevent)
diff --git a/src/input/frontend/qmouseevent.h b/src/input/frontend/qmouseevent.h
index 24bc763dc..ae44d9365 100644
--- a/src/input/frontend/qmouseevent.h
+++ b/src/input/frontend/qmouseevent.h
@@ -79,6 +79,7 @@ public:
KeypadModifier = Qt::KeypadModifier
};
Q_ENUM(Modifiers) // LCOV_EXCL_LINE
+ // TO DO Qt6 Modifiers -> Modifier and add Q_FLAG(Modifiers)
explicit QMouseEvent(const QT_PREPEND_NAMESPACE(QMouseEvent) &e);
~QMouseEvent();
@@ -136,12 +137,13 @@ public:
KeypadModifier = Qt::KeypadModifier
};
Q_ENUM(Modifiers) // LCOV_EXCL_LINE
+ // TO DO Qt6 Modifiers -> Modifier and add Q_FLAG(Modifiers)
explicit QWheelEvent(const QT_PREPEND_NAMESPACE(QWheelEvent) &e);
~QWheelEvent();
- inline int x() const { return m_event.x(); }
- inline int y() const { return m_event.y(); }
+ inline int x() const { return int(m_event.position().x()); }
+ inline int y() const { return int(m_event.position().y()); }
inline QPoint angleDelta() const { return m_event.angleDelta(); }
int buttons() const;
Modifiers modifiers() const;
diff --git a/src/input/frontend/qmousehandler.cpp b/src/input/frontend/qmousehandler.cpp
index c36ac50f1..89d76a057 100644
--- a/src/input/frontend/qmousehandler.cpp
+++ b/src/input/frontend/qmousehandler.cpp
@@ -42,7 +42,6 @@
#include <Qt3DInput/qmousedevice.h>
#include <Qt3DInput/qmouseevent.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtCore/QTimer>
QT_BEGIN_NAMESPACE
@@ -198,21 +197,21 @@ void QMouseHandlerPrivate::mouseEvent(const QMouseEventPtr &event)
\qmlsignal Qt3D.Input::MouseHandler::wheel(MouseEvent mouse)
This signal is emitted when the mouse wheel is used with the event details
- being contained within \a wheel
+ being contained within \a mouse.
*/
/*!
\fn Qt3DInput::QMouseHandler::clicked(Qt3DInput::QMouseEvent *mouse)
This signal is emitted when a mouse button is clicked with the event details
- being contained within \a mouse
+ being contained within \a mouse.
*/
/*!
\fn Qt3DInput::QMouseHandler::doubleClicked(Qt3DInput::QMouseEvent *mouse)
This signal is emitted when a mouse button is double clicked with the event
- details being contained within \a mouse
+ details being contained within \a mouse.
*/
/*!
@@ -299,6 +298,11 @@ void QMouseHandler::setSourceDevice(QMouseDevice *mouseDevice)
}
}
+// TODO Unused remove in Qt6
+void QMouseHandler::sceneChangeEvent(const QSceneChangePtr &)
+{
+}
+
/*!
* \property Qt3DInput::QMouseHandler::sourceDevice
*
@@ -335,24 +339,6 @@ void QMouseHandler::setContainsMouse(bool contains)
}
}
-/*! \internal */
-void QMouseHandler::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QMouseHandler);
- QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change);
- if (e->type() == PropertyUpdated) {
- if (e->propertyName() == QByteArrayLiteral("mouse")) {
- QMouseEventPtr ev = e->value().value<QMouseEventPtr>();
- d->mouseEvent(ev);
-#if QT_CONFIG(wheelevent)
- } else if (e->propertyName() == QByteArrayLiteral("wheel")) {
- QWheelEventPtr ev = e->value().value<QWheelEventPtr>();
- emit wheel(ev.data());
-#endif
- }
- }
-}
-
Qt3DCore::QNodeCreatedChangeBasePtr QMouseHandler::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QMouseHandlerData>::create(this);
diff --git a/src/input/frontend/qmousehandler.h b/src/input/frontend/qmousehandler.h
index aec450cb9..d95dbf4c3 100644
--- a/src/input/frontend/qmousehandler.h
+++ b/src/input/frontend/qmousehandler.h
@@ -87,6 +87,7 @@ Q_SIGNALS:
#endif
protected:
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
void setContainsMouse(bool contains);
diff --git a/src/input/frontend/qphysicaldevicecreatedchange.cpp b/src/input/frontend/qphysicaldevicecreatedchange.cpp
index c14770d80..905633b7f 100644
--- a/src/input/frontend/qphysicaldevicecreatedchange.cpp
+++ b/src/input/frontend/qphysicaldevicecreatedchange.cpp
@@ -54,7 +54,7 @@ QPhysicalDeviceCreatedChangeBasePrivate::QPhysicalDeviceCreatedChangeBasePrivate
}
/*!
- \class QPhysicalDeviceCreatedChangeBase
+ \class Qt3DInput::QPhysicalDeviceCreatedChangeBase
\inmodule Qt3DInput
\brief Base class for handling changes in physical devices.
*/
diff --git a/src/input/input.pro b/src/input/input.pro
index 73a571c9f..938e77643 100644
--- a/src/input/input.pro
+++ b/src/input/input.pro
@@ -5,9 +5,6 @@ DEFINES += QT3DINPUT_LIBRARY
MODULE = 3dinput
MODULE_PLUGIN_TYPES = 3dinputdevices
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
QT += core-private 3dcore-private
include(frontend/frontend.pri)
diff --git a/src/logic/executor.cpp b/src/logic/executor.cpp
index 6134e801e..1c428db47 100644
--- a/src/logic/executor.cpp
+++ b/src/logic/executor.cpp
@@ -64,8 +64,6 @@ void Executor::clearQueueAndProceed()
// If the semaphore is acquired, release it to allow the logic job and hence the
// manager and frame to complete and shutdown to continue.
m_nodeIds.clear();
- if (m_semaphore->available() == 0)
- m_semaphore->release();
}
void Executor::enqueueLogicFrameUpdates(const QVector<Qt3DCore::QNodeId> &nodeIds)
@@ -92,16 +90,12 @@ bool Executor::event(QEvent *e)
void Executor::processLogicFrameUpdates(float dt)
{
Q_ASSERT(m_scene);
- Q_ASSERT(m_semaphore);
const QVector<QNode *> nodes = m_scene->lookupNodes(m_nodeIds);
for (QNode *node : nodes) {
QFrameAction *frameAction = qobject_cast<QFrameAction *>(node);
if (frameAction && frameAction->isEnabled())
frameAction->onTriggered(dt);
}
-
- // Release the semaphore so the calling Manager can continue
- m_semaphore->release();
}
} // namespace Logic
diff --git a/src/logic/executor_p.h b/src/logic/executor_p.h
index e33ff842e..27b9c60c8 100644
--- a/src/logic/executor_p.h
+++ b/src/logic/executor_p.h
@@ -87,7 +87,6 @@ public:
explicit Executor(QObject *parent = 0);
void setScene(Qt3DCore::QScene *scene) { m_scene = scene; }
- void setSemephore(QSemaphore *semaphore) { m_semaphore = semaphore; }
void clearQueueAndProceed();
public Q_SLOTS:
@@ -100,7 +99,6 @@ protected:
private:
QVector<Qt3DCore::QNodeId> m_nodeIds;
Qt3DCore::QScene *m_scene;
- QSemaphore *m_semaphore;
};
} // namespace Logic
diff --git a/src/logic/logic.pro b/src/logic/logic.pro
index 584b9af4b..0fa0f8d55 100644
--- a/src/logic/logic.pro
+++ b/src/logic/logic.pro
@@ -3,9 +3,6 @@ MODULE = 3dlogic
QT = core-private gui-private 3dcore 3dcore-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/logic/manager.cpp b/src/logic/manager.cpp
index e10ace592..db90e6ad9 100644
--- a/src/logic/manager.cpp
+++ b/src/logic/manager.cpp
@@ -56,10 +56,10 @@ namespace Logic {
Manager::Manager()
: m_logicHandlerManager(new HandlerManager)
- , m_semaphore(1)
+ , m_logicAspect(nullptr)
+ , m_executor(nullptr)
, m_dt(0.0f)
{
- m_semaphore.acquire();
}
Manager::~Manager()
@@ -69,8 +69,6 @@ Manager::~Manager()
void Manager::setExecutor(Executor *executor)
{
m_executor = executor;
- if (m_executor)
- m_executor->setSemephore(&m_semaphore);
}
void Manager::appendHandler(Handler *handler)
@@ -93,6 +91,7 @@ bool Manager::hasFrameActions() const
return m_logicHandlers.count() > 0;
}
+// Called from Job Thread
void Manager::triggerLogicFrameUpdates()
{
Q_ASSERT(m_executor);
@@ -107,7 +106,6 @@ void Manager::triggerLogicFrameUpdates()
// release the semaphore when it has completed its work.
m_executor->enqueueLogicFrameUpdates(m_logicComponentIds);
qApp->postEvent(m_executor, new FrameUpdateEvent(m_dt));
- m_semaphore.acquire();
}
} // namespace Logic
diff --git a/src/logic/manager_p.h b/src/logic/manager_p.h
index 918bd57e0..e4fa08a47 100644
--- a/src/logic/manager_p.h
+++ b/src/logic/manager_p.h
@@ -95,7 +95,6 @@ private:
QVector<Qt3DCore::QNodeId> m_logicComponentIds;
QLogicAspect *m_logicAspect;
Executor *m_executor;
- QSemaphore m_semaphore;
float m_dt;
};
diff --git a/src/plugins/geometryloaders/default/default.pro b/src/plugins/geometryloaders/default/default.pro
index 6b5ae8f27..c126b5844 100644
--- a/src/plugins/geometryloaders/default/default.pro
+++ b/src/plugins/geometryloaders/default/default.pro
@@ -1,9 +1,6 @@
TARGET = defaultgeometryloader
QT += core-private 3dcore 3dcore-private 3drender 3drender-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
basegeometryloader_p.h \
diff --git a/src/plugins/geometryloaders/fbx/fbx.pro b/src/plugins/geometryloaders/fbx/fbx.pro
index a35035fad..a9c17d4e7 100644
--- a/src/plugins/geometryloaders/fbx/fbx.pro
+++ b/src/plugins/geometryloaders/fbx/fbx.pro
@@ -1,9 +1,6 @@
TARGET = fbxgeometryloader
QT += core-private 3dcore 3dcore-private 3drender 3drender-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
fbxgeometryloader.h \
diff --git a/src/plugins/geometryloaders/gltf/gltf.pro b/src/plugins/geometryloaders/gltf/gltf.pro
index da805fae1..815226b4e 100644
--- a/src/plugins/geometryloaders/gltf/gltf.pro
+++ b/src/plugins/geometryloaders/gltf/gltf.pro
@@ -1,9 +1,6 @@
TARGET = gltfgeometryloader
QT += core-private 3dcore 3dcore-private 3drender 3drender-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
gltfgeometryloader.h \
diff --git a/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp b/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp
index ddb950f86..ab783102d 100644
--- a/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp
+++ b/src/plugins/geometryloaders/gltf/gltfgeometryloader.cpp
@@ -139,7 +139,8 @@ GLTFGeometryLoader::BufferData::BufferData(const QJsonObject &json)
}
GLTFGeometryLoader::AccessorData::AccessorData()
- : type(QAttribute::Float)
+ : bufferViewIndex(0)
+ , type(QAttribute::Float)
, dataSize(0)
, count(0)
, offset(0)
diff --git a/src/plugins/renderplugins/scene2d/scene2d.pro b/src/plugins/renderplugins/scene2d/scene2d.pro
index 4f7ae6ea9..2cb07756b 100644
--- a/src/plugins/renderplugins/scene2d/scene2d.pro
+++ b/src/plugins/renderplugins/scene2d/scene2d.pro
@@ -1,9 +1,6 @@
TARGET = scene2d
QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dextras 3dquickscene2d 3dquickscene2d-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
scene2dplugin.h
diff --git a/src/plugins/renderplugins/scene2d/scene2dplugin.cpp b/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
index eeb6b5346..dfb6c8f2b 100644
--- a/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
+++ b/src/plugins/renderplugins/scene2d/scene2dplugin.cpp
@@ -96,7 +96,7 @@ bool Scene2DPlugin::registerBackendTypes(QRenderAspect *aspect,
{
registerBackendType(aspect, Qt3DRender::Quick::QScene2D::staticMetaObject,
QSharedPointer<Scene2DBackendNodeMapper<Render::Quick::Scene2D> >
- ::create(renderer, m_scene2dNodeManager));
+ ::create(renderer, m_scene2dNodeManager), true);
return true;
}
bool Scene2DPlugin::unregisterBackendTypes(QRenderAspect *aspect)
diff --git a/src/plugins/sceneparsers/assimp/assimp.pro b/src/plugins/sceneparsers/assimp/assimp.pro
index 28abef2b8..f761db12e 100644
--- a/src/plugins/sceneparsers/assimp/assimp.pro
+++ b/src/plugins/sceneparsers/assimp/assimp.pro
@@ -3,9 +3,6 @@ QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dextras 3dan
include(../../../3rdparty/assimp/assimp_dependency.pri)
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
assimphelpers.h \
assimpimporter.h
diff --git a/src/plugins/sceneparsers/assimp/assimphelpers.cpp b/src/plugins/sceneparsers/assimp/assimphelpers.cpp
index ce6619541..77209a7a9 100644
--- a/src/plugins/sceneparsers/assimp/assimphelpers.cpp
+++ b/src/plugins/sceneparsers/assimp/assimphelpers.cpp
@@ -157,29 +157,29 @@ void AssimpIOStream::Flush()
*
*/
-/*!
- * Builds a new instance of AssimpIOSystem.
- */
-AssimpIOSystem::AssimpIOSystem() :
- Assimp::IOSystem()
-{
- m_openModeMaps[QByteArrayLiteral("r")] = QIODevice::ReadOnly;
- m_openModeMaps[QByteArrayLiteral("r+")] = QIODevice::ReadWrite;
- m_openModeMaps[QByteArrayLiteral("w")] = QIODevice::WriteOnly | QIODevice::Truncate;
- m_openModeMaps[QByteArrayLiteral("w+")] = QIODevice::ReadWrite | QIODevice::Truncate;
- m_openModeMaps[QByteArrayLiteral("a")] = QIODevice::WriteOnly | QIODevice::Append;
- m_openModeMaps[QByteArrayLiteral("a+")] = QIODevice::ReadWrite | QIODevice::Append;
- m_openModeMaps[QByteArrayLiteral("wb")] = QIODevice::WriteOnly;
- m_openModeMaps[QByteArrayLiteral("wt")] = QIODevice::WriteOnly | QIODevice::Text;
- m_openModeMaps[QByteArrayLiteral("rb")] = QIODevice::ReadOnly;
- m_openModeMaps[QByteArrayLiteral("rt")] = QIODevice::ReadOnly | QIODevice::Text;
-}
-
-/*!
- * Clears an AssimpIOSystem instance before deletion.
- */
-AssimpIOSystem::~AssimpIOSystem()
+static QIODevice::OpenMode openModeFromText(const char *name) noexcept
{
+ static const struct OpenModeMapping {
+ char name[2];
+ ushort mode;
+ } openModeMapping[] = {
+ { { 'r', 0 }, QIODevice::ReadOnly },
+ { { 'r', '+' }, QIODevice::ReadWrite },
+ { { 'w', 0 }, QIODevice::WriteOnly | QIODevice::Truncate },
+ { { 'w', '+' }, QIODevice::ReadWrite | QIODevice::Truncate },
+ { { 'a', 0 }, QIODevice::WriteOnly | QIODevice::Append },
+ { { 'a', '+' }, QIODevice::ReadWrite | QIODevice::Append },
+ { { 'w', 'b' }, QIODevice::WriteOnly },
+ { { 'w', 't' }, QIODevice::WriteOnly | QIODevice::Text },
+ { { 'r', 'b' }, QIODevice::ReadOnly },
+ { { 'r', 't' }, QIODevice::ReadOnly | QIODevice::Text },
+ };
+
+ for (auto e : openModeMapping) {
+ if (qstrncmp(e.name, name, sizeof(OpenModeMapping::name)) == 0)
+ return static_cast<QIODevice::OpenMode>(e.mode);
+ }
+ return QIODevice::NotOpen;
}
/*!
@@ -205,14 +205,13 @@ char AssimpIOSystem::getOsSeparator() const
Assimp::IOStream *AssimpIOSystem::Open(const char *pFile, const char *pMode)
{
const QString fileName(QString::fromUtf8(pFile));
- const QByteArray cleanedMode(QByteArray(pMode).trimmed());
-
- const QIODevice::OpenMode openMode = m_openModeMaps.value(cleanedMode, QIODevice::NotOpen);
-
- QScopedPointer<QFile> file(new QFile(fileName));
- if (file->open(openMode))
- return new AssimpIOStream(file.take());
+ const QLatin1String cleanedMode = QLatin1String{pMode}.trimmed();
+ if (const QIODevice::OpenMode openMode = openModeFromText(cleanedMode.data())) {
+ QScopedPointer<QFile> file(new QFile(fileName));
+ if (file->open(openMode))
+ return new AssimpIOStream(file.take());
+ }
return nullptr;
}
diff --git a/src/plugins/sceneparsers/assimp/assimphelpers.h b/src/plugins/sceneparsers/assimp/assimphelpers.h
index 0db22ce7b..fd102213c 100644
--- a/src/plugins/sceneparsers/assimp/assimphelpers.h
+++ b/src/plugins/sceneparsers/assimp/assimphelpers.h
@@ -55,7 +55,6 @@
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include <QtCore/QIODevice>
-#include <QtCore/QMap>
QT_BEGIN_NAMESPACE
@@ -84,15 +83,10 @@ private:
class AssimpIOSystem : public Assimp::IOSystem
{
public :
- AssimpIOSystem();
- ~AssimpIOSystem();
bool Exists(const char *pFile) const override;
char getOsSeparator() const override;
Assimp::IOStream *Open(const char *pFile, const char *pMode) override;
void Close(Assimp::IOStream *pFile) override;
-
-private:
- QMap<QByteArray, QIODevice::OpenMode> m_openModeMaps;
};
} // namespace AssimpHelper
diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.h b/src/plugins/sceneparsers/assimp/assimpimporter.h
index 9a020b3e3..9d6bd73de 100644
--- a/src/plugins/sceneparsers/assimp/assimpimporter.h
+++ b/src/plugins/sceneparsers/assimp/assimpimporter.h
@@ -57,7 +57,6 @@
#include <assimp/postprocess.h>
#include <assimp/DefaultLogger.hpp>
-#include <QtCore/QMap>
#include <QtCore/QDir>
#include <QtCore/QLoggingCategory>
#include <QtCore/QVector>
@@ -139,7 +138,6 @@ private:
Assimp::Importer *m_importer;
mutable const aiScene *m_aiScene;
- QMap<uint, QAbstractTexture *> m_embeddedTextures;
QHash<aiTextureType, QString> m_textureToParameterName;
QVector<Qt3DAnimation::QKeyframeAnimation *> m_animations;
QVector<Qt3DAnimation::QMorphingAnimation *> m_morphAnimations;
diff --git a/src/plugins/sceneparsers/gltf/gltf.pro b/src/plugins/sceneparsers/gltf/gltf.pro
index 0005bb727..8f0cc2fe0 100644
--- a/src/plugins/sceneparsers/gltf/gltf.pro
+++ b/src/plugins/sceneparsers/gltf/gltf.pro
@@ -1,9 +1,6 @@
TARGET = gltfsceneimport
QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dextras
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
gltfimporter.h
diff --git a/src/plugins/sceneparsers/gltf/gltfimporter.cpp b/src/plugins/sceneparsers/gltf/gltfimporter.cpp
index 79f2bf2d3..a10a83cca 100644
--- a/src/plugins/sceneparsers/gltf/gltfimporter.cpp
+++ b/src/plugins/sceneparsers/gltf/gltfimporter.cpp
@@ -64,6 +64,7 @@
#include <Qt3DRender/qmultisampleantialiasing.h>
#include <Qt3DRender/qpointsize.h>
#include <Qt3DRender/qnodepthmask.h>
+#include <Qt3DRender/qdepthrange.h>
#include <Qt3DRender/qdepthtest.h>
#include <Qt3DRender/qseamlesscubemap.h>
#include <Qt3DRender/qstencilmask.h>
@@ -1513,16 +1514,6 @@ void GLTFImporter::processJSONBufferView(const QString &id, const QJsonObject& j
} else {
target = targetValue.toInt();
}
- Qt3DRender::QBuffer::BufferType ty(Qt3DRender::QBuffer::VertexBuffer);
-
- switch (target) {
- case GL_ARRAY_BUFFER: ty = Qt3DRender::QBuffer::VertexBuffer; break;
- case GL_ELEMENT_ARRAY_BUFFER: ty = Qt3DRender::QBuffer::IndexBuffer; break;
- default:
- qCWarning(GLTFImporterLog, "buffer %ls unsupported target: %d",
- qUtf16PrintableImpl(id), target);
- return;
- }
quint64 offset = 0;
const auto byteOffset = json.value(KEY_BYTE_OFFSET);
@@ -1540,7 +1531,6 @@ void GLTFImporter::processJSONBufferView(const QString &id, const QJsonObject& j
}
Qt3DRender::QBuffer *b = new Qt3DRender::QBuffer();
- b->setType(ty);
b->setData(bytes);
m_buffers[id] = b;
}
@@ -2403,9 +2393,11 @@ QRenderState* GLTFImporter::buildState(const QString& functionName, const QJsonV
}
if (functionName == QLatin1String("depthRange")) {
- //TODO: support render state depthRange
- qCWarning(GLTFImporterLog, "unsupported render state: %ls", qUtf16PrintableImpl(functionName));
- return nullptr;
+ type = GL_DEPTH_RANGE;
+ QDepthRange *depthRange = new QDepthRange;
+ depthRange->setNearValue(values.at(0).toDouble(0.0));
+ depthRange->setFarValue(values.at(1).toDouble(1.0));
+ return depthRange;
}
if (functionName == QLatin1String("frontFace")) {
diff --git a/src/plugins/sceneparsers/gltf/gltfparser.cpp b/src/plugins/sceneparsers/gltf/gltfparser.cpp
deleted file mode 100644
index 881e7f1b2..000000000
--- a/src/plugins/sceneparsers/gltf/gltfparser.cpp
+++ /dev/null
@@ -1,1560 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "gltfparser.h"
-
-#include <QtCore/QDir>
-#include <QtCore/QFileInfo>
-#include <QtCore/QJsonArray>
-#include <QtCore/QJsonObject>
-
-#include <QtGui/QVector2D>
-
-#include <Qt3DCore/QCameraLens>
-#include <Qt3DCore/QEntity>
-#include <Qt3DCore/QTransform>
-
-#include <Qt3DRender/private/qurlhelper_p.h>
-
-#include <Qt3DRender/QAlphaCoverage>
-#include <Qt3DRender/QBlendEquation>
-#include <Qt3DRender/QBlendStateSeparate>
-#include <Qt3DRender/QColorMask>
-#include <Qt3DRender/QCullFace>
-#include <Qt3DRender/QDepthMask>
-#include <Qt3DRender/QDepthTest>
-#include <Qt3DRender/QEffect>
-#include <Qt3DRender/QFrontFace>
-#include <Qt3DRender/QGeometry>
-#include <Qt3DRender/QGeometryRenderer>
-#include <Qt3DRender/QMaterial>
-#include <Qt3DRender/QGraphicsApiFilter>
-#include <Qt3DRender/QParameter>
-#include <Qt3DRender/QParameterMapping>
-#include <Qt3DRender/QPolygonOffset>
-#include <Qt3DRender/QRenderState>
-#include <Qt3DRender/QScissorTest>
-#include <Qt3DRender/QShaderProgram>
-#include <Qt3DRender/QTechnique>
-#include <Qt3DRender/QTexture>
-
-#include <Qt3DRender/QPhongMaterial>
-#include <Qt3DRender/QDiffuseMapMaterial>
-#include <Qt3DRender/QDiffuseSpecularMapMaterial>
-#include <Qt3DRender/QNormalDiffuseMapMaterial>
-#include <Qt3DRender/QNormalDiffuseSpecularMapMaterial>
-
-QT_BEGIN_NAMESPACE
-
-using namespace Qt3DCore;
-
-namespace Qt3DRender {
-
-Q_LOGGING_CATEGORY(GLTFParserLog, "Qt3D.GLTFParser")
-
-namespace {
-
-const QString KEY_CAMERA = QStringLiteral("camera");
-const QString KEY_CAMERAS = QStringLiteral("cameras");
-const QString KEY_SCENES = QStringLiteral("scenes");
-const QString KEY_NODES = QStringLiteral("nodes");
-const QString KEY_MESHES = QStringLiteral("meshes");
-const QString KEY_CHILDREN = QStringLiteral("children");
-const QString KEY_MATRIX = QStringLiteral("matrix");
-const QString KEY_ROTATION = QStringLiteral("rotation");
-const QString KEY_SCALE = QStringLiteral("scale");
-const QString KEY_TRANSLATION = QStringLiteral("translation");
-const QString KEY_TYPE = QStringLiteral("type");
-const QString KEY_PERSPECTIVE =QStringLiteral("perspective");
-const QString KEY_NAME = QStringLiteral("name");
-const QString KEY_COUNT = QStringLiteral("count");
-const QString KEY_YFOV = QStringLiteral("yfov");
-const QString KEY_ZNEAR = QStringLiteral("znear");
-const QString KEY_ZFAR = QStringLiteral("zfar");
-const QString KEY_MATERIALS = QStringLiteral("materials");
-const QString KEY_EXTENSIONS = QStringLiteral("extensions");
-const QString KEY_COMMON_MAT = QStringLiteral("KHR_materials_common");
-const QString KEY_TECHNIQUE = QStringLiteral("technique");
-const QString KEY_VALUES = QStringLiteral("values");
-const QString KEY_BUFFERS = QStringLiteral("buffers");
-const QString KEY_SHADERS = QStringLiteral("shaders");
-const QString KEY_PROGRAMS = QStringLiteral("programs");
-const QString KEY_PROGRAM = QStringLiteral("program");
-const QString KEY_TECHNIQUES = QStringLiteral("techniques");
-const QString KEY_ACCESSORS = QStringLiteral("accessors");
-const QString KEY_IMAGES = QStringLiteral("images");
-const QString KEY_TEXTURES = QStringLiteral("textures");
-const QString KEY_SCENE = QStringLiteral("scene");
-const QString KEY_BUFFER = QStringLiteral("buffer");
-const QString KEY_TARGET = QStringLiteral("target");
-const QString KEY_BYTE_OFFSET = QStringLiteral("byteOffset");
-const QString KEY_BYTE_LENGTH = QStringLiteral("byteLength");
-const QString KEY_BYTE_STRIDE = QStringLiteral("byteStride");
-const QString KEY_PRIMITIVES = QStringLiteral("primitives");
-const QString KEY_MODE = QStringLiteral("mode");
-const QString KEY_MATERIAL = QStringLiteral("material");
-const QString KEY_ATTRIBUTES = QStringLiteral("attributes");
-const QString KEY_INDICES = QStringLiteral("indices");
-const QString KEY_URI = QStringLiteral("uri");
-const QString KEY_FORMAT = QStringLiteral("format");
-const QString KEY_PASSES = QStringLiteral("passes");
-const QString KEY_SOURCE = QStringLiteral("source");
-const QString KEY_SAMPLER = QStringLiteral("sampler");
-const QString KEY_SAMPLERS = QStringLiteral("samplers");
-const QString KEY_SEMANTIC = QStringLiteral("semantic");
-const QString KEY_STATES = QStringLiteral("states");
-const QString KEY_UNIFORMS = QStringLiteral("uniforms");
-const QString KEY_PARAMETERS = QStringLiteral("parameters");
-const QString KEY_WRAP_S = QStringLiteral("wrapS");
-const QString KEY_MIN_FILTER = QStringLiteral("minFilter");
-const QString KEY_MAG_FILTER = QStringLiteral("magFilter");
-
-const QString KEY_INSTANCE_TECHNIQUE = QStringLiteral("instanceTechnique");
-const QString KEY_INSTANCE_PROGRAM = QStringLiteral("instanceProgram");
-const QString KEY_BUFFER_VIEWS = QStringLiteral("bufferViews");
-const QString KEY_BUFFER_VIEW = QStringLiteral("bufferView");
-const QString KEY_VERTEX_SHADER = QStringLiteral("vertexShader");
-const QString KEY_FRAGMENT_SHADER = QStringLiteral("fragmentShader");
-const QString KEY_INTERNAL_FORMAT = QStringLiteral("internalFormat");
-const QString KEY_COMPONENT_TYPE = QStringLiteral("componentType");
-const QString KEY_ASPECT_RATIO = QStringLiteral("aspect_ratio");
-const QString KEY_VALUE = QStringLiteral("value");
-const QString KEY_ENABLE = QStringLiteral("enable");
-const QString KEY_FUNCTIONS = QStringLiteral("functions");
-const QString KEY_TECHNIQUE_CORE = QStringLiteral("techniqueCore");
-const QString KEY_TECHNIQUE_GL2 = QStringLiteral("techniqueGL2");
-
-} // of anonymous namespace
-
-GLTFParser::GLTFParser() : QAbstractSceneParser(),
- m_parseDone(false)
-{
-}
-
-GLTFParser::~GLTFParser()
-{
-
-}
-
-void GLTFParser::setBasePath(const QString& path)
-{
- m_basePath = path;
-}
-
-bool GLTFParser::setJSON(const QJsonDocument &json )
-{
- if ( !json.isObject() ) {
- return false;
- }
-
- m_json = json;
- m_parseDone = false;
-
- cleanup();
-
- return true;
-}
-
-/*
- * Sets the \a path used by the parser to load the scene file.
- * If the file is valid, parsing is automatically triggered.
- */
-void GLTFParser::setSource(const QUrl &source)
-{
- const QString path = QUrlHelper::urlToLocalFileOrQrc(source);
- QFile f(path);
- if (Q_UNLIKELY(!f.open(QIODevice::ReadOnly))) {
- qCWarning(GLTFParserLog) << "cannot open " << path << ": " << f.errorString();
- return;
- }
-
- QByteArray jsonData = f.readAll();
- QJsonDocument sceneDocument = QJsonDocument::fromBinaryData(jsonData);
- if (sceneDocument.isNull())
- sceneDocument = QJsonDocument::fromJson(jsonData);
-
- if (!setJSON(sceneDocument)) {
- qCWarning(GLTFParserLog) << "not a JSON document";
- return;
- }
-
- setBasePath(QFileInfo(path).dir().absolutePath());
-}
-
-/*
- * Returns true if the extension of \a path is supported by the
- * GLTF parser.
- */
-bool GLTFParser::isExtensionSupported(const QUrl &source) const
-{
- const QString path = QUrlHelper::urlToLocalFileOrQrc(source);
- return GLTFParser::isGLTFPath(path);
-}
-
-Qt3DCore::QEntity* GLTFParser::node(const QString &id)
-{
- QJsonObject nodes = m_json.object().value(KEY_NODES).toObject();
- if (!nodes.contains(id)) {
- qCWarning(GLTFParserLog) << "unknown node" << id << "in GLTF file" << m_basePath;
- return NULL;
- }
-
- QJsonObject jsonObj = nodes.value(id).toObject();
- QEntity* result = nullptr;
-
- // Qt3D has a limitation that a QEntity can only have 1 mesh and 1 material component
- // So if the node has only 1 mesh, we only create 1 QEntity
- // Otherwise if there are n meshes, there is 1 QEntity, with n children for each mesh/material combo
- if (jsonObj.contains(KEY_MESHES)) {
- QVector<QEntity *> entities;
-
- Q_FOREACH (QJsonValue mesh, jsonObj.value(KEY_MESHES).toArray()) {
- if (!m_meshDict.contains(mesh.toString())) {
- qCWarning(GLTFParserLog) << "node" << id << "references unknown mesh" << mesh.toString();
- continue;
- }
-
- Q_FOREACH (QGeometryRenderer *geometryRenderer, m_meshDict.values(mesh.toString())) {
- QEntity *entity = new QEntity;
- entity->addComponent(geometryRenderer);
- QMaterial *mat = material(m_meshMaterialDict[geometryRenderer]);
- if (mat)
- entity->addComponent(mat);
- entities.append(entity);
- }
-
- }
-
- if (entities.count() == 1) {
- result = entities.first();
- } else {
- result = new QEntity;
- Q_FOREACH (QEntity *entity, entities) {
- entity->setParent(result);
- }
- }
- }
-
- //If the entity contains no meshes, results will still be null here
- if (result == nullptr)
- result = new QEntity;
-
- if ( jsonObj.contains(KEY_CHILDREN) ) {
- Q_FOREACH (QJsonValue c, jsonObj.value(KEY_CHILDREN).toArray()) {
- QEntity* child = node(c.toString());
- if (!child)
- continue;
- child->setParent(result);
- }
- }
-
- renameFromJson(jsonObj, result);
-
-
- // Node Transforms
- Qt3DCore::QTransform *trans = nullptr;
- if ( jsonObj.contains(KEY_MATRIX) ) {
- QMatrix4x4 m(Qt::Uninitialized);
-
- QJsonArray matrixValues = jsonObj.value(KEY_MATRIX).toArray();
- for (int i=0; i<16; ++i) {
- double v = matrixValues.at( i ).toDouble();
- m(i % 4, i >> 2) = v;
- }
-
- // ADD MATRIX TRANSFORM COMPONENT TO ENTITY
- if (trans == nullptr)
- trans = new Qt3DCore::QTransform;
- trans->setMatrix(m);
- }
-
- // Rotation quaternion
- if (jsonObj.contains(KEY_ROTATION)) {
- if (trans == nullptr)
- trans = new Qt3DCore::QTransform;
-
- QJsonArray quaternionValues = jsonObj.value(KEY_ROTATION).toArray();
- QQuaternion quaternion(quaternionValues[0].toDouble(),
- quaternionValues[1].toDouble(),
- quaternionValues[2].toDouble(),
- quaternionValues[3].toDouble());
- trans->setRotation(quaternion);
- }
-
- // Translation
- if (jsonObj.contains(KEY_TRANSLATION)) {
- if (trans == nullptr)
- trans = new Qt3DCore::QTransform;
-
- QJsonArray translationValues = jsonObj.value(KEY_TRANSLATION).toArray();
- trans->setTranslation(QVector3D(translationValues[0].toDouble(),
- translationValues[1].toDouble(),
- translationValues[2].toDouble()));
- }
-
- // Scale
- if (jsonObj.contains(KEY_SCALE)) {
- if (trans == nullptr)
- trans = new Qt3DCore::QTransform;
-
- QJsonArray scaleValues = jsonObj.value(KEY_SCALE).toArray();
- trans->setScale3D(QVector3D(scaleValues[0].toDouble(),
- scaleValues[1].toDouble(),
- scaleValues[2].toDouble()));
- }
-
- // Add the Transform component
- if (trans != nullptr)
- result->addComponent(trans);
-
- if ( jsonObj.contains(KEY_CAMERA) ) {
- QCameraLens* cam = camera( jsonObj.value(KEY_CAMERA).toString() );
- if (!cam) {
- qCWarning(GLTFParserLog) << "failed to build camera:" << jsonObj.value(KEY_CAMERA)
- << "on node" << id;
- } else {
- result->addComponent(cam);
- }
- } // of have camera attribute
-
- return result;
-}
-
-Qt3DCore::QEntity* GLTFParser::scene(const QString &id)
-{
- parse();
-
- QJsonObject scenes = m_json.object().value(KEY_SCENES).toObject();
- if (!scenes.contains(id)) {
- if (!id.isNull())
- qCWarning(GLTFParserLog) << "GLTF: no such scene" << id << "in file" << m_basePath;
- return defaultScene();
- }
-
- QJsonObject sceneObj = scenes.value(id).toObject();
- QEntity* sceneEntity = new QEntity;
- Q_FOREACH (QJsonValue nnv, sceneObj.value(KEY_NODES).toArray()) {
- QString nodeName = nnv.toString();
- QEntity* child = node(nodeName);
- if (!child)
- continue;
- child->setParent(sceneEntity);
- }
-
- return sceneEntity;
-}
-
-GLTFParser::BufferData::BufferData()
- : length(0)
- , data(nullptr)
-{
-}
-
-GLTFParser::BufferData::BufferData(QJsonObject json)
-{
- path = json.value(KEY_URI).toString();
- length = json.value(KEY_BYTE_LENGTH).toInt();
- data = nullptr;
-}
-
-GLTFParser::ParameterData::ParameterData() :
- type(0)
-{
-
-}
-
-GLTFParser::ParameterData::ParameterData(QJsonObject json)
-{
- type = json.value(KEY_TYPE).toInt();
- semantic = json.value(KEY_SEMANTIC).toString();
-}
-
-GLTFParser::AccessorData::AccessorData()
- : type(QAttribute::Float)
- , dataSize(0)
- , count(0)
- , offset(0)
- , stride(0)
-{
-
-}
-
-GLTFParser::AccessorData::AccessorData(const QJsonObject &json)
-{
- bufferViewName = json.value(KEY_BUFFER_VIEW).toString();
- offset = 0;
- stride = 0;
- int componentType = json.value(KEY_COMPONENT_TYPE).toInt();
- type = accessorTypeFromJSON(componentType);
- count = json.value(KEY_COUNT).toInt();
- dataSize = accessorDataSizeFromJson(json.value(KEY_TYPE).toString());
-
- if ( json.contains(KEY_BYTE_OFFSET))
- offset = json.value(KEY_BYTE_OFFSET).toInt();
- if ( json.contains(KEY_BYTE_STRIDE))
- stride = json.value(KEY_BYTE_STRIDE).toInt();
-}
-
-bool GLTFParser::isGLTFPath(const QString& path)
-{
- QFileInfo finfo(path);
- if (!finfo.exists())
- return false;
-
- // might need to detect other things in the future, but would
- // prefer to avoid doing a full parse.
- QString suffix = finfo.suffix().toLower();
- return (suffix == QStringLiteral("json") || suffix == QStringLiteral("gltf") || suffix == QStringLiteral("qgltf"));
-}
-
-void GLTFParser::renameFromJson(const QJsonObject &json, QObject * const object)
-{
- if ( json.contains(KEY_NAME) )
- object->setObjectName( json.value(KEY_NAME).toString() );
-}
-
-QString GLTFParser::standardUniformNamefromSemantic(const QString &semantic)
-{
- //Standard Uniforms
- //if (semantic == QStringLiteral("LOCAL"));
- if (semantic == QStringLiteral("MODEL"))
- return QStringLiteral("modelMatrix");
- if (semantic == QStringLiteral("VIEW"))
- return QStringLiteral("viewMatrix");
- if (semantic == QStringLiteral("PROJECTION"))
- return QStringLiteral("projectionMatrix");
- if (semantic == QStringLiteral("MODELVIEW"))
- return QStringLiteral("modelView");
- if (semantic == QStringLiteral("MODELVIEWPROJECTION"))
- return QStringLiteral("modelViewProjection");
- if (semantic == QStringLiteral("MODELINVERSE"))
- return QStringLiteral("inverseModelMatrix");
- if (semantic == QStringLiteral("VIEWINVERSE"))
- return QStringLiteral("inverViewMatrix");
- if (semantic == QStringLiteral("PROJECTIONINVERSE"))
- return QStringLiteral("inverseProjectionMatrix");
- if (semantic == QStringLiteral("MODELVIEWPROJECTIONINVERSE"))
- return QStringLiteral("inverseModelViewProjection");
- if (semantic == QStringLiteral("MODELINVERSETRANSPOSE"))
- return QStringLiteral("modelNormalMatrix");
- if (semantic == QStringLiteral("MODELVIEWINVERSETRANSPOSE"))
- return QStringLiteral("modelViewNormal");
- if (semantic == QStringLiteral("VIEWPORT"))
- return QStringLiteral("viewportMatrix");
-
- return QString();
-}
-
-QString GLTFParser::standardAttributeNameFromSemantic(const QString &semantic)
-{
- //Standard Attributes
- if (semantic.startsWith(QStringLiteral("POSITION")))
- return QAttribute::defaultPositionAttributeName();
- if (semantic.startsWith(QStringLiteral("NORMAL")))
- return QAttribute::defaultNormalAttributeName();
- if (semantic.startsWith(QStringLiteral("TEXCOORD")))
- return QAttribute::defaultTextureCoordinateAttributeName();
- if (semantic.startsWith(QStringLiteral("COLOR")))
- return QAttribute::defaultColorAttributeName();
- if (semantic.startsWith(QStringLiteral("TANGENT")))
- return QAttribute::defaultTangentAttributeName();
-
-// if (semantic.startsWith(QStringLiteral("JOINT")));
-// if (semantic.startsWith(QStringLiteral("JOINTMATRIX")));
-// if (semantic.startsWith(QStringLiteral("WEIGHT")));
-
- return QString();
-}
-
-QParameter *GLTFParser::parameterFromTechnique(QTechnique *technique, const QString &parameterName)
-{
- Q_FOREACH (QParameter *parameter, technique->parameters()) {
- if (parameter->name() == parameterName) {
- return parameter;
- }
- }
-
- return nullptr;
-}
-
-Qt3DCore::QEntity* GLTFParser::defaultScene()
-{
- if (m_defaultScene.isEmpty()) {
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "no default scene";
- return NULL;
- }
-
- return scene(m_defaultScene);
-}
-
-QMaterial *GLTFParser::materialWithCustomShader(const QString &id, const QJsonObject &jsonObj)
-{
- //Default ES2 Technique
- QString techniqueName = jsonObj.value(KEY_TECHNIQUE).toString();
- if (!m_techniques.contains(techniqueName)) {
- qCWarning(GLTFParserLog) << "unknown technique" << techniqueName
- << "for material" << id << "in GLTF file" << m_basePath;
- return NULL;
- }
- QTechnique *technique = m_techniques.value(techniqueName);
- technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGLES);
- technique->graphicsApiFilter()->setMajorVersion(2);
- technique->graphicsApiFilter()->setMinorVersion(0);
- technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
-
-
- //Optional Core technique
- QTechnique *coreTechnique = nullptr;
- QTechnique *gl2Technique = nullptr;
- QString coreTechniqueName = jsonObj.value(KEY_TECHNIQUE_CORE).toString();
- if (!coreTechniqueName.isNull()) {
- if (!m_techniques.contains(coreTechniqueName)) {
- qCWarning(GLTFParserLog) << "unknown technique" << coreTechniqueName
- << "for material" << id << "in GLTF file" << m_basePath;
- } else {
- coreTechnique = m_techniques.value(coreTechniqueName);
- coreTechnique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
- coreTechnique->graphicsApiFilter()->setMajorVersion(3);
- coreTechnique->graphicsApiFilter()->setMinorVersion(1);
- coreTechnique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
- }
- }
- //Optional GL2 technique
- QString gl2TechniqueName = jsonObj.value(KEY_TECHNIQUE_GL2).toString();
- if (!gl2TechniqueName.isNull()) {
- if (!m_techniques.contains(gl2TechniqueName)) {
- qCWarning(GLTFParserLog) << "unknown technique" << gl2TechniqueName
- << "for material" << id << "in GLTF file" << m_basePath;
- } else {
- gl2Technique = m_techniques.value(gl2TechniqueName);
- gl2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
- gl2Technique->graphicsApiFilter()->setMajorVersion(2);
- gl2Technique->graphicsApiFilter()->setMinorVersion(0);
- gl2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
- }
- }
-
-
- // glTF doesn't deal in effects, but we need a trivial one to wrap
- // up our techniques
- // However we need to create a unique effect for each material instead
- // of caching because QMaterial does not keep up with effects
- // its not the parent of.
- QEffect* effect = new QEffect;
- effect->setObjectName(techniqueName);
- effect->addTechnique(technique);
- if (coreTechnique != nullptr)
- effect->addTechnique(coreTechnique);
- if (gl2Technique != nullptr)
- effect->addTechnique(gl2Technique);
-
- QMaterial* mat = new QMaterial;
- mat->setEffect(effect);
-
- renameFromJson(jsonObj, mat);
-
- QJsonObject values = jsonObj.value(KEY_VALUES).toObject();
- Q_FOREACH (QString vName, values.keys()) {
- QParameter *param = parameterFromTechnique(technique, vName);
-
- if (param == nullptr && coreTechnique != nullptr) {
- param = parameterFromTechnique(coreTechnique, vName);
- }
-
- if (param == nullptr && gl2Technique != nullptr) {
- param = parameterFromTechnique(gl2Technique, vName);
- }
-
- if (param == nullptr) {
- qCWarning(GLTFParserLog) << "unknown parameter:" << vName << "in technique" << techniqueName
- << "processing material" << id;
- continue;
- }
-
- ParameterData paramData = m_parameterDataDict.value(param);
- QVariant var = parameterValueFromJSON(paramData.type, values.value(vName));
-
- mat->addParameter(new QParameter(param->name(), var));
- } // of material technique-instance values iteration
-
- return mat;
-}
-
-static inline QVariant vec4ToRgb(const QVariant &vec4Var)
-{
- const QVector4D v = vec4Var.value<QVector4D>();
- return QVariant(QColor::fromRgbF(v.x(), v.y(), v.z()));
-}
-
-QMaterial *GLTFParser::commonMaterial(const QJsonObject &jsonObj)
-{
- QVariantHash params;
- bool hasDiffuseMap = false;
- bool hasSpecularMap = false;
- bool hasNormalMap = false;
-
- QJsonObject values = jsonObj.value(KEY_VALUES).toObject();
- Q_FOREACH (const QString &vName, values.keys()) {
- const QJsonValue val = values.value(vName);
- QVariant var;
- QString propertyName = vName;
- if (vName == QStringLiteral("ambient") && val.isArray()) {
- var = vec4ToRgb(parameterValueFromJSON(GL_FLOAT_VEC4, val));
- } else if (vName == QStringLiteral("diffuse")) {
- if (val.isString()) {
- var = parameterValueFromJSON(GL_SAMPLER_2D, val);
- hasDiffuseMap = true;
- } else if (val.isArray()) {
- var = vec4ToRgb(parameterValueFromJSON(GL_FLOAT_VEC4, val));
- }
- } else if (vName == QStringLiteral("specular")) {
- if (val.isString()) {
- var = parameterValueFromJSON(GL_SAMPLER_2D, val);
- hasSpecularMap = true;
- } else if (val.isArray()) {
- var = vec4ToRgb(parameterValueFromJSON(GL_FLOAT_VEC4, val));
- }
- } else if (vName == QStringLiteral("shininess") && val.isDouble()) {
- var = parameterValueFromJSON(GL_FLOAT, val);
- } else if (vName == QStringLiteral("normalmap") && val.isString()) {
- var = parameterValueFromJSON(GL_SAMPLER_2D, val);
- propertyName = QStringLiteral("normal");
- hasNormalMap = true;
- } else if (vName == QStringLiteral("transparency")) {
- qCWarning(GLTFParserLog) << "Semi-transparent common materials are not currently supported, ignoring alpha";
- }
- if (var.isValid())
- params[propertyName] = var;
- }
-
- QMaterial *mat = nullptr;
- if (hasNormalMap) {
- if (hasSpecularMap) {
- mat = new QNormalDiffuseSpecularMapMaterial;
- } else {
- if (hasDiffuseMap)
- mat = new QNormalDiffuseMapMaterial;
- else
- qCWarning(GLTFParserLog) << "Common material with normal and specular maps needs a diffuse map as well";
- }
- } else {
- if (hasSpecularMap) {
- if (hasDiffuseMap)
- mat = new QDiffuseSpecularMapMaterial;
- else
- qCWarning(GLTFParserLog) << "Common material with specular map needs a diffuse map as well";
- } else if (hasDiffuseMap) {
- mat = new QDiffuseMapMaterial;
- } else {
- mat = new QPhongMaterial;
- }
- }
-
- if (mat) {
- for (QVariantHash::const_iterator it = params.constBegin(), itEnd = params.constEnd(); it != itEnd; ++it)
- mat->setProperty(it.key().toUtf8(), it.value());
- } else {
- qCWarning(GLTFParserLog) << "Could not find a suitable built-in material for KHR_materials_common";
- }
-
- return mat;
-}
-
-QMaterial* GLTFParser::material(const QString &id)
-{
- if (m_materialCache.contains(id))
- return m_materialCache.value(id);
-
- QJsonObject mats = m_json.object().value(KEY_MATERIALS).toObject();
- if (!mats.contains(id)) {
- qCWarning(GLTFParserLog) << "unknown material" << id << "in GLTF file" << m_basePath;
- return NULL;
- }
-
- QJsonObject jsonObj = mats.value(id).toObject();
-
- QMaterial *mat = nullptr;
-
- // Prefer common materials over custom shaders.
- if (jsonObj.contains(KEY_EXTENSIONS)) {
- QJsonObject extensions = jsonObj.value(KEY_EXTENSIONS).toObject();
- if (extensions.contains(KEY_COMMON_MAT))
- mat = commonMaterial(extensions.value(KEY_COMMON_MAT).toObject());
- }
-
- if (!mat)
- mat = materialWithCustomShader(id, jsonObj);
-
- m_materialCache[id] = mat;
- return mat;
-}
-
-QCameraLens* GLTFParser::camera(const QString &id) const
-{
- QJsonObject cams = m_json.object().value(KEY_CAMERAS).toObject();
- if (!cams.contains(id)) {
- qCWarning(GLTFParserLog) << "unknown camera" << id << "in GLTF file" << m_basePath;
- return nullptr;
- }
-
- QJsonObject jsonObj = cams.value(id).toObject();
- QString camTy = jsonObj.value(KEY_TYPE).toString();
-
- if (camTy == QStringLiteral("perspective")) {
- if (!jsonObj.contains(KEY_PERSPECTIVE)) {
- qCWarning(GLTFParserLog) << "camera:" << id << "missing 'perspective' object";
- return nullptr;
- }
-
- QJsonObject pObj = jsonObj.value(KEY_PERSPECTIVE).toObject();
- double aspectRatio = pObj.value(KEY_ASPECT_RATIO).toDouble();
- double yfov = pObj.value(KEY_YFOV).toDouble();
- double frustumNear = pObj.value(KEY_ZNEAR).toDouble();
- double frustumFar = pObj.value(KEY_ZFAR).toDouble();
-
- QCameraLens* result = new QCameraLens;
- result->setPerspectiveProjection(yfov, aspectRatio, frustumNear, frustumFar);
- return result;
- } else if (camTy == QStringLiteral("orthographic")) {
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "implement me";
-
- return nullptr;
- } else {
- qCWarning(GLTFParserLog) << "camera:" << id << "has unsupported type:" << camTy;
- return nullptr;
- }
-}
-
-
-void GLTFParser::parse()
-{
- if (m_parseDone)
- return;
-
- QJsonObject buffers = m_json.object().value(KEY_BUFFERS).toObject();
- Q_FOREACH (QString nm, buffers.keys()) {
- processJSONBuffer( nm, buffers.value(nm).toObject() );
- }
-
- QJsonObject views = m_json.object().value(KEY_BUFFER_VIEWS).toObject();
- loadBufferData();
- Q_FOREACH (QString nm, views.keys()) {
- processJSONBufferView( nm, views.value(nm).toObject() );
- }
- unloadBufferData();
-
- QJsonObject shaders = m_json.object().value(KEY_SHADERS).toObject();
- Q_FOREACH (QString nm, shaders.keys()) {
- processJSONShader( nm, shaders.value(nm).toObject() );
- }
-
- QJsonObject programs = m_json.object().value(KEY_PROGRAMS).toObject();
- Q_FOREACH (QString nm, programs.keys()) {
- processJSONProgram( nm, programs.value(nm).toObject() );
- }
-
- QJsonObject techniques = m_json.object().value(KEY_TECHNIQUES).toObject();
- Q_FOREACH (QString nm, techniques.keys()) {
- processJSONTechnique( nm, techniques.value(nm).toObject() );
- }
-
- QJsonObject attrs = m_json.object().value(KEY_ACCESSORS).toObject();
- Q_FOREACH (QString nm, attrs.keys()) {
- processJSONAccessor( nm, attrs.value(nm).toObject() );
- }
-
- QJsonObject meshes = m_json.object().value(KEY_MESHES).toObject();
- Q_FOREACH (QString nm, meshes.keys()) {
- processJSONMesh( nm, meshes.value(nm).toObject() );
- }
-
- QJsonObject images = m_json.object().value(KEY_IMAGES).toObject();
- Q_FOREACH (QString nm, images.keys()) {
- processJSONImage( nm, images.value(nm).toObject() );
- }
-
- QJsonObject textures = m_json.object().value(KEY_TEXTURES).toObject();
- Q_FOREACH (QString nm, textures.keys()) {
- processJSONTexture(nm, textures.value(nm).toObject() );
- }
-
- m_defaultScene = m_json.object().value(KEY_SCENE).toString();
- m_parseDone = true;
-}
-
-void GLTFParser::cleanup()
-{
- m_meshDict.clear();
- m_meshMaterialDict.clear();
- m_accessorDict.clear();
- //Check for Materials with no parent
- Q_FOREACH (QMaterial *material, m_materialCache.values()) {
- if (material->parent() == nullptr)
- delete material;
- }
- m_materialCache.clear();
- m_bufferDatas.clear();
- m_buffers.clear();
- m_shaderPaths.clear();
- //Check for ShaderPrograms with no parent
- Q_FOREACH (QShaderProgram *program, m_programs.values()) {
- if (program->parent() == nullptr)
- delete program;
- }
- m_programs.clear();
- //Check for Techniques with no parent
- Q_FOREACH (QTechnique *technique, m_techniques.values()) {
- if (technique->parent() == nullptr)
- delete technique;
- }
- m_techniques.clear();
- //Check for Textures with no parent
- Q_FOREACH (QAbstractTextureProvider *texture, m_textures.values()) {
- if (texture->parent() == nullptr)
- delete texture;
- }
- m_textures.clear();
- m_imagePaths.clear();
- m_defaultScene.clear();
- m_parameterDataDict.clear();
-}
-
-void GLTFParser::processJSONBuffer(const QString &id, const QJsonObject& json)
-{
- // simply cache buffers for lookup by buffer-views
- m_bufferDatas[id] = BufferData(json);
-}
-
-void GLTFParser::processJSONBufferView(const QString &id, const QJsonObject& json)
-{
- QString bufName = json.value(KEY_BUFFER).toString();
- if (!m_bufferDatas.contains(bufName)) {
- qCWarning(GLTFParserLog) << "unknown buffer:" << bufName << "processing view:" << id;
- return;
- }
-
- int target = json.value(KEY_TARGET).toInt();
- QBuffer::BufferType ty(QBuffer::VertexBuffer);
-
- switch (target) {
- case GL_ARRAY_BUFFER: ty = QBuffer::VertexBuffer; break;
- case GL_ELEMENT_ARRAY_BUFFER: ty = QBuffer::IndexBuffer; break;
- default:
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "buffer" << id << "unsupported target:" << target;
- return;
- }
-
- quint64 offset = 0;
- if (json.contains(KEY_BYTE_OFFSET)) {
- offset = json.value(KEY_BYTE_OFFSET).toInt();
- qCDebug(GLTFParserLog) << "bv:" << id << "has offset:" << offset;
- }
-
- quint64 len = json.value(KEY_BYTE_LENGTH).toInt();
-
- QByteArray bytes(m_bufferDatas[bufName].data->mid(offset, len));
- if (bytes.count() != (int) len) {
- qCWarning(GLTFParserLog) << "failed to read sufficient bytes from:" << m_bufferDatas[bufName].path
- << "for view" << id;
- }
-
- QBuffer *b(new QBuffer(ty));
- b->setData(bytes);
- m_buffers[id] = b;
-}
-
-void GLTFParser::processJSONShader(const QString &id, const QJsonObject &jsonObject)
-{
- // shaders are trivial for the moment, defer the real work
- // to the program section
- QString path = jsonObject.value(KEY_URI).toString();
-
- QFileInfo info(m_basePath, path);
- if (!info.exists()) {
- qCWarning(GLTFParserLog) << "can't find shader" << id << "from path" << path;
- return;
- }
-
- m_shaderPaths[id] = info.absoluteFilePath();
-}
-
-void GLTFParser::processJSONProgram(const QString &id, const QJsonObject &jsonObject)
-{
- QShaderProgram* prog = new QShaderProgram;
- prog->setObjectName(id);
-
- QString fragName = jsonObject.value(KEY_FRAGMENT_SHADER).toString(),
- vertName = jsonObject.value(KEY_VERTEX_SHADER).toString();
- if (!m_shaderPaths.contains(fragName) || !m_shaderPaths.contains(vertName)) {
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "program:" << id << "missing shader:"
- << fragName << vertName;
- return;
- }
-
- prog->setFragmentShaderCode(QShaderProgram::loadSource(QUrl::fromLocalFile(m_shaderPaths[fragName])));
- prog->setVertexShaderCode(QShaderProgram::loadSource(QUrl::fromLocalFile(m_shaderPaths[vertName])));
- m_programs[id] = prog;
-}
-
-void GLTFParser::processJSONTechnique(const QString &id, const QJsonObject &jsonObject )
-{
- QTechnique *t = new QTechnique;
- t->setObjectName(id);
-
- // Parameters
- QHash<QString, QParameter*> paramDict;
- QJsonObject params = jsonObject.value(KEY_PARAMETERS).toObject();
- Q_FOREACH (QString pname, params.keys()) {
- QJsonObject po = params.value(pname).toObject();
-
- //QString semantic = po.value(KEY_SEMANTIC).toString();
- QParameter *p = new QParameter(t);
- p->setName(pname);
- m_parameterDataDict.insert(p, ParameterData(po));
-
- //If the parameter has default value, set it
- QJsonValue value = po.value(KEY_VALUE);
- if (!value.isUndefined()) {
- int dataType = po.value(KEY_TYPE).toInt();
- p->setValue(parameterValueFromJSON(dataType, value));
- }
-
- t->addParameter(p);
-
- paramDict[pname] = p;
- } // of parameters iteration
-
- // Program
- QString programName = jsonObject.value(KEY_PROGRAM).toString();
- if (!m_programs.contains(programName)) {
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "technique" << id
- << ": missing program" << programName;
- }
-
- QRenderPass* pass = new QRenderPass;
- pass->setShaderProgram(m_programs[programName]);
-
- // Attributes
- QJsonObject attrs = jsonObject.value(KEY_ATTRIBUTES).toObject();
- Q_FOREACH ( QString shaderAttributeName, attrs.keys() ) {
- QString pname = attrs.value(shaderAttributeName).toString();
- QParameter *parameter = paramDict.value(pname, nullptr);
- QString attributeName = pname;
- if (parameter == nullptr) {
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "attribute " << pname
- << "defined in instanceProgram but not as parameter";
- continue;
- }
- //Check if the parameter has a standard attribute semantic
- QString standardAttributeName = standardAttributeNameFromSemantic(m_parameterDataDict[parameter].semantic);
- if (!standardAttributeName.isNull()) {
- attributeName = standardAttributeName;
- t->removeParameter(parameter);
- m_parameterDataDict.remove(parameter);
- delete parameter;
- }
-
- pass->addBinding(new QParameterMapping(attributeName, shaderAttributeName, QParameterMapping::Attribute));
- } // of program-instance attributes
-
- // Uniforms
- QJsonObject uniforms = jsonObject.value(KEY_UNIFORMS).toObject();
- Q_FOREACH (QString shaderUniformName, uniforms.keys()) {
- QString pname = uniforms.value(shaderUniformName).toString();
- QParameter *parameter = paramDict.value(pname, nullptr);
- if (parameter == nullptr) {
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "uniform " << pname
- << "defined in instanceProgram but not as parameter";
- continue;
- }
- //Check if the parameter has a standard uniform semantic
- QString standardUniformName = standardUniformNamefromSemantic(m_parameterDataDict[parameter].semantic);
- if (standardUniformName.isNull()) {
- pass->addBinding(new QParameterMapping(pname, shaderUniformName, QParameterMapping::Uniform));
- } else {
- pass->addBinding(new QParameterMapping(standardUniformName, shaderUniformName, QParameterMapping::StandardUniform));
- t->removeParameter(parameter);
- m_parameterDataDict.remove(parameter);
- delete parameter;
- }
- } // of program-instance uniforms
-
-
- // States
- QJsonObject states = jsonObject.value(KEY_STATES).toObject();
-
- //Process states to enable
- QJsonArray enableStatesArray = states.value(KEY_ENABLE).toArray();
- QVector<int> enableStates;
- Q_FOREACH (QJsonValue enableValue, enableStatesArray) {
- enableStates.append(enableValue.toInt());
- }
-
- //Process the list of state functions
- QJsonObject functions = states.value(KEY_FUNCTIONS).toObject();
- Q_FOREACH (QString functionName, functions.keys()) {
- int enableStateType = 0;
- QRenderState *renderState = buildState(functionName, functions.value(functionName), enableStateType);
- if (renderState != nullptr) {
- //Remove the need to set a default state values for enableStateType
- enableStates.removeOne(enableStateType);
- pass->addRenderState(renderState);
- }
- }
-
- //Create render states with default values for any remaining enable states
- Q_FOREACH (int enableState, enableStates) {
- QRenderState *renderState = buildStateEnable(enableState);
- if (renderState != nullptr)
- pass->addRenderState(renderState);
- }
-
-
- t->addPass(pass);
-
- m_techniques[id] = t;
-}
-
-void GLTFParser::processJSONAccessor( const QString &id, const QJsonObject& json )
-{
- m_accessorDict[id] = AccessorData(json);
-}
-
-void GLTFParser::processJSONMesh(const QString &id, const QJsonObject &json)
-{
- QJsonArray primitivesArray = json.value(KEY_PRIMITIVES).toArray();
- Q_FOREACH (QJsonValue primitiveValue, primitivesArray) {
- QJsonObject primitiveObject = primitiveValue.toObject();
- int type = primitiveObject.value(KEY_MODE).toInt();
- QString material = primitiveObject.value(KEY_MATERIAL).toString();
-
- if ( material.isEmpty()) {
- qCWarning(GLTFParserLog) << "malformed primitive on " << id << ", missing material value"
- << material;
- continue;
- }
-
- QGeometryRenderer *geometryRenderer = new QGeometryRenderer;
- QGeometry *meshGeometry = new QGeometry(geometryRenderer);
-
- //Set Primitive Type
- geometryRenderer->setPrimitiveType(static_cast<QGeometryRenderer::PrimitiveType>(type));
-
- //Save Material for mesh
- m_meshMaterialDict[geometryRenderer] = material;
-
- QJsonObject attrs = primitiveObject.value(KEY_ATTRIBUTES).toObject();
- Q_FOREACH (QString attrName, attrs.keys()) {
- QString k = attrs.value(attrName).toString();
- if (!m_accessorDict.contains(k)) {
- qCWarning(GLTFParserLog) << "unknown attribute accessor:" << k << "on mesh" << id;
- continue;
- }
-
- QString attributeName = standardAttributeNameFromSemantic(attrName);
- if (attributeName.isEmpty())
- attributeName = attrName;
-
- //Get buffer handle for accessor
- QBuffer *buffer = m_buffers.value(m_accessorDict[k].bufferViewName, nullptr);
- if (buffer == nullptr) {
- qCWarning(GLTFParserLog) << "unknown buffer-view:" << m_accessorDict[k].bufferViewName << "processing accessor:" << id;
- continue;
- }
-
- QAttribute *attribute = new QAttribute(buffer,
- attributeName,
- m_accessorDict[k].type,
- m_accessorDict[k].dataSize,
- m_accessorDict[k].count,
- m_accessorDict[k].offset,
- m_accessorDict[k].stride);
- attribute->setAttributeType(QAttribute::VertexAttribute);
- meshGeometry->addAttribute(attribute);
- }
-
- if ( primitiveObject.contains(KEY_INDICES)) {
- QString k = primitiveObject.value(KEY_INDICES).toString();
- if (!m_accessorDict.contains(k)) {
- qCWarning(GLTFParserLog) << "unknown index accessor:" << k << "on mesh" << id;
- } else {
- //Get buffer handle for accessor
- QBuffer *buffer = m_buffers.value(m_accessorDict[k].bufferViewName, nullptr);
- if (buffer == nullptr) {
- qCWarning(GLTFParserLog) << "unknown buffer-view:" << m_accessorDict[k].bufferViewName << "processing accessor:" << id;
- continue;
- }
-
- QAttribute *attribute = new QAttribute(buffer,
- m_accessorDict[k].type,
- m_accessorDict[k].dataSize,
- m_accessorDict[k].count,
- m_accessorDict[k].offset,
- m_accessorDict[k].stride);
- attribute->setAttributeType(QAttribute::IndexAttribute);
- meshGeometry->addAttribute(attribute);
- }
- } // of has indices
-
- geometryRenderer->setGeometry(meshGeometry);
-
- m_meshDict.insert( id, geometryRenderer);
- } // of primitives iteration
-}
-
-void GLTFParser::processJSONImage(const QString &id, const QJsonObject &jsonObject)
-{
- QString path = jsonObject.value(KEY_URI).toString();
- QFileInfo info(m_basePath, path);
- if (!info.exists()) {
- qCWarning(GLTFParserLog) << "can't find image" << id << "from path" << path;
- return;
- }
-
- m_imagePaths[id] = info.absoluteFilePath();
-}
-
-void GLTFParser::processJSONTexture(const QString &id, const QJsonObject &jsonObject)
-{
- int target = jsonObject.value(KEY_TARGET).toInt(GL_TEXTURE_2D);
- //TODO: support other targets that GL_TEXTURE_2D (though the spec doesn't support anything else)
- if (target != GL_TEXTURE_2D) {
- qCWarning(GLTFParserLog) << "unsupported texture target: " << target;
- return;
- }
-
- QTexture2D* tex = new QTexture2D;
-
- // TODO: Choose suitable internal format - may vary on OpenGL context type
- //int pixelFormat = jsonObj.value(KEY_FORMAT).toInt(GL_RGBA);
- int internalFormat = jsonObject.value(KEY_INTERNAL_FORMAT).toInt(GL_RGBA);
-
- tex->setFormat(static_cast<QAbstractTextureProvider::TextureFormat>(internalFormat));
-
- QString samplerId = jsonObject.value(KEY_SAMPLER).toString();
- QString source = jsonObject.value(KEY_SOURCE).toString();
- if (!m_imagePaths.contains(source)) {
- qCWarning(GLTFParserLog) << "texture" << id << "references missing image" << source;
- return;
- }
-
- QTextureImage *texImage = new QTextureImage(tex);
- texImage->setSource(QUrl::fromLocalFile(m_imagePaths[source]));
- tex->addTextureImage(texImage);
-
- QJsonObject samplersDict(m_json.object().value(KEY_SAMPLERS).toObject());
- if (!samplersDict.contains(samplerId)) {
- qCWarning(GLTFParserLog) << "texture" << id << "references unknown sampler" << samplerId;
- return;
- }
-
- QJsonObject sampler = samplersDict.value(samplerId).toObject();
-
- tex->setWrapMode(QTextureWrapMode(static_cast<QTextureWrapMode::WrapMode>(sampler.value(KEY_WRAP_S).toInt())));
- tex->setMinificationFilter(static_cast<QAbstractTextureProvider::Filter>(sampler.value(KEY_MIN_FILTER).toInt()));
- if (tex->minificationFilter() == QAbstractTextureProvider::NearestMipMapLinear ||
- tex->minificationFilter() == QAbstractTextureProvider::LinearMipMapNearest ||
- tex->minificationFilter() == QAbstractTextureProvider::NearestMipMapNearest ||
- tex->minificationFilter() == QAbstractTextureProvider::LinearMipMapLinear) {
-
- tex->setGenerateMipMaps(true);
- }
- tex->setMagnificationFilter(static_cast<QAbstractTextureProvider::Filter>(sampler.value(KEY_MAG_FILTER).toInt()));
-
- m_textures[id] = tex;
-}
-
-void GLTFParser::loadBufferData()
-{
- Q_FOREACH (QString bufferName, m_bufferDatas.keys()) {
- if (m_bufferDatas[bufferName].data == nullptr) {
- QFile* bufferFile = resolveLocalData(m_bufferDatas[bufferName].path);
- QByteArray *data = new QByteArray(bufferFile->readAll());
- m_bufferDatas[bufferName].data = data;
- delete bufferFile;
- }
- }
-}
-
-void GLTFParser::unloadBufferData()
-{
- Q_FOREACH (QString bufferName, m_bufferDatas.keys()) {
- QByteArray *data = m_bufferDatas[bufferName].data;
- delete data;
- }
-}
-
-QFile *GLTFParser::resolveLocalData(QString path) const
-{
- QDir d(m_basePath);
- Q_ASSERT(d.exists());
-
- QString absPath = d.absoluteFilePath(path);
- QFile* f = new QFile(absPath);
- f->open(QIODevice::ReadOnly);
- return f;
-}
-
-QVariant GLTFParser::parameterValueFromJSON(int type, const QJsonValue &value) const
-{
- if (value.isBool()) {
- if (type == GL_BOOL)
- return QVariant(static_cast<GLboolean>(value.toBool()));
- } else if (value.isString()) {
- if (type == GL_SAMPLER_2D) {
- //Textures are special because we need to do a lookup to return the
- //QAbstractTextureProvider
- QString textureId = value.toString();
- if (!m_textures.contains(textureId)) {
- qCWarning(GLTFParserLog) << "unknown texture" << textureId;
- return QVariant();
- } else {
- return QVariant::fromValue(m_textures.value(textureId));
- }
- }
- } else if (value.isDouble()) {
- switch (type) {
- case GL_BYTE:
- return QVariant(static_cast<GLbyte>(value.toInt()));
- case GL_UNSIGNED_BYTE:
- return QVariant(static_cast<GLubyte>(value.toInt()));
- case GL_SHORT:
- return QVariant(static_cast<GLshort>(value.toInt()));
- case GL_UNSIGNED_SHORT:
- return QVariant(static_cast<GLushort>(value.toInt()));
- case GL_INT:
- return QVariant(static_cast<GLint>(value.toInt()));
- case GL_UNSIGNED_INT:
- return QVariant(static_cast<GLuint>(value.toInt()));
- case GL_FLOAT:
- return QVariant(static_cast<GLfloat>(value.toDouble()));
- }
- } else if (value.isArray()) {
-
- QJsonArray valueArray = value.toArray();
-
- QVector2D vector2D;
- QVector3D vector3D;
- QVector4D vector4D;
- QVector<float> dataMat2(4, 0.0f);
- QVector<float> dataMat3(9, 0.0f);
-
- switch (type) {
- case GL_BYTE:
- return QVariant(static_cast<GLbyte>(valueArray.first().toInt()));
- case GL_UNSIGNED_BYTE:
- return QVariant(static_cast<GLubyte>(valueArray.first().toInt()));
- case GL_SHORT:
- return QVariant(static_cast<GLshort>(valueArray.first().toInt()));
- case GL_UNSIGNED_SHORT:
- return QVariant(static_cast<GLushort>(valueArray.first().toInt()));
- case GL_INT:
- return QVariant(static_cast<GLint>(valueArray.first().toInt()));
- case GL_UNSIGNED_INT:
- return QVariant(static_cast<GLuint>(valueArray.first().toInt()));
- case GL_FLOAT:
- return QVariant(static_cast<GLfloat>(valueArray.first().toDouble()));
- case GL_FLOAT_VEC2:
- vector2D.setX(static_cast<GLfloat>(valueArray.at(0).toDouble()));
- vector2D.setY(static_cast<GLfloat>(valueArray.at(1).toDouble()));
- return QVariant(vector2D);
- case GL_FLOAT_VEC3:
- vector3D.setX(static_cast<GLfloat>(valueArray.at(0).toDouble()));
- vector3D.setY(static_cast<GLfloat>(valueArray.at(1).toDouble()));
- vector3D.setZ(static_cast<GLfloat>(valueArray.at(2).toDouble()));
- return QVariant(vector3D);
- case GL_FLOAT_VEC4:
- vector4D.setX(static_cast<GLfloat>(valueArray.at(0).toDouble()));
- vector4D.setY(static_cast<GLfloat>(valueArray.at(1).toDouble()));
- vector4D.setZ(static_cast<GLfloat>(valueArray.at(2).toDouble()));
- vector4D.setW(static_cast<GLfloat>(valueArray.at(3).toDouble()));
- return QVariant(vector4D);
- case GL_INT_VEC2:
- vector2D.setX(static_cast<GLint>(valueArray.at(0).toInt()));
- vector2D.setY(static_cast<GLint>(valueArray.at(1).toInt()));
- return QVariant(vector2D);
- case GL_INT_VEC3:
- vector3D.setX(static_cast<GLint>(valueArray.at(0).toInt()));
- vector3D.setY(static_cast<GLint>(valueArray.at(1).toInt()));
- vector3D.setZ(static_cast<GLint>(valueArray.at(2).toInt()));
- return QVariant(vector3D);
- case GL_INT_VEC4:
- vector4D.setX(static_cast<GLint>(valueArray.at(0).toInt()));
- vector4D.setY(static_cast<GLint>(valueArray.at(1).toInt()));
- vector4D.setZ(static_cast<GLint>(valueArray.at(2).toInt()));
- vector4D.setW(static_cast<GLint>(valueArray.at(3).toInt()));
- return QVariant(vector4D);
- case GL_BOOL:
- return QVariant(static_cast<GLboolean>(valueArray.first().toBool()));
- case GL_BOOL_VEC2:
- vector2D.setX(static_cast<GLboolean>(valueArray.at(0).toBool()));
- vector2D.setY(static_cast<GLboolean>(valueArray.at(1).toBool()));
- return QVariant(vector2D);
- case GL_BOOL_VEC3:
- vector3D.setX(static_cast<GLboolean>(valueArray.at(0).toBool()));
- vector3D.setY(static_cast<GLboolean>(valueArray.at(1).toBool()));
- vector3D.setZ(static_cast<GLboolean>(valueArray.at(2).toBool()));
- return QVariant(vector3D);
- case GL_BOOL_VEC4:
- vector4D.setX(static_cast<GLboolean>(valueArray.at(0).toBool()));
- vector4D.setY(static_cast<GLboolean>(valueArray.at(1).toBool()));
- vector4D.setZ(static_cast<GLboolean>(valueArray.at(2).toBool()));
- vector4D.setW(static_cast<GLboolean>(valueArray.at(3).toBool()));
- return QVariant(vector4D);
- case GL_FLOAT_MAT2:
- //Matrix2x2 is in Row Major ordering (so we need to convert)
- dataMat2[0] = static_cast<GLfloat>(valueArray.at(0).toDouble());
- dataMat2[1] = static_cast<GLfloat>(valueArray.at(2).toDouble());
- dataMat2[2] = static_cast<GLfloat>(valueArray.at(1).toDouble());
- dataMat2[3] = static_cast<GLfloat>(valueArray.at(3).toDouble());
- return QVariant::fromValue(QMatrix2x2(dataMat2.constData()));
- case GL_FLOAT_MAT3:
- //Matrix3x3 is in Row Major ordering (so we need to convert)
- dataMat3[0] = static_cast<GLfloat>(valueArray.at(0).toDouble());
- dataMat3[1] = static_cast<GLfloat>(valueArray.at(3).toDouble());
- dataMat3[2] = static_cast<GLfloat>(valueArray.at(6).toDouble());
- dataMat3[3] = static_cast<GLfloat>(valueArray.at(1).toDouble());
- dataMat3[4] = static_cast<GLfloat>(valueArray.at(4).toDouble());
- dataMat3[5] = static_cast<GLfloat>(valueArray.at(7).toDouble());
- dataMat3[6] = static_cast<GLfloat>(valueArray.at(2).toDouble());
- dataMat3[7] = static_cast<GLfloat>(valueArray.at(5).toDouble());
- dataMat3[8] = static_cast<GLfloat>(valueArray.at(8).toDouble());
- return QVariant::fromValue(QMatrix3x3(dataMat3.constData()));
- case GL_FLOAT_MAT4:
- //Matrix4x4 is Column Major ordering
- return QVariant(QMatrix4x4(static_cast<GLfloat>(valueArray.at(0).toDouble()),
- static_cast<GLfloat>(valueArray.at(1).toDouble()),
- static_cast<GLfloat>(valueArray.at(2).toDouble()),
- static_cast<GLfloat>(valueArray.at(3).toDouble()),
- static_cast<GLfloat>(valueArray.at(4).toDouble()),
- static_cast<GLfloat>(valueArray.at(5).toDouble()),
- static_cast<GLfloat>(valueArray.at(6).toDouble()),
- static_cast<GLfloat>(valueArray.at(7).toDouble()),
- static_cast<GLfloat>(valueArray.at(8).toDouble()),
- static_cast<GLfloat>(valueArray.at(9).toDouble()),
- static_cast<GLfloat>(valueArray.at(10).toDouble()),
- static_cast<GLfloat>(valueArray.at(11).toDouble()),
- static_cast<GLfloat>(valueArray.at(12).toDouble()),
- static_cast<GLfloat>(valueArray.at(13).toDouble()),
- static_cast<GLfloat>(valueArray.at(14).toDouble()),
- static_cast<GLfloat>(valueArray.at(15).toDouble())));
- case GL_SAMPLER_2D:
- return QVariant(valueArray.at(0).toString());
- }
- }
- return QVariant();
-}
-
-QAttribute::DataType GLTFParser::accessorTypeFromJSON(int componentType)
-{
- if (componentType == GL_BYTE) {
- return QAttribute::Byte;
- } else if (componentType == GL_UNSIGNED_BYTE) {
- return QAttribute::UnsignedByte;
- } else if (componentType == GL_SHORT) {
- return QAttribute::Short;
- } else if (componentType == GL_UNSIGNED_SHORT) {
- return QAttribute::UnsignedShort;
- } else if (componentType == GL_UNSIGNED_INT) {
- return QAttribute::UnsignedInt;
- } else if (componentType == GL_FLOAT) {
- return QAttribute::Float;
- }
-
- //There shouldn't be an invalid case here
- qCWarning(GLTFParserLog) << "unsupported accessor type" << componentType;
- return QAttribute::Float;
-}
-
-uint GLTFParser::accessorDataSizeFromJson(const QString &type)
-{
- QString typeName = type.toUpper();
- if (typeName == "SCALAR")
- return 1;
- if (typeName == "VEC2")
- return 2;
- if (typeName == "VEC3")
- return 3;
- if (typeName == "VEC4")
- return 4;
- if (typeName == "MAT2")
- return 4;
- if (typeName == "MAT3")
- return 9;
- if (typeName == "MAT4")
- return 16;
-
- return 0;
-}
-
-QRenderState *GLTFParser::buildStateEnable(int state)
-{
- int type = 0;
- //By calling buildState with QJsonValue(), a Render State with
- //default values is created.
-
- if (state == GL_BLEND) {
- //It doesn't make sense to handle this state alone
- return nullptr;
- }
-
- if (state == GL_CULL_FACE) {
- return buildState(QStringLiteral("cullFace"), QJsonValue(), type);
- }
-
- if (state == GL_DEPTH_TEST) {
- return buildState(QStringLiteral("depthFunc"), QJsonValue(), type);
- }
-
- if (state == GL_POLYGON_OFFSET_FILL) {
- return buildState(QStringLiteral("polygonOffset"), QJsonValue(), type);
- }
-
- if (state == GL_SAMPLE_ALPHA_TO_COVERAGE) {
- return new QAlphaCoverage();
- }
-
- if (state == GL_SCISSOR_TEST) {
- return buildState(QStringLiteral("scissor"), QJsonValue(), type);
- }
-
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << state;
-
- return nullptr;
-}
-
-QRenderState* GLTFParser::buildState(const QString& functionName, const QJsonValue &value, int &type)
-{
- type = -1;
- QJsonArray values = value.toArray();
-
- if (functionName == QStringLiteral("blendColor")) {
- type = GL_BLEND;
- //TODO: support render state blendColor
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << functionName;
- return nullptr;
- }
-
- if (functionName == QStringLiteral("blendEquationSeparate")) {
- type = GL_BLEND;
- //TODO: support settings blendEquation alpha
- QBlendEquation *blendEquation = new QBlendEquation;
- blendEquation->setMode((QBlendEquation::BlendMode)values.at(0).toInt(GL_FUNC_ADD));
- return blendEquation;
- }
-
- if (functionName == QStringLiteral("blendFuncSeparate")) {
- type = GL_BLEND;
- QBlendStateSeparate *blendState = new QBlendStateSeparate;
- blendState->setSrcRGB((QBlendState::Blending)values.at(0).toInt(GL_ONE));
- blendState->setSrcAlpha((QBlendState::Blending)values.at(1).toInt(GL_ONE));
- blendState->setDstRGB((QBlendState::Blending)values.at(2).toInt(GL_ZERO));
- blendState->setDstAlpha((QBlendState::Blending)values.at(3).toInt(GL_ZERO));
- return blendState;
- }
-
- if (functionName == QStringLiteral("colorMask")) {
- QColorMask *colorMask = new QColorMask;
- colorMask->setRed(values.at(0).toBool(true));
- colorMask->setGreen(values.at(1).toBool(true));
- colorMask->setBlue(values.at(2).toBool(true));
- colorMask->setAlpha(values.at(3).toBool(true));
- return colorMask;
- }
-
- if (functionName == QStringLiteral("cullFace")) {
- type = GL_CULL_FACE;
- QCullFace *cullFace = new QCullFace;
- cullFace->setMode((QCullFace::CullingMode)values.at(0).toInt(GL_BACK));
- return cullFace;
- }
-
- if (functionName == QStringLiteral("depthFunc")) {
- type = GL_DEPTH_TEST;
- QDepthTest *depthTest = new QDepthTest;
- depthTest->setFunc((QDepthTest::DepthFunc)values.at(0).toInt(GL_LESS));
- return depthTest;
- }
-
- if (functionName == QStringLiteral("depthMask")) {
- QDepthMask *depthMask = new QDepthMask;
- depthMask->setMask(values.at(0).toBool(true));
- }
-
- if (functionName == QStringLiteral("depthRange")) {
- //TODO: support render state depthRange
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << functionName;
- return nullptr;
- }
-
- if (functionName == QStringLiteral("frontFace")) {
- QFrontFace *frontFace = new QFrontFace;
- frontFace->setDirection((QFrontFace::FaceDir)values.at(0).toInt(GL_CCW));
- return frontFace;
- }
-
- if (functionName == QStringLiteral("lineWidth")) {
- //TODO: support render state lineWidth
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << functionName;
- return nullptr;
- }
-
- if (functionName == QStringLiteral("polygonOffset")) {
- type = GL_POLYGON_OFFSET_FILL;
- QPolygonOffset *polygonOffset = new QPolygonOffset;
- polygonOffset->setFactor((float)values.at(0).toDouble(0.0f));
- polygonOffset->setUnits((float)values.at(1).toDouble(0.0f));
- return polygonOffset;
- }
-
- if (functionName == QStringLiteral("scissor")) {
- type = GL_SCISSOR_TEST;
- QScissorTest *scissorTest = new QScissorTest;
- scissorTest->setLeft(values.at(0).toDouble(0.0f));
- scissorTest->setBottom(values.at(1).toDouble(0.0f));
- scissorTest->setWidth(values.at(2).toDouble(0.0f));
- scissorTest->setHeight(values.at(3).toDouble(0.0f));
- return scissorTest;
- }
-
- qCWarning(GLTFParserLog) << Q_FUNC_INFO << "unsupported render state:" << functionName;
- return nullptr;
-}
-
-} // namespace Qt3DRender
-
-QT_END_NAMESPACE
diff --git a/src/plugins/sceneparsers/gltfexport/gltfexport.pro b/src/plugins/sceneparsers/gltfexport/gltfexport.pro
index 9d9791732..9da330605 100644
--- a/src/plugins/sceneparsers/gltfexport/gltfexport.pro
+++ b/src/plugins/sceneparsers/gltfexport/gltfexport.pro
@@ -1,9 +1,6 @@
TARGET = gltfsceneexport
QT += core-private 3dcore 3dcore-private 3drender 3drender-private 3dextras
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
gltfexporter.h
diff --git a/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp b/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp
index ad657b4f2..b4b87ef76 100644
--- a/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp
+++ b/src/plugins/sceneparsers/gltfexport/gltfexporter.cpp
@@ -84,6 +84,7 @@
#include <Qt3DRender/qclipplane.h>
#include <Qt3DRender/qcolormask.h>
#include <Qt3DRender/qcullface.h>
+#include <Qt3DRender/qdepthrange.h>
#include <Qt3DRender/qdepthtest.h>
#include <Qt3DRender/qdithering.h>
#include <Qt3DRender/qfrontface.h>
@@ -1679,7 +1680,6 @@ void GLTFExporter::exportMaterials(QJsonObject &materials)
{
QHash<QString, bool> imageHasAlpha;
- QHashIterator<QMaterial *, MaterialInfo> matIt(m_materialInfo);
for (auto matIt = m_materialInfo.constBegin(); matIt != m_materialInfo.constEnd(); ++matIt) {
const QMaterial *material = matIt.key();
const MaterialInfo &matInfo = matIt.value();
@@ -1938,6 +1938,11 @@ void GLTFExporter::exportRenderStates(QJsonObject &jsonObj, const QRenderPass *p
auto s = qobject_cast<QCullFace *>(state);
arr << s->mode();
funcObj["cullFace"] = arr;
+ } else if (qobject_cast<QDepthRange *>(state)) {
+ auto s = qobject_cast<QDepthRange *>(state);
+ arr << s->nearValue();
+ arr << s->farValue();
+ funcObj["depthRange"] = arr;
} else if (qobject_cast<QDepthTest *>(state)) {
auto s = qobject_cast<QDepthTest *>(state);
arr << s->depthFunction();
diff --git a/src/quick3d/imports/animation/importsanimation.pro b/src/quick3d/imports/animation/importsanimation.pro
index 7b637dd3c..734c5186b 100644
--- a/src/quick3d/imports/animation/importsanimation.pro
+++ b/src/quick3d/imports/animation/importsanimation.pro
@@ -5,9 +5,6 @@ IMPORT_VERSION = 2.$$QT_MINOR_VERSION
QT += core-private qml qml-private 3dcore 3drender 3danimation 3dquick 3dquickrender 3dquickanimation 3dquick-private 3dquickanimation-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
qt3dquick3danimationplugin.h
diff --git a/src/quick3d/imports/animation/plugins.qmltypes b/src/quick3d/imports/animation/plugins.qmltypes
index a8f207245..aff5ccb9c 100644
--- a/src/quick3d/imports/animation/plugins.qmltypes
+++ b/src/quick3d/imports/animation/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Animation 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Animation 2.14'
Module {
dependencies: ["Qt3D.Core 2.0"]
@@ -699,4 +699,57 @@ Module {
isReadonly: true
}
}
+ Component {
+ name: "Qt3DCore::QNode"
+ defaultProperty: "data"
+ prototype: "QObject"
+ exports: ["Qt3D.Animation/Node 2.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [209]
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
+ Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
+ Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
+ Signal {
+ name: "parentChanged"
+ Parameter { name: "parent"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "enabledChanged"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ Signal { name: "nodeDestroyed" }
+ Method {
+ name: "setParent"
+ Parameter { name: "parent"; type: "QNode"; isPointer: true }
+ }
+ Method {
+ name: "setEnabled"
+ Parameter { name: "isEnabled"; type: "bool" }
+ }
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ Property { name: "propertyTrackingOverrides"; revision: 209; type: "QJSValue" }
+ Property { name: "data"; revision: 209; type: "QObject"; isList: true; isReadonly: true }
+ Property {
+ name: "childNodes"
+ revision: 209
+ type: "Qt3DCore::QNode"
+ isList: true
+ isReadonly: true
+ }
+ }
}
diff --git a/src/quick3d/imports/core/importscore.pro b/src/quick3d/imports/core/importscore.pro
index 4ff71488a..9ba6ac66d 100644
--- a/src/quick3d/imports/core/importscore.pro
+++ b/src/quick3d/imports/core/importscore.pro
@@ -5,9 +5,6 @@ IMPORT_VERSION = 2.$$QT_MINOR_VERSION
QT += core-private qml qml-private quick quick-private 3dcore 3dcore-private 3dquick 3dquick-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
qt3dquick3dcoreplugin.h
diff --git a/src/quick3d/imports/core/plugins.qmltypes b/src/quick3d/imports/core/plugins.qmltypes
index 390fd78fb..476bb99a7 100644
--- a/src/quick3d/imports/core/plugins.qmltypes
+++ b/src/quick3d/imports/core/plugins.qmltypes
@@ -4,11 +4,73 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable Qt3D.Core 2.13'
+// 'qmlplugindump -nonrelocatable Qt3D.Core 2.14'
Module {
dependencies: ["QtQuick 2.0"]
Component {
+ name: "QQmlEasingValueType"
+ exports: ["Qt3D.Core/Easing 2.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Type"
+ values: {
+ "Linear": 0,
+ "InQuad": 1,
+ "OutQuad": 2,
+ "InOutQuad": 3,
+ "OutInQuad": 4,
+ "InCubic": 5,
+ "OutCubic": 6,
+ "InOutCubic": 7,
+ "OutInCubic": 8,
+ "InQuart": 9,
+ "OutQuart": 10,
+ "InOutQuart": 11,
+ "OutInQuart": 12,
+ "InQuint": 13,
+ "OutQuint": 14,
+ "InOutQuint": 15,
+ "OutInQuint": 16,
+ "InSine": 17,
+ "OutSine": 18,
+ "InOutSine": 19,
+ "OutInSine": 20,
+ "InExpo": 21,
+ "OutExpo": 22,
+ "InOutExpo": 23,
+ "OutInExpo": 24,
+ "InCirc": 25,
+ "OutCirc": 26,
+ "InOutCirc": 27,
+ "OutInCirc": 28,
+ "InElastic": 29,
+ "OutElastic": 30,
+ "InOutElastic": 31,
+ "OutInElastic": 32,
+ "InBack": 33,
+ "OutBack": 34,
+ "InOutBack": 35,
+ "OutInBack": 36,
+ "InBounce": 37,
+ "OutBounce": 38,
+ "InOutBounce": 39,
+ "OutInBounce": 40,
+ "InCurve": 41,
+ "OutCurve": 42,
+ "SineCurve": 43,
+ "CosineCurve": 44,
+ "Bezier": 45
+ }
+ }
+ Property { name: "type"; type: "Type" }
+ Property { name: "amplitude"; type: "double" }
+ Property { name: "overshoot"; type: "double" }
+ Property { name: "period"; type: "double" }
+ Property { name: "bezierCurve"; type: "QVariantList" }
+ }
+ Component {
name: "Qt3DCore::QAbstractSkeleton"
prototype: "Qt3DCore::QNode"
exports: ["Qt3D.Core/AbstractSkeleton 2.10"]
@@ -266,8 +328,8 @@ Module {
Component {
name: "Qt3DCore::QTransform"
prototype: "Qt3DCore::QComponent"
- exports: ["Qt3D.Core/Transform 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["Qt3D.Core/Transform 2.0", "Qt3D.Core/Transform 2.14"]
+ exportMetaObjectRevisions: [0, 14]
Property { name: "matrix"; type: "QMatrix4x4" }
Property { name: "scale"; type: "float" }
Property { name: "scale3D"; type: "QVector3D" }
@@ -276,6 +338,7 @@ Module {
Property { name: "rotationX"; type: "float" }
Property { name: "rotationY"; type: "float" }
Property { name: "rotationZ"; type: "float" }
+ Property { name: "worldMatrix"; revision: 14; type: "QMatrix4x4"; isReadonly: true }
Signal {
name: "scaleChanged"
Parameter { name: "scale"; type: "float" }
@@ -304,6 +367,10 @@ Module {
name: "rotationZChanged"
Parameter { name: "rotationZ"; type: "float" }
}
+ Signal {
+ name: "worldMatrixChanged"
+ Parameter { name: "worldMatrix"; type: "QMatrix4x4" }
+ }
Method {
name: "setScale"
Parameter { name: "scale"; type: "float" }
diff --git a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp
index 0f8f7d11e..59df221ab 100644
--- a/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp
+++ b/src/quick3d/imports/core/qt3dquick3dcoreplugin.cpp
@@ -69,6 +69,7 @@ void Qt3DQuick3DCorePlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DCore::Quick::Quick3DEntityLoader, 12>(uri, 2, 12, "EntityLoader");
qmlRegisterType<Qt3DCore::Quick::Quick3DNodeInstantiator>(uri, 2, 0, "NodeInstantiator");
qmlRegisterType<Qt3DCore::QTransform>(uri, 2, 0, "Transform");
+ qmlRegisterType<Qt3DCore::QTransform, 14>(uri, 2, 14, "Transform");
qmlRegisterType<Qt3DCore::QArmature>(uri, 2, 10, "Armature");
qmlRegisterUncreatableType<Qt3DCore::QAbstractSkeleton>(uri, 2, 10, "AbstractSkeleton", QStringLiteral("AbstractSkeleton is an abstract base class"));
qmlRegisterType<Qt3DCore::QSkeletonLoader>(uri, 2, 10, "SkeletonLoader");
diff --git a/src/quick3d/imports/extras/importsextras.pro b/src/quick3d/imports/extras/importsextras.pro
index ea5b39a89..1ac629422 100644
--- a/src/quick3d/imports/extras/importsextras.pro
+++ b/src/quick3d/imports/extras/importsextras.pro
@@ -5,9 +5,6 @@ IMPORT_VERSION = 2.$$QT_MINOR_VERSION
QT += core-private qml qml-private quick quick-private 3dcore 3dcore-private 3dquick 3dquick-private 3dextras 3dlogic 3dquickextras 3dquickextras-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
qt3dquick3dextrasplugin.h
diff --git a/src/quick3d/imports/extras/plugins.qmltypes b/src/quick3d/imports/extras/plugins.qmltypes
index 72857d402..fcc15e022 100644
--- a/src/quick3d/imports/extras/plugins.qmltypes
+++ b/src/quick3d/imports/extras/plugins.qmltypes
@@ -4,10 +4,51 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Extras 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Extras 2.14'
Module {
dependencies: ["Qt3D.Logic 2.0", "Qt3D.Render 2.0"]
+ Component { name: "Qt3DCore::QEntity"; prototype: "Qt3DCore::QNode" }
+ Component {
+ name: "Qt3DCore::QNode"
+ prototype: "QObject"
+ Enum {
+ name: "PropertyTrackingMode"
+ values: {
+ "TrackFinalValues": 0,
+ "DontTrackValues": 1,
+ "TrackAllValues": 2
+ }
+ }
+ Property { name: "parent"; type: "Qt3DCore::QNode"; isPointer: true }
+ Property { name: "enabled"; type: "bool" }
+ Property { name: "defaultPropertyTrackingMode"; revision: 9; type: "PropertyTrackingMode" }
+ Signal {
+ name: "parentChanged"
+ Parameter { name: "parent"; type: "QObject"; isPointer: true }
+ }
+ Signal {
+ name: "enabledChanged"
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Signal {
+ name: "defaultPropertyTrackingModeChanged"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ Signal { name: "nodeDestroyed" }
+ Method {
+ name: "setParent"
+ Parameter { name: "parent"; type: "QNode"; isPointer: true }
+ }
+ Method {
+ name: "setEnabled"
+ Parameter { name: "isEnabled"; type: "bool" }
+ }
+ Method {
+ name: "setDefaultPropertyTrackingMode"
+ Parameter { name: "mode"; type: "PropertyTrackingMode" }
+ }
+ }
Component {
name: "Qt3DExtras::Extras::Quick::Quick3DLevelOfDetailLoader"
prototype: "Qt3DCore::QEntity"
@@ -758,13 +799,15 @@ Module {
prototype: "Qt3DRender::QTechniqueFilter"
exports: [
"Qt3D.Extras/ForwardRenderer 2.0",
+ "Qt3D.Extras/ForwardRenderer 2.14",
"Qt3D.Extras/ForwardRenderer 2.9"
]
- exportMetaObjectRevisions: [0, 9]
+ exportMetaObjectRevisions: [0, 14, 9]
Property { name: "surface"; type: "QObject"; isPointer: true }
Property { name: "window"; type: "QObject"; isPointer: true }
Property { name: "viewportRect"; type: "QRectF" }
Property { name: "clearColor"; type: "QColor" }
+ Property { name: "buffersToClear"; revision: 14; type: "Qt3DRender::QClearBuffers::BufferType" }
Property { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
Property { name: "externalRenderTargetSize"; type: "QSize" }
Property { name: "frustumCulling"; type: "bool" }
@@ -778,6 +821,10 @@ Module {
Parameter { name: "clearColor"; type: "QColor" }
}
Signal {
+ name: "buffersToClearChanged"
+ Parameter { type: "Qt3DRender::QClearBuffers::BufferType" }
+ }
+ Signal {
name: "cameraChanged"
Parameter { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
}
@@ -806,6 +853,10 @@ Module {
Parameter { name: "clearColor"; type: "QColor" }
}
Method {
+ name: "setBuffersToClear"
+ Parameter { type: "Qt3DRender::QClearBuffers::BufferType" }
+ }
+ Method {
name: "setCamera"
Parameter { name: "camera"; type: "Qt3DCore::QEntity"; isPointer: true }
}
diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
index 91ec85795..b675ec283 100644
--- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
+++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
@@ -87,6 +87,7 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri)
// Framegraphs
qmlRegisterType<Qt3DExtras::QForwardRenderer>(uri, 2, 0, "ForwardRenderer");
qmlRegisterType<Qt3DExtras::QForwardRenderer, 9>(uri, 2, 9, "ForwardRenderer");
+ qmlRegisterType<Qt3DExtras::QForwardRenderer, 14>(uri, 2, 14, "ForwardRenderer");
// Entities
qmlRegisterType<Qt3DExtras::QSkyboxEntity>(uri, 2, 0, "SkyboxEntity");
diff --git a/src/quick3d/imports/input/importsinput.pro b/src/quick3d/imports/input/importsinput.pro
index 2b0dd0354..ec333f992 100644
--- a/src/quick3d/imports/input/importsinput.pro
+++ b/src/quick3d/imports/input/importsinput.pro
@@ -5,9 +5,6 @@ IMPORT_VERSION = 2.$$QT_MINOR_VERSION
QT += core-private qml 3dcore 3dinput 3dinput-private 3dquickinput-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
OTHER_FILES += qmldir
HEADERS += \
diff --git a/src/quick3d/imports/input/plugins.qmltypes b/src/quick3d/imports/input/plugins.qmltypes
index 8e9cac4d1..0a70b97c3 100644
--- a/src/quick3d/imports/input/plugins.qmltypes
+++ b/src/quick3d/imports/input/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Input 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Input 2.14'
Module {
dependencies: ["Qt3D.Core 2.0"]
diff --git a/src/quick3d/imports/logic/importslogic.pro b/src/quick3d/imports/logic/importslogic.pro
index 955a4fd61..2fc2accc5 100644
--- a/src/quick3d/imports/logic/importslogic.pro
+++ b/src/quick3d/imports/logic/importslogic.pro
@@ -5,9 +5,6 @@ IMPORT_VERSION = 2.$$QT_MINOR_VERSION
QT += core-private qml 3dcore 3dlogic
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
OTHER_FILES += qmldir
HEADERS += \
diff --git a/src/quick3d/imports/logic/plugins.qmltypes b/src/quick3d/imports/logic/plugins.qmltypes
index 294f6b068..1ad7b1f58 100644
--- a/src/quick3d/imports/logic/plugins.qmltypes
+++ b/src/quick3d/imports/logic/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Logic 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Logic 2.14'
Module {
dependencies: ["Qt3D.Core 2.0"]
diff --git a/src/quick3d/imports/render/importsrender.pro b/src/quick3d/imports/render/importsrender.pro
index a8d68c8ee..977668c40 100644
--- a/src/quick3d/imports/render/importsrender.pro
+++ b/src/quick3d/imports/render/importsrender.pro
@@ -5,9 +5,6 @@ IMPORT_VERSION = 2.$$QT_MINOR_VERSION
QT += core-private qml qml-private 3dcore 3drender 3drender-private 3dquick 3dquick-private 3dquickrender-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
qt3dquick3drenderplugin.h
diff --git a/src/quick3d/imports/render/plugins.qmltypes b/src/quick3d/imports/render/plugins.qmltypes
index f5f5b3c61..6408abb27 100644
--- a/src/quick3d/imports/render/plugins.qmltypes
+++ b/src/quick3d/imports/render/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Render 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json Qt3D.Render 2.14'
Module {
dependencies: ["Qt3D.Core 2.0"]
@@ -362,7 +362,8 @@ Module {
"R5G6B5": 36194,
"RGB5A1": 32855,
"RGBA4": 32854,
- "RGB10A2": 36975,
+ "RGB10A2": 32857,
+ "RGB10A2U": 36975,
"D16": 33189,
"D24": 33190,
"D24S8": 35056,
@@ -588,6 +589,10 @@ Module {
name: "setSamples"
Parameter { name: "samples"; type: "int" }
}
+ Method {
+ name: "updateData"
+ Parameter { name: "update"; type: "QTextureDataUpdate" }
+ }
}
Component {
name: "Qt3DRender::QAbstractTextureImage"
@@ -1068,8 +1073,12 @@ Module {
Component {
name: "Qt3DRender::QCamera"
prototype: "Qt3DCore::QEntity"
- exports: ["Qt3D.Render/Camera 2.0", "Qt3D.Render/Camera 2.9"]
- exportMetaObjectRevisions: [0, 9]
+ exports: [
+ "Qt3D.Render/Camera 2.0",
+ "Qt3D.Render/Camera 2.14",
+ "Qt3D.Render/Camera 2.9"
+ ]
+ exportMetaObjectRevisions: [0, 14, 9]
Enum {
name: "CameraTranslationOption"
values: {
@@ -1093,6 +1102,20 @@ Module {
Property { name: "viewCenter"; type: "QVector3D" }
Property { name: "viewVector"; type: "QVector3D"; isReadonly: true }
Property { name: "viewMatrix"; type: "QMatrix4x4"; isReadonly: true }
+ Property {
+ name: "lens"
+ revision: 14
+ type: "Qt3DRender::QCameraLens"
+ isReadonly: true
+ isPointer: true
+ }
+ Property {
+ name: "transform"
+ revision: 14
+ type: "Qt3DCore::QTransform"
+ isReadonly: true
+ isPointer: true
+ }
Signal {
name: "projectionTypeChanged"
Parameter { name: "projectionType"; type: "QCameraLens::ProjectionType" }
@@ -1666,6 +1689,30 @@ Module {
}
}
Component {
+ name: "Qt3DRender::QDepthRange"
+ prototype: "Qt3DRender::QRenderState"
+ exports: ["Qt3D.Render/DepthRange 2.14"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "nearValue"; type: "double" }
+ Property { name: "farValue"; type: "double" }
+ Signal {
+ name: "nearValueChanged"
+ Parameter { name: "nearValue"; type: "double" }
+ }
+ Signal {
+ name: "farValueChanged"
+ Parameter { name: "farValue"; type: "double" }
+ }
+ Method {
+ name: "setNearValue"
+ Parameter { name: "value"; type: "double" }
+ }
+ Method {
+ name: "setFarValue"
+ Parameter { name: "value"; type: "double" }
+ }
+ }
+ Component {
name: "Qt3DRender::QDepthTest"
prototype: "Qt3DRender::QRenderState"
exports: ["Qt3D.Render/DepthTest 2.0"]
@@ -2335,6 +2382,12 @@ Module {
exportMetaObjectRevisions: [0]
}
Component {
+ name: "Qt3DRender::QNoPicking"
+ prototype: "Qt3DRender::QFrameGraphNode"
+ exports: ["Qt3D.Render/NoPicking 2.14"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
name: "Qt3DRender::QObjectPicker"
prototype: "Qt3DCore::QComponent"
exports: [
@@ -2429,9 +2482,9 @@ Module {
Component {
name: "Qt3DRender::QPickEvent"
prototype: "QObject"
- exports: ["Qt3D.Render/PickEvent 2.0"]
+ exports: ["Qt3D.Render/PickEvent 2.0", "Qt3D.Render/PickEvent 2.14"]
isCreatable: false
- exportMetaObjectRevisions: [0]
+ exportMetaObjectRevisions: [0, 14]
Enum {
name: "Buttons"
values: {
@@ -2461,6 +2514,20 @@ Module {
Property { name: "button"; type: "Qt3DRender::QPickEvent::Buttons"; isReadonly: true }
Property { name: "buttons"; type: "int"; isReadonly: true }
Property { name: "modifiers"; type: "int"; isReadonly: true }
+ Property {
+ name: "viewport"
+ revision: 14
+ type: "Qt3DRender::QViewport"
+ isReadonly: true
+ isPointer: true
+ }
+ Property {
+ name: "entity"
+ revision: 14
+ type: "Qt3DCore::QEntity"
+ isReadonly: true
+ isPointer: true
+ }
Signal {
name: "acceptedChanged"
Parameter { name: "accepted"; type: "bool" }
@@ -2654,6 +2721,46 @@ Module {
}
}
Component {
+ name: "Qt3DRender::QRasterMode"
+ prototype: "Qt3DRender::QRenderState"
+ exports: ["Qt3D.Render/RasterMode 2.13"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "RasterMode"
+ values: {
+ "Points": 6912,
+ "Lines": 6913,
+ "Fill": 6914
+ }
+ }
+ Enum {
+ name: "FaceMode"
+ values: {
+ "Front": 1028,
+ "Back": 1029,
+ "FrontAndBack": 1032
+ }
+ }
+ Property { name: "rasterMode"; type: "RasterMode" }
+ Property { name: "faceMode"; type: "FaceMode" }
+ Signal {
+ name: "rasterModeChanged"
+ Parameter { name: "rasterMode"; type: "RasterMode" }
+ }
+ Signal {
+ name: "faceModeChanged"
+ Parameter { name: "faceMode"; type: "FaceMode" }
+ }
+ Method {
+ name: "setRasterMode"
+ Parameter { name: "rasterMode"; type: "RasterMode" }
+ }
+ Method {
+ name: "setFaceMode"
+ Parameter { name: "faceMode"; type: "FaceMode" }
+ }
+ }
+ Component {
name: "Qt3DRender::QRayCaster"
prototype: "Qt3DRender::QAbstractRayCaster"
Property { name: "origin"; type: "QVector3D" }
@@ -3151,6 +3258,120 @@ Module {
exportMetaObjectRevisions: [0]
}
Component {
+ name: "Qt3DRender::QShaderImage"
+ prototype: "Qt3DCore::QNode"
+ exports: ["Qt3D.Render/ShaderImage 2.14"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Access"
+ values: {
+ "ReadOnly": 0,
+ "WriteOnly": 1,
+ "ReadWrite": 2
+ }
+ }
+ Enum {
+ name: "ImageFormat"
+ values: {
+ "NoFormat": 0,
+ "Automatic": 1,
+ "R8_UNorm": 33321,
+ "RG8_UNorm": 33323,
+ "RGBA8_UNorm": 32856,
+ "R16_UNorm": 33322,
+ "RG16_UNorm": 33324,
+ "RGBA16_UNorm": 32859,
+ "R8_SNorm": 36756,
+ "RG8_SNorm": 36757,
+ "RGBA8_SNorm": 36759,
+ "R16_SNorm": 36760,
+ "RG16_SNorm": 36761,
+ "RGBA16_SNorm": 36763,
+ "R8U": 33330,
+ "RG8U": 33336,
+ "RGBA8U": 36220,
+ "R16U": 33332,
+ "RG16U": 33338,
+ "RGBA16U": 36214,
+ "R32U": 33334,
+ "RG32U": 33340,
+ "RGBA32U": 36208,
+ "R8I": 33329,
+ "RG8I": 33335,
+ "RGBA8I": 36238,
+ "R16I": 33331,
+ "RG16I": 33337,
+ "RGBA16I": 36232,
+ "R32I": 33333,
+ "RG32I": 33339,
+ "RGBA32I": 36226,
+ "R16F": 33325,
+ "RG16F": 33327,
+ "RGBA16F": 34842,
+ "R32F": 33326,
+ "RG32F": 33328,
+ "RGBA32F": 34836,
+ "RG11B10F": 35898,
+ "RGB10A2": 32857,
+ "RGB10A2U": 36975
+ }
+ }
+ Property { name: "texture"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ Property { name: "layered"; type: "bool" }
+ Property { name: "mipLevel"; type: "int" }
+ Property { name: "layer"; type: "int" }
+ Property { name: "access"; type: "Access" }
+ Property { name: "format"; type: "ImageFormat" }
+ Signal {
+ name: "textureChanged"
+ Parameter { name: "texture"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Signal {
+ name: "layeredChanged"
+ Parameter { name: "layered"; type: "bool" }
+ }
+ Signal {
+ name: "mipLevelChanged"
+ Parameter { name: "mipLevel"; type: "int" }
+ }
+ Signal {
+ name: "layerChanged"
+ Parameter { name: "layer"; type: "int" }
+ }
+ Signal {
+ name: "accessChanged"
+ Parameter { name: "access"; type: "Access" }
+ }
+ Signal {
+ name: "formatChanged"
+ Parameter { name: "format"; type: "ImageFormat" }
+ }
+ Method {
+ name: "setTexture"
+ Parameter { name: "texture"; type: "Qt3DRender::QAbstractTexture"; isPointer: true }
+ }
+ Method {
+ name: "setLayered"
+ Parameter { name: "layered"; type: "bool" }
+ }
+ Method {
+ name: "setMipLevel"
+ Parameter { name: "mipLevel"; type: "int" }
+ }
+ Method {
+ name: "setLayer"
+ Parameter { name: "layer"; type: "int" }
+ }
+ Method {
+ name: "setAccess"
+ Parameter { name: "access"; type: "Access" }
+ }
+ Method {
+ name: "setFormat"
+ Parameter { name: "format"; type: "ImageFormat" }
+ }
+ }
+ Component {
name: "Qt3DRender::QShaderProgram"
prototype: "Qt3DCore::QNode"
exports: [
@@ -3400,7 +3621,8 @@ Module {
"StateChangeCost": 1,
"BackToFront": 2,
"Material": 4,
- "FrontToBack": 8
+ "FrontToBack": 8,
+ "Texture": 16
}
}
Property { name: "sortTypes"; type: "QVector<int>" }
@@ -3653,6 +3875,25 @@ Module {
}
}
Component {
+ name: "Qt3DRender::QSubtreeEnabler"
+ prototype: "Qt3DRender::QFrameGraphNode"
+ exports: ["Qt3D.Render/SubtreeEnabler 2.14"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Enablement"
+ values: {
+ "Persistent": 0,
+ "SingleShot": 1
+ }
+ }
+ Property { name: "enablement"; type: "Enablement" }
+ Signal {
+ name: "enablementChanged"
+ Parameter { name: "enablement"; type: "Qt3DRender::QSubtreeEnabler::Enablement" }
+ }
+ Method { name: "requestUpdate" }
+ }
+ Component {
name: "Qt3DRender::QTechnique"
defaultProperty: "data"
prototype: "Qt3DCore::QNode"
diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
index 3f4a1278e..e16314c8e 100644
--- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
+++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
@@ -55,6 +55,7 @@
#include <Qt3DRender/qcolormask.h>
#include <Qt3DRender/qcomputecommand.h>
#include <Qt3DRender/qcullface.h>
+#include <Qt3DRender/qdepthrange.h>
#include <Qt3DRender/qdepthtest.h>
#include <Qt3DRender/qdirectionallight.h>
#include <Qt3DRender/qdispatchcompute.h>
@@ -114,6 +115,10 @@
#include <Qt3DRender/qblitframebuffer.h>
#include <Qt3DRender/qsetfence.h>
#include <Qt3DRender/qwaitfence.h>
+#include <Qt3DRender/qrastermode.h>
+#include <Qt3DRender/qnopicking.h>
+#include <Qt3DRender/qshaderimage.h>
+#include <Qt3DRender/qsubtreeenabler.h>
#include <QtGui/qwindow.h>
@@ -188,6 +193,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
// Camera
qmlRegisterType<Qt3DRender::QCamera>(uri, 2, 0, "Camera");
qmlRegisterType<Qt3DRender::QCamera, 9>(uri, 2, 9, "Camera");
+ qmlRegisterType<Qt3DRender::QCamera, 14>(uri, 2, 14, "Camera");
qmlRegisterType<Qt3DRender::QCameraLens>(uri, 2, 0, "CameraLens");
qmlRegisterType<Qt3DRender::QCameraLens, 9>(uri, 2, 9, "CameraLens");
@@ -210,6 +216,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
qmlRegisterUncreatableType<Qt3DRender::QAbstractTextureImage>(uri, 2, 0, "QAbstractTextureImage", QStringLiteral("QAbstractTextureImage is abstract"));
qmlRegisterType<Qt3DRender::QTextureImage>(uri, 2, 0, "TextureImage");
qmlRegisterType<Qt3DRender::QSharedGLTexture>(uri, 2, 13, "SharedGLTexture");
+ qmlRegisterType<Qt3DRender::QShaderImage>(uri, 2, 14, "ShaderImage");
// Geometry
qmlRegisterType<Qt3DRender::QAttribute>(uri, 2, 0, "Attribute");
@@ -232,6 +239,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DRender::QObjectPicker, 9>(uri, 2, 9, "ObjectPicker");
qmlRegisterType<Qt3DRender::QObjectPicker, 13>(uri, 2, 13, "ObjectPicker");
qmlRegisterUncreatableType<Qt3DRender::QPickEvent>(uri, 2, 0, "PickEvent", QStringLiteral("Events cannot be created"));
+ qmlRegisterUncreatableType<Qt3DRender::QPickEvent, 14>(uri, 2, 14, "PickEvent", QStringLiteral("Events cannot be created"));
qmlRegisterType<Qt3DRender::Render::Quick::Quick3DRayCaster>(uri, 2, 11, "RayCaster");
qmlRegisterType<Qt3DRender::Render::Quick::Quick3DScreenRayCaster>(uri, 2, 11, "ScreenRayCaster");
@@ -272,6 +280,8 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DRender::QBlitFramebuffer>(uri, 2, 10, "BlitFramebuffer");
qmlRegisterType<Qt3DRender::QSetFence>(uri, 2, 13, "SetFence");
qmlRegisterType<Qt3DRender::QWaitFence>(uri, 2, 13, "WaitFence");
+ qmlRegisterType<Qt3DRender::QNoPicking>(uri, 2, 14, "NoPicking");
+ qmlRegisterType<Qt3DRender::QSubtreeEnabler>(uri, 2, 14, "SubtreeEnabler");
// RenderTarget
qmlRegisterType<Qt3DRender::QRenderTargetOutput>(uri, 2, 0, "RenderTargetOutput");
@@ -288,6 +298,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DRender::QBlendEquationArguments>(uri, 2, 0, "BlendEquationArguments");
qmlRegisterType<Qt3DRender::QBlendEquation>(uri, 2, 0, "BlendEquation");
qmlRegisterType<Qt3DRender::QAlphaTest>(uri, 2, 0, "AlphaTest");
+ qmlRegisterType<Qt3DRender::QDepthRange>(uri, 2, 14, "DepthRange");
qmlRegisterType<Qt3DRender::QDepthTest>(uri, 2, 0, "DepthTest");
qmlRegisterType<Qt3DRender::QMultiSampleAntiAliasing>(uri, 2, 0, "MultiSampleAntiAliasing");
qmlRegisterType<Qt3DRender::QNoDepthMask>(uri, 2, 0, "NoDepthMask");
@@ -307,6 +318,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DRender::QStencilOperation>(uri, 2, 0, "StencilOperation");
qmlRegisterType<Qt3DRender::QStencilMask>(uri, 2, 0, "StencilMask");
qmlRegisterType<Qt3DRender::QLineWidth>(uri, 2, 10, "LineWidth");
+ qmlRegisterType<Qt3DRender::QRasterMode>(uri, 2, 13, "RasterMode");
// Auto-increment the import to stay in sync with ALL future Qt minor versions
qmlRegisterModule(uri, 2, QT_VERSION_MINOR);
diff --git a/src/quick3d/imports/scene2d/importsscene2d.pro b/src/quick3d/imports/scene2d/importsscene2d.pro
index 1582d4ee4..cb87f4ca9 100644
--- a/src/quick3d/imports/scene2d/importsscene2d.pro
+++ b/src/quick3d/imports/scene2d/importsscene2d.pro
@@ -5,9 +5,6 @@ IMPORT_VERSION = 2.$$QT_MINOR_VERSION
QT += qml quick 3dcore 3drender 3drender-private 3dinput 3dlogic 3dquickscene2d 3dquickscene2d-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
qtquickscene2dplugin.h \
diff --git a/src/quick3d/imports/scene2d/plugins.qmltypes b/src/quick3d/imports/scene2d/plugins.qmltypes
index 9d2c855a6..32fb8122f 100644
--- a/src/quick3d/imports/scene2d/plugins.qmltypes
+++ b/src/quick3d/imports/scene2d/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene2D 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene2D 2.14'
Module {
dependencies: ["Qt3D.Core 2.0", "Qt3D.Render 2.0"]
diff --git a/src/quick3d/imports/scene3d/importsscene3d.pro b/src/quick3d/imports/scene3d/importsscene3d.pro
index a8ad8f417..e29f7b831 100644
--- a/src/quick3d/imports/scene3d/importsscene3d.pro
+++ b/src/quick3d/imports/scene3d/importsscene3d.pro
@@ -9,9 +9,6 @@ qtConfig(qt3d-input): QT += 3dinput
qtConfig(qt3d-logic): QT += 3dlogic
qtConfig(qt3d-animation): QT += 3danimation
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
HEADERS += \
qtquickscene3dplugin.h \
scene3dlogging_p.h \
@@ -20,7 +17,8 @@ HEADERS += \
scene3drenderer_p.h \
scene3dsgnode_p.h \
scene3dsgmaterialshader_p.h \
- scene3dsgmaterial_p.h
+ scene3dsgmaterial_p.h \
+ scene3dview_p.h
SOURCES += \
qtquickscene3dplugin.cpp \
@@ -30,7 +28,8 @@ SOURCES += \
scene3drenderer.cpp \
scene3dsgnode.cpp \
scene3dsgmaterialshader.cpp \
- scene3dsgmaterial.cpp
+ scene3dsgmaterial.cpp \
+ scene3dview.cpp
OTHER_FILES += qmldir
diff --git a/src/quick3d/imports/scene3d/plugins.qmltypes b/src/quick3d/imports/scene3d/plugins.qmltypes
index da3d7ec3e..aca01ac25 100644
--- a/src/quick3d/imports/scene3d/plugins.qmltypes
+++ b/src/quick3d/imports/scene3d/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene3D 2.13'
+// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtQuick.Scene3D 2.14'
Module {
dependencies: ["Qt3D.Core 2.0", "QtQuick 2.0"]
@@ -12,8 +12,11 @@ Module {
name: "Qt3DRender::Scene3DItem"
defaultProperty: "entity"
prototype: "QQuickItem"
- exports: ["QtQuick.Scene3D/Scene3D 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtQuick.Scene3D/Scene3D 2.0",
+ "QtQuick.Scene3D/Scene3D 2.14"
+ ]
+ exportMetaObjectRevisions: [0, 14]
Enum {
name: "CameraAspectRatioMode"
values: {
@@ -21,11 +24,19 @@ Module {
"UserAspectRatio": 1
}
}
+ Enum {
+ name: "CompositingMode"
+ values: {
+ "FBO": 0,
+ "Underlay": 1
+ }
+ }
Property { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true }
Property { name: "aspects"; type: "QStringList" }
Property { name: "multisample"; type: "bool" }
Property { name: "cameraAspectRatioMode"; type: "CameraAspectRatioMode" }
Property { name: "hoverEnabled"; type: "bool" }
+ Property { name: "compositingMode"; revision: 14; type: "CompositingMode" }
Signal {
name: "cameraAspectRatioModeChanged"
Parameter { name: "mode"; type: "CameraAspectRatioMode" }
@@ -47,9 +58,30 @@ Module {
Parameter { name: "enabled"; type: "bool" }
}
Method {
+ name: "setCompositingMode"
+ Parameter { name: "mode"; type: "CompositingMode" }
+ }
+ Method {
name: "setItemAreaAndDevicePixelRatio"
Parameter { name: "area"; type: "QSize" }
Parameter { name: "devicePixelRatio"; type: "double" }
}
}
+ Component {
+ name: "Qt3DRender::Scene3DView"
+ defaultProperty: "entity"
+ prototype: "QQuickItem"
+ exports: ["QtQuick.Scene3D/Scene3DView 2.14"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true }
+ Property { name: "scene3D"; type: "Qt3DRender::Scene3DItem"; isPointer: true }
+ Method {
+ name: "setEntity"
+ Parameter { name: "entity"; type: "Qt3DCore::QEntity"; isPointer: true }
+ }
+ Method {
+ name: "setScene3D"
+ Parameter { name: "scene3D"; type: "Scene3DItem"; isPointer: true }
+ }
+ }
}
diff --git a/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp b/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp
index d7b985e9f..00f24070e 100644
--- a/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp
+++ b/src/quick3d/imports/scene3d/qtquickscene3dplugin.cpp
@@ -42,12 +42,15 @@
#include <QtQml>
#include <scene3ditem_p.h>
+#include <scene3dview_p.h>
QT_BEGIN_NAMESPACE
void QtQuickScene3DPlugin::registerTypes(const char *uri)
{
qmlRegisterType<Qt3DRender::Scene3DItem>(uri, 2, 0, "Scene3D");
+ qmlRegisterType<Qt3DRender::Scene3DItem, 14>(uri, 2, 14, "Scene3D");
+ qmlRegisterType<Qt3DRender::Scene3DView>(uri, 2, 14, "Scene3DView");
// Auto-increment the import to stay in sync with ALL future Qt minor versions
qmlRegisterModule(uri, 2, QT_VERSION_MINOR);
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp
index eb8c6ffd9..5a1cec495 100644
--- a/src/quick3d/imports/scene3d/scene3ditem.cpp
+++ b/src/quick3d/imports/scene3d/scene3ditem.cpp
@@ -67,10 +67,16 @@
#include <Qt3DRender/private/qrendersurfaceselector_p.h>
#include <Qt3DRender/private/qrenderaspect_p.h>
+#include <Qt3DRender/private/rendersettings_p.h>
#include <scene3dcleaner_p.h>
#include <scene3dlogging_p.h>
#include <scene3drenderer_p.h>
#include <scene3dsgnode_p.h>
+#include <scene3dview_p.h>
+
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <QThread>
QT_BEGIN_NAMESPACE
@@ -117,20 +123,55 @@ namespace Qt3DRender {
\endqml
to that material.
+
+ It is not recommended to instantiate more than a single Scene3D instance
+ per application. The reason for this is that a Scene3D instance
+ instantiates the entire Qt 3D engine (memory managers, thread pool, render
+ ...) under the scene. You should instead look into using \l Scene3DView
+ instances in conjunction with a single Scene3D instance.
+
+ When using Scene3D with Scene3DViews the following conditions are expected:
+ \list
+ \li The compositingMode is set to FBO
+ \li The Scene3D is sized to occupy the full window size
+ \li The Scene3D instance is instantiated prior to any Scene3DView
+ \li The Scene3D entity property is left unset
+ \endlist
+
+ \note Åšetting the visibility of the Scene3D element to false will halt the
+ Qt 3D simulation loop. This means that binding the visible property to an
+ expression that depends on property updates driven by the Qt 3D simulation
+ loop (FrameAction) will never reavaluates.
*/
Scene3DItem::Scene3DItem(QQuickItem *parent)
: QQuickItem(parent)
, m_entity(nullptr)
+ , m_viewHolderEntity(nullptr)
+ , m_viewHolderFG(nullptr)
, m_aspectEngine(new Qt3DCore::QAspectEngine())
, m_renderAspect(nullptr)
, m_renderer(nullptr)
, m_rendererCleaner(new Scene3DCleaner())
, m_multisample(true)
+ , m_dirty(true)
+ , m_dirtyViews(false)
+ , m_clearsWindowByDefault(true)
+ , m_disableClearWindow(false)
, m_cameraAspectRatioMode(AutomaticAspectRatio)
+ , m_compositingMode(FBO)
+ , m_dummySurface(nullptr)
{
setFlag(QQuickItem::ItemHasContents, true);
setAcceptedMouseButtons(Qt::MouseButtonMask);
// TO DO: register the event source in the main thread
+
+ // Use manual drive mode when using Scene3D
+ m_aspectEngine->setRunMode(Qt3DCore::QAspectEngine::Manual);
+
+ // Give a default size so that if nothing is specified by the user
+ // we still won't get ignored by the QtQuick SG when in Underlay mode
+ setWidth(1);
+ setHeight(1);
}
Scene3DItem::~Scene3DItem()
@@ -169,7 +210,7 @@ Qt3DCore::QEntity *Scene3DItem::entity() const
void Scene3DItem::setAspects(const QStringList &aspects)
{
if (!m_aspects.isEmpty()) {
- qWarning() << "Aspects already set on the Scene3D, ignoring";
+ qCWarning(Scene3D) << "Aspects already set on the Scene3D, ignoring";
return;
}
@@ -237,6 +278,45 @@ void Scene3DItem::setHoverEnabled(bool enabled)
}
/*!
+ \qmlproperty enumeration Scene3D::compositingMode
+
+ \value FBO
+ Scene is rendered into a Frame Buffer Object which can be costly on
+ some platform and hardware but allows a greater amount of
+ flexibility. Automatic aspect ratio. This is the compositing mode to
+ choose if your Scene3D element shouldn't occupy the entire screen
+ and if you optionally plan on having it resized or animated. In this
+ mode, the position of the Scene3D in the QML file controls its
+ stacking order with regard to the other Qt Quick elements.
+
+ \value Underlay
+ Suitable for full screen 3D scenes where using an FBO might be too
+ resource intensive. Scene3D behaves as a QtQuick underlay.
+
+ Please note that when using this mode, the size of the Scene3D and
+ its transformations are ignored and the rendering will occupy the
+ whole screen. The position of the Scene3D in the QML file won't have
+ any effect either. The Qt 3D content will be drawn prior to any Qt
+ Quick content. Care has to be taken not to overdraw and hide the Qt
+ 3D content by overlapping Qt Quick content.
+
+ Additionally when using this mode, the window clearBeforeRendering
+ will be set to false automatically.
+
+ \since 5.14
+ \default FBO
+ */
+void Scene3DItem::setCompositingMode(Scene3DItem::CompositingMode mode)
+{
+ if (m_compositingMode == mode)
+ return;
+ m_compositingMode = mode;
+ emit compositingModeChanged();
+
+ QQuickItem::update();
+}
+
+/*!
\qmlproperty enumeration Scene3D::cameraAspectRatioMode
\value Scene3D.AutomaticAspectRatio
@@ -251,6 +331,71 @@ Scene3DItem::CameraAspectRatioMode Scene3DItem::cameraAspectRatioMode() const
return m_cameraAspectRatioMode;
}
+Scene3DItem::CompositingMode Scene3DItem::compositingMode() const
+{
+ return m_compositingMode;
+}
+
+// MainThread called by Scene3DView
+void Scene3DItem::addView(Scene3DView *view)
+{
+ if (m_views.contains(view))
+ return;
+
+ Qt3DRender::QFrameGraphNode *viewFG = view->viewFrameGraph();
+ Qt3DCore::QEntity *subtreeRoot = view->viewSubtree();
+
+ if (m_viewHolderEntity == nullptr) {
+ m_viewHolderEntity = new Qt3DCore::QEntity;
+
+ if (m_entity != nullptr) {
+ qCWarning(Scene3D) << "Scene3DView is not supported if the Scene3D entity property has been set";
+ }
+
+ Qt3DRender::QRenderSettings *settings = new Qt3DRender::QRenderSettings();
+ Qt3DRender::QRenderSurfaceSelector *surfaceSelector = new Qt3DRender::QRenderSurfaceSelector();
+ m_viewHolderFG = surfaceSelector;
+ surfaceSelector->setSurface(window());
+
+ // Copy setting properties from first View
+ QVector<Qt3DRender::QRenderSettings *> viewRenderSettings = subtreeRoot->componentsOfType<Qt3DRender::QRenderSettings>();
+ if (viewRenderSettings.size() > 0) {
+ Qt3DRender::QRenderSettings *viewRenderSetting = viewRenderSettings.first();
+ settings->setRenderPolicy(viewRenderSetting->renderPolicy());
+ settings->pickingSettings()->setPickMethod(viewRenderSetting->pickingSettings()->pickMethod());
+ settings->pickingSettings()->setPickResultMode(viewRenderSetting->pickingSettings()->pickResultMode());
+ }
+ settings->setActiveFrameGraph(m_viewHolderFG);
+ m_viewHolderEntity->addComponent(settings);
+
+ setEntity(m_viewHolderEntity);
+ }
+
+ // Parent FG and Subtree
+ viewFG->setParent(m_viewHolderFG);
+ subtreeRoot->setParent(m_viewHolderEntity);
+
+ m_views.push_back(view);
+ m_dirtyViews |= true;
+}
+
+// MainThread called by Scene3DView
+void Scene3DItem::removeView(Scene3DView *view)
+{
+ if (!m_views.contains(view))
+ return;
+
+ Qt3DRender::QFrameGraphNode *viewFG = view->viewFrameGraph();
+ Qt3DCore::QEntity *subtreeRoot = view->viewSubtree();
+
+ // Unparent FG and Subtree
+ viewFG->setParent(Q_NODE_NULLPTR);
+ subtreeRoot->setParent(Q_NODE_NULLPTR);
+
+ m_views.removeOne(view);
+ m_dirtyViews |= true;
+}
+
void Scene3DItem::applyRootEntityChange()
{
if (m_aspectEngine->rootEntity() != m_entity) {
@@ -286,6 +431,106 @@ void Scene3DItem::applyRootEntityChange()
}
}
+bool Scene3DItem::needsRender()
+{
+ auto renderAspectPriv = static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect));
+ const bool dirty = m_dirty
+ || (renderAspectPriv
+ && renderAspectPriv->m_renderer
+ && renderAspectPriv->m_renderer->settings()
+ && renderAspectPriv->m_renderer->settings()->renderPolicy() == QRenderSettings::Always);
+ m_dirty = false;
+ return dirty;
+}
+
+// This function is triggered in the context of the Main Thread
+// when afterAnimating is emitted
+
+// The QtQuick SG proceeds like indicated below:
+// afterAnimating (Main Thread)
+// beforeSynchronizing (SG Thread and MainThread locked)
+// afterSynchronizing (SG Thread and MainThread locked)
+// beforeRendering (SG Thread)
+
+// Note: we connect to afterAnimating rather than beforeSynchronizing as a
+// direct connection on beforeSynchronizing is executed within the SG Render
+// Thread context. This is executed before the RenderThread is asked to
+// synchronize and render
+// Note: we might still not be done rendering when this is called but
+// processFrame will block and wait for renderer to have been finished
+void Scene3DItem::onBeforeSync()
+{
+ // If we are not visible, don't processFrame changes as we would end up
+ // waiting forever for the scene to be rendered which won't happen
+ // if the Scene3D item is not visible
+ if (!isVisible())
+ return;
+
+ // Has anything in the 3D scene actually changed that requires us to render?
+ if (!needsRender())
+ return;
+
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ // Since we are in manual mode, trigger jobs for the next frame
+ Qt3DCore::QAspectEnginePrivate *aspectEnginePriv = static_cast<Qt3DCore::QAspectEnginePrivate *>(QObjectPrivate::get(m_aspectEngine));
+ if (!aspectEnginePriv->m_initialized || !m_renderer)
+ return;
+
+ // Set compositing mode on renderer
+ m_renderer->setCompositingMode(m_compositingMode);
+ const bool usesFBO = m_compositingMode == FBO;
+
+ // Make renderer aware of any Scene3DView we are dealing with
+ if (m_dirtyViews) {
+ // Scene3DViews checks
+ if (m_entity != m_viewHolderEntity) {
+ qCWarning(Scene3D) << "Scene3DView is not supported if the Scene3D entity property has been set";
+ }
+ if (!usesFBO) {
+ qCWarning(Scene3D) << "Scene3DView is only supported when Scene3D compositingMode is set to FBO";
+ }
+ // The Scene3DRender will take care of providing the texture containing the 3D scene
+ m_renderer->setScene3DViews(m_views);
+ m_dirtyViews = false;
+ }
+
+ Q_ASSERT(m_aspectEngine->runMode() == Qt3DCore::QAspectEngine::Manual);
+ m_aspectEngine->processFrame();
+ // The above essentially sets the number of RV for the RenderQueue and
+ // processes the jobs for the frame (it's blocking) When
+ // Scene3DRender::updatePaintNode is called, following this step, we know
+ // that the RenderQueue target count has been set and that everything
+ // should be ready for rendering
+
+
+ // processFrame() must absolutely be followed by a single call to
+ // render
+ // At startup, we have no garantee that the QtQuick Render Thread doesn't
+ // start rendering before this function has been called
+ // We add in a safety to skip such frames as this could otherwise
+ // make Qt3D enter a locked state
+ m_renderer->allowRender();
+
+ // Note: it's too early to request an update at this point as
+ // beforeSync() triggered by afterAnimating is considered
+ // to be as being part of the current frame update
+}
+
+void Scene3DItem::requestUpdate()
+{
+ // When using the FBO mode, only the QQuickItem needs to be updated
+ // When using the Underlay mode, the whole windows needs updating
+ const bool usesFBO = m_compositingMode == FBO;
+ if (usesFBO) {
+ QQuickItem::update();
+ for (Scene3DView *view : m_views)
+ view->update();
+ } else {
+ window()->update();
+ }
+}
+
void Scene3DItem::setWindowSurface(QObject *rootObject)
{
Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(rootObject);
@@ -313,7 +558,7 @@ void Scene3DItem::setWindowSurface(QObject *rootObject)
/*!
\qmlmethod void Scene3D::setItemAreaAndDevicePixelRatio(size area, real devicePixelRatio)
- \brief \TODO
+ Sets the item area to \a area and the pixel ratio to \a devicePixelRatio.
*/
void Scene3DItem::setItemAreaAndDevicePixelRatio(QSize area, qreal devicePixelRatio)
{
@@ -336,25 +581,45 @@ bool Scene3DItem::isHoverEnabled() const
void Scene3DItem::setCameraAspectModeHelper()
{
- switch (m_cameraAspectRatioMode) {
- case AutomaticAspectRatio:
- connect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
- connect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
- // Update the aspect ratio the first time the surface is set
- updateCameraAspectRatio();
- break;
- case UserAspectRatio:
- disconnect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
- disconnect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
- break;
+ if (m_compositingMode == FBO) {
+ switch (m_cameraAspectRatioMode) {
+ case AutomaticAspectRatio:
+ connect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ connect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ // Update the aspect ratio the first time the surface is set
+ updateCameraAspectRatio();
+ break;
+ case UserAspectRatio:
+ disconnect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ disconnect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ break;
+ }
+ } else {
+ // In Underlay mode, we rely on the window for aspect ratio and not the size of the Scene3DItem
+ switch (m_cameraAspectRatioMode) {
+ case AutomaticAspectRatio:
+ connect(window(), &QWindow::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ connect(window(), &QWindow::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ // Update the aspect ratio the first time the surface is set
+ updateCameraAspectRatio();
+ break;
+ case UserAspectRatio:
+ disconnect(window(), &QWindow::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ disconnect(window(), &QWindow::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ break;
+ }
}
}
void Scene3DItem::updateCameraAspectRatio()
{
if (m_camera) {
- m_camera->setAspectRatio(static_cast<float>(width()) /
- static_cast<float>(height()));
+ if (m_compositingMode == FBO)
+ m_camera->setAspectRatio(static_cast<float>(width()) /
+ static_cast<float>(height()));
+ else
+ m_camera->setAspectRatio(static_cast<float>(window()->width()) /
+ static_cast<float>(window()->height()));
}
}
@@ -394,19 +659,60 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
static_cast<Qt3DRender::QRenderAspectPrivate *>(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect))->m_screen =
(rw ? rw->screen() : window()->screen());
m_aspectEngine->registerAspect(m_renderAspect);
+
+ // Before Synchronizing is in the SG Thread, we want beforeSync to be triggered
+ // in the context of the main thread
+ QObject::connect(window(), &QQuickWindow::afterAnimating,
+ this, &Scene3DItem::onBeforeSync, Qt::DirectConnection);
+ auto renderAspectPriv = static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect));
+ QObject::connect(renderAspectPriv->m_aspectManager->changeArbiter(), &Qt3DCore::QChangeArbiter::receivedChange,
+ this, [this] { m_dirty = true; }, Qt::DirectConnection);
}
if (m_renderer == nullptr) {
m_renderer = new Scene3DRenderer(this, m_aspectEngine, m_renderAspect);
m_renderer->setCleanerHelper(m_rendererCleaner);
}
-
+ const bool usesFBO = m_compositingMode == FBO;
+ const bool hasScene3DViews = !m_views.empty();
Scene3DSGNode *fboNode = static_cast<Scene3DSGNode *>(node);
- if (fboNode == nullptr) {
- fboNode = new Scene3DSGNode();
- m_renderer->setSGNode(fboNode);
+
+ // When usin Scene3DViews or Scene3D in Underlay mode
+ // we shouldn't be managing a Scene3DSGNode
+ if (!usesFBO || hasScene3DViews) {
+ if (fboNode != nullptr) {
+ delete fboNode;
+ fboNode = nullptr;
+ m_renderer->setSGNode(fboNode);
+ }
+ } else {
+ // Regular Scene3D only case
+ // Create SGNode if using FBO and no Scene3DViews
+ if (fboNode == nullptr) {
+ fboNode = new Scene3DSGNode();
+ m_renderer->setSGNode(fboNode);
+ }
+ fboNode->setRect(boundingRect());
+ }
+
+ if (usesFBO) {
+ // Reset clear flag if we've set it to false it's still set to that
+ if (m_disableClearWindow && !window()->clearBeforeRendering())
+ window()->setClearBeforeRendering(m_clearsWindowByDefault);
+ m_disableClearWindow = false;
+ } else {
+ // Record clearBeforeRendering value before we force it to false
+ m_clearsWindowByDefault = window()->clearBeforeRendering();
+ m_disableClearWindow = true;
+ if (m_clearsWindowByDefault)
+ window()->setClearBeforeRendering(false);
}
- fboNode->setRect(boundingRect());
+
+ // Request update for next frame so that we can check whether we need to
+ // render again or not
+ static int requestUpdateMethodIdx = Scene3DItem::staticMetaObject.indexOfMethod("requestUpdate()");
+ static QMetaMethod requestUpdateMethod =Scene3DItem::staticMetaObject.method(requestUpdateMethodIdx);
+ requestUpdateMethod.invoke(this, Qt::QueuedConnection);
return fboNode;
}
diff --git a/src/quick3d/imports/scene3d/scene3ditem_p.h b/src/quick3d/imports/scene3d/scene3ditem_p.h
index 4106ff459..e46bb20af 100644
--- a/src/quick3d/imports/scene3d/scene3ditem_p.h
+++ b/src/quick3d/imports/scene3d/scene3ditem_p.h
@@ -69,6 +69,8 @@ class QCamera;
class QRenderAspect;
class Scene3DRenderer;
class Scene3DCleaner;
+class Scene3DView;
+class QFrameGraphNode;
class Scene3DItem : public QQuickItem
{
@@ -78,6 +80,7 @@ class Scene3DItem : public QQuickItem
Q_PROPERTY(bool multisample READ multisample WRITE setMultisample NOTIFY multisampleChanged)
Q_PROPERTY(CameraAspectRatioMode cameraAspectRatioMode READ cameraAspectRatioMode WRITE setCameraAspectRatioMode NOTIFY cameraAspectRatioModeChanged)
Q_PROPERTY(bool hoverEnabled READ isHoverEnabled WRITE setHoverEnabled NOTIFY hoverEnabledChanged)
+ Q_PROPERTY(CompositingMode compositingMode READ compositingMode WRITE setCompositingMode NOTIFY compositingModeChanged REVISION 14)
Q_CLASSINFO("DefaultProperty", "entity")
public:
explicit Scene3DItem(QQuickItem *parent = 0);
@@ -98,11 +101,22 @@ public:
Q_ENUM(CameraAspectRatioMode); // LCOV_EXCL_LINE
CameraAspectRatioMode cameraAspectRatioMode() const;
+ enum CompositingMode {
+ FBO,
+ Underlay
+ };
+ Q_ENUM(CompositingMode) // LCOV_EXCL_LINE
+ CompositingMode compositingMode() const;
+
+ void addView(Scene3DView *view);
+ void removeView(Scene3DView *view);
+
public Q_SLOTS:
void setAspects(const QStringList &aspects);
void setEntity(Qt3DCore::QEntity *entity);
void setCameraAspectRatioMode(CameraAspectRatioMode mode);
void setHoverEnabled(bool enabled);
+ void setCompositingMode(CompositingMode mode);
Q_SIGNALS:
void aspectsChanged();
@@ -110,9 +124,12 @@ Q_SIGNALS:
void multisampleChanged();
void cameraAspectRatioModeChanged(CameraAspectRatioMode mode);
void hoverEnabledChanged();
+ void compositingModeChanged();
private Q_SLOTS:
void applyRootEntityChange();
+ void onBeforeSync();
+ void requestUpdate();
private:
QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *nodeData) override;
@@ -120,9 +137,12 @@ private:
void setCameraAspectModeHelper();
void updateCameraAspectRatio();
void mousePressEvent(QMouseEvent *event) override;
+ bool needsRender();
QStringList m_aspects;
Qt3DCore::QEntity *m_entity;
+ Qt3DCore::QEntity *m_viewHolderEntity;
+ Qt3DRender::QFrameGraphNode *m_viewHolderFG;
Qt3DCore::QAspectEngine *m_aspectEngine;
QRenderAspect *m_renderAspect;
@@ -130,10 +150,16 @@ private:
Scene3DCleaner *m_rendererCleaner;
bool m_multisample;
+ bool m_dirty;
+ bool m_dirtyViews;
+ bool m_clearsWindowByDefault;
+ bool m_disableClearWindow;
QPointer<Qt3DRender::QCamera> m_camera;
CameraAspectRatioMode m_cameraAspectRatioMode;
+ CompositingMode m_compositingMode;
QOffscreenSurface *m_dummySurface;
+ QVector<Scene3DView *> m_views;
};
} // Qt3DRender
diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp
index b96fc516d..1e322a615 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer.cpp
+++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp
@@ -47,11 +47,17 @@
#include <QtQuick/qquickwindow.h>
#include <Qt3DRender/private/qrenderaspect_p.h>
+#include <Qt3DRender/private/abstractrenderer_p.h>
#include <Qt3DCore/private/qaspectengine_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qchangearbiter_p.h>
+#include <Qt3DCore/private/qservicelocator_p.h>
+
#include <scene3dcleaner_p.h>
#include <scene3ditem_p.h>
#include <scene3dlogging_p.h>
#include <scene3dsgnode_p.h>
+#include <scene3dview_p.h>
QT_BEGIN_NAMESPACE
@@ -101,6 +107,21 @@ private:
The Scene3DRenderer class renders a Qt3D scene as provided by a Scene3DItem.
It owns the aspectEngine even though it doesn't instantiate it.
+ The render loop goes as follows:
+ \list
+ \li The main thread runs, drives Animations, etc. and causes changes to be
+ reported to the Qt3D change arbiter. The first change reported will cause
+ the scene3drenderer to be marked dirty.
+ \li The QtQuick render thread starts a new frame, synchronizes the scene
+ graph and emits afterSynchronizing. This will trigger some preparational
+ steps for rendering and mark the QSGNode dirty if the Scene3DRenderer is
+ dirty.
+ \li The QtQuick render loop emits beforeRendering. If we're marked dirty or
+ if the renderPolicy is set to Always, we'll ask the Qt3D renderer aspect to
+ render. That call is blocking. If the aspect jobs are not done, yet, the
+ renderer will exit early and we skip a frame.
+ \endlist
+
The shutdown procedure is a two steps process that goes as follow:
\list
@@ -137,14 +158,17 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp
, m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead
, m_lastMultisample(false)
, m_needsShutdown(true)
- , m_blocking(false)
, m_forceRecreate(false)
+ , m_shouldRender(false)
+ , m_dirtyViews(false)
+ , m_allowRendering(0)
+ , m_compositingMode(Scene3DItem::FBO)
{
Q_CHECK_PTR(m_item);
Q_CHECK_PTR(m_item->window());
m_window = m_item->window();
- QObject::connect(m_item->window(), &QQuickWindow::afterSynchronizing, this, &Scene3DRenderer::synchronize, Qt::DirectConnection);
+ QObject::connect(m_item->window(), &QQuickWindow::beforeSynchronizing, this, &Scene3DRenderer::beforeSynchronize, Qt::DirectConnection);
QObject::connect(m_item->window(), &QQuickWindow::beforeRendering, this, &Scene3DRenderer::render, Qt::DirectConnection);
QObject::connect(m_item->window(), &QQuickWindow::sceneGraphInvalidated, this, &Scene3DRenderer::onSceneGraphInvalidated, Qt::DirectConnection);
// So that we can schedule the cleanup
@@ -159,9 +183,6 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp
ContextSaver saver;
static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderInitialize(saver.context());
scheduleRootEntityChange();
-
- const bool blockingRendermode = !qgetenv("SCENE3D_BLOCKING_RENDERMODE").isEmpty();
- m_blocking = blockingRendermode;
}
Scene3DRenderer::~Scene3DRenderer()
@@ -169,6 +190,7 @@ Scene3DRenderer::~Scene3DRenderer()
qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
}
+
QOpenGLFramebufferObject *Scene3DRenderer::createMultisampledFramebufferObject(const QSize &size)
{
QOpenGLFramebufferObjectFormat format;
@@ -247,20 +269,28 @@ void Scene3DRenderer::onWindowChanged(QQuickWindow *w)
}
}
-void Scene3DRenderer::synchronize()
+// Render Thread, GUI locked
+void Scene3DRenderer::beforeSynchronize()
{
if (m_item && m_window) {
- m_multisample = m_item->multisample();
- if (m_aspectEngine->rootEntity() != m_item->entity()) {
- scheduleRootEntityChange();
- }
+ // Only render if we are sure aspectManager->processFrame was called prior
+ // We could otherwise enter a deadlock state
+ if (!m_allowRendering.tryAcquire(std::max(m_allowRendering.available(), 1)))
+ return;
+ m_shouldRender = true;
+ // Check size / multisampling
+ m_multisample = m_item->multisample();
const QSize boundingRectSize = m_item->boundingRect().size().toSize();
const QSize currentSize = boundingRectSize * m_window->effectiveDevicePixelRatio();
const bool sizeHasChanged = currentSize != m_lastSize;
const bool multisampleHasChanged = m_multisample != m_lastMultisample;
- m_forceRecreate = sizeHasChanged || multisampleHasChanged;
+ const bool forceRecreate = sizeHasChanged || multisampleHasChanged;
+ // Store the current size as a comparison
+ // point for the next frame
+ m_lastSize = currentSize;
+ m_lastMultisample = m_multisample;
if (sizeHasChanged) {
static const QMetaMethod setItemAreaAndDevicePixelRatio = setItemAreaAndDevicePixelRatioMethod();
@@ -268,26 +298,88 @@ void Scene3DRenderer::synchronize()
Q_ARG(qreal, m_window->effectiveDevicePixelRatio()));
}
- // Store the current size as a comparison
- // point for the next frame
- m_lastSize = currentSize;
- m_lastMultisample = m_multisample;
+ // Rebuild FBO if size/multisampling has changed
+ const bool usesFBO = m_compositingMode == Scene3DItem::FBO;
+ if (usesFBO) {
+ // Rebuild FBO and textures if never created or a resize has occurred
+ if ((m_multisampledFBO.isNull() || forceRecreate) && m_multisample) {
+ m_multisampledFBO.reset(createMultisampledFramebufferObject(m_lastSize));
+ if (m_multisampledFBO->format().samples() == 0 || !QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
+ m_multisample = false;
+ m_multisampledFBO.reset(nullptr);
+ }
+ }
+
+ const bool generateNewTexture = m_finalFBO.isNull() || forceRecreate;
+ if (generateNewTexture) {
+ m_finalFBO.reset(createFramebufferObject(m_lastSize));
+ m_texture.reset(m_window->createTextureFromId(m_finalFBO->texture(), m_finalFBO->size(), QQuickWindow::TextureHasAlphaChannel));
+ }
+
+ // We can render either the Scene3D or the Scene3DView but not both
+ // at the same time
+ Q_ASSERT((m_node == nullptr || m_views.empty()) ||
+ (m_node != nullptr && m_views.empty()) ||
+ (m_node == nullptr && !m_views.empty()));
+
+ // Set texture on node
+ if (m_node && (!m_node->texture() || generateNewTexture))
+ m_node->setTexture(m_texture.data());
+
+ // Set textures on Scene3DView
+ if (m_dirtyViews || generateNewTexture) {
+ for (Scene3DView *view : qAsConst(m_views))
+ if (!view->texture() || generateNewTexture)
+ view->setTexture(m_texture.data());
+ m_dirtyViews = false;
+ }
+ }
+
+ if (m_aspectEngine->rootEntity() != m_item->entity()) {
+ scheduleRootEntityChange();
+ }
+
+ // Mark SGNodes as dirty so that QQuick will trigger some rendering
+ if (m_node)
+ m_node->markDirty(QSGNode::DirtyMaterial);
+
+ for (Scene3DView *view : qAsConst(m_views))
+ view->markSGNodeDirty();
+
+ m_item->update();
}
}
+void Scene3DRenderer::allowRender()
+{
+ m_allowRendering.release(1);
+}
+
+void Scene3DRenderer::setCompositingMode(Scene3DItem::CompositingMode mode)
+{
+ m_compositingMode = mode;
+}
+
+// Main Thread, Render Thread locked
+void Scene3DRenderer::setScene3DViews(const QVector<Scene3DView *> views)
+{
+ m_views = views;
+ m_dirtyViews = true;
+}
+
void Scene3DRenderer::setSGNode(Scene3DSGNode *node)
{
m_node = node;
- if (!m_texture.isNull())
- node->setTexture(m_texture.data());
}
+// Render Thread, Main Thread is unlocked at this point
void Scene3DRenderer::render()
{
QMutexLocker l(&m_windowMutex);
// Lock to ensure the window doesn't change while we are rendering
- if (!m_window)
+ if (!m_window || !m_shouldRender)
return;
+ m_shouldRender = false;
ContextSaver saver;
@@ -295,59 +387,49 @@ void Scene3DRenderer::render()
// it here to give Qt3D the clean state it expects
m_window->resetOpenGLState();
- // Rebuild FBO and textures if never created or a resize has occurred
- if ((m_multisampledFBO.isNull() || m_forceRecreate) && m_multisample) {
- m_multisampledFBO.reset(createMultisampledFramebufferObject(m_lastSize));
- if (m_multisampledFBO->format().samples() == 0 || !QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) {
- m_multisample = false;
- m_multisampledFBO.reset(nullptr);
- }
- }
-
- if (m_finalFBO.isNull() || m_forceRecreate) {
- m_finalFBO.reset(createFramebufferObject(m_lastSize));
- m_texture.reset(m_window->createTextureFromId(m_finalFBO->texture(), m_finalFBO->size(), QQuickWindow::TextureHasAlphaChannel));
- m_node->setTexture(m_texture.data());
+ // Create and bind FBO if using the FBO compositing mode
+ const bool usesFBO = m_compositingMode == Scene3DItem::FBO;
+ if (usesFBO) {
+ // Bind FBO
+ if (m_multisample) //Only try to use MSAA when available
+ m_multisampledFBO->bind();
+ else
+ m_finalFBO->bind();
}
- // Bind FBO
- if (m_multisample) //Only try to use MSAA when available
- m_multisampledFBO->bind();
- else
- m_finalFBO->bind();
-
// Render Qt3D Scene
- static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(m_blocking);
+ static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(usesFBO);
// We may have called doneCurrent() so restore the context if the rendering surface was changed
// Note: keep in mind that the ContextSave also restores the surface when destroyed
if (saver.context()->surface() != saver.surface())
saver.context()->makeCurrent(saver.surface());
- if (m_multisample) {
- // Blit multisampled FBO with non multisampled FBO with texture attachment
- const QRect dstRect(QPoint(0, 0), m_finalFBO->size());
- const QRect srcRect(QPoint(0, 0), m_multisampledFBO->size());
- QOpenGLFramebufferObject::blitFramebuffer(m_finalFBO.data(), dstRect,
- m_multisampledFBO.data(), srcRect,
- GL_COLOR_BUFFER_BIT,
- GL_NEAREST,
- 0, 0,
- QOpenGLFramebufferObject::DontRestoreFramebufferBinding);
- }
+ if (usesFBO) {
+ if (m_multisample) {
+ // Blit multisampled FBO with non multisampled FBO with texture attachment
+ const QRect dstRect(QPoint(0, 0), m_finalFBO->size());
+ const QRect srcRect(QPoint(0, 0), m_multisampledFBO->size());
+ QOpenGLFramebufferObject::blitFramebuffer(m_finalFBO.data(), dstRect,
+ m_multisampledFBO.data(), srcRect,
+ GL_COLOR_BUFFER_BIT,
+ GL_NEAREST,
+ 0, 0,
+ QOpenGLFramebufferObject::DontRestoreFramebufferBinding);
+ }
+
+ // Restore QtQuick FBO
+ QOpenGLFramebufferObject::bindDefault();
- // Restore QtQuick FBO
- QOpenGLFramebufferObject::bindDefault();
+ // Only show the node once Qt3D has rendered to it
+ // Avoids showing garbage on the first frame
+ if (m_node)
+ m_node->show();
+ }
// Reset the state used by the Qt Quick scenegraph to avoid any
// interference when rendering the rest of the UI.
m_window->resetOpenGLState();
-
- // Mark material as dirty to request a new frame
- m_node->markDirty(QSGNode::DirtyMaterial);
-
- // Request next frame
- m_window->update();
}
} // namespace Qt3DRender
diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h
index e28ecbe6e..4f3651cd3 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer_p.h
+++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h
@@ -54,6 +54,8 @@
#include <QtCore/QObject>
#include <QtCore/qsize.h>
#include <QtCore/QMutex>
+#include <QtCore/QSemaphore>
+#include <scene3ditem_p.h>
QT_BEGIN_NAMESPACE
@@ -69,8 +71,8 @@ namespace Qt3DRender {
class QRenderAspect;
class Scene3DCleaner;
-class Scene3DItem;
class Scene3DSGNode;
+class Scene3DViews;
class Scene3DRenderer : public QObject
{
@@ -81,12 +83,12 @@ public:
QRenderAspect *renderAspect);
~Scene3DRenderer();
- QOpenGLFramebufferObject *createMultisampledFramebufferObject(const QSize &size);
- QOpenGLFramebufferObject *createFramebufferObject(const QSize &size);
- void scheduleRootEntityChange();
void setSGNode(Scene3DSGNode *node);
void setCleanerHelper(Scene3DCleaner *cleaner);
- void synchronize();
+ void allowRender();
+ void setCompositingMode(Scene3DItem::CompositingMode mode);
+
+ void setScene3DViews(const QVector<Scene3DView *> views);
public Q_SLOTS:
void render();
@@ -95,6 +97,11 @@ public Q_SLOTS:
void onWindowChanged(QQuickWindow *w);
private:
+ QOpenGLFramebufferObject *createMultisampledFramebufferObject(const QSize &size);
+ QOpenGLFramebufferObject *createFramebufferObject(const QSize &size);
+ void beforeSynchronize();
+ void scheduleRootEntityChange();
+
Scene3DItem *m_item; // Will be released by the QQuickWindow/QML Engine
Qt3DCore::QAspectEngine *m_aspectEngine; // Will be released by the Scene3DRendererCleaner
QRenderAspect *m_renderAspect; // Will be released by the aspectEngine
@@ -109,8 +116,12 @@ private:
bool m_multisample;
bool m_lastMultisample;
bool m_needsShutdown;
- bool m_blocking;
bool m_forceRecreate;
+ bool m_shouldRender;
+ bool m_dirtyViews;
+ QSemaphore m_allowRendering;
+ Scene3DItem::CompositingMode m_compositingMode;
+ QVector<Scene3DView *> m_views;
friend class Scene3DCleaner;
};
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp b/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp
index 1b8b08a4e..80a1c2c9c 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterial.cpp
@@ -60,6 +60,7 @@ namespace Qt3DRender {
Scene3DSGMaterial::Scene3DSGMaterial()
: QSGMaterial()
, m_texture(nullptr)
+ , m_visible(false)
{
}
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h b/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
index c096f2a74..59724782b 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterial_p.h
@@ -75,8 +75,12 @@ public:
QSGMaterialType *type() const final { return &Scene3DSGMaterialShader::type; }
QSGMaterialShader *createShader() const final { return new Scene3DSGMaterialShader(); }
+ void show() { m_visible = true; }
+ bool visible() const { return m_visible; }
+
private:
QSGTexture *m_texture;
+ bool m_visible;
};
} // namespace Qt3DRender
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
index 3fab345e1..cfe39e8c7 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader.cpp
@@ -76,6 +76,7 @@ Scene3DSGMaterialShader::Scene3DSGMaterialShader()
: QSGMaterialShader()
, m_matrixId(-1)
, m_opacityId(-1)
+ , m_visibleId(-1)
{
}
@@ -118,21 +119,25 @@ const char *Scene3DSGMaterialShader::fragmentShader() const
if (ctx->format().version() >= qMakePair(3, 2) && ctx->format().profile() == QSurfaceFormat::CoreProfile) {
return ""
"#version 150 core \n"
+ "uniform bool visible; \n"
"uniform sampler2D source; \n"
"uniform float qt_Opacity; \n"
"in vec2 qt_TexCoord; \n"
"out vec4 fragColor; \n"
"void main() { \n"
- " vec4 p = texture(source, qt_TexCoord); \n"
+ " if (!visible) discard; \n"
+ " vec4 p = texture(source, qt_TexCoord); \n"
" float a = qt_Opacity * p.a; \n"
" fragColor = vec4(p.rgb * a, a); \n"
"}";
} else {
return ""
+ "uniform bool visible; \n"
"uniform highp sampler2D source; \n"
"uniform highp float qt_Opacity; \n"
"varying highp vec2 qt_TexCoord; \n"
"void main() { \n"
+ " if (!visible) discard; \n"
" highp vec4 p = texture2D(source, qt_TexCoord); \n"
" highp float a = qt_Opacity * p.a; \n"
" gl_FragColor = vec4(p.rgb * a, a); \n"
@@ -144,6 +149,7 @@ void Scene3DSGMaterialShader::initialize()
{
m_matrixId = program()->uniformLocation("qt_Matrix");
m_opacityId = program()->uniformLocation("qt_Opacity");
+ m_visibleId = program()->uniformLocation("visible");
}
void Scene3DSGMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
@@ -154,21 +160,26 @@ void Scene3DSGMaterialShader::updateState(const RenderState &state, QSGMaterial
QSGTexture *t = tx->texture();
- bool npotSupported = const_cast<QOpenGLContext *>(state.context())
- ->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
- if (!npotSupported) {
- QSize size = t->textureSize();
- const bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
- if (isNpot) {
- t->setHorizontalWrapMode(QSGTexture::ClampToEdge);
- t->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ if (t != nullptr) {
+ bool npotSupported = const_cast<QOpenGLContext *>(state.context())
+ ->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
+ if (!npotSupported) {
+ QSize size = t->textureSize();
+ const bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height());
+ if (isNpot) {
+ t->setHorizontalWrapMode(QSGTexture::ClampToEdge);
+ t->setVerticalWrapMode(QSGTexture::ClampToEdge);
+ }
}
+
+ if (oldTx == 0 || oldTx->texture()->textureId() != t->textureId())
+ t->bind();
+ else
+ t->updateBindOptions();
}
- if (oldTx == 0 || oldTx->texture()->textureId() != t->textureId())
- t->bind();
- else
- t->updateBindOptions();
+ if (oldTx == nullptr || oldTx->visible() != tx->visible())
+ program()->setUniformValue(m_visibleId, tx->visible());
if (state.isMatrixDirty())
program()->setUniformValue(m_matrixId, state.combinedMatrix());
diff --git a/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h b/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
index c372a1170..60edf6d45 100644
--- a/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
+++ b/src/quick3d/imports/scene3d/scene3dsgmaterialshader_p.h
@@ -74,6 +74,7 @@ protected:
private:
int m_matrixId;
int m_opacityId;
+ int m_visibleId;
};
} // namespace Qt3DRender
diff --git a/src/quick3d/imports/scene3d/scene3dsgnode.cpp b/src/quick3d/imports/scene3d/scene3dsgnode.cpp
index 8806b59a9..630cf49a9 100644
--- a/src/quick3d/imports/scene3d/scene3dsgnode.cpp
+++ b/src/quick3d/imports/scene3d/scene3dsgnode.cpp
@@ -74,17 +74,22 @@ Scene3DSGNode::~Scene3DSGNode()
// is terminated.
}
-void Scene3DSGNode::setRect(const QRectF &rect)
+void Scene3DSGNode::setRect(const QRectF &rect, const QRectF textureRect)
{
if (rect != m_rect) {
m_rect = rect;
- // Map the item's bounding rect to normalized texture coordinates
- const QRectF sourceRect(0.0f, 1.0f, 1.0f, -1.0f);
- QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, sourceRect);
+ // By default, map the item's bounding rect to normalized texture coordinates
+ QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, textureRect);
markDirty(DirtyGeometry);
}
}
+void Scene3DSGNode::show()
+{
+ m_material.show();
+ m_opaqueMaterial.show();
+}
+
} // namespace Qt3DRender
QT_END_NAMESPACE
diff --git a/src/quick3d/imports/scene3d/scene3dsgnode_p.h b/src/quick3d/imports/scene3d/scene3dsgnode_p.h
index 68b68eea5..a7873bdb8 100644
--- a/src/quick3d/imports/scene3d/scene3dsgnode_p.h
+++ b/src/quick3d/imports/scene3d/scene3dsgnode_p.h
@@ -75,9 +75,11 @@ public:
}
QSGTexture *texture() const Q_DECL_NOTHROW { return m_material.texture(); }
- void setRect(const QRectF &rect);
+ void setRect(const QRectF &rect, const QRectF textureRect = QRectF(0.0f, 1.0f, 1.0f, -1.0f));
QRectF rect() const Q_DECL_NOTHROW { return m_rect; }
+ void show();
+
private:
Scene3DSGMaterial m_material;
Scene3DSGMaterial m_opaqueMaterial;
diff --git a/src/quick3d/imports/scene3d/scene3dview.cpp b/src/quick3d/imports/scene3d/scene3dview.cpp
new file mode 100644
index 000000000..f38d135f0
--- /dev/null
+++ b/src/quick3d/imports/scene3d/scene3dview.cpp
@@ -0,0 +1,320 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scene3dview_p.h"
+#include <Qt3DCore/QEntity>
+#include <Qt3DRender/QRenderSettings>
+#include <Qt3DRender/QFrameGraphNode>
+#include <Qt3DRender/QLayer>
+#include <Qt3DRender/QLayerFilter>
+#include <Qt3DRender/QViewport>
+#include <scene3dsgnode_p.h>
+#include <scene3ditem_p.h>
+#include <QQuickWindow>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+/*!
+ \qmltype Scene3DView
+ \inherits Item
+ \inqmlmodule QtQuick.Scene3D
+ \since 5.14
+
+ \preliminary
+
+ \brief The Scene3DView type is used to integrate a Qt 3D sub scene into a
+ QtQuick 2 scene using Scene3D. Whereas you should only use a single Scene3D
+ instance per application, you can have multiple Scene3DView instances.
+
+ Essentially, if you need to render multiple scenes each in a separate view,
+ you should use a single Scene3D instance and as many Scene3DView items as
+ you have scenes to render.
+
+ Typical usage looks like:
+ \qml
+ Scene3D {
+ id: mainScene3D
+ anchors.fill: parent
+ }
+
+ Scene3DView {
+ id: view1
+ scene3D: mainScene3D
+ width: 200
+ height: 200
+ Entity {
+ ...
+ }
+ }
+
+ Scene3DView {
+ id: view2
+ scene3D: mainScene3D
+ width: 200
+ height: 200
+ x: 200
+ Entity {
+ ...
+ }
+ }
+ \endqml
+
+ There are a few limitations when using Scene3DView:
+ \list
+ \li The Scene3D compositingMode has to be set to FBO
+ \li The Scene3D is sized to occupy the full window size (at the very least
+ it must be sized as wide as the area occupied by all Scene3DViews)
+ \li The Scene3D instance is instantiated prior to any Scene3DView
+ \li The Scene3D entity property is left unset
+ \endlist
+
+ Scene3D behaves likes a texture atlas from which all Scene3DView instances.
+ For this reason, care should be taken that only the first Scene3DView
+ declared in the scene clears the color/depth. Additionally overlapping
+ Scene3DView instances is discouraged as this might not produce the expected
+ output.
+
+ It is expected that a Scene3DView's Entity provide a RenderSettings with a
+ valid SceneGraph. Please note that only the RenderSettings of the first
+ Scene3DView instantiated will be taken into account.
+
+ There are no restriction on the sharing of elements between different scenes
+ in different Scene3DView instances.
+ */
+
+namespace {
+
+Qt3DRender::QFrameGraphNode *frameGraphFromEntity(Qt3DCore::QEntity *entity)
+{
+ const auto renderSettingsComponents = entity->componentsOfType<Qt3DRender::QRenderSettings>();
+
+ if (renderSettingsComponents.size() > 0) {
+ Qt3DRender::QRenderSettings *renderSettings = renderSettingsComponents.first();
+ return renderSettings->activeFrameGraph();
+ }
+ return nullptr;
+}
+
+}
+
+Scene3DView::Scene3DView(QQuickItem *parent)
+ : QQuickItem(parent)
+ , m_scene3D(nullptr)
+ , m_entity(nullptr)
+ , m_previousFGParent(nullptr)
+ , m_holderEntity(new Qt3DCore::QEntity())
+ , m_holderLayer(new Qt3DRender::QLayer())
+ , m_holderLayerFilter(new Qt3DRender::QLayerFilter())
+ , m_holderViewport(new Qt3DRender::QViewport())
+ , m_dirtyFlags(DirtyNode|DirtyTexture)
+ , m_texture(nullptr)
+{
+ setFlag(QQuickItem::ItemHasContents, true);\
+
+ m_holderLayer->setRecursive(true);
+ m_holderEntity->addComponent(m_holderLayer);
+ m_holderLayerFilter->setParent(m_holderViewport);
+ m_holderLayerFilter->addLayer(m_holderLayer);
+}
+
+Scene3DView::~Scene3DView()
+{
+ if (m_entity)
+ abandonSubtree(m_entity);
+
+ if (m_scene3D)
+ m_scene3D->removeView(this);
+}
+
+Qt3DCore::QEntity *Scene3DView::entity() const
+{
+ return m_entity;
+}
+
+Scene3DItem *Scene3DView::scene3D() const
+{
+ return m_scene3D;
+}
+
+Qt3DCore::QEntity *Scene3DView::viewSubtree() const
+{
+ return m_holderEntity;
+}
+
+QFrameGraphNode *Scene3DView::viewFrameGraph() const
+{
+ return m_holderViewport;
+}
+
+// Called by Scene3DRender::beforeSynchronizing in RenderThread
+void Scene3DView::setTexture(QSGTexture *texture)
+{
+ m_dirtyFlags |= DirtyTexture;
+ m_texture = texture;
+ QQuickItem::update();
+}
+
+QSGTexture *Scene3DView::texture() const
+{
+ return m_texture;
+}
+
+// Called by Scene3DRender::beforeSynchronizing in RenderThread
+void Scene3DView::markSGNodeDirty()
+{
+ m_dirtyFlags |= DirtyNode;
+ QQuickItem::update();
+}
+
+// Main Thread
+void Scene3DView::setEntity(Qt3DCore::QEntity *entity)
+{
+ if (m_entity == entity)
+ return;
+
+ if (m_entity)
+ abandonSubtree(m_entity);
+
+ m_entity = entity;
+ emit entityChanged();
+
+ if (m_entity)
+ adoptSubtree(m_entity);
+}
+
+// Main Thread
+void Scene3DView::setScene3D(Scene3DItem *scene3D)
+{
+ if (m_scene3D == scene3D)
+ return;
+
+ if (m_scene3D) {
+ m_scene3D->removeView(this);
+ QObject::disconnect(m_scene3DDestroyedConnection);
+ }
+
+ setTexture(nullptr);
+ m_scene3D = scene3D;
+ emit scene3DChanged();
+
+
+ if (m_scene3D) {
+ m_scene3DDestroyedConnection = QObject::connect(m_scene3D,
+ &Scene3DItem::destroyed,
+ this,
+ [this] {
+ m_scene3D = nullptr;
+ });
+ m_scene3D->addView(this);
+ }
+}
+
+// Render Thread
+QSGNode *Scene3DView::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *)
+{
+ Scene3DSGNode *fboNode = static_cast<Scene3DSGNode *>(node);
+ if (fboNode == nullptr)
+ fboNode = new Scene3DSGNode();
+
+ // We only need to draw a sub part of the texture based
+ // on our size, Scene3D essentially acts as a TextureAtlas
+ const QRectF itemRect(mapRectToScene(boundingRect()));
+ const QSize winSize = window() ? window()->size() : QSize();
+ const QRectF normalizedViewportRect(itemRect.x() / winSize.width(),
+ itemRect.y() / winSize.height(),
+ itemRect.width() / winSize.width(),
+ itemRect.height() / winSize.height());
+ // Swap Y axis to match GL coordinates
+ const QRectF textureRect(itemRect.x() / winSize.width(),
+ 1.0f - (itemRect.y() / winSize.height()),
+ itemRect.width() / winSize.width(),
+ -(itemRect.height() / winSize.height()));
+
+ // TO DO: Should be done from main thread
+ // updateViewport
+ m_holderViewport->setNormalizedRect(normalizedViewportRect);
+
+ // update node rect and texture coordinates
+ fboNode->setRect(boundingRect(), textureRect);
+
+ if (m_dirtyFlags & DirtyTexture) {
+ fboNode->setTexture(m_texture);
+ m_dirtyFlags.setFlag(DirtyTexture, false);
+ // Show FBO Node at this point
+ fboNode->show();
+ }
+ if (m_dirtyFlags & DirtyNode) {
+ fboNode->markDirty(QSGNode::DirtyMaterial);
+ m_dirtyFlags.setFlag(DirtyNode, false);
+ }
+
+ return fboNode;
+}
+
+// Main Thread
+void Scene3DView::adoptSubtree(Qt3DCore::QEntity *subtree)
+{
+ // Reparent FrameGraph
+ Qt3DRender::QFrameGraphNode *fgNode = frameGraphFromEntity(subtree);
+ if (fgNode) {
+ m_previousFGParent = fgNode->parentNode();
+ fgNode->setParent(m_holderLayerFilter);
+ }
+
+ // Insert Entity Subtree
+ subtree->setParent(m_holderEntity);
+}
+
+// Main Thread
+void Scene3DView::abandonSubtree(Qt3DCore::QEntity *subtree)
+{
+ // Remove FrameGraph part
+ Qt3DRender::QFrameGraphNode *fgNode = frameGraphFromEntity(subtree);
+ if (fgNode)
+ fgNode->setParent(m_previousFGParent);
+
+ // Remove Entity Subtree
+ subtree->setParent(Q_NODE_NULLPTR);
+}
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/renderers/opengl/renderer/commandthread_p.h b/src/quick3d/imports/scene3d/scene3dview_p.h
index 0508675c4..ffb80f93b 100644
--- a/src/render/renderers/opengl/renderer/commandthread_p.h
+++ b/src/quick3d/imports/scene3d/scene3dview_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,79 +37,101 @@
**
****************************************************************************/
-#ifndef QT3DRENDER_RENDER_COMMANDTHREAD_P_H
-#define QT3DRENDER_RENDER_COMMANDTHREAD_P_H
+#ifndef SCENE3DVIEW_P_H
+#define SCENE3DVIEW_P_H
//
// W A R N I N G
// -------------
//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
-#include <QtCore/QThread>
-#include <QtCore/QSemaphore>
-#include <QtCore/QMutex>
+#include <QtQuick/QQuickItem>
+#include <QtCore/QFlags>
QT_BEGIN_NAMESPACE
-class QOpenGLContext;
+class QSGTexture;
-namespace Qt3DRender {
+namespace Qt3DCore {
+class QEntity;
+class QNode;
+}
-namespace Render {
+namespace Qt3DRender {
-class Renderer;
-class GLCommand;
-class OffscreenSurfaceHelper;
-class GraphicsContext;
-class ShaderCache;
+class QLayer;
+class QLayerFilter;
+class Scene3DItem;
+class QFrameGraphNode;
+class QViewport;
-class CommandThread : public QThread
+class Scene3DView : public QQuickItem
{
Q_OBJECT
+ Q_PROPERTY(Qt3DCore::QEntity* entity READ entity WRITE setEntity NOTIFY entityChanged)
+ Q_PROPERTY(Qt3DRender::Scene3DItem *scene3D READ scene3D WRITE setScene3D NOTIFY scene3DChanged)
+ Q_CLASSINFO("DefaultProperty", "entity")
+
public:
- explicit CommandThread(Renderer *renderer);
- ~CommandThread();
+ enum DirtyFlag {
+ DirtyNode = 1 << 0,
+ DirtyTexture = 1 << 1
+ };
+ Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
- Render::Renderer* renderer() const { return m_renderer; }
+ explicit Scene3DView(QQuickItem *parent = nullptr);
+ ~Scene3DView();
- void setShaderCache(ShaderCache *shaderCache);
- ShaderCache *shaderCache() const { return m_shaderCache; }
+ Qt3DCore::QEntity *entity() const;
+ Scene3DItem *scene3D() const;
- void initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper);
- void shutdown();
+ Qt3DCore::QEntity *viewSubtree() const;
+ Qt3DRender::QFrameGraphNode *viewFrameGraph() const;
- void executeCommand(GLCommand *command);
+ void setTexture(QSGTexture *texture);
+ QSGTexture *texture() const;
-private:
- void run() override;
- void executeCommandInternal(Qt3DRender::Render::GLCommand *command);
+ void markSGNodeDirty();
+
+public Q_SLOTS:
+ void setEntity(Qt3DCore::QEntity *entity);
+ void setScene3D(Scene3DItem *scene3D);
+
+Q_SIGNALS:
+ void entityChanged();
+ void scene3DChanged();
private:
- Renderer* m_renderer;
- QSemaphore m_waitForStartSemaphore;
- QSemaphore m_initializedSemaphore;
- QSemaphore m_commandRequestedSemaphore;
- QSemaphore m_commandExecutionSemaphore;
- QMutex m_blockingCallerMutex;
- QOpenGLContext *m_mainContext;
- ShaderCache *m_shaderCache;
- OffscreenSurfaceHelper *m_offsreenSurfaceHelper;
- QScopedPointer<QOpenGLContext> m_localContext;
- QScopedPointer<GraphicsContext> m_graphicsContext;
- GLCommand *m_currentCommand;
- QAtomicInt m_running;
+ QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *nodeData) override;
+ void adoptSubtree(Qt3DCore::QEntity *subtree);
+ void abandonSubtree(Qt3DCore::QEntity *subtree);
+
+ Scene3DItem *m_scene3D;
+ Qt3DCore::QEntity *m_entity;
+ Qt3DCore::QNode *m_previousFGParent;
+
+ Qt3DCore::QEntity *m_holderEntity;
+ Qt3DRender::QLayer *m_holderLayer;
+ Qt3DRender::QLayerFilter *m_holderLayerFilter;
+ Qt3DRender::QViewport *m_holderViewport;
+
+ QMetaObject::Connection m_scene3DDestroyedConnection;
+
+ DirtyFlags m_dirtyFlags;
+ QSGTexture *m_texture;
};
-} // Render
+Q_DECLARE_OPERATORS_FOR_FLAGS(Scene3DView::DirtyFlags)
+
} // Qt3DRender
QT_END_NAMESPACE
-#endif // QT3DRENDER_RENDER_COMMANDTHREAD_P_H
+#endif // SCENE3DVIEW_P_H
diff --git a/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp b/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
index 2bf94d371..938747a95 100644
--- a/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
+++ b/src/quick3d/quick3d/items/quick3dnodeinstantiator.cpp
@@ -47,11 +47,11 @@
#include <QQmlIncubator>
#include <Qt3DCore/private/qnode_p.h>
-#include <QtQml/private/qqmlchangeset_p.h>
+#include <private/qqmlchangeset_p.h>
#if QT_CONFIG(qml_delegate_model)
-#include <QtQml/private/qqmldelegatemodel_p.h>
+#include <private/qqmldelegatemodel_p.h>
#endif
-#include <QtQml/private/qqmlobjectmodel_p.h>
+#include <private/qqmlobjectmodel_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick3d/quick3d/qt3dquick_global.cpp b/src/quick3d/quick3d/qt3dquick_global.cpp
index afba0ad32..6b34f3719 100644
--- a/src/quick3d/quick3d/qt3dquick_global.cpp
+++ b/src/quick3d/quick3d/qt3dquick_global.cpp
@@ -44,7 +44,6 @@
#include <QtQml/private/qqmlglobal_p.h>
#include <QtQml/private/qv4engine_p.h>
#include <QtQml/private/qv4object_p.h>
-#include <QtQml/private/qv8engine_p.h>
QT_BEGIN_NAMESPACE
@@ -267,7 +266,7 @@ public:
return QMatrix4x4();
}
- static QMatrix4x4 matrix4x4FromObject(QQmlV4Handle object, QV4::ExecutionEngine *v4, bool *ok)
+ static QMatrix4x4 matrix4x4FromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
{
if (ok) *ok = false;
QV4::Scope scope(v4);
@@ -525,7 +524,7 @@ public:
return false;
}
- bool variantFromJsObject(int type, QQmlV4Handle object, QV4::ExecutionEngine *v4, QVariant *v) override
+ bool variantFromJsObject(int type, const QV4::Value &object, QV4::ExecutionEngine *v4, QVariant *v) override
{
QV4::Scope scope(v4);
#ifndef QT_NO_DEBUG
diff --git a/src/quick3d/quick3d/quick3d.pro b/src/quick3d/quick3d/quick3d.pro
index c6c4f65c0..b7edec507 100644
--- a/src/quick3d/quick3d/quick3d.pro
+++ b/src/quick3d/quick3d/quick3d.pro
@@ -3,9 +3,6 @@ MODULE = 3dquick
QT += core-private gui-private qml qml-private quick quick-private 3dcore 3dcore-private
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/quick3d/quick3danimation/quick3danimation.pro b/src/quick3d/quick3danimation/quick3danimation.pro
index 946c6c78d..4b166327f 100644
--- a/src/quick3d/quick3danimation/quick3danimation.pro
+++ b/src/quick3d/quick3danimation/quick3danimation.pro
@@ -4,9 +4,6 @@ MODULE = 3dquickanimation
QT += core core-private qml qml-private 3dcore 3drender 3danimation 3dquick 3dquick-private 3dcore-private 3drender-private
CONFIG -= precompile_header
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
CONFIG += static
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/quick3d/quick3dextras/quick3dextras.pro b/src/quick3d/quick3dextras/quick3dextras.pro
index bf28b4e4c..f7c956f8a 100644
--- a/src/quick3d/quick3dextras/quick3dextras.pro
+++ b/src/quick3d/quick3dextras/quick3dextras.pro
@@ -5,9 +5,6 @@ QT += core core-private qml qml-private 3dcore 3dinput 3dquick 3dquick-priv
CONFIG -= precompile_header
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/quick3d/quick3dinput/quick3dinput.pro b/src/quick3d/quick3dinput/quick3dinput.pro
index a05c2190f..e797f3fae 100644
--- a/src/quick3d/quick3dinput/quick3dinput.pro
+++ b/src/quick3d/quick3dinput/quick3dinput.pro
@@ -4,9 +4,6 @@ MODULE = 3dquickinput
QT += core core-private qml qml-private 3dcore 3dinput 3dquick 3dquick-private 3dcore-private 3dinput-private
CONFIG -= precompile_header
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/quick3d/quick3drender/items/quick3dparameter_p.h b/src/quick3d/quick3drender/items/quick3dparameter_p.h
index 939cfaab8..286bb846a 100644
--- a/src/quick3d/quick3drender/items/quick3dparameter_p.h
+++ b/src/quick3d/quick3drender/items/quick3dparameter_p.h
@@ -67,13 +67,13 @@ class Q_3DQUICKRENDERSHARED_PRIVATE_EXPORT Quick3DParameter : public QParameter
{
Q_OBJECT
public:
- explicit Quick3DParameter(QNode *parent = 0);
+ explicit Quick3DParameter(QNode *parent = nullptr);
private:
Q_DECLARE_PRIVATE(Quick3DParameter)
protected:
- Quick3DParameter(Quick3DParameterPrivate &dd, QNode *parent = 0);
+ Quick3DParameter(Quick3DParameterPrivate &dd, QNode *parent = nullptr);
};
} // namespace Quick
diff --git a/src/quick3d/quick3drender/items/quick3draycaster.cpp b/src/quick3d/quick3drender/items/quick3draycaster.cpp
index 55c08a806..b8f086983 100644
--- a/src/quick3d/quick3drender/items/quick3draycaster.cpp
+++ b/src/quick3d/quick3drender/items/quick3draycaster.cpp
@@ -73,38 +73,38 @@ QJSValue Quick3DRayCasterPrivate::convertHits(const QAbstractRayCaster::Hits &hi
auto jsHits = engine->newArray(hits.length());
for (int i=0; i<hits.size(); i++) {
QJSValue v = engine->newObject();
- v.setProperty(QLatin1Literal("type"), hits[i].type());
- v.setProperty(QLatin1Literal("entity"), engine->newQObject(hits[i].entity()));
- v.setProperty(QLatin1Literal("distance"), hits[i].distance());
+ v.setProperty(QLatin1String("type"), hits[i].type());
+ v.setProperty(QLatin1String("entity"), engine->newQObject(hits[i].entity()));
+ v.setProperty(QLatin1String("distance"), hits[i].distance());
{
QJSValue p = engine->newObject();
- p.setProperty(QLatin1Literal("x"), hits[i].localIntersection().x());
- p.setProperty(QLatin1Literal("y"), hits[i].localIntersection().y());
- p.setProperty(QLatin1Literal("z"), hits[i].localIntersection().z());
- v.setProperty(QLatin1Literal("localIntersection"), p);
+ p.setProperty(QLatin1String("x"), hits[i].localIntersection().x());
+ p.setProperty(QLatin1String("y"), hits[i].localIntersection().y());
+ p.setProperty(QLatin1String("z"), hits[i].localIntersection().z());
+ v.setProperty(QLatin1String("localIntersection"), p);
}
{
QJSValue p = engine->newObject();
- p.setProperty(QLatin1Literal("x"), hits[i].worldIntersection().x());
- p.setProperty(QLatin1Literal("y"), hits[i].worldIntersection().y());
- p.setProperty(QLatin1Literal("z"), hits[i].worldIntersection().z());
- v.setProperty(QLatin1Literal("worldIntersection"), p);
+ p.setProperty(QLatin1String("x"), hits[i].worldIntersection().x());
+ p.setProperty(QLatin1String("y"), hits[i].worldIntersection().y());
+ p.setProperty(QLatin1String("z"), hits[i].worldIntersection().z());
+ v.setProperty(QLatin1String("worldIntersection"), p);
}
switch (hits[i].type()) {
case Qt3DRender::QRayCasterHit::TriangleHit:
- v.setProperty(QLatin1Literal("primitiveIndex"), hits[i].primitiveIndex());
- v.setProperty(QLatin1Literal("vertex1Index"), hits[i].vertex1Index());
- v.setProperty(QLatin1Literal("vertex2Index"), hits[i].vertex2Index());
- v.setProperty(QLatin1Literal("vertex3Index"), hits[i].vertex3Index());
+ v.setProperty(QLatin1String("primitiveIndex"), hits[i].primitiveIndex());
+ v.setProperty(QLatin1String("vertex1Index"), hits[i].vertex1Index());
+ v.setProperty(QLatin1String("vertex2Index"), hits[i].vertex2Index());
+ v.setProperty(QLatin1String("vertex3Index"), hits[i].vertex3Index());
break;
case Qt3DRender::QRayCasterHit::LineHit:
- v.setProperty(QLatin1Literal("primitiveIndex"), hits[i].primitiveIndex());
- v.setProperty(QLatin1Literal("vertex1Index"), hits[i].vertex1Index());
- v.setProperty(QLatin1Literal("vertex2Index"), hits[i].vertex2Index());
+ v.setProperty(QLatin1String("primitiveIndex"), hits[i].primitiveIndex());
+ v.setProperty(QLatin1String("vertex1Index"), hits[i].vertex1Index());
+ v.setProperty(QLatin1String("vertex2Index"), hits[i].vertex2Index());
break;
case Qt3DRender::QRayCasterHit::PointHit:
- v.setProperty(QLatin1Literal("primitiveIndex"), hits[i].primitiveIndex());
+ v.setProperty(QLatin1String("primitiveIndex"), hits[i].primitiveIndex());
break;
default: break;
}
diff --git a/src/quick3d/quick3drender/quick3drender.pro b/src/quick3d/quick3drender/quick3drender.pro
index 6db744984..4c158a7b7 100644
--- a/src/quick3d/quick3drender/quick3drender.pro
+++ b/src/quick3d/quick3drender/quick3drender.pro
@@ -4,9 +4,6 @@ MODULE = 3dquickrender
QT += core core-private qml qml-private 3dcore 3drender 3dquick 3dquick-private 3dcore-private 3drender-private
CONFIG -= precompile_header
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.cpp b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
index 8908894c8..09d50a5aa 100644
--- a/src/quick3d/quick3dscene2d/items/qscene2d.cpp
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.cpp
@@ -42,8 +42,6 @@
#include "scene2devent_p.h"
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -54,6 +52,12 @@ namespace Qt3DRender {
namespace Quick {
/*!
+ \namespace Qt3DRender::Quick
+ \inmodule Qt3DScene2D
+ \brief Internal namespace to import QML types.
+*/
+
+/*!
\class Qt3DRender::Quick::QScene2D
\inheaderfile Qt3DQuickScene2D/QScene2D
\inmodule Qt3DScene2D
@@ -194,15 +198,6 @@ QScene2DPrivate::~QScene2DPrivate()
delete m_renderManager;
}
-void QScene2DPrivate::setScene(Qt3DCore::QScene *scene)
-{
- Q_Q(QScene2D);
- QNodePrivate::setScene(scene);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(q->id());
- change->setPropertyName("sceneInitialized");
- notifyObservers(change);
-}
-
/*!
The constructor creates a new QScene2D instance with the specified \a parent.
@@ -325,12 +320,7 @@ void QScene2D::addEntity(Qt3DCore::QEntity *entity)
d->m_entities.append(entity);
d->registerDestructionHelper(entity, &QScene2D::removeEntity, d->m_entities);
-
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), entity);
- change->setPropertyName("entities");
- d->notifyObservers(change);
- }
+ d->updateNode(entity, "entities", PropertyValueAdded);
}
}
@@ -344,12 +334,7 @@ void QScene2D::removeEntity(Qt3DCore::QEntity *entity)
d->m_entities.removeAll(entity);
d->unregisterDestructionHelper(entity);
-
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), entity);
- change->setPropertyName("entities");
- d->notifyObservers(change);
- }
+ d->updateNode(entity, "entities", PropertyValueRemoved);
}
}
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d.h b/src/quick3d/quick3dscene2d/items/qscene2d.h
index eab900ca4..45d0f26c9 100644
--- a/src/quick3d/quick3dscene2d/items/qscene2d.h
+++ b/src/quick3d/quick3dscene2d/items/qscene2d.h
@@ -51,11 +51,6 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-/*!
- \namespace Qt3DRender::Quick
-
- \brief Internal namespace to import QML types.
-*/
namespace Quick {
class QScene2DPrivate;
diff --git a/src/quick3d/quick3dscene2d/items/qscene2d_p.h b/src/quick3d/quick3dscene2d/items/qscene2d_p.h
index ce354845a..4814564c2 100644
--- a/src/quick3d/quick3dscene2d/items/qscene2d_p.h
+++ b/src/quick3d/quick3dscene2d/items/qscene2d_p.h
@@ -74,8 +74,6 @@ public:
QScene2DPrivate();
~QScene2DPrivate();
- void setScene(Qt3DCore::QScene *scene) override;
-
Scene2DManager *m_renderManager;
QMetaObject::Connection m_textureDestroyedConnection;
Qt3DRender::QRenderTargetOutput *m_output;
diff --git a/src/quick3d/quick3dscene2d/items/scene2d.cpp b/src/quick3d/quick3dscene2d/items/scene2d.cpp
index b5c25431f..bfd6ce7ef 100644
--- a/src/quick3d/quick3dscene2d/items/scene2d.cpp
+++ b/src/quick3d/quick3dscene2d/items/scene2d.cpp
@@ -37,8 +37,10 @@
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DQuickScene2D/qscene2d.h>
#include <Qt3DRender/qpicktriangleevent.h>
+#include <Qt3DRender/qobjectpicker.h>
#include <QtCore/qthread.h>
#include <QtCore/qatomic.h>
@@ -55,7 +57,9 @@
#include <private/attachmentpack_p.h>
#include <private/qt3dquickscene2d_logging_p.h>
#include <private/qbackendnode_p.h>
+#include <private/qobjectpicker_p.h>
#include <private/qpickevent_p.h>
+#include <private/qpicktriangleevent_p.h>
#include <private/entity_p.h>
#include <private/platformsurfacefilter_p.h>
#include <private/trianglesvisitor_p.h>
@@ -128,7 +132,9 @@ Scene2D::Scene2D()
Scene2D::~Scene2D()
{
- stopGrabbing();
+ for (auto connection: qAsConst(m_connections))
+ QObject::disconnect(connection);
+ m_connections.clear();
}
void Scene2D::setOutput(Qt3DCore::QNodeId outputId)
@@ -139,12 +145,9 @@ void Scene2D::setOutput(Qt3DCore::QNodeId outputId)
void Scene2D::initializeSharedObject()
{
if (!m_initialized) {
-
// bail out if we're running autotests
- if (!m_sharedObject->m_renderManager
- || m_sharedObject->m_renderManager->thread() == QThread::currentThread()) {
+ if (!qgetenv("QT3D_SCENE2D_DISABLE_RENDERING").isEmpty())
return;
- }
renderThreadClientCount->fetchAndAddAcquire(1);
@@ -169,73 +172,55 @@ void Scene2D::initializeSharedObject()
}
}
-void Scene2D::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Scene2D::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QScene2DData>>(change);
- const auto &data = typedChange->data;
- m_renderPolicy = data.renderPolicy;
- setSharedObject(data.sharedObject);
- setOutput(data.output);
- m_entities = data.entityIds;
- m_mouseEnabled = data.mouseEnabled;
-}
+ Qt3DRender::Render::BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QScene2D *node = qobject_cast<const QScene2D *>(frontEnd);
+ if (!node)
+ return;
+ const QScene2DPrivate *dnode = static_cast<const QScene2DPrivate *>(QScene2DPrivate::get(node));
-void Scene2D::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
-
- case Qt3DCore::PropertyUpdated: {
-
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange
- = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("renderPolicy")) {
- m_renderPolicy = propertyChange->value().value<QScene2D::RenderPolicy>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("output")) {
- Qt3DCore::QNodeId outputId = propertyChange->value().value<Qt3DCore::QNodeId>();
- setOutput(outputId);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("pressed")) {
- QPickEventPtr ev = propertyChange->value().value<QPickEventPtr>();
- handlePickEvent(QEvent::MouseButtonPress, ev);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("released")) {
- QPickEventPtr ev = propertyChange->value().value<QPickEventPtr>();
- handlePickEvent(QEvent::MouseButtonRelease, ev);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("moved")) {
- QPickEventPtr ev = propertyChange->value().value<QPickEventPtr>();
- handlePickEvent(QEvent::MouseMove, ev);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("mouseEnabled")) {
- m_mouseEnabled = propertyChange->value().toBool();
- if (m_mouseEnabled && !m_cachedPickEvent.isNull()) {
- handlePickEvent(QEvent::MouseButtonPress, m_cachedPickEvent);
- m_cachedPickEvent.clear();
- }
- } else if (propertyChange->propertyName() == QByteArrayLiteral("sceneInitialized")) {
- startGrabbing();
+ if (m_mouseEnabled != node->isMouseEnabled()) {
+ m_mouseEnabled = node->isMouseEnabled();
+ if (!firstTime && m_mouseEnabled && m_cachedPickEvent) {
+ handlePickEvent(QEvent::MouseButtonPress, m_cachedPickEvent.data());
+ m_cachedPickEvent.clear();
}
- break;
}
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("entities")) {
- m_entities.push_back(change->addedNodeId());
- registerObjectPickerEvents(change->addedNodeId());
- }
- break;
- }
+ m_renderPolicy = node->renderPolicy();
+ auto id = Qt3DCore::qIdForNode(node->output());
+ if (id != m_outputId)
+ setOutput(id);
+
+ auto ids = Qt3DCore::qIdsForNodes(const_cast<QScene2D *>(node)->entities());
+ std::sort(std::begin(ids), std::end(ids));
+ Qt3DCore::QNodeIdVector addedEntities;
+ Qt3DCore::QNodeIdVector removedEntities;
+ std::set_difference(std::begin(ids), std::end(ids),
+ std::begin(m_entities), std::end(m_entities),
+ std::inserter(addedEntities, addedEntities.end()));
+ std::set_difference(std::begin(m_entities), std::end(m_entities),
+ std::begin(ids), std::end(ids),
+ std::inserter(removedEntities, removedEntities.end()));
+ for (const auto &id: addedEntities) {
+ Qt3DCore::QEntity *entity = qobject_cast<Qt3DCore::QEntity *>(dnode->m_scene->lookupNode(id));
+ if (!entity)
+ return;
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("entities")) {
- m_entities.removeOne(change->removedNodeId());
- unregisterObjectPickerEvents(change->removedNodeId());
- }
- break;
+ if (registerObjectPickerEvents(entity))
+ m_entities.push_back(id);
+ else
+ Qt3DCore::QNodePrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd))->update();
}
-
- default:
- break;
+ for (const auto &id: removedEntities) {
+ m_entities.removeOne(id);
+ unregisterObjectPickerEvents(id);
}
- BackendNode::sceneChangeEvent(e);
+ std::sort(std::begin(m_entities), std::end(m_entities));
+
+ if (firstTime)
+ setSharedObject(dnode->m_renderManager->m_sharedObject);
}
void Scene2D::setSharedObject(Qt3DRender::Quick::Scene2DSharedObjectPtr sharedObject)
@@ -438,25 +423,40 @@ void Scene2D::cleanup()
}
if (m_renderThread) {
renderThreadClientCount->fetchAndSubAcquire(1);
- if (renderThreadClientCount->load() == 0)
+ if (renderThreadClientCount->loadRelaxed() == 0)
renderThread->quit();
}
}
-bool Scene2D::registerObjectPickerEvents(Qt3DCore::QNodeId entityId)
+bool Scene2D::registerObjectPickerEvents(Qt3DCore::QEntity *qentity)
{
Entity *entity = nullptr;
if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
- entityId, (void**)&entity, nullptr)) {
+ qentity->id(), (void**)&entity, nullptr)) {
+ qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO
+ << "Entity not yet available in backend";
return false;
}
+
if (!entity->containsComponentsOfType<ObjectPicker>() ||
!entity->containsComponentsOfType<GeometryRenderer>()) {
qCWarning(Qt3DRender::Quick::Scene2D) << Q_FUNC_INFO
<< "Entity does not contain required components: ObjectPicker and GeometryRenderer";
return false;
}
+
+ QObjectPicker *picker = qentity->componentsOfType<QObjectPicker>().front();
+ m_connections << QObject::connect(picker, &QObjectPicker::pressed, qentity, [this](Qt3DRender::QPickEvent *pick) {
+ handlePickEvent(QEvent::MouseButtonPress, pick);
+ });
+ m_connections << QObject::connect(picker, &QObjectPicker::released, qentity, [this](Qt3DRender::QPickEvent *pick) {
+ handlePickEvent(QEvent::MouseButtonRelease, pick);
+ });
+ m_connections << QObject::connect(picker, &QObjectPicker::moved, qentity, [this](Qt3DRender::QPickEvent *pick) {
+ handlePickEvent(QEvent::MouseMove, pick);
+ });
+
Qt3DCore::QBackendNodePrivate *priv = Qt3DCore::QBackendNodePrivate::get(this);
Qt3DCore::QChangeArbiter *arbiter = static_cast<Qt3DCore::QChangeArbiter*>(priv->m_arbiter);
arbiter->registerObserver(d_ptr, entity->componentUuid<ObjectPicker>());
@@ -467,26 +467,27 @@ void Scene2D::unregisterObjectPickerEvents(Qt3DCore::QNodeId entityId)
{
Entity *entity = nullptr;
if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
- entityId, (void**)&entity, nullptr)) {
+ entityId, (void**)&entity, nullptr))
return;
- }
+
Qt3DCore::QBackendNodePrivate *priv = Qt3DCore::QBackendNodePrivate::get(this);
Qt3DCore::QChangeArbiter *arbiter = static_cast<Qt3DCore::QChangeArbiter*>(priv->m_arbiter);
arbiter->unregisterObserver(d_ptr, entity->componentUuid<ObjectPicker>());
}
-void Scene2D::handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev)
+void Scene2D::handlePickEvent(int type, const Qt3DRender::QPickEvent *ev)
{
if (!isEnabled())
return;
if (m_mouseEnabled) {
- QPickTriangleEvent *pickTriangle = static_cast<QPickTriangleEvent *>(ev.data());
+ const QPickTriangleEvent *pickTriangle = static_cast<const QPickTriangleEvent *>(ev);
+ Q_ASSERT(pickTriangle->entity());
Entity *entity = nullptr;
if (!resourceAccessor()->accessResource(RenderBackendResourceAccessor::EntityHandle,
- QPickEventPrivate::get(pickTriangle)->m_entity,
- (void**)&entity, nullptr)) {
+ Qt3DCore::qIdForNode(pickTriangle->entity()),
+ (void**)&entity, nullptr))
return;
- }
+
CoordinateReader reader(renderer()->nodeManagers());
if (reader.setGeometry(entity->renderComponent<GeometryRenderer>(),
QAttribute::defaultTextureCoordinateAttributeName())) {
@@ -510,24 +511,14 @@ void Scene2D::handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev)
QCoreApplication::postEvent(m_sharedObject->m_quickWindow, mouseEvent);
}
} else if (type == QEvent::MouseButtonPress) {
- m_cachedPickEvent = ev;
+ const QPickTriangleEvent *pickTriangle = static_cast<const QPickTriangleEvent *>(ev);
+ const QPickTriangleEventPrivate *dpick = QPickTriangleEventPrivate::get(pickTriangle);
+ m_cachedPickEvent = QPickEventPtr(dpick->clone());
} else {
m_cachedPickEvent.clear();
}
}
-void Scene2D::startGrabbing()
-{
- for (Qt3DCore::QNodeId e : qAsConst(m_entities))
- registerObjectPickerEvents(e);
-}
-
-void Scene2D::stopGrabbing()
-{
- for (Qt3DCore::QNodeId e : qAsConst(m_entities))
- unregisterObjectPickerEvents(e);
-}
-
} // namespace Quick
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/quick3d/quick3dscene2d/items/scene2d_p.h b/src/quick3d/quick3dscene2d/items/scene2d_p.h
index bd7874cd6..2f2b556ec 100644
--- a/src/quick3d/quick3dscene2d/items/scene2d_p.h
+++ b/src/quick3d/quick3dscene2d/items/scene2d_p.h
@@ -94,16 +94,13 @@ public:
void setOutput(Qt3DCore::QNodeId outputId);
void initializeSharedObject();
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
bool updateFbo(QOpenGLTexture *texture);
void syncRenderControl();
- void startGrabbing();
- void stopGrabbing();
- bool registerObjectPickerEvents(Qt3DCore::QNodeId entityId);
+ bool registerObjectPickerEvents(Qt3DCore::QEntity *qentity);
void unregisterObjectPickerEvents(Qt3DCore::QNodeId entityId);
- void handlePickEvent(int type, const Qt3DRender::QPickEventPtr &ev);
+ void handlePickEvent(int type, const QPickEvent *ev);
QOpenGLContext *m_context;
QOpenGLContext *m_shareContext;
@@ -126,6 +123,7 @@ public:
#ifdef QT_OPENGL_ES_2_ANGLE
bool m_usingAngle;
#endif
+ QVector<QMetaObject::Connection> m_connections;
};
} // Quick
diff --git a/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp b/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp
index 1176d8e8e..2b967f2d2 100644
--- a/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp
+++ b/src/quick3d/quick3dscene2d/items/scene2dmanager.cpp
@@ -40,8 +40,6 @@
#include "scene2dmanager_p.h"
#include "scene2devent_p.h"
-#include <Qt3DCore/QPropertyUpdatedChange>
-
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
diff --git a/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
index 1dd798d94..aed624501 100644
--- a/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
+++ b/src/quick3d/quick3dscene2d/items/scene2dsharedobject.cpp
@@ -41,8 +41,6 @@
#include "scene2devent_p.h"
#include "scene2dsharedobject_p.h"
-#include <Qt3DCore/QPropertyUpdatedChange>
-
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
@@ -61,6 +59,7 @@ Scene2DSharedObject::Scene2DSharedObject(Scene2DManager *manager)
, m_quickWindow(nullptr)
, m_renderManager(manager)
, m_surface(nullptr)
+ , m_renderThread(nullptr)
, m_renderObject(nullptr)
, m_disallowed(false)
, m_quit(false)
diff --git a/src/quick3d/quick3dscene2d/quick3dscene2d.pro b/src/quick3d/quick3dscene2d/quick3dscene2d.pro
index fb599187b..b0596e8de 100644
--- a/src/quick3d/quick3dscene2d/quick3dscene2d.pro
+++ b/src/quick3d/quick3dscene2d/quick3dscene2d.pro
@@ -4,9 +4,6 @@ MODULE = 3dquickscene2d
QT += core core-private qml qml-private 3dcore 3drender 3dquick 3dquick-private 3dcore-private 3drender-private
CONFIG -= precompile_header
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index 273ab359a..b618eda55 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -68,7 +68,6 @@ class QScreen;
namespace Qt3DCore {
class QAbstractFrameAdvanceService;
-class QBackendNodeFactory;
class QEventFilterService;
class QAbstractAspectJobManager;
class QServiceLocator;
@@ -115,7 +114,6 @@ public:
JointDirty = 1 << 11,
LayersDirty = 1 << 12,
TechniquesDirty = 1 << 13,
- EntityHierarchyDirty= 1 << 14,
LightsDirty = 1 << 15,
AllDirty = 0xffffff
};
@@ -142,7 +140,7 @@ public:
// Threaded renderer
virtual void render() = 0;
// Synchronous renderer
- virtual void doRender(bool scene3dBlocking = false) = 0;
+ virtual void doRender(bool swapBuffers) = 0;
virtual void cleanGraphicsResources() = 0;
@@ -160,10 +158,10 @@ public:
virtual QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() = 0;
virtual Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() = 0;
virtual Qt3DCore::QAspectJobPtr rayCastingJob() = 0;
- virtual Qt3DCore::QAspectJobPtr syncTextureLoadingJob() = 0;
+ virtual Qt3DCore::QAspectJobPtr syncLoadingJobs() = 0;
virtual Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() = 0;
- virtual void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Entity *root) = 0;
+ virtual void setSceneRoot(Entity *root) = 0;
virtual Entity *sceneRoot() const = 0;
virtual FrameGraphNode *frameGraphRoot() const = 0;
diff --git a/src/render/backend/backendnode.cpp b/src/render/backend/backendnode.cpp
index 0dc8da237..642f6e44d 100644
--- a/src/render/backend/backendnode.cpp
+++ b/src/render/backend/backendnode.cpp
@@ -41,6 +41,7 @@
#include <private/renderer_p.h>
#include <private/resourceaccessor_p.h>
#include <private/nodemanagers_p.h>
+#include <Qt3DCore/private/qbackendnode_p.h>
QT_BEGIN_NAMESPACE
@@ -55,6 +56,12 @@ BackendNode::BackendNode(Mode mode)
{
}
+BackendNode::BackendNode(Qt3DCore::QBackendNodePrivate &dd)
+ : QBackendNode(dd)
+ , m_renderer(nullptr)
+{
+}
+
BackendNode::~BackendNode()
{
}
@@ -81,6 +88,13 @@ QSharedPointer<RenderBackendResourceAccessor> BackendNode::resourceAccessor()
return r->nodeManagers()->resourceAccessor();
}
+void BackendNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
+{
+ Q_UNUSED(firstTime);
+
+ d_ptr->setEnabled(frontEnd->isEnabled());
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/backendnode_p.h b/src/render/backend/backendnode_p.h
index f94033c1a..37f8305af 100644
--- a/src/render/backend/backendnode_p.h
+++ b/src/render/backend/backendnode_p.h
@@ -58,6 +58,12 @@
QT_BEGIN_NAMESPACE
+namespace Qt3DCore {
+
+class QBackendNodePrivate;
+
+}
+
namespace Qt3DRender {
namespace Render {
@@ -70,12 +76,15 @@ public:
BackendNode(Qt3DCore::QBackendNode::Mode mode = ReadOnly);
~BackendNode();
+ virtual void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime);
+
void setRenderer(AbstractRenderer *renderer);
AbstractRenderer *renderer() const;
QSharedPointer<RenderBackendResourceAccessor> resourceAccessor();
protected:
+ explicit BackendNode(Qt3DCore::QBackendNodePrivate &dd);
void markDirty(AbstractRenderer::BackendNodeDirtySet changes);
AbstractRenderer *m_renderer;
};
diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp
index 42635bad7..d902a08c7 100644
--- a/src/render/backend/cameralens.cpp
+++ b/src/render/backend/cameralens.cpp
@@ -41,14 +41,13 @@
#include <Qt3DRender/qcameralens.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
-#include <Qt3DRender/private/qcameralens_p.h>
#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/sphere_p.h>
#include <Qt3DRender/private/computefilteredboundingvolumejob_p.h>
+#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qtransform.h>
QT_BEGIN_NAMESPACE
@@ -116,15 +115,49 @@ Matrix4x4 CameraLens::viewMatrix(const Matrix4x4 &worldTransform)
m.lookAt(convertToQVector3D(Vector3D(position)),
convertToQVector3D(Vector3D(position + viewDirection)),
convertToQVector3D(Vector3D(upVector)));
+
+ qDebug(Jobs) << Q_FUNC_INFO << "Transform Matrix" << worldTransform << "View Matrix" << m;
+
return Matrix4x4(m);
}
-void CameraLens::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void CameraLens::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QCameraLensData>>(change);
- const auto &data = typedChange->data;
- m_projection = Matrix4x4(data.projectionMatrix);
- m_exposure = data.exposure;
+ const QCameraLens *node = qobject_cast<const QCameraLens *>(frontEnd);
+ if (!node)
+ return;
+
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const Matrix4x4 projectionMatrix(node->projectionMatrix());
+ if (projectionMatrix != m_projection) {
+ m_projection = projectionMatrix;
+ markDirty(AbstractRenderer::AllDirty);
+ }
+
+ if (node->exposure() != m_exposure) {
+ m_exposure = node->exposure();
+ markDirty(AbstractRenderer::AllDirty);
+ }
+
+ const QCameraLensPrivate *d = static_cast<const QCameraLensPrivate *>(QNodePrivate::get(node));
+ if (d->m_pendingViewAllCommand != m_pendingViewAllCommand) {
+ m_pendingViewAllCommand = d->m_pendingViewAllCommand;
+
+ if (m_pendingViewAllCommand) {
+ const QVariant v = m_pendingViewAllCommand.data;
+ const QNodeCommand::CommandId commandId = m_pendingViewAllCommand.commandId;
+
+ if (m_pendingViewAllCommand.name == QLatin1String("QueryRootBoundingVolume")) {
+ const QNodeId id = v.value<QNodeId>();
+ computeSceneBoundingVolume({}, id, commandId);
+ } else if (m_pendingViewAllCommand.name == QLatin1String("QueryEntityBoundingVolume")) {
+ const QVector<QNodeId> ids = v.value<QVector<QNodeId>>();
+ if (ids.size() == 2)
+ computeSceneBoundingVolume(ids[0], ids[1], commandId);
+ }
+ }
+ }
}
void CameraLens::computeSceneBoundingVolume(QNodeId entityId,
@@ -152,15 +185,16 @@ void CameraLens::computeSceneBoundingVolume(QNodeId entityId,
void CameraLens::notifySceneBoundingVolume(const Sphere &sphere, QNodeCommand::CommandId commandId)
{
- if (m_pendingViewAllCommand != commandId)
+ if (!m_pendingViewAllCommand || m_pendingViewAllCommand.commandId != commandId)
return;
if (sphere.radius() > 0.f) {
QVector<float> data = { sphere.center().x(), sphere.center().y(), sphere.center().z(),
sphere.radius() };
QVariant v;
v.setValue(data);
- sendCommand(QLatin1Literal("ViewAll"), v, m_pendingViewAllCommand);
+ sendCommand(QLatin1String("ViewAll"), v, m_pendingViewAllCommand.commandId);
}
+ m_pendingViewAllCommand = {};
}
void CameraLens::setProjection(const Matrix4x4 &projection)
@@ -173,47 +207,6 @@ void CameraLens::setExposure(float exposure)
m_exposure = exposure;
}
-void CameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyUpdated: {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
-
- if (propertyChange->propertyName() == QByteArrayLiteral("projectionMatrix")) {
- QMatrix4x4 projectionMatrix = propertyChange->value().value<QMatrix4x4>();
- m_projection = Matrix4x4(projectionMatrix);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("exposure")) {
- setExposure(propertyChange->value().toFloat());
- }
-
- markDirty(AbstractRenderer::AllDirty);
- }
- break;
-
- case CommandRequested: {
- QNodeCommandPtr command = qSharedPointerCast<QNodeCommand>(e);
-
- if (command->name() == QLatin1Literal("QueryRootBoundingVolume")) {
- m_pendingViewAllCommand = command->commandId();
- QVariant v = command->data();
- QNodeId id = v.value<QNodeId>();
- computeSceneBoundingVolume({}, id, command->commandId());
- } else if (command->name() == QLatin1Literal("QueryEntityBoundingVolume")) {
- m_pendingViewAllCommand = command->commandId();
- QVariant v = command->data();
- QVector<QNodeId> ids = v.value<QVector<QNodeId>>();
- if (ids.size() == 2)
- computeSceneBoundingVolume(ids[0], ids[1], command->commandId());
- }
- }
- break;
-
- default:
- break;
- }
- BackendNode::sceneChangeEvent(e);
-}
-
bool CameraLens::viewMatrixForCamera(EntityManager* manager, Qt3DCore::QNodeId cameraId,
Matrix4x4 &viewMatrix, Matrix4x4 &projectionMatrix)
{
diff --git a/src/render/backend/cameralens_p.h b/src/render/backend/cameralens_p.h
index 80a1715cf..bd721d5e9 100644
--- a/src/render/backend/cameralens_p.h
+++ b/src/render/backend/cameralens_p.h
@@ -54,6 +54,7 @@
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DCore/private/qnodecommand_p.h>
#include <Qt3DCore/private/matrix4x4_p.h>
+#include <Qt3DRender/private/qcameralens_p.h>
#include <QRectF>
QT_BEGIN_NAMESPACE
@@ -96,21 +97,20 @@ public:
void setExposure(float exposure);
inline float exposure() const { return m_exposure; }
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
void notifySceneBoundingVolume(const Sphere &sphere, Qt3DCore::QNodeCommand::CommandId commandId);
static bool viewMatrixForCamera(EntityManager *manager, Qt3DCore::QNodeId cameraId,
Matrix4x4 &viewMatrix, Matrix4x4 &projectionMatrix);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
void computeSceneBoundingVolume(Qt3DCore::QNodeId entityId,
Qt3DCore::QNodeId cameraId,
Qt3DCore::QNodeCommand::CommandId commandId);
QRenderAspect *m_renderAspect;
- Qt3DCore::QNodeCommand::CommandId m_pendingViewAllCommand;
+ CameraLensCommand m_pendingViewAllCommand;
Matrix4x4 m_projection;
float m_exposure;
};
diff --git a/src/render/backend/commandexecuter.cpp b/src/render/backend/commandexecuter.cpp
index 182ba89d1..5ed0c970d 100644
--- a/src/render/backend/commandexecuter.cpp
+++ b/src/render/backend/commandexecuter.cpp
@@ -248,10 +248,10 @@ QJsonObject parameterPackToJson(const Render::ShaderParameterPack &pack)
const Render::PackUniformHash &uniforms = pack.uniforms();
QJsonArray uniformsArray;
- for (auto it = uniforms.cbegin(), end = uniforms.cend(); it != end; ++it) {
+ for (int i = 0, m = uniforms.keys.size(); i < m; ++i) {
QJsonObject uniformObj;
- uniformObj.insert(QLatin1String("name"), Render::StringToInt::lookupString(it.key()));
- const Render::UniformValue::ValueType type = it.value().valueType();
+ uniformObj.insert(QLatin1String("name"), Render::StringToInt::lookupString(uniforms.keys.at(i)));
+ const Render::UniformValue::ValueType type = uniforms.values.at(i).valueType();
uniformObj.insert(QLatin1String("type"),
type == Render::UniformValue::ScalarValue
? QLatin1String("value")
@@ -261,11 +261,11 @@ QJsonObject parameterPackToJson(const Render::ShaderParameterPack &pack)
obj.insert(QLatin1String("uniforms"), uniformsArray);
QJsonArray texturesArray;
- const QVector<Render::ShaderParameterPack::NamedTexture> &textures = pack.textures();
+ const QVector<Render::ShaderParameterPack::NamedResource> &textures = pack.textures();
for (const auto & texture : textures) {
QJsonObject textureObj;
textureObj.insert(QLatin1String("name"), Render::StringToInt::lookupString(texture.glslNameId));
- textureObj.insert(QLatin1String("id"), qint64(texture.texId.id()));
+ textureObj.insert(QLatin1String("id"), qint64(texture.nodeId.id()));
texturesArray.push_back(textureObj);
}
obj.insert(QLatin1String("textures"), texturesArray);
@@ -346,15 +346,15 @@ void CommandExecuter::performAsynchronousCommandExecution(const QVector<Render::
viewObj.insert(QLatin1String("clearStencilValue"), v->clearStencilValue());
QJsonArray renderCommandsArray;
- for (Render::RenderCommand *c : v->commands()) {
+ for (const Render::RenderCommand &c : v->commands()) {
QJsonObject commandObj;
Render::NodeManagers *nodeManagers = m_renderer->nodeManagers();
- commandObj.insert(QLatin1String("shader"), backendNodeToJSon(c->m_shader, nodeManagers->shaderManager()));
- commandObj.insert(QLatin1String("vao"), double(c->m_vao.handle()));
- commandObj.insert(QLatin1String("instanceCount"), c->m_instanceCount);
- commandObj.insert(QLatin1String("geometry"), backendNodeToJSon(c->m_geometry, nodeManagers->geometryManager()));
- commandObj.insert(QLatin1String("geometryRenderer"), backendNodeToJSon(c->m_geometryRenderer, nodeManagers->geometryRendererManager()));
- commandObj.insert(QLatin1String("shaderParameterPack"), parameterPackToJson(c->m_parameterPack));
+ commandObj.insert(QLatin1String("shader"), backendNodeToJSon(c.m_shader, nodeManagers->shaderManager()));
+ commandObj.insert(QLatin1String("vao"), double(c.m_vao.handle()));
+ commandObj.insert(QLatin1String("instanceCount"), c.m_instanceCount);
+ commandObj.insert(QLatin1String("geometry"), backendNodeToJSon(c.m_geometry, nodeManagers->geometryManager()));
+ commandObj.insert(QLatin1String("geometryRenderer"), backendNodeToJSon(c.m_geometryRenderer, nodeManagers->geometryRendererManager()));
+ commandObj.insert(QLatin1String("shaderParameterPack"), parameterPackToJson(c.m_parameterPack));
renderCommandsArray.push_back(commandObj);
}
diff --git a/src/render/backend/computecommand.cpp b/src/render/backend/computecommand.cpp
index 349941965..bc82291f0 100644
--- a/src/render/backend/computecommand.cpp
+++ b/src/render/backend/computecommand.cpp
@@ -53,6 +53,7 @@ ComputeCommand::ComputeCommand()
: BackendNode(ReadWrite)
, m_frameCount(0)
, m_runType(QComputeCommand::Continuous)
+ , m_hasReachedFrameCount(false)
{
m_workGroups[0] = 1;
m_workGroups[1] = 1;
@@ -71,38 +72,45 @@ void ComputeCommand::cleanup()
m_workGroups[2] = 1;
m_frameCount = 0;
m_runType = QComputeCommand::Continuous;
+ m_hasReachedFrameCount = false;
}
-void ComputeCommand::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void ComputeCommand::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QComputeCommandData>>(change);
- const auto &data = typedChange->data;
- m_workGroups[0] = data.workGroupX;
- m_workGroups[1] = data.workGroupY;
- m_workGroups[2] = data.workGroupZ;
- m_runType = data.runType;
- m_frameCount = data.frameCount;
- if (m_renderer != nullptr)
- BackendNode::markDirty(AbstractRenderer::ComputeDirty);
-}
+ const QComputeCommand *node = qobject_cast<const QComputeCommand *>(frontEnd);
+ if (!node)
+ return;
-void ComputeCommand::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (e->type() == Qt3DCore::PropertyUpdated) {
- if (propertyChange->propertyName() == QByteArrayLiteral("workGroupX"))
- m_workGroups[0] = propertyChange->value().toInt();
- else if (propertyChange->propertyName() == QByteArrayLiteral("workGroupY"))
- m_workGroups[1] = propertyChange->value().toInt();
- else if (propertyChange->propertyName() == QByteArrayLiteral("workGroupZ"))
- m_workGroups[2] = propertyChange->value().toInt();
- else if (propertyChange->propertyName() == QByteArrayLiteral("frameCount"))
- m_frameCount = propertyChange->value().toInt();
- else if (propertyChange->propertyName() == QByteArrayLiteral("runType"))
- m_runType = static_cast<QComputeCommand::RunType>(propertyChange->value().toInt());
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (m_workGroups[0] != node->workGroupX()) {
+ m_workGroups[0] = node->workGroupX();
+ markDirty(AbstractRenderer::ComputeDirty);
+ }
+ if (m_workGroups[1] != node->workGroupY()) {
+ m_workGroups[1] = node->workGroupY();
+ markDirty(AbstractRenderer::ComputeDirty);
+ }
+ if (m_workGroups[2] != node->workGroupZ()) {
+ m_workGroups[2] = node->workGroupZ();
+ markDirty(AbstractRenderer::ComputeDirty);
+ }
+ if (node->runType() != m_runType) {
+ m_runType = node->runType();
+ markDirty(AbstractRenderer::ComputeDirty);
+ }
+ const QComputeCommandPrivate *d = static_cast<const QComputeCommandPrivate *>(Qt3DCore::QNodePrivate::get(node));
+ // Check frame count only if frontend is enabled
+ // If disabled that means we might have disabled the frontend because
+ // framecount reached 0
+ if (d->m_enabled && d->m_frameCount != m_frameCount) {
+ m_frameCount = d->m_frameCount;
+ m_hasReachedFrameCount = m_frameCount <= 0;
markDirty(AbstractRenderer::ComputeDirty);
}
- BackendNode::sceneChangeEvent(e);
+
+ if (firstTime)
+ markDirty(AbstractRenderer::ComputeDirty);
}
// Called from buildComputeRenderCommands in a job
@@ -110,14 +118,19 @@ void ComputeCommand::updateFrameCount()
{
// Disable frontend node when reaching 0
--m_frameCount;
- if (m_frameCount <= 0) {
- setEnabled(false);
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("enabled");
- e->setValue(false);
- notifyObservers(e);
- }
+ if (m_frameCount <= 0)
+ m_hasReachedFrameCount = true;
+ // Backend will be disabled on the next sync
+}
+
+void ComputeCommand::resetHasReachedFrameCount()
+{
+ m_hasReachedFrameCount = false;
+}
+
+bool ComputeCommand::hasReachedFrameCount() const
+{
+ return m_hasReachedFrameCount;
}
} // Render
diff --git a/src/render/backend/computecommand_p.h b/src/render/backend/computecommand_p.h
index 10e10fd25..5012930ae 100644
--- a/src/render/backend/computecommand_p.h
+++ b/src/render/backend/computecommand_p.h
@@ -69,7 +69,7 @@ public:
~ComputeCommand();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
inline int x() const Q_DECL_NOTHROW { return m_workGroups[0]; }
inline int y() const Q_DECL_NOTHROW { return m_workGroups[1]; }
@@ -79,12 +79,14 @@ public:
// Called from a job
void updateFrameCount();
+ bool hasReachedFrameCount() const;
+ void resetHasReachedFrameCount();
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
int m_workGroups[3];
int m_frameCount;
QComputeCommand::RunType m_runType;
+ bool m_hasReachedFrameCount;
};
} // Render
diff --git a/src/render/backend/entity.cpp b/src/render/backend/entity.cpp
index bf128b508..682dc000e 100644
--- a/src/render/backend/entity.cpp
+++ b/src/render/backend/entity.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "entity_p.h"
+#include "entity_p_p.h"
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/qabstractlight.h>
@@ -59,10 +60,7 @@
#include <Qt3DRender/qcameralens.h>
#include <Qt3DCore/qarmature.h>
-#include <Qt3DCore/qcomponentaddedchange.h>
-#include <Qt3DCore/qcomponentremovedchange.h>
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/private/qentity_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
@@ -77,8 +75,33 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
+
+EntityPrivate::EntityPrivate()
+ : Qt3DCore::QBackendNodePrivate(Entity::ReadOnly)
+{
+}
+
+EntityPrivate *EntityPrivate::get(Entity *node)
+{
+ return node->d_func();
+}
+
+void EntityPrivate::componentAdded(Qt3DCore::QNode *frontend)
+{
+ Q_Q(Entity);
+ const auto componentIdAndType = QNodeIdTypePair(frontend->id(), QNodePrivate::findStaticMetaObject(frontend->metaObject()));
+ q->addComponent(componentIdAndType);
+}
+
+void EntityPrivate::componentRemoved(Qt3DCore::QNode *frontend)
+{
+ Q_Q(Entity);
+ q->removeComponent(frontend->id());
+}
+
+
Entity::Entity()
- : BackendNode()
+ : BackendNode(*new EntityPrivate)
, m_nodeManagers(nullptr)
, m_boundingDirty(false)
, m_treeEnabled(true)
@@ -95,11 +118,19 @@ void Entity::cleanup()
if (m_nodeManagers != nullptr) {
m_nodeManagers->worldMatrixManager()->releaseResource(peerId());
qCDebug(Render::RenderNodes) << Q_FUNC_INFO;
+
+ removeFromParentChildHandles();
+
+ for (auto &childHandle : qAsConst(m_childrenHandles)) {
+ auto child = m_nodeManagers->renderNodesManager()->data(childHandle);
+ // children should always exist and have this as parent
+ // if they were destroyed, they would have removed themselves from our m_childrenHandles
+ Q_ASSERT(child);
+ Q_ASSERT(child->m_parentHandle == m_handle);
+ child->m_parentHandle = {};
+ }
}
- if (!m_parentEntityId.isNull())
- markDirty(AbstractRenderer::EntityHierarchyDirty);
- m_parentEntityId = Qt3DCore::QNodeId();
m_worldTransform = HMatrix();
// Release all component will have to perform their own release when they receive the
// NodeDeleted notification
@@ -122,6 +153,7 @@ void Entity::cleanup()
m_localBoundingVolume.reset();
m_worldBoundingVolume.reset();
m_worldBoundingVolumeWithChildren.reset();
+ m_parentHandle = {};
m_boundingDirty = false;
QBackendNode::setEnabled(false);
}
@@ -129,6 +161,12 @@ void Entity::cleanup()
void Entity::setParentHandle(HEntity parentHandle)
{
Q_ASSERT(m_nodeManagers);
+
+ if (parentHandle == m_parentHandle)
+ return;
+
+ removeFromParentChildHandles();
+
m_parentHandle = parentHandle;
auto parent = m_nodeManagers->renderNodesManager()->data(parentHandle);
if (parent != nullptr && !parent->m_childrenHandles.contains(m_handle))
@@ -145,89 +183,60 @@ void Entity::setHandle(HEntity handle)
m_handle = handle;
}
-void Entity::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
+void Entity::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<QNodeCreatedChange<Qt3DCore::QEntityData>>(change);
- const auto &data = typedChange->data;
-
- // Note this is *not* the parentId as that is the ID of the parent QNode, which is not
- // necessarily the same as the parent QEntity (which may be further up the tree).
- m_parentEntityId = data.parentEntityId;
- qCDebug(Render::RenderNodes) << "Creating Entity id =" << peerId() << "parentId =" << m_parentEntityId;
-
- // TODO: Store string id instead and only in debug mode
- //m_objectName = peer->objectName();
- m_worldTransform = m_nodeManagers->worldMatrixManager()->getOrAcquireHandle(peerId());
-
- // TODO: Suboptimal -> Maybe have a Hash<QComponent, QEntityList> instead
- m_transformComponent = QNodeId();
- m_materialComponent = QNodeId();
- m_cameraComponent = QNodeId();
- m_geometryRendererComponent = QNodeId();
- m_objectPickerComponent = QNodeId();
- m_boundingVolumeDebugComponent = QNodeId();
- m_computeComponent = QNodeId();
- m_layerComponents.clear();
- m_levelOfDetailComponents.clear();
- m_rayCasterComponents.clear();
- m_shaderDataComponents.clear();
- m_lightComponents.clear();
- m_environmentLightComponents.clear();
- m_localBoundingVolume = QSharedPointer<Sphere>::create(peerId());
- m_worldBoundingVolume = QSharedPointer<Sphere>::create(peerId());
- m_worldBoundingVolumeWithChildren = QSharedPointer<Sphere>::create(peerId());
+ const Qt3DCore::QEntity *node = qobject_cast<const Qt3DCore::QEntity *>(frontEnd);
+ if (!node)
+ return;
- for (const auto &idAndType : qAsConst(data.componentIdsAndTypes))
- addComponent(idAndType);
+ if (this->isEnabled() != node->isEnabled()) {
+ markDirty(AbstractRenderer::EntityEnabledDirty);
+ // We let QBackendNode::syncFromFrontEnd change the enabled property
+ }
- markDirty(AbstractRenderer::EntityHierarchyDirty);
-}
+ const auto parentID = node->parentEntity() ? node->parentEntity()->id() : Qt3DCore::QNodeId();
+ auto parentHandle = m_nodeManagers->renderNodesManager()->lookupHandle(parentID);
-void Entity::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
+ // All entity creation is done from top-down and always during the same frame, so
+ // we if we have a valid parent node, we should always be able to resolve the
+ // backend parent at this time
+ Q_ASSERT(!node->parentEntity() || (!parentHandle.isNull() && m_nodeManagers->renderNodesManager()->data(parentHandle)));
- case ComponentAdded: {
- QComponentAddedChangePtr change = qSharedPointerCast<QComponentAddedChange>(e);
- const auto componentIdAndType = QNodeIdTypePair(change->componentId(), change->componentMetaObject());
- addComponent(componentIdAndType);
- qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Added. Id =" << change->componentId();
+ if (parentHandle != m_parentHandle) {
markDirty(AbstractRenderer::AllDirty);
- break;
}
- case ComponentRemoved: {
- QComponentRemovedChangePtr change = qSharedPointerCast<QComponentRemovedChange>(e);
- removeComponent(change->componentId());
- qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "Component Removed. Id =" << change->componentId();
- markDirty(AbstractRenderer::AllDirty);
- break;
- }
+ setParentHandle(parentHandle);
- case PropertyUpdated: {
- QPropertyUpdatedChangePtr change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("enabled")) {
- // We only mark as dirty the renderer
- markDirty(AbstractRenderer::EntityEnabledDirty);
- // We let QBackendNode::sceneChangeEvent change the enabled property
- } else if (change->propertyName() == QByteArrayLiteral("parentEntityUpdated")) {
- auto newParent = change->value().value<Qt3DCore::QNodeId>();
- qCDebug(Render::RenderNodes) << "Setting parent for " << peerId() << ", new parentId =" << newParent;
- if (m_parentEntityId != newParent) {
- m_parentEntityId = newParent;
- // TODO: change to EventHierarchyDirty and update renderer to
- // ensure all jobs are run that depend on Entity hierarchy.
- markDirty(AbstractRenderer::AllDirty);
- }
- }
+ if (firstTime) {
+ m_worldTransform = m_nodeManagers->worldMatrixManager()->getOrAcquireHandle(peerId());
- break;
+ // TODO: Suboptimal -> Maybe have a Hash<QComponent, QEntityList> instead
+ m_transformComponent = QNodeId();
+ m_materialComponent = QNodeId();
+ m_cameraComponent = QNodeId();
+ m_geometryRendererComponent = QNodeId();
+ m_objectPickerComponent = QNodeId();
+ m_boundingVolumeDebugComponent = QNodeId();
+ m_computeComponent = QNodeId();
+ m_layerComponents.clear();
+ m_levelOfDetailComponents.clear();
+ m_rayCasterComponents.clear();
+ m_shaderDataComponents.clear();
+ m_lightComponents.clear();
+ m_environmentLightComponents.clear();
+ m_localBoundingVolume = QSharedPointer<Sphere>::create(peerId());
+ m_worldBoundingVolume = QSharedPointer<Sphere>::create(peerId());
+ m_worldBoundingVolumeWithChildren = QSharedPointer<Sphere>::create(peerId());
+
+ const QComponentVector &components = node->components();
+ for (QComponent *c : components) {
+ const auto idAndType = QNodeIdTypePair(c->id(), QNodePrivate::findStaticMetaObject(c->metaObject()));
+ addComponent(idAndType);
+ }
}
- default:
- break;
- }
- BackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
}
void Entity::dump() const
@@ -246,35 +255,12 @@ Entity *Entity::parent() const
return m_nodeManagers->renderNodesManager()->data(m_parentHandle);
}
-
-// clearEntityHierarchy and rebuildEntityHierarchy should only be called
-// from UpdateEntityHierarchyJob to update the entity hierarchy for the
-// entire scene at once
-void Entity::clearEntityHierarchy()
+void Entity::removeFromParentChildHandles()
{
- m_childrenHandles.clear();
- m_parentHandle = HEntity();
-}
-
-// clearEntityHierarchy and rebuildEntityHierarchy should only be called
-// from UpdateEntityHierarchyJob to update the entity hierarchy for the
-// entire scene at once
-void Entity::rebuildEntityHierarchy()
-{
- if (!m_parentEntityId.isNull())
- setParentHandle(m_nodeManagers->renderNodesManager()->lookupHandle(m_parentEntityId));
- else
- qCDebug(Render::RenderNodes) << Q_FUNC_INFO << "No parent entity found for Entity" << peerId();
-}
-
-void Entity::appendChildHandle(HEntity childHandle)
-{
- if (!m_childrenHandles.contains(childHandle)) {
- m_childrenHandles.append(childHandle);
- Entity *child = m_nodeManagers->renderNodesManager()->data(childHandle);
- if (child != nullptr)
- child->m_parentHandle = m_handle;
- }
+ // remove ourself from our parent's list of children.
+ auto p = parent();
+ if (p)
+ p->removeChildHandle(m_handle);
}
QVector<Entity *> Entity::children() const
@@ -358,6 +344,7 @@ void Entity::addComponent(Qt3DCore::QNodeIdTypePair idAndType)
} else if (type->inherits(&QArmature::staticMetaObject)) {
m_armatureComponent = id;
}
+ markDirty(AbstractRenderer::AllDirty);
}
void Entity::removeComponent(Qt3DCore::QNodeId nodeId)
@@ -392,6 +379,7 @@ void Entity::removeComponent(Qt3DCore::QNodeId nodeId)
} else if (m_armatureComponent == nodeId) {
m_armatureComponent = QNodeId();
}
+ markDirty(AbstractRenderer::AllDirty);
}
bool Entity::isBoundingVolumeDirty() const
diff --git a/src/render/backend/entity_p.h b/src/render/backend/entity_p.h
index b4c9541f2..d13d96784 100644
--- a/src/render/backend/entity_p.h
+++ b/src/render/backend/entity_p.h
@@ -79,6 +79,7 @@ namespace Render {
class Sphere;
class Renderer;
class NodeManagers;
+class EntityPrivate;
class Q_AUTOTEST_EXPORT Entity : public BackendNode
{
@@ -89,7 +90,7 @@ public:
void setParentHandle(HEntity parentHandle);
void setNodeManagers(NodeManagers *manager);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void dump() const;
@@ -97,11 +98,8 @@ public:
HEntity handle() const { return m_handle; }
Entity *parent() const;
HEntity parentHandle() const { return m_parentHandle; }
- Qt3DCore::QNodeId parentEntityId() const { return m_parentEntityId; }
-
- void clearEntityHierarchy();
- void rebuildEntityHierarchy();
+ void removeFromParentChildHandles();
void appendChildHandle(HEntity childHandle);
void removeChildHandle(HEntity childHandle) { m_childrenHandles.removeOne(childHandle); }
QVector<HEntity> childrenHandles() const { return m_childrenHandles; }
@@ -178,17 +176,15 @@ public:
return containsComponentsOfType<T>() && containsComponentsOfType<Ts, Ts2...>();
}
+protected:
+ Q_DECLARE_PRIVATE(Entity)
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
NodeManagers *m_nodeManagers;
HEntity m_handle;
HEntity m_parentHandle;
QVector<HEntity > m_childrenHandles;
- Qt3DCore::QNodeId m_parentEntityId;
-
HMatrix m_worldTransform;
QSharedPointer<Sphere> m_localBoundingVolume;
QSharedPointer<Sphere> m_worldBoundingVolume;
@@ -306,7 +302,7 @@ ENTITY_COMPONENT_LIST_TEMPLATE_SPECIALIZATION(ShaderData, HShaderData)
ENTITY_COMPONENT_LIST_TEMPLATE_SPECIALIZATION(Light, HLight)
ENTITY_COMPONENT_LIST_TEMPLATE_SPECIALIZATION(EnvironmentLight, HEnvironmentLight)
-class RenderEntityFunctor : public Qt3DCore::QBackendNodeMapper
+class Q_AUTOTEST_EXPORT RenderEntityFunctor : public Qt3DCore::QBackendNodeMapper
{
public:
explicit RenderEntityFunctor(AbstractRenderer *renderer, NodeManagers *manager);
diff --git a/src/render/backend/entity_p_p.h b/src/render/backend/entity_p_p.h
new file mode 100644
index 000000000..4ac6ab978
--- /dev/null
+++ b/src/render/backend/entity_p_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_ENTITY_P_P_H
+#define QT3DRENDER_RENDER_ENTITY_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/entity_p.h>
+#include <Qt3DCore/private/qbackendnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DCore {
+class QNode;
+}
+
+namespace Qt3DRender {
+
+class QRenderAspect;
+
+namespace Render {
+
+class Q_AUTOTEST_EXPORT EntityPrivate : public Qt3DCore::QBackendNodePrivate {
+public:
+ EntityPrivate();
+
+ Q_DECLARE_PUBLIC(Entity)
+
+ static EntityPrivate *get(Entity *node);
+
+ void componentAdded(Qt3DCore::QNode *frontend) override;
+ void componentRemoved(Qt3DCore::QNode *frontend) override;
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_ENTITY_P_P_H
diff --git a/src/render/backend/handle_types_p.h b/src/render/backend/handle_types_p.h
index 035bbfc91..195fc2cc6 100644
--- a/src/render/backend/handle_types_p.h
+++ b/src/render/backend/handle_types_p.h
@@ -94,10 +94,12 @@ class Light;
class EnvironmentLight;
class ComputeCommand;
class GLBuffer;
+class GLTexture;
class RenderStateNode;
class Armature;
class Skeleton;
class Joint;
+class ShaderImage;
typedef Qt3DCore::QHandle<RenderTargetOutput> HAttachment;
typedef Qt3DCore::QHandle<CameraLens> HCamera;
@@ -132,10 +134,12 @@ typedef Qt3DCore::QHandle<Light> HLight;
typedef Qt3DCore::QHandle<EnvironmentLight> HEnvironmentLight;
typedef Qt3DCore::QHandle<ComputeCommand> HComputeCommand;
typedef Qt3DCore::QHandle<GLBuffer> HGLBuffer;
+typedef Qt3DCore::QHandle<GLTexture> HGLTexture;
typedef Qt3DCore::QHandle<RenderStateNode> HRenderState;
typedef Qt3DCore::QHandle<Armature> HArmature;
typedef Qt3DCore::QHandle<Skeleton> HSkeleton;
typedef Qt3DCore::QHandle<Joint> HJoint;
+typedef Qt3DCore::QHandle<ShaderImage> HShaderImage;
} // namespace Render
diff --git a/src/render/backend/layer.cpp b/src/render/backend/layer.cpp
index 976c35fd5..f1b6d2fc6 100644
--- a/src/render/backend/layer.cpp
+++ b/src/render/backend/layer.cpp
@@ -41,7 +41,6 @@
#include <Qt3DRender/qlayer.h>
#include <Qt3DRender/private/qlayer_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QVariant>
QT_BEGIN_NAMESPACE
@@ -67,26 +66,22 @@ void Layer::cleanup()
QBackendNode::setEnabled(false);
}
-void Layer::sceneChangeEvent(const QSceneChangePtr &e)
+void Layer::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- QByteArray propertyName = propertyChange->propertyName();
- if (propertyName == QByteArrayLiteral("recursive")) {
- m_recursive = propertyChange->value().toBool();
- markDirty(AbstractRenderer::LayersDirty);
- }
- if (propertyName == QByteArrayLiteral("enabled"))
- markDirty(AbstractRenderer::LayersDirty);
- }
- BackendNode::sceneChangeEvent(e);
-}
+ const QLayer *node = qobject_cast<const QLayer *>(frontEnd);
+ if (!node)
+ return;
-void Layer::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLayerData>>(change);
- const auto &data = typedChange->data;
- m_recursive = data.m_recursive;
+ const bool oldEnabled = isEnabled();
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (isEnabled() != oldEnabled || firstTime)
+ markDirty(AbstractRenderer::LayersDirty);
+
+ if (node->recursive() != m_recursive) {
+ m_recursive = node->recursive();
+ markDirty(AbstractRenderer::LayersDirty);
+ }
}
bool Layer::recursive() const
diff --git a/src/render/backend/layer_p.h b/src/render/backend/layer_p.h
index 1513157f9..8631e2d92 100644
--- a/src/render/backend/layer_p.h
+++ b/src/render/backend/layer_p.h
@@ -76,11 +76,9 @@ public:
bool recursive() const;
void setRecursive(bool recursive);
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
bool m_recursive;
};
diff --git a/src/render/backend/levelofdetail.cpp b/src/render/backend/levelofdetail.cpp
index 157bfc004..7f528a9d5 100644
--- a/src/render/backend/levelofdetail.cpp
+++ b/src/render/backend/levelofdetail.cpp
@@ -41,7 +41,7 @@
#include <Qt3DRender/QLevelOfDetail>
#include <Qt3DRender/private/qlevelofdetail_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DRender/QCamera>
#include <QVariant>
QT_BEGIN_NAMESPACE
@@ -64,53 +64,54 @@ LevelOfDetail::~LevelOfDetail()
cleanup();
}
-void LevelOfDetail::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
+void LevelOfDetail::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLevelOfDetailData>>(change);
- const auto &data = typedChange->data;
- m_camera = data.camera;
- m_currentIndex = data.currentIndex;
- m_thresholdType = data.thresholdType;
- m_thresholds = data.thresholds;
- m_volumeOverride = data.volumeOverride;
-}
+ const QLevelOfDetail *node = qobject_cast<const QLevelOfDetail *>(frontEnd);
+ if (!node)
+ return;
-void LevelOfDetail::cleanup()
-{
- QBackendNode::setEnabled(false);
-}
+ const bool oldEnabled = isEnabled();
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
-void LevelOfDetail::sceneChangeEvent(const QSceneChangePtr &e)
-{
- if (e->type() == PropertyUpdated) {
- const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("currentIndex"))
- m_currentIndex = propertyChange->value().value<int>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("camera"))
- m_camera = propertyChange->value().value<Qt3DCore::QNodeId>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("thresholdType"))
- m_thresholdType = propertyChange->value().value<QLevelOfDetail::ThresholdType>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("thresholds"))
- m_thresholds = propertyChange->value().value<QVector<qreal>>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("volumeOverride"))
- m_volumeOverride = propertyChange->value().value<Qt3DRender::QLevelOfDetailBoundingSphere>();
+ const Qt3DCore::QNodeId cameraId = Qt3DCore::qIdForNode(node->camera());
+ if (cameraId != m_camera) {
+ m_camera = cameraId;
+ markDirty(AbstractRenderer::GeometryDirty);
}
- markDirty(AbstractRenderer::GeometryDirty);
+ if (node->currentIndex() != m_currentIndex) {
+ m_currentIndex = node->currentIndex();
+ markDirty(AbstractRenderer::GeometryDirty);
+ }
- BackendNode::sceneChangeEvent(e);
+ if (node->thresholdType() != m_thresholdType) {
+ m_thresholdType = node->thresholdType();
+ markDirty(AbstractRenderer::GeometryDirty);
+ }
+
+ if (node->thresholds() != m_thresholds) {
+ m_thresholds = node->thresholds();
+ markDirty(AbstractRenderer::GeometryDirty);
+ }
+
+ if (node->volumeOverride() != m_volumeOverride) {
+ m_volumeOverride = node->volumeOverride();
+ markDirty(AbstractRenderer::GeometryDirty);
+ }
+
+ if (isEnabled() != oldEnabled || firstTime)
+ markDirty(AbstractRenderer::LayersDirty);
+}
+
+void LevelOfDetail::cleanup()
+{
+ QBackendNode::setEnabled(false);
}
void LevelOfDetail::setCurrentIndex(int currentIndex)
{
- if (m_currentIndex != currentIndex) {
+ if (m_currentIndex != currentIndex)
m_currentIndex = currentIndex;
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("currentIndex");
- e->setValue(m_currentIndex);
- notifyObservers(e);
- }
}
} // namespace Render
diff --git a/src/render/backend/levelofdetail_p.h b/src/render/backend/levelofdetail_p.h
index 4cf835d9b..8399e19b7 100644
--- a/src/render/backend/levelofdetail_p.h
+++ b/src/render/backend/levelofdetail_p.h
@@ -73,7 +73,7 @@ public:
LevelOfDetail();
~LevelOfDetail();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
Qt3DCore::QNodeId camera() const { return m_camera; }
int currentIndex() const { return m_currentIndex; }
@@ -86,7 +86,6 @@ public:
void setCurrentIndex(int currentIndex);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
Qt3DCore::QNodeId m_camera;
int m_currentIndex;
QLevelOfDetail::ThresholdType m_thresholdType;
diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h
index f28dbe768..759c16f64 100644
--- a/src/render/backend/managers_p.h
+++ b/src/render/backend/managers_p.h
@@ -86,6 +86,7 @@
#include <Qt3DRender/private/armature_p.h>
#include <Qt3DRender/private/skeleton_p.h>
#include <Qt3DRender/private/joint_p.h>
+#include <Qt3DRender/private/shaderimage_p.h>
QT_BEGIN_NAMESPACE
@@ -302,6 +303,15 @@ public:
ParameterManager() {}
};
+class ShaderImageManager : public Qt3DCore::QResourceManager<
+ ShaderImage,
+ Qt3DCore::QNodeId,
+ Qt3DCore::NonLockingPolicy>
+{
+public:
+ ShaderImageManager() {}
+};
+
class ShaderDataManager : public Qt3DCore::QResourceManager<
ShaderData,
Qt3DCore::QNodeId,
@@ -466,6 +476,7 @@ Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Armature, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Skeleton, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::Joint, Q_REQUIRES_CLEANUP)
Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::ShaderBuilder, Q_REQUIRES_CLEANUP)
+Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::ShaderImage, Q_REQUIRES_CLEANUP)
QT_END_NAMESPACE
diff --git a/src/render/backend/nodemanagers.cpp b/src/render/backend/nodemanagers.cpp
index 584ddd65c..5e452f886 100644
--- a/src/render/backend/nodemanagers.cpp
+++ b/src/render/backend/nodemanagers.cpp
@@ -43,7 +43,6 @@
#include <Qt3DRender/private/scenemanager_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/gltexturemanager_p.h>
-#include <Qt3DRender/private/texturedatamanager_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/private/techniquemanager_p.h>
#include <Qt3DRender/private/armature_p.h>
@@ -71,9 +70,7 @@ NodeManagers::NodeManagers()
, m_renderPassManager(new RenderPassManager())
, m_textureManager(new TextureManager())
, m_textureImageManager(new TextureImageManager())
- , m_textureDataManager(new TextureDataManager())
- , m_textureImageDataManager(new TextureImageDataManager())
- , m_glTextureManager(new GLTextureManager(m_textureImageManager, m_textureDataManager, m_textureImageDataManager))
+ , m_glTextureManager(new GLTextureManager())
, m_layerManager(new LayerManager())
, m_levelOfDetailManager(new LevelOfDetailManager())
, m_filterKeyManager(new FilterKeyManager())
@@ -100,6 +97,7 @@ NodeManagers::NodeManagers()
, m_armatureManager(new ArmatureManager())
, m_skeletonManager(new SkeletonManager())
, m_jointManager(new JointManager())
+ , m_shaderImageManager(new ShaderImageManager())
, m_resourceAccessor(new ResourceAccessor(this))
{
}
@@ -117,8 +115,6 @@ NodeManagers::~NodeManagers()
delete m_renderPassManager;
delete m_glTextureManager;
delete m_textureManager;
- delete m_textureDataManager;
- delete m_textureImageDataManager;
delete m_layerManager;
delete m_levelOfDetailManager;
delete m_filterKeyManager;
@@ -150,6 +146,7 @@ NodeManagers::~NodeManagers()
delete m_armatureManager;
delete m_skeletonManager;
delete m_jointManager;
+ delete m_shaderImageManager;
}
QSharedPointer<ResourceAccessor> NodeManagers::resourceAccessor()
@@ -158,233 +155,233 @@ QSharedPointer<ResourceAccessor> NodeManagers::resourceAccessor()
}
template<>
-CameraManager *NodeManagers::manager<CameraLens>() const Q_DECL_NOTHROW
+CameraManager *NodeManagers::manager<CameraLens>() const noexcept
{
return m_cameraManager;
}
template<>
-EntityManager *NodeManagers::manager<Entity>() const Q_DECL_NOTHROW
+EntityManager *NodeManagers::manager<Entity>() const noexcept
{
return m_renderNodesManager;
}
template<>
-MaterialManager *NodeManagers::manager<Material>() const Q_DECL_NOTHROW
+MaterialManager *NodeManagers::manager<Material>() const noexcept
{
return m_materialManager;
}
template<>
-MatrixManager *NodeManagers::manager<Matrix4x4>() const Q_DECL_NOTHROW
+MatrixManager *NodeManagers::manager<Matrix4x4>() const noexcept
{
return m_worldMatrixManager;
}
template<>
-VAOManager *NodeManagers::manager<OpenGLVertexArrayObject>() const Q_DECL_NOTHROW
+VAOManager *NodeManagers::manager<OpenGLVertexArrayObject>() const noexcept
{
return m_vaoManager;
}
template<>
-ShaderManager *NodeManagers::manager<Shader>() const Q_DECL_NOTHROW
+ShaderManager *NodeManagers::manager<Shader>() const noexcept
{
return m_shaderManager;
}
template<>
-ShaderBuilderManager *NodeManagers::manager<ShaderBuilder>() const Q_DECL_NOTHROW
+ShaderBuilderManager *NodeManagers::manager<ShaderBuilder>() const noexcept
{
return m_shaderBuilderManager;
}
template<>
-TechniqueManager *NodeManagers::manager<Technique>() const Q_DECL_NOTHROW
+TechniqueManager *NodeManagers::manager<Technique>() const noexcept
{
return m_techniqueManager;
}
template<>
-EffectManager *NodeManagers::manager<Effect>() const Q_DECL_NOTHROW
+EffectManager *NodeManagers::manager<Effect>() const noexcept
{
return m_effectManager;
}
template<>
-RenderPassManager *NodeManagers::manager<RenderPass>() const Q_DECL_NOTHROW
+RenderPassManager *NodeManagers::manager<RenderPass>() const noexcept
{
return m_renderPassManager;
}
template<>
-TextureManager *NodeManagers::manager<Texture>() const Q_DECL_NOTHROW
+TextureManager *NodeManagers::manager<Texture>() const noexcept
{
return m_textureManager;
}
template<>
-TextureDataManager *NodeManagers::manager<QTextureImageData>() const Q_DECL_NOTHROW
-{
- return m_textureDataManager;
-}
-
-template<>
-LayerManager *NodeManagers::manager<Layer>() const Q_DECL_NOTHROW
+LayerManager *NodeManagers::manager<Layer>() const noexcept
{
return m_layerManager;
}
template<>
-LevelOfDetailManager *NodeManagers::manager<LevelOfDetail>() const Q_DECL_NOTHROW
+LevelOfDetailManager *NodeManagers::manager<LevelOfDetail>() const noexcept
{
return m_levelOfDetailManager;
}
template<>
-FilterKeyManager *NodeManagers::manager<FilterKey>() const Q_DECL_NOTHROW
+FilterKeyManager *NodeManagers::manager<FilterKey>() const noexcept
{
return m_filterKeyManager;
}
template<>
-FrameGraphManager *NodeManagers::manager<FrameGraphNode*>() const Q_DECL_NOTHROW
+FrameGraphManager *NodeManagers::manager<FrameGraphNode*>() const noexcept
{
return m_frameGraphManager;
}
template<>
-TransformManager *NodeManagers::manager<Transform>() const Q_DECL_NOTHROW
+TransformManager *NodeManagers::manager<Transform>() const noexcept
{
return m_transformManager;
}
template<>
-RenderTargetManager *NodeManagers::manager<RenderTarget>() const Q_DECL_NOTHROW
+RenderTargetManager *NodeManagers::manager<RenderTarget>() const noexcept
{
return m_renderTargetManager;
}
template<>
-SceneManager *NodeManagers::manager<Scene>() const Q_DECL_NOTHROW
+SceneManager *NodeManagers::manager<Scene>() const noexcept
{
return m_sceneManager;
}
template<>
-AttachmentManager *NodeManagers::manager<RenderTargetOutput>() const Q_DECL_NOTHROW
+AttachmentManager *NodeManagers::manager<RenderTargetOutput>() const noexcept
{
return m_attachmentManager;
}
template<>
-ParameterManager *NodeManagers::manager<Parameter>() const Q_DECL_NOTHROW
+ParameterManager *NodeManagers::manager<Parameter>() const noexcept
{
return m_parameterManager;
}
template<>
-ShaderDataManager *NodeManagers::manager<ShaderData>() const Q_DECL_NOTHROW
+ShaderDataManager *NodeManagers::manager<ShaderData>() const noexcept
{
return m_shaderDataManager;
}
template<>
-GLBufferManager *NodeManagers::manager<GLBuffer>() const Q_DECL_NOTHROW
+GLBufferManager *NodeManagers::manager<GLBuffer>() const noexcept
{
return m_glBufferManager;
}
template<>
-TextureImageManager *NodeManagers::manager<TextureImage>() const Q_DECL_NOTHROW
+TextureImageManager *NodeManagers::manager<TextureImage>() const noexcept
{
return m_textureImageManager;
}
template<>
-BufferManager *NodeManagers::manager<Buffer>() const Q_DECL_NOTHROW
+BufferManager *NodeManagers::manager<Buffer>() const noexcept
{
return m_bufferManager;
}
template<>
-AttributeManager *NodeManagers::manager<Attribute>() const Q_DECL_NOTHROW
+AttributeManager *NodeManagers::manager<Attribute>() const noexcept
{
return m_attributeManager;
}
template<>
-GeometryManager *NodeManagers::manager<Geometry>() const Q_DECL_NOTHROW
+GeometryManager *NodeManagers::manager<Geometry>() const noexcept
{
return m_geometryManager;
}
template<>
-GeometryRendererManager *NodeManagers::manager<GeometryRenderer>() const Q_DECL_NOTHROW
+GeometryRendererManager *NodeManagers::manager<GeometryRenderer>() const noexcept
{
return m_geometryRendererManager;
}
template<>
-ObjectPickerManager *NodeManagers::manager<ObjectPicker>() const Q_DECL_NOTHROW
+ObjectPickerManager *NodeManagers::manager<ObjectPicker>() const noexcept
{
return m_objectPickerManager;
}
template<>
-RayCasterManager *NodeManagers::manager<RayCaster>() const Q_DECL_NOTHROW
+RayCasterManager *NodeManagers::manager<RayCaster>() const noexcept
{
return m_rayCasterManager;
}
//template<>
-//BoundingVolumeDebugManager *NodeManagers::manager<BoundingVolumeDebug>() const Q_DECL_NOTHROW
+//BoundingVolumeDebugManager *NodeManagers::manager<BoundingVolumeDebug>() const noexcept
//{
// return m_boundingVolumeDebugManager;
//}
template<>
-LightManager *NodeManagers::manager<Light>() const Q_DECL_NOTHROW
+LightManager *NodeManagers::manager<Light>() const noexcept
{
return m_lightManager;
}
template<>
-EnvironmentLightManager *NodeManagers::manager<EnvironmentLight>() const Q_DECL_NOTHROW
+EnvironmentLightManager *NodeManagers::manager<EnvironmentLight>() const noexcept
{
return m_environmentLightManager;
}
template<>
-ComputeCommandManager *NodeManagers::manager<ComputeCommand>() const Q_DECL_NOTHROW
+ComputeCommandManager *NodeManagers::manager<ComputeCommand>() const noexcept
{
return m_computeJobManager;
}
template<>
-RenderStateManager *NodeManagers::manager<RenderStateNode>() const Q_DECL_NOTHROW
+RenderStateManager *NodeManagers::manager<RenderStateNode>() const noexcept
{
return m_renderStateManager;
}
template<>
-ArmatureManager *NodeManagers::manager<Armature>() const Q_DECL_NOTHROW
+ArmatureManager *NodeManagers::manager<Armature>() const noexcept
{
return m_armatureManager;
}
template<>
-SkeletonManager *NodeManagers::manager<Skeleton>() const Q_DECL_NOTHROW
+SkeletonManager *NodeManagers::manager<Skeleton>() const noexcept
{
return m_skeletonManager;
}
template<>
-JointManager *NodeManagers::manager<Joint>() const Q_DECL_NOTHROW
+JointManager *NodeManagers::manager<Joint>() const noexcept
{
return m_jointManager;
}
+template<>
+ShaderImageManager *NodeManagers::manager<ShaderImage>() const noexcept
+{
+ return m_shaderImageManager;
+}
+
} // Render
} // Qt3DRender
diff --git a/src/render/backend/nodemanagers_p.h b/src/render/backend/nodemanagers_p.h
index 4ef1f4927..8dda4e8ad 100644
--- a/src/render/backend/nodemanagers_p.h
+++ b/src/render/backend/nodemanagers_p.h
@@ -105,6 +105,7 @@ class RenderStateManager;
class ArmatureManager;
class SkeletonManager;
class JointManager;
+class ShaderImageManager;
class FrameGraphNode;
class Entity;
@@ -143,6 +144,7 @@ class Armature;
class Skeleton;
class Joint;
class OpenGLVertexArrayObject;
+class ShaderImage;
class ResourceAccessor;
@@ -153,7 +155,7 @@ public:
~NodeManagers();
template<class Backend, typename Manager>
- Manager *manager() const Q_DECL_NOEXCEPT
+ Manager *manager() const noexcept
{
return nullptr;
}
@@ -186,47 +188,46 @@ public:
}
- inline CameraManager *cameraManager() const Q_DECL_NOEXCEPT { return m_cameraManager; }
- inline EntityManager *renderNodesManager() const Q_DECL_NOEXCEPT { return m_renderNodesManager; }
- inline MaterialManager *materialManager() const Q_DECL_NOEXCEPT { return m_materialManager; }
- inline MatrixManager *worldMatrixManager() const Q_DECL_NOEXCEPT { return m_worldMatrixManager; }
- inline VAOManager *vaoManager() const Q_DECL_NOEXCEPT { return m_vaoManager; }
- inline ShaderManager *shaderManager() const Q_DECL_NOEXCEPT { return m_shaderManager; }
- inline ShaderBuilderManager *shaderBuilderManager() const Q_DECL_NOEXCEPT { return m_shaderBuilderManager; }
- inline TechniqueManager *techniqueManager() const Q_DECL_NOEXCEPT { return m_techniqueManager; }
- inline EffectManager *effectManager() const Q_DECL_NOEXCEPT { return m_effectManager; }
- inline RenderPassManager *renderPassManager() const Q_DECL_NOEXCEPT { return m_renderPassManager; }
- inline GLTextureManager *glTextureManager() const Q_DECL_NOEXCEPT { return m_glTextureManager; }
- inline TextureManager *textureManager() const Q_DECL_NOEXCEPT { return m_textureManager; }
- inline TextureDataManager *textureDataManager() const Q_DECL_NOEXCEPT { return m_textureDataManager; }
- inline TextureImageDataManager *textureImageDataManager() const Q_DECL_NOEXCEPT { return m_textureImageDataManager; }
- inline LayerManager *layerManager() const Q_DECL_NOEXCEPT { return m_layerManager; }
- inline LevelOfDetailManager *levelOfDetailManager() const Q_DECL_NOEXCEPT { return m_levelOfDetailManager; }
- inline FilterKeyManager *filterKeyManager() const Q_DECL_NOEXCEPT { return m_filterKeyManager; }
- inline FrameGraphManager *frameGraphManager() const Q_DECL_NOEXCEPT { return m_frameGraphManager; }
- inline TransformManager *transformManager() const Q_DECL_NOEXCEPT { return m_transformManager; }
- inline RenderTargetManager *renderTargetManager() const Q_DECL_NOEXCEPT { return m_renderTargetManager; }
- inline SceneManager *sceneManager() const Q_DECL_NOEXCEPT { return m_sceneManager; }
- inline AttachmentManager *attachmentManager() const Q_DECL_NOEXCEPT { return m_attachmentManager; }
- inline ParameterManager *parameterManager() const Q_DECL_NOEXCEPT { return m_parameterManager; }
- inline ShaderDataManager *shaderDataManager() const Q_DECL_NOEXCEPT { return m_shaderDataManager; }
- inline GLBufferManager *glBufferManager() const Q_DECL_NOEXCEPT { return m_glBufferManager; }
- inline GLFenceManager *glFenceManager() const Q_DECL_NOEXCEPT { return m_glFenceManager; }
- inline TextureImageManager *textureImageManager() const Q_DECL_NOEXCEPT { return m_textureImageManager; }
- inline BufferManager *bufferManager() const Q_DECL_NOEXCEPT { return m_bufferManager; }
- inline AttributeManager *attributeManager() const Q_DECL_NOEXCEPT { return m_attributeManager; }
- inline GeometryManager *geometryManager() const Q_DECL_NOEXCEPT { return m_geometryManager; }
- inline GeometryRendererManager *geometryRendererManager() const Q_DECL_NOEXCEPT { return m_geometryRendererManager; }
- inline ObjectPickerManager *objectPickerManager() const Q_DECL_NOEXCEPT { return m_objectPickerManager; }
- inline RayCasterManager *rayCasterManager() const Q_DECL_NOEXCEPT { return m_rayCasterManager; }
- // inline BoundingVolumeDebugManager *boundingVolumeDebugManager() const Q_DECL_NOEXCEPT { return m_boundingVolumeDebugManager; }
- inline LightManager *lightManager() const Q_DECL_NOEXCEPT { return m_lightManager; }
- inline EnvironmentLightManager *environmentLightManager() const Q_DECL_NOEXCEPT { return m_environmentLightManager; }
- inline ComputeCommandManager *computeJobManager() const Q_DECL_NOEXCEPT { return m_computeJobManager; }
- inline RenderStateManager *renderStateManager() const Q_DECL_NOEXCEPT { return m_renderStateManager; }
- inline ArmatureManager *armatureManager() const Q_DECL_NOEXCEPT { return m_armatureManager; }
- inline SkeletonManager *skeletonManager() const Q_DECL_NOEXCEPT { return m_skeletonManager; }
- inline JointManager *jointManager() const Q_DECL_NOEXCEPT { return m_jointManager; }
+ inline CameraManager *cameraManager() const noexcept { return m_cameraManager; }
+ inline EntityManager *renderNodesManager() const noexcept { return m_renderNodesManager; }
+ inline MaterialManager *materialManager() const noexcept { return m_materialManager; }
+ inline MatrixManager *worldMatrixManager() const noexcept { return m_worldMatrixManager; }
+ inline VAOManager *vaoManager() const noexcept { return m_vaoManager; }
+ inline ShaderManager *shaderManager() const noexcept { return m_shaderManager; }
+ inline ShaderBuilderManager *shaderBuilderManager() const noexcept { return m_shaderBuilderManager; }
+ inline TechniqueManager *techniqueManager() const noexcept { return m_techniqueManager; }
+ inline EffectManager *effectManager() const noexcept { return m_effectManager; }
+ inline RenderPassManager *renderPassManager() const noexcept { return m_renderPassManager; }
+ inline GLTextureManager *glTextureManager() const noexcept { return m_glTextureManager; }
+ inline TextureManager *textureManager() const noexcept { return m_textureManager; }
+ inline LayerManager *layerManager() const noexcept { return m_layerManager; }
+ inline LevelOfDetailManager *levelOfDetailManager() const noexcept { return m_levelOfDetailManager; }
+ inline FilterKeyManager *filterKeyManager() const noexcept { return m_filterKeyManager; }
+ inline FrameGraphManager *frameGraphManager() const noexcept { return m_frameGraphManager; }
+ inline TransformManager *transformManager() const noexcept { return m_transformManager; }
+ inline RenderTargetManager *renderTargetManager() const noexcept { return m_renderTargetManager; }
+ inline SceneManager *sceneManager() const noexcept { return m_sceneManager; }
+ inline AttachmentManager *attachmentManager() const noexcept { return m_attachmentManager; }
+ inline ParameterManager *parameterManager() const noexcept { return m_parameterManager; }
+ inline ShaderDataManager *shaderDataManager() const noexcept { return m_shaderDataManager; }
+ inline GLBufferManager *glBufferManager() const noexcept { return m_glBufferManager; }
+ inline GLFenceManager *glFenceManager() const noexcept { return m_glFenceManager; }
+ inline TextureImageManager *textureImageManager() const noexcept { return m_textureImageManager; }
+ inline BufferManager *bufferManager() const noexcept { return m_bufferManager; }
+ inline AttributeManager *attributeManager() const noexcept { return m_attributeManager; }
+ inline GeometryManager *geometryManager() const noexcept { return m_geometryManager; }
+ inline GeometryRendererManager *geometryRendererManager() const noexcept { return m_geometryRendererManager; }
+ inline ObjectPickerManager *objectPickerManager() const noexcept { return m_objectPickerManager; }
+ inline RayCasterManager *rayCasterManager() const noexcept { return m_rayCasterManager; }
+ // inline BoundingVolumeDebugManager *boundingVolumeDebugManager() const noexcept { return m_boundingVolumeDebugManager; }
+ inline LightManager *lightManager() const noexcept { return m_lightManager; }
+ inline EnvironmentLightManager *environmentLightManager() const noexcept { return m_environmentLightManager; }
+ inline ComputeCommandManager *computeJobManager() const noexcept { return m_computeJobManager; }
+ inline RenderStateManager *renderStateManager() const noexcept { return m_renderStateManager; }
+ inline ArmatureManager *armatureManager() const noexcept { return m_armatureManager; }
+ inline SkeletonManager *skeletonManager() const noexcept { return m_skeletonManager; }
+ inline JointManager *jointManager() const noexcept { return m_jointManager; }
+ inline ShaderImageManager *shaderImageManager() const noexcept { return m_shaderImageManager; }
QSharedPointer<ResourceAccessor> resourceAccessor();
@@ -243,8 +244,6 @@ private:
RenderPassManager *m_renderPassManager;
TextureManager *m_textureManager;
TextureImageManager *m_textureImageManager;
- TextureDataManager *m_textureDataManager;
- TextureImageDataManager *m_textureImageDataManager;
GLTextureManager *m_glTextureManager;
LayerManager *m_layerManager;
LevelOfDetailManager *m_levelOfDetailManager;
@@ -272,6 +271,7 @@ private:
ArmatureManager *m_armatureManager;
SkeletonManager *m_skeletonManager;
JointManager *m_jointManager;
+ ShaderImageManager *m_shaderImageManager;
QSharedPointer<ResourceAccessor> m_resourceAccessor;
};
@@ -279,118 +279,118 @@ private:
// Specializations
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT CameraManager *NodeManagers::manager<CameraLens>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT CameraManager *NodeManagers::manager<CameraLens>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT EntityManager *NodeManagers::manager<Entity>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT EntityManager *NodeManagers::manager<Entity>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT MaterialManager *NodeManagers::manager<Material>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT MaterialManager *NodeManagers::manager<Material>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT MatrixManager *NodeManagers::manager<QMatrix4x4*>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT MatrixManager *NodeManagers::manager<QMatrix4x4*>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT VAOManager *NodeManagers::manager<OpenGLVertexArrayObject>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT VAOManager *NodeManagers::manager<OpenGLVertexArrayObject>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderManager *NodeManagers::manager<Shader>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderManager *NodeManagers::manager<Shader>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderBuilderManager *NodeManagers::manager<ShaderBuilder>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderBuilderManager *NodeManagers::manager<ShaderBuilder>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT TechniqueManager *NodeManagers::manager<Technique>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT TechniqueManager *NodeManagers::manager<Technique>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT EffectManager *NodeManagers::manager<Effect>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT EffectManager *NodeManagers::manager<Effect>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT RenderPassManager *NodeManagers::manager<RenderPass>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT RenderPassManager *NodeManagers::manager<RenderPass>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT TextureManager *NodeManagers::manager<Texture>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT TextureManager *NodeManagers::manager<Texture>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT TextureDataManager *NodeManagers::manager<QTextureImageData>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT LayerManager *NodeManagers::manager<Layer>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT LayerManager *NodeManagers::manager<Layer>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT LevelOfDetailManager *NodeManagers::manager<LevelOfDetail>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT LevelOfDetailManager *NodeManagers::manager<LevelOfDetail>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT FilterKeyManager *NodeManagers::manager<FilterKey>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT FilterKeyManager *NodeManagers::manager<FilterKey>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT FrameGraphManager *NodeManagers::manager<FrameGraphNode*>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT FrameGraphManager *NodeManagers::manager<FrameGraphNode*>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT TransformManager *NodeManagers::manager<Transform>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT TransformManager *NodeManagers::manager<Transform>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT RenderTargetManager *NodeManagers::manager<RenderTarget>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT RenderTargetManager *NodeManagers::manager<RenderTarget>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT SceneManager *NodeManagers::manager<Scene>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT SceneManager *NodeManagers::manager<Scene>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT AttachmentManager *NodeManagers::manager<RenderTargetOutput>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT AttachmentManager *NodeManagers::manager<RenderTargetOutput>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT ParameterManager *NodeManagers::manager<Parameter>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT ParameterManager *NodeManagers::manager<Parameter>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderDataManager *NodeManagers::manager<ShaderData>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderDataManager *NodeManagers::manager<ShaderData>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT GLBufferManager *NodeManagers::manager<GLBuffer>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT GLBufferManager *NodeManagers::manager<GLBuffer>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT TextureImageManager *NodeManagers::manager<TextureImage>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT TextureImageManager *NodeManagers::manager<TextureImage>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT BufferManager *NodeManagers::manager<Buffer>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT BufferManager *NodeManagers::manager<Buffer>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT AttributeManager *NodeManagers::manager<Attribute>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT AttributeManager *NodeManagers::manager<Attribute>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT GeometryManager *NodeManagers::manager<Geometry>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT GeometryManager *NodeManagers::manager<Geometry>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT GeometryRendererManager *NodeManagers::manager<GeometryRenderer>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT GeometryRendererManager *NodeManagers::manager<GeometryRenderer>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT ObjectPickerManager *NodeManagers::manager<ObjectPicker>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT ObjectPickerManager *NodeManagers::manager<ObjectPicker>() const Q_DECL_NOEXCEPT;
-
-template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT RayCasterManager *NodeManagers::manager<RayCaster>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT RayCasterManager *NodeManagers::manager<RayCaster>() const noexcept;
//template<>
-//Q_3DRENDERSHARED_PRIVATE_EXPORT BoundingVolumeDebugManager *NodeManagers::manager<BoundingVolumeDebug>() const Q_DECL_NOEXCEPT;
+//Q_3DRENDERSHARED_PRIVATE_EXPORT BoundingVolumeDebugManager *NodeManagers::manager<BoundingVolumeDebug>() const noexcept;
+
+template<>
+LightManager *NodeManagers::manager<Light>() const noexcept;
template<>
-LightManager *NodeManagers::manager<Light>() const Q_DECL_NOEXCEPT;
+EnvironmentLightManager *NodeManagers::manager<EnvironmentLight>() const noexcept;
template<>
-EnvironmentLightManager *NodeManagers::manager<EnvironmentLight>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT ComputeCommandManager *NodeManagers::manager<ComputeCommand>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT ComputeCommandManager *NodeManagers::manager<ComputeCommand>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT RenderStateManager *NodeManagers::manager<RenderStateNode>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT RenderStateManager *NodeManagers::manager<RenderStateNode>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT ArmatureManager *NodeManagers::manager<Armature>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT ArmatureManager *NodeManagers::manager<Armature>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT SkeletonManager *NodeManagers::manager<Skeleton>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT SkeletonManager *NodeManagers::manager<Skeleton>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT JointManager *NodeManagers::manager<Joint>() const noexcept;
template<>
-Q_3DRENDERSHARED_PRIVATE_EXPORT JointManager *NodeManagers::manager<Joint>() const Q_DECL_NOEXCEPT;
+Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderImageManager *NodeManagers::manager<ShaderImage>() const noexcept;
} // Render
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
index 6b60dfcda..9510b9530 100644
--- a/src/render/backend/render-backend.pri
+++ b/src/render/backend/render-backend.pri
@@ -11,6 +11,7 @@ HEADERS += \
$$PWD/platformsurfacefilter_p.h \
$$PWD/cameralens_p.h \
$$PWD/entity_p.h \
+ $$PWD/entity_p_p.h \
$$PWD/entityvisitor_p.h \
$$PWD/entityaccumulator_p.h \
$$PWD/layer_p.h \
diff --git a/src/render/backend/rendersettings.cpp b/src/render/backend/rendersettings.cpp
index 5734f96a6..8638352c4 100644
--- a/src/render/backend/rendersettings.cpp
+++ b/src/render/backend/rendersettings.cpp
@@ -43,7 +43,6 @@
#include <Qt3DRender/private/abstractrenderer_p.h>
#include <Qt3DRender/private/qrendersettings_p.h>
#include <Qt3DCore/qnodecommand.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -63,42 +62,43 @@ RenderSettings::RenderSettings()
{
}
-void RenderSettings::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void RenderSettings::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderSettingsData>>(change);
- const auto &data = typedChange->data;
- m_activeFrameGraph = data.activeFrameGraphId;
- m_renderPolicy = data.renderPolicy;
- m_pickMethod = data.pickMethod;
- m_pickResultMode = data.pickResultMode;
- m_pickWorldSpaceTolerance = data.pickWorldSpaceTolerance;
- m_faceOrientationPickingMode = data.faceOrientationPickingMode;
-}
+ const QRenderSettings *node = qobject_cast<const QRenderSettings *>(frontEnd);
+ if (!node)
+ return;
-void RenderSettings::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("pickMethod"))
- m_pickMethod = propertyChange->value().value<QPickingSettings::PickMethod>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("pickResult"))
- m_pickResultMode = propertyChange->value().value<QPickingSettings::PickResultMode>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("faceOrientationPickingMode"))
- m_faceOrientationPickingMode = propertyChange->value().value<QPickingSettings::FaceOrientationPickingMode>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("pickWorldSpaceTolerance"))
- m_pickWorldSpaceTolerance = propertyChange->value().toFloat();
- else if (propertyChange->propertyName() == QByteArrayLiteral("activeFrameGraph"))
- m_activeFrameGraph = propertyChange->value().value<QNodeId>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("renderPolicy"))
- m_renderPolicy = propertyChange->value().value<QRenderSettings::RenderPolicy>();
- markDirty(AbstractRenderer::AllDirty);
- } else if (e->type() == CommandRequested) {
- QNodeCommandPtr command = qSharedPointerCast<QNodeCommand>(e);
- if (command->name() == QLatin1Literal("InvalidateFrame"))
- markDirty(AbstractRenderer::AllDirty);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const Qt3DCore::QNodeId activeFGId = Qt3DCore::qIdForNode(node->activeFrameGraph());
+ if (activeFGId != m_activeFrameGraph) {
+ m_activeFrameGraph = activeFGId;
+ }
+
+ if (node->renderPolicy() != m_renderPolicy) {
+ m_renderPolicy = node->renderPolicy();
+ }
+
+ auto ncnode = const_cast<QRenderSettings *>(node);
+ if (ncnode->pickingSettings()->pickMethod() != m_pickMethod) {
+ m_pickMethod = ncnode->pickingSettings()->pickMethod();
}
- BackendNode::sceneChangeEvent(e);
+ if (ncnode->pickingSettings()->pickResultMode() != m_pickResultMode) {
+ m_pickResultMode = ncnode->pickingSettings()->pickResultMode();
+ }
+
+ if (ncnode->pickingSettings()->worldSpaceTolerance() != m_pickWorldSpaceTolerance) {
+ m_pickWorldSpaceTolerance = ncnode->pickingSettings()->worldSpaceTolerance();
+ }
+
+ if (ncnode->pickingSettings()->faceOrientationPickingMode() != m_faceOrientationPickingMode) {
+ m_faceOrientationPickingMode = ncnode->pickingSettings()->faceOrientationPickingMode();
+ }
+
+ // Either because something above as changed or if QRenderSettingsPrivate::invalidFrame()
+ // was called
+ markDirty(AbstractRenderer::AllDirty);
}
RenderSettingsFunctor::RenderSettingsFunctor(AbstractRenderer *renderer)
@@ -131,8 +131,10 @@ void RenderSettingsFunctor::destroy(Qt3DCore::QNodeId id) const
Q_UNUSED(id);
// Deletes the old settings object
auto settings = m_renderer->settings();
- delete settings;
- m_renderer->setSettings(nullptr);
+ if (settings && settings->peerId() == id) {
+ m_renderer->setSettings(nullptr);
+ delete settings;
+ }
}
} // namespace Render
diff --git a/src/render/backend/rendersettings_p.h b/src/render/backend/rendersettings_p.h
index d2880c134..1c8c0ca72 100644
--- a/src/render/backend/rendersettings_p.h
+++ b/src/render/backend/rendersettings_p.h
@@ -67,7 +67,7 @@ class Q_AUTOTEST_EXPORT RenderSettings : public BackendNode
public:
RenderSettings();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
Qt3DCore::QNodeId activeFrameGraphID() const { return m_activeFrameGraph; }
QRenderSettings::RenderPolicy renderPolicy() const { return m_renderPolicy; }
@@ -80,8 +80,6 @@ public:
void setActiveFrameGraphId(Qt3DCore::QNodeId frameGraphNodeId) { m_activeFrameGraph = frameGraphNodeId; }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QRenderSettings::RenderPolicy m_renderPolicy;
QPickingSettings::PickMethod m_pickMethod;
QPickingSettings::PickResultMode m_pickResultMode;
diff --git a/src/render/backend/rendertarget.cpp b/src/render/backend/rendertarget.cpp
index b0565a26b..088818c94 100644
--- a/src/render/backend/rendertarget.cpp
+++ b/src/render/backend/rendertarget.cpp
@@ -41,9 +41,6 @@
#include <Qt3DRender/qrendertarget.h>
#include <Qt3DRender/private/qrendertarget_p.h>
#include <Qt3DRender/qrendertargetoutput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <QVariant>
QT_BEGIN_NAMESPACE
@@ -58,11 +55,21 @@ RenderTarget::RenderTarget()
{
}
-void RenderTarget::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void RenderTarget::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderTargetData>>(change);
- const auto &data = typedChange->data;
- m_renderOutputs = data.outputIds;
+ const QRenderTarget *node = qobject_cast<const QRenderTarget *>(frontEnd);
+ if (!node)
+ return;
+
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ auto outputIds = qIdsForNodes(node->outputs());
+ std::sort(std::begin(outputIds), std::end(outputIds));
+
+ if (m_renderOutputs != outputIds) {
+ m_renderOutputs = outputIds;
+ markDirty(AbstractRenderer::AllDirty);
+ }
}
void RenderTarget::cleanup()
@@ -87,33 +94,6 @@ QVector<Qt3DCore::QNodeId> RenderTarget::renderOutputs() const
return m_renderOutputs;
}
-void RenderTarget::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case Qt3DCore::PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("output")) {
- appendRenderOutput(change->addedNodeId());
- markDirty(AbstractRenderer::AllDirty);
- }
- break;
- }
-
- case Qt3DCore::PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("output")) {
- removeRenderOutput(change->removedNodeId());
- markDirty(AbstractRenderer::AllDirty);
- }
- break;
- }
-
- default:
- break;
- }
- BackendNode::sceneChangeEvent(e);
-}
-
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/rendertarget_p.h b/src/render/backend/rendertarget_p.h
index 5e3e63582..30769dcfc 100644
--- a/src/render/backend/rendertarget_p.h
+++ b/src/render/backend/rendertarget_p.h
@@ -76,11 +76,9 @@ public:
QVector<Qt3DCore::QNodeId> renderOutputs() const;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DCore::QNodeId> m_renderOutputs;
};
diff --git a/src/render/backend/rendertargetoutput.cpp b/src/render/backend/rendertargetoutput.cpp
index cba92596d..e98acf3b8 100644
--- a/src/render/backend/rendertargetoutput.cpp
+++ b/src/render/backend/rendertargetoutput.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include <Qt3DRender/private/rendertargetoutput_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qtexture.h>
#include <Qt3DRender/private/qrendertargetoutput_p.h>
#include <QVariant>
@@ -55,15 +54,39 @@ RenderTargetOutput::RenderTargetOutput()
{
}
-void RenderTargetOutput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void RenderTargetOutput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderTargetOutputData>>(change);
- const auto &data = typedChange->data;
- m_attachmentData.m_point = data.attachmentPoint;
- m_attachmentData.m_mipLevel = data.mipLevel;
- m_attachmentData.m_layer = data.layer;
- m_attachmentData.m_face = data.face;
- m_attachmentData.m_textureUuid = data.textureId;
+ const QRenderTargetOutput *node = qobject_cast<const QRenderTargetOutput *>(frontEnd);
+ if (!node)
+ return;
+
+ const bool oldEnabled = isEnabled();
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (node->attachmentPoint() != m_attachmentData.m_point) {
+ m_attachmentData.m_point = node->attachmentPoint();
+ markDirty(AbstractRenderer::AllDirty);
+ }
+ if (node->mipLevel() != m_attachmentData.m_mipLevel) {
+ m_attachmentData.m_mipLevel = node->mipLevel();
+ markDirty(AbstractRenderer::AllDirty);
+ }
+ if (node->layer() != m_attachmentData.m_layer) {
+ m_attachmentData.m_layer = node->layer();
+ markDirty(AbstractRenderer::AllDirty);
+ }
+ if (node->face() != m_attachmentData.m_face) {
+ m_attachmentData.m_face = node->face();
+ markDirty(AbstractRenderer::AllDirty);
+ }
+ const auto textureId = Qt3DCore::qIdForNode(node->texture());
+ if (textureId != m_attachmentData.m_textureUuid) {
+ m_attachmentData.m_textureUuid = textureId;
+ markDirty(AbstractRenderer::AllDirty);
+ }
+
+ if (oldEnabled != isEnabled())
+ markDirty(AbstractRenderer::AllDirty);
}
Qt3DCore::QNodeId RenderTargetOutput::textureUuid() const
@@ -96,31 +119,6 @@ QRenderTargetOutput::AttachmentPoint RenderTargetOutput::point() const
return m_attachmentData.m_point;
}
-void RenderTargetOutput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (e->type() == PropertyUpdated) {
- if (propertyChange->propertyName() == QByteArrayLiteral("type")) {
- m_attachmentData.m_point = static_cast<QRenderTargetOutput::AttachmentPoint>(propertyChange->value().toInt());
- }
- else if (propertyChange->propertyName() == QByteArrayLiteral("texture")) {
- m_attachmentData.m_textureUuid = propertyChange->value().value<QNodeId>();
- }
- else if (propertyChange->propertyName() == QByteArrayLiteral("mipLevel")) {
- m_attachmentData.m_mipLevel = propertyChange->value().toInt();
- }
- else if (propertyChange->propertyName() == QByteArrayLiteral("layer")) {
- m_attachmentData.m_layer = propertyChange->value().toInt();
- }
- else if (propertyChange->propertyName() == QByteArrayLiteral("face")) {
- m_attachmentData.m_face = static_cast<QAbstractTexture::CubeMapFace>(propertyChange->value().toInt());
- }
- markDirty(AbstractRenderer::AllDirty);
- }
-
- BackendNode::sceneChangeEvent(e);
-}
-
Qt3DRender::Render::Attachment *RenderTargetOutput::attachment()
{
return &m_attachmentData;
diff --git a/src/render/backend/rendertargetoutput_p.h b/src/render/backend/rendertargetoutput_p.h
index 20476547b..d72f6d231 100644
--- a/src/render/backend/rendertargetoutput_p.h
+++ b/src/render/backend/rendertargetoutput_p.h
@@ -76,12 +76,11 @@ public:
QString name() const;
QAbstractTexture::CubeMapFace face() const;
QRenderTargetOutput::AttachmentPoint point() const;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
Attachment *attachment();
const Attachment *attachment() const;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
Qt3DCore::QNodeId m_attachmentUuid;
Attachment m_attachmentData;
};
diff --git a/src/render/backend/resourceaccessor.cpp b/src/render/backend/resourceaccessor.cpp
index c6496976a..4f70df436 100644
--- a/src/render/backend/resourceaccessor.cpp
+++ b/src/render/backend/resourceaccessor.cpp
@@ -42,7 +42,6 @@
#include <private/nodemanagers_p.h>
#include <private/texture_p.h>
#include <private/rendertargetoutput_p.h>
-#include <private/texturedatamanager_p.h>
#include <private/gltexturemanager_p.h>
#include <private/managers_p.h>
#include <private/gltexture_p.h>
diff --git a/src/render/backend/transform.cpp b/src/render/backend/transform.cpp
index 20574d6f7..9e78bc96f 100644
--- a/src/render/backend/transform.cpp
+++ b/src/render/backend/transform.cpp
@@ -39,7 +39,6 @@
#include "transform_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/private/qtransform_p.h>
@@ -52,7 +51,7 @@ namespace Qt3DRender {
namespace Render {
Transform::Transform()
- : BackendNode()
+ : BackendNode(ReadWrite)
, m_rotation()
, m_scale(1.0f, 1.0f, 1.0f)
, m_translation()
@@ -68,16 +67,6 @@ void Transform::cleanup()
QBackendNode::setEnabled(false);
}
-void Transform::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QTransformData>>(change);
- const auto &data = typedChange->data;
- m_rotation = data.rotation;
- m_scale = data.scale;
- m_translation = data.translation;
- updateMatrix();
-}
-
Matrix4x4 Transform::transformMatrix() const
{
return m_transformMatrix;
@@ -98,25 +87,25 @@ QVector3D Transform::translation() const
return m_translation;
}
-void Transform::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void Transform::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- // TODO: Flag the matrix as dirty and update all matrices batched in a job
- if (e->type() == PropertyUpdated) {
- const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("scale3D")) {
- m_scale = propertyChange->value().value<QVector3D>();
- updateMatrix();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("rotation")) {
- m_rotation = propertyChange->value().value<QQuaternion>();
- updateMatrix();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("translation")) {
- m_translation = propertyChange->value().value<QVector3D>();
- updateMatrix();
- }
+ const Qt3DCore::QTransform *transform = qobject_cast<const Qt3DCore::QTransform *>(frontEnd);
+ if (!transform)
+ return;
+
+ bool dirty = m_rotation != transform->rotation();
+ m_rotation = transform->rotation();
+ dirty |= m_scale != transform->scale3D();
+ m_scale = transform->scale3D();
+ dirty |= m_translation != transform->translation();
+ m_translation = transform->translation();
+
+ if (dirty || firstTime) {
+ updateMatrix();
+ markDirty(AbstractRenderer::TransformDirty);
}
- markDirty(AbstractRenderer::TransformDirty);
- BackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
}
void Transform::updateMatrix()
diff --git a/src/render/backend/transform_p.h b/src/render/backend/transform_p.h
index 8e3e9d639..8c0cd826a 100644
--- a/src/render/backend/transform_p.h
+++ b/src/render/backend/transform_p.h
@@ -76,13 +76,10 @@ public:
QQuaternion rotation() const;
QVector3D translation() const;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
-
- void updateMatrix();
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) final;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
+ void updateMatrix();
Matrix4x4 m_transformMatrix;
QQuaternion m_rotation;
QVector3D m_scale;
diff --git a/src/render/backend/uniform_p.h b/src/render/backend/uniform_p.h
index 7f273566e..c8731637c 100644
--- a/src/render/backend/uniform_p.h
+++ b/src/render/backend/uniform_p.h
@@ -101,6 +101,7 @@ enum UniformType {
Mat3x4,
Mat4x3,
Sampler,
+ Image,
Unknown
};
@@ -111,7 +112,8 @@ public:
ScalarValue,
NodeId,
TextureValue,
- BufferValue
+ BufferValue,
+ ShaderImageValue
};
// UniformValue implicitely converts doubles to floats to ensure
@@ -225,9 +227,9 @@ public:
return !(*this == other);
}
private:
- // Allocate 4 floats on stack
+ // Allocate 16 floats on stack
// For larger elements, heap allocation will be used
- QVarLengthArray<float, 4> m_data;
+ QVarLengthArray<float, 16> m_data;
ValueType m_valueType = ScalarValue;
diff --git a/src/render/framegraph/blitframebuffer.cpp b/src/render/framegraph/blitframebuffer.cpp
index 342594baf..0ecfbf5c4 100644
--- a/src/render/framegraph/blitframebuffer.cpp
+++ b/src/render/framegraph/blitframebuffer.cpp
@@ -39,7 +39,6 @@
#include <Qt3DRender/private/qblitframebuffer_p.h>
#include <Qt3DRender/private/blitframebuffer_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -60,48 +59,44 @@ BlitFramebuffer::BlitFramebuffer()
{
}
-void BlitFramebuffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void BlitFramebuffer::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("sourceRenderTarget")) {
- m_sourceRenderTargetId = propertyChange->value().value<QNodeId>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("destinationRenderTarget")) {
- m_destinationRenderTargetId = propertyChange->value().value<QNodeId>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("sourceRect")) {
- m_sourceRect = propertyChange->value().toRect();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("destinationRect")) {
- m_destinationRect = propertyChange->value().toRect();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("sourceAttachmentPoint")) {
- m_sourceAttachmentPoint = propertyChange->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("destinationAttachmentPoint")) {
- m_destinationAttachmentPoint = propertyChange->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("interpolationMethod")) {
- m_interpolationMethod = propertyChange->value().value<QBlitFramebuffer::InterpolationMethod>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- }
- FrameGraphNode::sceneChangeEvent(e);
-}
+ const QBlitFramebuffer *node = qobject_cast<const QBlitFramebuffer *>(frontEnd);
+ if (!node)
+ return;
-void BlitFramebuffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QBlitFramebufferData> >(change);
- const auto &data = typedChange->data;
- m_sourceRect = data.m_sourceRect;
- m_destinationRect = data.m_destinationRect;
- m_sourceRenderTargetId = data.m_sourceRenderTargetId;
- m_destinationRenderTargetId = data.m_destinationRenderTargetId;
- m_sourceAttachmentPoint = data.m_sourceAttachmentPoint;
- m_destinationAttachmentPoint = data.m_destinationAttachmentPoint;
- m_interpolationMethod = data.m_interpolationMethod;
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (node->sourceRect().toRect() != m_sourceRect) {
+ m_sourceRect = node->sourceRect().toRect();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+ if (node->destinationRect().toRect() != m_destinationRect) {
+ m_destinationRect = node->destinationRect().toRect();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+ if (node->sourceAttachmentPoint() != m_sourceAttachmentPoint) {
+ m_sourceAttachmentPoint = node->sourceAttachmentPoint();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+ if (node->destinationAttachmentPoint() != m_destinationAttachmentPoint) {
+ m_destinationAttachmentPoint = node->destinationAttachmentPoint();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+ if (node->interpolationMethod() != m_interpolationMethod) {
+ m_interpolationMethod = node->interpolationMethod();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+ const QNodeId destinationNodeId = qIdForNode(node->destination());
+ if (destinationNodeId != m_destinationRenderTargetId) {
+ m_destinationRenderTargetId = destinationNodeId;
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+ const QNodeId sourceNodeId = qIdForNode(node->source());
+ if (sourceNodeId != m_sourceRenderTargetId) {
+ m_sourceRenderTargetId = sourceNodeId;
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
}
Qt3DRender::QRenderTargetOutput::AttachmentPoint BlitFramebuffer::destinationAttachmentPoint() const
diff --git a/src/render/framegraph/blitframebuffer_p.h b/src/render/framegraph/blitframebuffer_p.h
index 796c223ca..fa9ddacd9 100644
--- a/src/render/framegraph/blitframebuffer_p.h
+++ b/src/render/framegraph/blitframebuffer_p.h
@@ -65,7 +65,7 @@ class Q_AUTOTEST_EXPORT BlitFramebuffer : public FrameGraphNode
public:
BlitFramebuffer();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
Qt3DCore::QNodeId sourceRenderTargetId() const;
@@ -82,8 +82,6 @@ public:
QBlitFramebuffer::InterpolationMethod interpolationMethod() const;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_sourceRenderTargetId;
Qt3DCore::QNodeId m_destinationRenderTargetId;
QRect m_sourceRect;
diff --git a/src/render/framegraph/buffercapture.cpp b/src/render/framegraph/buffercapture.cpp
index 4e89150df..b5e80eb29 100644
--- a/src/render/framegraph/buffercapture.cpp
+++ b/src/render/framegraph/buffercapture.cpp
@@ -40,7 +40,6 @@
#include <Qt3DRender/private/qbuffercapture_p.h>
#include <Qt3DRender/private/buffercapture_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/framegraph/cameraselectornode.cpp b/src/render/framegraph/cameraselectornode.cpp
index 357611c7c..3beb0ef71 100644
--- a/src/render/framegraph/cameraselectornode.cpp
+++ b/src/render/framegraph/cameraselectornode.cpp
@@ -40,9 +40,7 @@
#include "cameraselectornode_p.h"
#include <Qt3DRender/private/qcameraselector_p.h>
#include <Qt3DRender/private/renderer_p.h>
-#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/renderlogging_p.h>
QT_BEGIN_NAMESPACE
@@ -57,25 +55,19 @@ CameraSelector::CameraSelector()
{
}
-void CameraSelector::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void CameraSelector::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QCameraSelectorData>>(change);
- const auto &data = typedChange->data;
- m_cameraUuid = data.cameraId;
-}
+ const QCameraSelector *node = qobject_cast<const QCameraSelector *>(frontEnd);
+ if (!node)
+ return;
-void CameraSelector::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- qCDebug(Render::Framegraph) << Q_FUNC_INFO;
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("camera")) {
- m_cameraUuid = propertyChange->value().value<QNodeId>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const QNodeId cameraId = qIdForNode(node->camera());
+ if (m_cameraUuid != cameraId) {
+ m_cameraUuid = cameraId;
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
- FrameGraphNode::sceneChangeEvent(e);
}
QNodeId CameraSelector::cameraUuid() const
diff --git a/src/render/framegraph/cameraselectornode_p.h b/src/render/framegraph/cameraselectornode_p.h
index 0e532d68f..dd7e050d0 100644
--- a/src/render/framegraph/cameraselectornode_p.h
+++ b/src/render/framegraph/cameraselectornode_p.h
@@ -69,12 +69,11 @@ class CameraSelector : public FrameGraphNode
public:
CameraSelector();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
Qt3DCore::QNodeId cameraUuid() const;
-private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+private:
Qt3DCore::QNodeId m_cameraUuid;
};
diff --git a/src/render/framegraph/clearbuffers.cpp b/src/render/framegraph/clearbuffers.cpp
index ab6225a4b..3f99e0e20 100644
--- a/src/render/framegraph/clearbuffers.cpp
+++ b/src/render/framegraph/clearbuffers.cpp
@@ -39,7 +39,6 @@
#include "clearbuffers_p.h"
#include <Qt3DRender/private/qclearbuffers_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -50,53 +49,55 @@ namespace Render {
static QVector4D vec4dFromColor(const QColor &color)
{
- return QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF());
+ if (!color.isValid())
+ return QVector4D(0.0f, 0.0f, 0.0f, 1.0f);
+ return QVector4D(float(color.redF()), float(color.greenF()), float(color.blueF()), float(color.alphaF()));
}
ClearBuffers::ClearBuffers()
: FrameGraphNode(FrameGraphNode::ClearBuffers)
, m_type(QClearBuffers::None)
+ , m_clearColor(vec4dFromColor(m_clearColorAsColor))
+ , m_clearColorAsColor(Qt::black)
, m_clearDepthValue(1.f)
, m_clearStencilValue(0)
{
}
-void ClearBuffers::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void ClearBuffers::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QClearBuffersData>>(change);
- const auto &data = typedChange->data;
- m_type = data.buffersType;
- m_clearColorAsColor = data.clearColor;
- m_clearColor = vec4dFromColor(m_clearColorAsColor);
- m_clearDepthValue = data.clearDepthValue;
- m_clearStencilValue = data.clearStencilValue;
- m_colorBufferId = data.bufferId;
-}
+ const QClearBuffers *node = qobject_cast<const QClearBuffers *>(frontEnd);
+ if (!node)
+ return;
-void ClearBuffers::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("buffers")) {
- m_type = static_cast<QClearBuffers::BufferType>(propertyChange->value().toInt());
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("clearColor")) {
- m_clearColorAsColor = propertyChange->value().value<QColor>();
- m_clearColor = vec4dFromColor(m_clearColorAsColor);
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("clearDepthValue")) {
- m_clearDepthValue = propertyChange->value().toFloat();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("clearStencilValue")) {
- m_clearStencilValue = propertyChange->value().toInt();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("colorBuffer")) {
- m_colorBufferId = propertyChange->value().value<QNodeId>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (m_clearColorAsColor != node->clearColor()) {
+ m_clearColorAsColor = node->clearColor();
+ m_clearColor = vec4dFromColor(node->clearColor());
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ if (!qFuzzyCompare(m_clearDepthValue, node->clearDepthValue())) {
+ m_clearDepthValue = node->clearDepthValue();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ if (m_clearStencilValue != node->clearStencilValue()) {
+ m_clearStencilValue = node->clearStencilValue();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ const QNodeId colorBufferId = qIdForNode(node->colorBuffer());
+ if (m_colorBufferId != colorBufferId) {
+ m_colorBufferId = colorBufferId;
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ if (m_type != node->buffers()) {
+ m_type = node->buffers();
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
- FrameGraphNode::sceneChangeEvent(e);
}
QClearBuffers::BufferType ClearBuffers::type() const
diff --git a/src/render/framegraph/clearbuffers_p.h b/src/render/framegraph/clearbuffers_p.h
index e3c56c165..ca55d2a98 100644
--- a/src/render/framegraph/clearbuffers_p.h
+++ b/src/render/framegraph/clearbuffers_p.h
@@ -67,8 +67,6 @@ class ClearBuffers : public FrameGraphNode
public:
ClearBuffers();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
-
QClearBuffers::BufferType type() const;
float clearDepthValue() const;
int clearStencilValue() const;
@@ -85,10 +83,9 @@ public:
QColor clearColorAsColor() const;
bool clearsAllColorBuffers() const;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QClearBuffers::BufferType m_type;
QVector4D m_clearColor;
QColor m_clearColorAsColor;
diff --git a/src/render/framegraph/dispatchcompute.cpp b/src/render/framegraph/dispatchcompute.cpp
index f7e9dcff4..4161d37b5 100644
--- a/src/render/framegraph/dispatchcompute.cpp
+++ b/src/render/framegraph/dispatchcompute.cpp
@@ -39,7 +39,6 @@
#include "dispatchcompute_p.h"
#include <Qt3DRender/private/qdispatchcompute_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -66,32 +65,26 @@ void DispatchCompute::cleanup()
m_workGroups[2] = 1;
}
-void DispatchCompute::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void DispatchCompute::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QDispatchComputeData>>(change);
- const auto &data = typedChange->data;
- m_workGroups[0] = data.workGroupX;
- m_workGroups[1] = data.workGroupY;
- m_workGroups[2] = data.workGroupZ;
-}
+ const QDispatchCompute *node = qobject_cast<const QDispatchCompute *>(frontEnd);
+ if (!node)
+ return;
-void DispatchCompute::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("workGroupX")) {
- m_workGroups[0] = propertyChange->value().toInt();
- markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("workGroupY")) {
- m_workGroups[1] = propertyChange->value().toInt();
- markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("workGroupZ")) {
- m_workGroups[2] = propertyChange->value().toInt();
- markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty);
- }
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (m_workGroups[0] != node->workGroupX()) {
+ m_workGroups[0] = node->workGroupX();
+ markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty);
+ }
+ if (m_workGroups[1] != node->workGroupY()) {
+ m_workGroups[1] = node->workGroupY();
+ markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty);
+ }
+ if (m_workGroups[2] != node->workGroupZ()) {
+ m_workGroups[2] = node->workGroupZ();
+ markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::ComputeDirty);
}
- FrameGraphNode::sceneChangeEvent(e);
}
} // Render
diff --git a/src/render/framegraph/dispatchcompute_p.h b/src/render/framegraph/dispatchcompute_p.h
index aa88a35c5..24a641938 100644
--- a/src/render/framegraph/dispatchcompute_p.h
+++ b/src/render/framegraph/dispatchcompute_p.h
@@ -68,13 +68,13 @@ public:
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
inline int x() const Q_DECL_NOTHROW { return m_workGroups[0]; }
inline int y() const Q_DECL_NOTHROW { return m_workGroups[1]; }
inline int z() const Q_DECL_NOTHROW { return m_workGroups[2]; }
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
int m_workGroups[3];
};
diff --git a/src/render/framegraph/framegraph.pri b/src/render/framegraph/framegraph.pri
index b969c85e5..bb833422f 100644
--- a/src/render/framegraph/framegraph.pri
+++ b/src/render/framegraph/framegraph.pri
@@ -64,7 +64,12 @@ HEADERS += \
$$PWD/qwaitfence_p.h \
$$PWD/qsetfence_p.h \
$$PWD/setfence_p.h \
- $$PWD/waitfence_p.h
+ $$PWD/waitfence_p.h \
+ $$PWD/qnopicking.h \
+ $$PWD/nopicking_p.h \
+ $$PWD/qsubtreeenabler.h \
+ $$PWD/qsubtreeenabler_p.h \
+ $$PWD/subtreeenabler_p.h
SOURCES += \
$$PWD/cameraselectornode.cpp \
@@ -110,4 +115,8 @@ SOURCES += \
$$PWD/qsetfence.cpp \
$$PWD/qwaitfence.cpp \
$$PWD/setfence.cpp \
- $$PWD/waitfence.cpp
+ $$PWD/waitfence.cpp \
+ $$PWD/qnopicking.cpp \
+ $$PWD/nopicking.cpp \
+ $$PWD/qsubtreeenabler.cpp \
+ $$PWD/subtreeenabler.cpp
diff --git a/src/render/framegraph/framegraphnode.cpp b/src/render/framegraph/framegraphnode.cpp
index 16f54df3b..40d8fca3d 100644
--- a/src/render/framegraph/framegraphnode.cpp
+++ b/src/render/framegraph/framegraphnode.cpp
@@ -41,7 +41,6 @@
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -66,13 +65,6 @@ FrameGraphNode::~FrameGraphNode()
{
}
-void FrameGraphNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- // Set up the parent child relationship and enabled state
- const auto creationChange = qSharedPointerCast<QFrameGraphNodeCreatedChangeBase>(change);
- setParentId(creationChange->parentFrameGraphNodeId());
-}
-
void FrameGraphNode::setFrameGraphManager(FrameGraphManager *manager)
{
if (m_manager != manager)
@@ -128,34 +120,34 @@ QVector<FrameGraphNode *> FrameGraphNode::children() const
return children;
}
-void FrameGraphNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void FrameGraphNode::cleanup()
{
- switch (e->type()) {
-
- case Qt3DCore::PropertyUpdated: {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) {
- d_func()->m_enabled = propertyChange->value().toBool();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("parentFrameGraphUpdated")) {
- auto newParent = propertyChange->value().value<Qt3DCore::QNodeId>();
- setParentId(newParent);
- markDirty(AbstractRenderer::AllDirty);
- }
- break;
- }
- default:
- markDirty(AbstractRenderer::AllDirty);
- break;
- }
+ setParentId({});
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
-void FrameGraphNode::cleanup()
+void FrameGraphNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- setParentId({});
+ const QFrameGraphNode *node = qobject_cast<const QFrameGraphNode *>(frontEnd);
+
+ const auto parentId = Qt3DCore::qIdForNode(node->parentFrameGraphNode());
+ if (parentId != m_parentId) {
+ setParentId(parentId);
+ // TO DO: Check if FrameGraphDirty wouldn't be enough here
+ markDirty(AbstractRenderer::AllDirty);
+ }
+
+ if (node->isEnabled() != d_func()->m_enabled) {
+ d_func()->m_enabled = node->isEnabled();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ if (firstTime)
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/framegraph/framegraphnode_p.h b/src/render/framegraph/framegraphnode_p.h
index 6aa3b3d6d..846dc8060 100644
--- a/src/render/framegraph/framegraphnode_p.h
+++ b/src/render/framegraph/framegraphnode_p.h
@@ -90,7 +90,7 @@ public:
Viewport,
ClearBuffers,
SortMethod,
- SubtreeSelector,
+ SubtreeEnabler,
StateSet,
NoDraw,
FrustumCulling,
@@ -103,7 +103,8 @@ public:
ProximityFilter,
BlitFramebuffer,
SetFence,
- WaitFence
+ WaitFence,
+ NoPicking
};
FrameGraphNodeType nodeType() const { return m_nodeType; }
@@ -120,11 +121,10 @@ public:
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
protected:
FrameGraphNode(FrameGraphNodeType nodeType, QBackendNode::Mode mode = QBackendNode::ReadOnly);
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
private:
FrameGraphNodeType m_nodeType;
diff --git a/src/render/framegraph/framegraphvisitor.cpp b/src/render/framegraph/framegraphvisitor.cpp
index cd8b08219..9af0297a0 100644
--- a/src/render/framegraph/framegraphvisitor.cpp
+++ b/src/render/framegraph/framegraphvisitor.cpp
@@ -41,6 +41,7 @@
#include "framegraphvisitor_p.h"
#include "framegraphnode_p.h"
+#include "subtreeenabler_p.h"
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <QThreadPool>
@@ -61,6 +62,7 @@ FrameGraphVisitor::FrameGraphVisitor(const FrameGraphManager *manager)
QVector<FrameGraphNode *> FrameGraphVisitor::traverse(FrameGraphNode *root)
{
m_leaves.clear();
+ m_enablersToDisable.clear();
Q_ASSERT_X(root, Q_FUNC_INFO, "The FrameGraphRoot is null");
@@ -72,12 +74,23 @@ QVector<FrameGraphNode *> FrameGraphVisitor::traverse(FrameGraphNode *root)
return m_leaves;
}
+// intended to be called after traverse
+// (returns data that is captured during the traverse)
+QVector<FrameGraphNode *> &&FrameGraphVisitor::takeEnablersToDisable()
+{
+ return std::move(m_enablersToDisable);
+}
+
void FrameGraphVisitor::visit(Render::FrameGraphNode *node)
{
- // TO DO: check if node is a subtree selector
- // in which case, we only visit the subtrees returned
- // by the selector functor and not all the children
- // as we would otherwise do
+ if (node->nodeType() == Render::FrameGraphNode::SubtreeEnabler) {
+ if (!node->isEnabled())
+ return;
+ if (static_cast<SubtreeEnabler*>(node)->enablement() == QSubtreeEnabler::SingleShot) {
+ node->setEnabled(false);
+ m_enablersToDisable.push_back(node);
+ }
+ }
// Recurse to children (if we have any), otherwise if this is a leaf node,
// initiate a rendering from the current camera
diff --git a/src/render/framegraph/framegraphvisitor_p.h b/src/render/framegraph/framegraphvisitor_p.h
index f4c0d7796..5706a169d 100644
--- a/src/render/framegraph/framegraphvisitor_p.h
+++ b/src/render/framegraph/framegraphvisitor_p.h
@@ -72,12 +72,14 @@ public:
explicit FrameGraphVisitor(const FrameGraphManager *nodeManager);
QVector<FrameGraphNode *> traverse(FrameGraphNode *root);
+ QVector<FrameGraphNode *> &&takeEnablersToDisable();
private:
void visit(Render::FrameGraphNode *node);
const FrameGraphManager *m_manager;
QVector<FrameGraphNode *> m_leaves;
+ QVector<FrameGraphNode *> m_enablersToDisable;
};
} // namespace Render
diff --git a/src/render/framegraph/frustumculling.cpp b/src/render/framegraph/frustumculling.cpp
index 9f38d6be9..cf3a4ec57 100644
--- a/src/render/framegraph/frustumculling.cpp
+++ b/src/render/framegraph/frustumculling.cpp
@@ -39,7 +39,6 @@
#include "frustumculling_p.h"
#include <Qt3DRender/qfrustumculling.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/framegraph/layerfilternode.cpp b/src/render/framegraph/layerfilternode.cpp
index f9881be0d..f50fc1306 100644
--- a/src/render/framegraph/layerfilternode.cpp
+++ b/src/render/framegraph/layerfilternode.cpp
@@ -40,9 +40,7 @@
#include "layerfilternode_p.h"
#include "qlayerfilter.h"
#include <Qt3DRender/private/qlayerfilter_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -57,48 +55,25 @@ LayerFilterNode::LayerFilterNode()
{
}
-void LayerFilterNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void LayerFilterNode::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLayerFilterData>>(change);
- const auto &data = typedChange->data;
- setLayerIds(data.layerIds);
- m_filterMode = data.filterMode;
-}
+ const QLayerFilter *node = qobject_cast<const QLayerFilter *>(frontEnd);
+ if (!node)
+ return;
-void LayerFilterNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("layer"))
- m_layerIds.append(change->addedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::LayersDirty);
- break;
- }
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("layer"))
- m_layerIds.removeOne(change->removedNodeId());
+ if (m_filterMode != node->filterMode()) {
+ m_filterMode = node->filterMode();
markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::LayersDirty);
- break;
}
- case PropertyUpdated: {
- const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("filterMode")) {
- m_filterMode = static_cast<QLayerFilter::FilterMode>(change->value().value<int>());
- markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::LayersDirty);
- break;
- }
- }
-
- default:
- break;
+ auto layerIds = qIdsForNodes(node->layers());
+ std::sort(std::begin(layerIds), std::end(layerIds));
+ if (m_layerIds != layerIds) {
+ m_layerIds = layerIds;
+ markDirty(AbstractRenderer::FrameGraphDirty|AbstractRenderer::LayersDirty);
}
-
- FrameGraphNode::sceneChangeEvent(e);
}
QNodeIdVector LayerFilterNode::layerIds() const
diff --git a/src/render/framegraph/layerfilternode_p.h b/src/render/framegraph/layerfilternode_p.h
index 18ba4ee7a..27cdc49d3 100644
--- a/src/render/framegraph/layerfilternode_p.h
+++ b/src/render/framegraph/layerfilternode_p.h
@@ -53,6 +53,7 @@
#include <Qt3DRender/private/framegraphnode_p.h>
#include <Qt3DRender/QLayerFilter>
+#include <Qt3DRender/QLayer>
#include <QStringList>
QT_BEGIN_NAMESPACE
@@ -68,15 +69,14 @@ class LayerFilterNode : public FrameGraphNode
public:
LayerFilterNode();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+
Qt3DCore::QNodeIdVector layerIds() const;
void setLayerIds(const Qt3DCore::QNodeIdVector &list);
QLayerFilter::FilterMode filterMode() const;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeIdVector m_layerIds;
QLayerFilter::FilterMode m_filterMode;
};
diff --git a/src/render/framegraph/memorybarrier.cpp b/src/render/framegraph/memorybarrier.cpp
index 59b3071ab..bcc81464a 100644
--- a/src/render/framegraph/memorybarrier.cpp
+++ b/src/render/framegraph/memorybarrier.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "memorybarrier_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/qmemorybarrier_p.h>
QT_BEGIN_NAMESPACE
@@ -62,24 +61,18 @@ QMemoryBarrier::Operations MemoryBarrier::waitOperations() const
return m_waitOperations;
}
-void MemoryBarrier::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void MemoryBarrier::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("waitOperations")) {
- m_waitOperations = propertyChange->value().value<QMemoryBarrier::Operations>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- }
- FrameGraphNode::sceneChangeEvent(e);
-}
+ const QMemoryBarrier *node = qobject_cast<const QMemoryBarrier *>(frontEnd);
+ if (!node)
+ return;
-void MemoryBarrier::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMemoryBarrierData>>(change);
- const QMemoryBarrierData &data = typedChange->data;
- m_waitOperations = data.waitOperations;
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (node->waitOperations() != m_waitOperations) {
+ m_waitOperations = node->waitOperations();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
}
} // Render
diff --git a/src/render/framegraph/memorybarrier_p.h b/src/render/framegraph/memorybarrier_p.h
index e0fd3e9cd..ce545cd09 100644
--- a/src/render/framegraph/memorybarrier_p.h
+++ b/src/render/framegraph/memorybarrier_p.h
@@ -67,10 +67,9 @@ public:
~MemoryBarrier();
QMemoryBarrier::Operations waitOperations() const;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
QMemoryBarrier::Operations m_waitOperations;
};
diff --git a/src/render/framegraph/nodraw.cpp b/src/render/framegraph/nodraw.cpp
index f2020d7ce..f64eb92d7 100644
--- a/src/render/framegraph/nodraw.cpp
+++ b/src/render/framegraph/nodraw.cpp
@@ -39,7 +39,6 @@
#include "nodraw_p.h"
#include <Qt3DRender/qnodraw.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/qsceneobserverinterface.cpp b/src/render/framegraph/nopicking.cpp
index 784ff654e..e36e2894b 100644
--- a/src/core/qsceneobserverinterface.cpp
+++ b/src/render/framegraph/nopicking.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,16 +37,25 @@
**
****************************************************************************/
-#include "qsceneobserverinterface_p.h"
+#include "nopicking_p.h"
QT_BEGIN_NAMESPACE
-namespace Qt3DCore {
+using namespace Qt3DCore;
-QSceneObserverInterface::~QSceneObserverInterface()
+namespace Qt3DRender {
+namespace Render {
+
+NoPicking::NoPicking()
+ : FrameGraphNode(FrameGraphNode::NoPicking)
+{
+}
+
+NoPicking::~NoPicking()
{
}
-} // Qt3D
+} // Render
+} // Qt3DRender
QT_END_NAMESPACE
diff --git a/src/core/qbackendnodefactory_p.h b/src/render/framegraph/nopicking_p.h
index 5752205c0..4ecf6e33b 100644
--- a/src/core/qbackendnodefactory_p.h
+++ b/src/render/framegraph/nopicking_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,9 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DCORE_QBACKENDNODEFACTORY_P_H
-#define QT3DCORE_QBACKENDNODEFACTORY_P_H
-
+#ifndef QT3DRENDER_RENDER_NOPICKING_P_H
+#define QT3DRENDER_RENDER_NOPICKING_P_H
//
// W A R N I N G
// -------------
@@ -51,25 +50,25 @@
// We mean it.
//
-#include <Qt3DCore/qnodecreatedchange.h>
-
-#include <Qt3DCore/private/qt3dcore_global_p.h>
+#include <Qt3DRender/private/framegraphnode_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DCore {
+namespace Qt3DRender {
-class QBackendNode;
+namespace Render {
-class Q_3DCORE_PRIVATE_EXPORT QBackendNodeFactory
+class Q_AUTOTEST_EXPORT NoPicking : public FrameGraphNode
{
public:
- virtual ~QBackendNodeFactory();
- virtual QBackendNode *createBackendNode(const QNodeCreatedChangeBasePtr &change) const = 0;
+ NoPicking();
+ ~NoPicking();
};
-} // namespace Qt3DCore
+} // Render
+
+} // Qt3DRender
QT_END_NAMESPACE
-#endif // QT3DCORE_QBACKENDNODEFACTORY_P_H
+#endif // QT3DRENDER_RENDER_NOPICKING_P_H
diff --git a/src/render/framegraph/proximityfilter.cpp b/src/render/framegraph/proximityfilter.cpp
index cdfd7e51e..03dd2a7ec 100644
--- a/src/render/framegraph/proximityfilter.cpp
+++ b/src/render/framegraph/proximityfilter.cpp
@@ -39,7 +39,6 @@
#include "proximityfilter_p.h"
#include <Qt3DRender/private/qproximityfilter_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -53,29 +52,24 @@ ProximityFilter::ProximityFilter()
{
}
-void ProximityFilter::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void ProximityFilter::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QProximityFilterData>>(change);
- const QProximityFilterData &data = typedChange->data;
- m_entityId = data.entityId;
- m_distanceThreshold = data.distanceThreshold;
-}
+ const QProximityFilter *node = qobject_cast<const QProximityFilter *>(frontEnd);
+ if (!node)
+ return;
-void ProximityFilter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- qCDebug(Render::Framegraph) << Q_FUNC_INFO;
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("entity")) {
- m_entityId = propertyChange->value().value<Qt3DCore::QNodeId>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("distanceThreshold")) {
- m_distanceThreshold = propertyChange->value().toFloat();
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const auto entityId = Qt3DCore::qIdForNode(node->entity());
+ if (entityId != m_entityId) {
+ m_entityId = entityId;
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ if (node->distanceThreshold() != m_distanceThreshold) {
+ m_distanceThreshold = node->distanceThreshold();
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
- FrameGraphNode::sceneChangeEvent(e);
}
} // namespace Render
diff --git a/src/render/framegraph/proximityfilter_p.h b/src/render/framegraph/proximityfilter_p.h
index e57b53dea..5c2f7ad66 100644
--- a/src/render/framegraph/proximityfilter_p.h
+++ b/src/render/framegraph/proximityfilter_p.h
@@ -64,7 +64,7 @@ class Q_AUTOTEST_EXPORT ProximityFilter : public FrameGraphNode
public:
ProximityFilter();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
float distanceThreshold() const { return m_distanceThreshold; }
Qt3DCore::QNodeId entityId() const { return m_entityId; }
@@ -76,8 +76,6 @@ public:
#endif
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
float m_distanceThreshold;
Qt3DCore::QNodeId m_entityId;
};
diff --git a/src/render/framegraph/qblitframebuffer.cpp b/src/render/framegraph/qblitframebuffer.cpp
index d0e1bdbf3..252758af4 100644
--- a/src/render/framegraph/qblitframebuffer.cpp
+++ b/src/render/framegraph/qblitframebuffer.cpp
@@ -40,7 +40,6 @@
#include "qblitframebuffer.h"
#include "qblitframebuffer_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -71,6 +70,10 @@ namespace Qt3DRender {
Specifies the interpolation applied if the image is stretched.
+ \value Nearest
+ Nearest-neighbor interpolation.
+ \value Linear
+ Linear interpolation.
*/
/*!
\property Qt3DRender::QBlitFramebuffer::destination
@@ -364,6 +367,7 @@ void QBlitFramebuffer::setDestination(QRenderTarget *destination)
}
}
+// TO DO Qt6: convert QRectF to QRect
/*!
Sets the source rectangle to \a inputRect. The coordinates are assumed to
follow the normal Qt coordinate system, meaning Y runs from top to bottom.
diff --git a/src/render/framegraph/qbuffercapture.cpp b/src/render/framegraph/qbuffercapture.cpp
index 8e180a7c3..c71c0adb7 100644
--- a/src/render/framegraph/qbuffercapture.cpp
+++ b/src/render/framegraph/qbuffercapture.cpp
@@ -40,7 +40,6 @@
#include <Qt3DRender/qbuffercapture.h>
#include <Qt3DRender/private/qbuffercapture_p.h>
#include <Qt3DCore/QSceneChange>
-#include <Qt3DCore/QPropertyUpdatedChange>
#include <Qt3DRender/QFrameGraphNodeCreatedChange>
QT_BEGIN_NAMESPACE
diff --git a/src/render/framegraph/qcameraselector.cpp b/src/render/framegraph/qcameraselector.cpp
index 45abf638e..af293dc56 100644
--- a/src/render/framegraph/qcameraselector.cpp
+++ b/src/render/framegraph/qcameraselector.cpp
@@ -41,7 +41,6 @@
#include "qcameraselector_p.h"
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/private/qentity_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/framegraph/qclearbuffers.cpp b/src/render/framegraph/qclearbuffers.cpp
index 4cc4c98b6..31a31420c 100644
--- a/src/render/framegraph/qclearbuffers.cpp
+++ b/src/render/framegraph/qclearbuffers.cpp
@@ -39,7 +39,6 @@
#include "qclearbuffers.h"
#include "qclearbuffers_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/framegraph/qframegraphnode.cpp b/src/render/framegraph/qframegraphnode.cpp
index d52b728a8..2390cb1c9 100644
--- a/src/render/framegraph/qframegraphnode.cpp
+++ b/src/render/framegraph/qframegraphnode.cpp
@@ -40,7 +40,6 @@
#include "qframegraphnode.h"
#include "qframegraphnode_p.h"
#include <Qt3DRender/qframegraphnodecreatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/QNode>
@@ -258,13 +257,9 @@ Qt3DCore::QNodeCreatedChangeBasePtr QFrameGraphNode::createNodeCreationChange()
void QFrameGraphNode::onParentChanged(QObject *)
{
- const auto parentID = parentFrameGraphNode() ? parentFrameGraphNode()->id() : Qt3DCore::QNodeId();
- auto parentChange = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
- parentChange->setPropertyName("parentFrameGraphUpdated");
- parentChange->setValue(QVariant::fromValue(parentID));
- const bool blocked = blockNotifications(false);
- notifyObservers(parentChange);
- blockNotifications(blocked);
+ // Direct sync update request
+ Q_D(QFrameGraphNode);
+ d->update();
}
} // namespace Qt3DRender
diff --git a/src/render/framegraph/qlayerfilter.cpp b/src/render/framegraph/qlayerfilter.cpp
index 04ebca572..8bad46f5d 100644
--- a/src/render/framegraph/qlayerfilter.cpp
+++ b/src/render/framegraph/qlayerfilter.cpp
@@ -40,9 +40,6 @@
#include "qlayerfilter.h"
#include "qlayerfilter_p.h"
#include "qlayer.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -206,11 +203,7 @@ void QLayerFilter::addLayer(QLayer *layer)
if (!layer->parent())
layer->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), layer);
- change->setPropertyName("layer");
- d->notifyObservers(change);
- }
+ d->updateNode(layer, "layer", Qt3DCore::PropertyValueAdded);
}
}
@@ -221,11 +214,7 @@ void QLayerFilter::removeLayer(QLayer *layer)
{
Q_ASSERT(layer);
Q_D(QLayerFilter);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), layer);
- change->setPropertyName("layer");
- d->notifyObservers(change);
- }
+ d->updateNode(layer, "layer", Qt3DCore::PropertyValueRemoved);
d->m_layers.removeOne(layer);
// Remove bookkeeping connection
d->unregisterDestructionHelper(layer);
diff --git a/src/render/framegraph/qmemorybarrier.cpp b/src/render/framegraph/qmemorybarrier.cpp
index b39537dcf..5da462f1b 100644
--- a/src/render/framegraph/qmemorybarrier.cpp
+++ b/src/render/framegraph/qmemorybarrier.cpp
@@ -140,7 +140,7 @@ void QMemoryBarrier::setWaitOperations(QMemoryBarrier::Operations waitOperations
if (waitOperations != d->m_waitOperations) {
d->m_waitOperations = waitOperations;
emit waitOperationsChanged(waitOperations);
- d->notifyPropertyChange("waitOperations", QVariant::fromValue(waitOperations));
+ d->notifyPropertyChange("waitOperations", QVariant::fromValue(waitOperations)); // TODOSYNC
}
}
diff --git a/src/render/framegraph/qnopicking.cpp b/src/render/framegraph/qnopicking.cpp
new file mode 100644
index 000000000..069560175
--- /dev/null
+++ b/src/render/framegraph/qnopicking.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnopicking.h"
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+/*!
+ \class Qt3DRender::QNoPicking
+ \inmodule Qt3DRender
+ \since 5.14
+
+ \brief When a Qt3DRender::QNoPicking node is present in a FrameGraph
+ branch, this prevents the render aspect from performing picking selection
+ for the given branch.
+
+ When disabled, a Qt3DRender::QNoPicking node won't prevent picking from
+ being performed. Toggling the enabled property is therefore a way to make a
+ Qt3DRender::QNoPicking active or inactive.
+
+ When using multiple subviewports in the FrameGraph, QNoPicking can be
+ useful to prevent picking conflicts between overlapping viewports or non
+ visual ones. It can also be used as an optimization to prevent unnecessary
+ work for hidden viewports or for sections of the scenes which don't require
+ any picking.
+
+ \code
+ Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
+ Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector(viewport);
+ Qt3DRender::QNoPicking *noPicking = new Qt3DRender::QNoPicking(cameraSelector);
+
+ Qt3DRender::QClearBuffers *clearBuffers = new Qt3DRender::QClearBuffers(noPicking);
+ clearBuffers->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer);
+
+ Qt3DRender::QRenderPassFilter *mainPass = new Qt3DRender::QRenderPassFilter(cameraSelector);
+ ....
+ Qt3DRender::QRenderPassFilter *previewPass = new Qt3DRender::QRenderPassFilter(cameraSelector);
+ ....
+ \endcode
+ \sa Qt3DRender::QObjectPicker, Qt3DRender::QRayCaster, Qt3DRender::QScreenRayCaster
+ */
+
+/*!
+ \qmltype NoPicking
+ \instantiates Qt3DRender::QNoPicking
+ \inherits FrameGraphNode
+ \inqmlmodule Qt3D.Render
+ \since 5.14
+
+ \brief When a NoPicking node is present in a FrameGraph branch, this
+ prevents the render aspect from performing picking selection for the given
+ branch.
+
+ When disabled, a NoPicking node won't prevent picking from being performed.
+ Toggling the enabled property is therefore a way to make a NoPicking active
+ or inactive.
+
+ When using multiple subviewports in the FrameGraph, NoPicking can be useful
+ to prevent picking conflicts between overlapping viewports or non visual
+ ones. It can also be used as an optimization to prevent unnecessary work for
+ hidden viewports or for sections of the scenes which don't require any
+ picking.
+
+
+ \code
+
+ Viewport {
+ CameraSelector {
+ NoPicking {
+ ClearBuffers {
+ buffers: ClearBuffers.ColorDepthBuffer
+ NoDraw { } // Prevents from drawing anything
+ }
+ RenderPassFilter {
+ ...
+ }
+ RenderPassFilter {
+ ...
+ }
+ }
+ }
+ }
+
+ \endcode
+ \sa ObjectPicker, RayCaster, ScreenRayCaster
+
+*/
+
+QNoPicking::QNoPicking(Qt3DCore::QNode *parent)
+ : QFrameGraphNode(parent)
+{
+}
+
+QNoPicking::~QNoPicking()
+{
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/core/qbackendnodefactory.cpp b/src/render/framegraph/qnopicking.h
index 6fd5b33d1..e3bd6e2fd 100644
--- a/src/core/qbackendnodefactory.cpp
+++ b/src/render/framegraph/qnopicking.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,16 +37,25 @@
**
****************************************************************************/
-#include "qbackendnodefactory_p.h"
+#ifndef QT3DRENDER_QNOPICKING_H
+#define QT3DRENDER_QNOPICKING_H
+
+#include <Qt3DRender/qframegraphnode.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DCore {
+namespace Qt3DRender {
-QBackendNodeFactory::~QBackendNodeFactory()
+class Q_3DRENDERSHARED_EXPORT QNoPicking : public QFrameGraphNode
{
-}
+ Q_OBJECT
+public:
+ explicit QNoPicking(Qt3DCore::QNode *parent = nullptr);
+ ~QNoPicking();
+};
-} // namespace Qt3DCore
+} // Qt3DRender
QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QNOPICKING_H
diff --git a/src/render/framegraph/qrendercapture.cpp b/src/render/framegraph/qrendercapture.cpp
index 5bda569f9..2169f72dd 100644
--- a/src/render/framegraph/qrendercapture.cpp
+++ b/src/render/framegraph/qrendercapture.cpp
@@ -326,11 +326,9 @@ QRenderCaptureReply *QRenderCapture::requestCapture(int captureId)
d->replyDestroyed(reply);
});
- Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(id()));
- change->setPropertyName(QByteArrayLiteral("renderCaptureRequest"));
const QRenderCaptureRequest request = { captureId, QRect() };
- change->setValue(QVariant::fromValue(request));
- d->notifyObservers(change);
+ d->m_pendingRequests.push_back(request);
+ d->update();
return reply;
}
@@ -351,11 +349,9 @@ QRenderCaptureReply *QRenderCapture::requestCapture(const QRect &rect)
d->replyDestroyed(reply);
});
- Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(id()));
- change->setPropertyName(QByteArrayLiteral("renderCaptureRequest"));
const QRenderCaptureRequest request = { captureId, rect };
- change->setValue(QVariant::fromValue(request));
- d->notifyObservers(change);
+ d->m_pendingRequests.push_back(request);
+ d->update();
captureId++;
diff --git a/src/render/framegraph/qrendercapture_p.h b/src/render/framegraph/qrendercapture_p.h
index 4e509cc59..3dec4d280 100644
--- a/src/render/framegraph/qrendercapture_p.h
+++ b/src/render/framegraph/qrendercapture_p.h
@@ -57,6 +57,12 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+struct QRenderCaptureRequest
+{
+ int captureId;
+ QRect rect;
+};
+
class QRenderCapturePrivate : public QFrameGraphNodePrivate
{
public:
@@ -64,6 +70,7 @@ public:
~QRenderCapturePrivate();
QVector<QRenderCaptureReply *> m_waitingReplies;
QMutex m_mutex;
+ mutable QVector<QRenderCaptureRequest> m_pendingRequests;
QRenderCaptureReply *createReply(int captureId);
QRenderCaptureReply *takeReply(int captureId);
@@ -82,6 +89,7 @@ public:
int m_captureId;
bool m_complete;
+
Q_DECLARE_PUBLIC(QRenderCaptureReply)
};
@@ -100,12 +108,6 @@ struct RenderCaptureData
typedef QSharedPointer<RenderCaptureData> RenderCaptureDataPtr;
-struct QRenderCaptureRequest
-{
- int captureId;
- QRect rect;
-};
-
} // Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/framegraph/qrenderpassfilter.cpp b/src/render/framegraph/qrenderpassfilter.cpp
index 56c229d9c..952657eb6 100644
--- a/src/render/framegraph/qrenderpassfilter.cpp
+++ b/src/render/framegraph/qrenderpassfilter.cpp
@@ -42,9 +42,6 @@
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qparameter.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -142,11 +139,7 @@ void QRenderPassFilter::addMatch(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey);
- change->setPropertyName("match");
- d->notifyObservers(change);
- }
+ d->updateNode(filterKey, "match", Qt3DCore::PropertyValueAdded);
}
}
@@ -158,11 +151,7 @@ void QRenderPassFilter::removeMatch(QFilterKey *filterKey)
Q_ASSERT(filterKey);
Q_D(QRenderPassFilter);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey);
- change->setPropertyName("match");
- d->notifyObservers(change);
- }
+ d->updateNode(filterKey, "match", Qt3DCore::PropertyValueRemoved);
d->m_matchList.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -188,11 +177,7 @@ void QRenderPassFilter::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -204,11 +189,7 @@ void QRenderPassFilter::removeParameter(QParameter *parameter)
Q_ASSERT(parameter);
Q_D(QRenderPassFilter);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
diff --git a/src/render/framegraph/qrenderstateset.cpp b/src/render/framegraph/qrenderstateset.cpp
index 6f70456ab..5341b3c7d 100644
--- a/src/render/framegraph/qrenderstateset.cpp
+++ b/src/render/framegraph/qrenderstateset.cpp
@@ -41,9 +41,6 @@
#include "qrenderstateset_p.h"
#include <Qt3DRender/qrenderstate.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -194,11 +191,7 @@ void QRenderStateSet::addRenderState(QRenderState *state)
if (!state->parent())
state->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), state);
- change->setPropertyName("renderState");
- d->notifyObservers(change);
- }
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueAdded);
}
}
@@ -210,11 +203,7 @@ void QRenderStateSet::removeRenderState(QRenderState *state)
Q_ASSERT(state);
Q_D(QRenderStateSet);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), state);
- change->setPropertyName("renderState");
- d->notifyObservers(change);
- }
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueRemoved);
d->m_renderStates.removeOne(state);
// Remove bookkeeping connection
d->unregisterDestructionHelper(state);
diff --git a/src/render/framegraph/qrendersurfaceselector.cpp b/src/render/framegraph/qrendersurfaceselector.cpp
index 848d86f53..df30663cb 100644
--- a/src/render/framegraph/qrendersurfaceselector.cpp
+++ b/src/render/framegraph/qrendersurfaceselector.cpp
@@ -44,7 +44,6 @@
#include <QtGui/QScreen>
#include <QtGui/QOffscreenSurface>
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qrendersettings.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
@@ -252,31 +251,17 @@ void QRenderSurfaceSelector::setSurface(QObject *surfaceObject)
d->m_surfaceEventFilter->setSurface(window);
if (window) {
- d->m_widthConn = QObject::connect(window, &QWindow::widthChanged, [=] (int width) {
- if (d->m_changeArbiter != nullptr) {
- Qt3DCore::QPropertyUpdatedChangePtr change(
- new Qt3DCore::QPropertyUpdatedChange(id()));
-
- change->setPropertyName("width");
- change->setValue(QVariant::fromValue(width));
- d->notifyObservers(change);
- }
+ d->m_widthConn = QObject::connect(window, &QWindow::widthChanged, [=] (int) {
+ d->update();
});
- d->m_heightConn = QObject::connect(window, &QWindow::heightChanged, [=] (int height) {
- if (d->m_changeArbiter != nullptr) {
- Qt3DCore::QPropertyUpdatedChangePtr change(
- new Qt3DCore::QPropertyUpdatedChange(id()));
-
- change->setPropertyName("height");
- change->setValue(QVariant::fromValue(height));
- d->notifyObservers(change);
- }
+ d->m_heightConn = QObject::connect(window, &QWindow::heightChanged, [=] (int) {
+ d->update();
});
d->m_screenConn = QObject::connect(window, &QWindow::screenChanged, [=] (QScreen *screen) {
- if (screen && surfacePixelRatio() != screen->devicePixelRatio())
- setSurfacePixelRatio(screen->devicePixelRatio());
+ if (screen && !qFuzzyCompare(surfacePixelRatio(), float(screen->devicePixelRatio())))
+ setSurfacePixelRatio(float(screen->devicePixelRatio()));
});
- setSurfacePixelRatio(window->devicePixelRatio());
+ setSurfacePixelRatio(float(window->devicePixelRatio()));
}
break;
@@ -306,7 +291,7 @@ QSize QRenderSurfaceSelector::externalRenderTargetSize() const
void QRenderSurfaceSelector::setSurfacePixelRatio(float ratio)
{
Q_D(QRenderSurfaceSelector);
- if (d->m_surfacePixelRatio == ratio)
+ if (qFuzzyCompare(d->m_surfacePixelRatio, ratio))
return;
d->m_surfacePixelRatio = ratio;
emit surfacePixelRatioChanged(ratio);
diff --git a/src/render/framegraph/qrendertargetselector.cpp b/src/render/framegraph/qrendertargetselector.cpp
index 1b4afc7e6..c997c23cc 100644
--- a/src/render/framegraph/qrendertargetselector.cpp
+++ b/src/render/framegraph/qrendertargetselector.cpp
@@ -40,7 +40,6 @@
#include "qrendertargetselector.h"
#include "qrendertargetselector_p.h"
#include <Qt3DRender/qrendertarget.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/qrenderpass_p.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
@@ -153,13 +152,7 @@ void QRenderTargetSelector::setOutputs(const QVector<QRenderTargetOutput::Attach
Q_D(QRenderTargetSelector);
if (buffers != d->m_outputs) {
d->m_outputs = buffers;
-
- if (d->m_changeArbiter) {
- auto change = QPropertyUpdatedChangePtr::create(d->m_id);
- change->setPropertyName("outputs");
- change->setValue(QVariant::fromValue(d->m_outputs));
- d->notifyObservers(change);
- }
+ d->update();
}
}
diff --git a/src/render/framegraph/qsetfence.cpp b/src/render/framegraph/qsetfence.cpp
index 5cb82f3db..262dbd4ad 100644
--- a/src/render/framegraph/qsetfence.cpp
+++ b/src/render/framegraph/qsetfence.cpp
@@ -54,7 +54,8 @@ QSetFencePrivate::QSetFencePrivate()
}
/*!
- \class QSetFence
+ \class Qt3DRender::QSetFence
+ \inmodule Qt3DRender
\brief FrameGraphNode used to insert a fence in the graphics command stream.
Fence allow to synchronosize GPU and CPU workloads. GPU commands usually
@@ -100,7 +101,7 @@ QSetFence::QSetFence(QSetFencePrivate &dd, Qt3DCore::QNode *parent)
are supported.
*/
/*!
- \property QSetFence::handleType
+ \property Qt3DRender::QSetFence::handleType
Specifies the type of handle being used. Currently only OpenGL Fence ids
are supported.
@@ -123,12 +124,12 @@ void QSetFencePrivate::setHandleType(QSetFence::HandleType type)
}
/*!
- \qmlproperty variant AbstractFence::handle
+ \qmlproperty variant SetFence::handle
Holds the underlying fence handle wrapped in a variant.
*/
/*!
- \property QAbstractFence::handle
+ \property Qt3DRender::QSetFence::handle
Holds the underlying fence handle wrapped in a QVariant.
*/
diff --git a/src/render/framegraph/qsortpolicy.cpp b/src/render/framegraph/qsortpolicy.cpp
index 6f852afbd..a24dd5eae 100644
--- a/src/render/framegraph/qsortpolicy.cpp
+++ b/src/render/framegraph/qsortpolicy.cpp
@@ -102,6 +102,8 @@ QSortPolicyPrivate::QSortPolicyPrivate()
\value FrontToBack sort the objects from front to back. The opposite of
BackToFront.
+
+ \value [since 5.14] Texture sort the objects to minimize texture changes.
*/
/*!
@@ -124,6 +126,7 @@ QSortPolicyPrivate::QSortPolicyPrivate()
\li Material - sort the objects based on their material value
\li FrontToBack - sort the objects from front to back. The opposite of
BackToFront.
+ \li [since 5.14] Texture - sort the objects to minimize texture changes.
\endlist
*/
@@ -178,7 +181,10 @@ void QSortPolicy::setSortTypes(const QVector<SortType> &sortTypes)
if (sortTypes != d->m_sortTypes) {
d->m_sortTypes = sortTypes;
emit sortTypesChanged(sortTypes);
+
+ const bool wasBlocked = blockNotifications(true);
emit sortTypesChanged(sortTypesInt());
+ blockNotifications(wasBlocked);
}
}
diff --git a/src/render/framegraph/qsortpolicy.h b/src/render/framegraph/qsortpolicy.h
index 67dfe6ac2..a302caa8b 100644
--- a/src/render/framegraph/qsortpolicy.h
+++ b/src/render/framegraph/qsortpolicy.h
@@ -60,7 +60,8 @@ public:
StateChangeCost = (1 << 0),
BackToFront = (1 << 1),
Material = (1 << 2),
- FrontToBack = (1 << 3)
+ FrontToBack = (1 << 3),
+ Texture = (1 << 4),
};
Q_ENUM(SortType) // LCOV_EXCL_LINE
diff --git a/src/render/framegraph/qsubtreeenabler.cpp b/src/render/framegraph/qsubtreeenabler.cpp
new file mode 100644
index 000000000..e5d182d00
--- /dev/null
+++ b/src/render/framegraph/qsubtreeenabler.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsubtreeenabler_p.h"
+#include <Qt3DRender/qframegraphnodecreatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender
+{
+
+/*!
+ \class Qt3DRender::QSubtreeEnabler
+ \inmodule Qt3DRender
+ \brief Enables or disables entire subtrees of framegraph nodes.
+ \since 5.14
+
+ While QFrameGraphNodes can be individually enabled and disabled via the
+ \c enabled property, this can become tedious when an entire path
+ needs to be turned on or off. QSubtreeEnabler is a convenience node
+ that makes this use case trivial, allowing all of its children to be
+ controlled by a single switch.
+
+ QSubtreeEnabler is enabled by default.
+*/
+
+/*!
+ \qmltype SubtreeEnabler
+ \inqmlmodule Qt3D.Render
+ \since 5.14
+ \instantiates Qt3DRender::QSubtreeEnabler
+ \inherits FrameGraphNode
+ \brief Enables or disables entire subtrees of frame graph nodes.
+
+ While FrameGraphNodes can be individually enabled and disabled via the
+ \c enabled property, this can become tedious when an entire path
+ needs to be turned on or off. SubtreeEnabler is a convenience node
+ that makes this use case trivial, allowing all of its children to be
+ controlled by a single switch.
+
+ For example, the following simplified frame graph includes a subtree for
+ debug rendering that can easily be enabled only when debugging.
+
+ \qml
+ RenderSurfaceSelector {
+ ClearBuffers {
+ Viewport {
+ CameraSelector {}
+ }
+ }
+
+ SubtreeEnabler {
+ enabled: showDebugView
+ Viewport {
+ CameraSelector {
+ RenderPassFilter {}
+ }
+ }
+ }
+ }
+ \endqml
+
+ SubtreeEnabler is enabled by default.
+ */
+
+QSubtreeEnabler::QSubtreeEnabler(Qt3DCore::QNode *parent)
+ : QFrameGraphNode(*new QSubtreeEnablerPrivate, parent)
+{
+}
+
+QSubtreeEnabler::~QSubtreeEnabler()
+{
+}
+
+/*!
+ \enum QSubtreeEnabler::Enablement
+
+ Specifies whether subtree enablement is persistent or transient.
+
+ \value Persistent
+ The value of enabled is persistent. This is the default.
+
+ \value SingleShot
+ The value of enabled will last for a single frame and then be reset to false.
+ This might be used for a subtree drawing to an FBO, for example, to only update
+ the FBO when the relevant portions of the scene changed.
+*/
+
+/*!
+ \qmlproperty enumeration Qt3D.Render::SubtreeEnabler::enablement
+ Controls whether subtree enablement is persistent or transient.
+
+ \value Persistent
+ The value of enabled is persistent. This is the default.
+
+ \value SingleShot
+ The value of enabled will last for a single frame and then be reset to false.
+ This might be used for a subtree drawing to an FBO, for example, to only update
+ the FBO when the relevant portions of the scene changed.
+*/
+
+/*!
+ \property Qt3DRender::QSubtreeEnabler::enablement
+ Controls whether subtree enablement is persistent or transient.
+*/
+QSubtreeEnabler::Enablement QSubtreeEnabler::enablement() const
+{
+ Q_D(const QSubtreeEnabler);
+ return d->m_enablement;
+}
+
+void QSubtreeEnabler::setEnablement(QSubtreeEnabler::Enablement enablement)
+{
+ Q_D(QSubtreeEnabler);
+ if (d->m_enablement == enablement)
+ return;
+ d->m_enablement = enablement;
+ emit enablementChanged(d->m_enablement);
+}
+
+/*!
+ \qmlmethod void Qt3D.Render::SubtreeEnabler::requestUpdate()
+ Requests that the subtree be enabled.
+
+ A conveninence method intended to be used with \c SingleShot enablement.
+ */
+
+/*!
+ Requests that the subtree be enabled.
+
+ A convenience method intended to be used with \c SingleShot enablement.
+ */
+void QSubtreeEnabler::requestUpdate()
+{
+ setEnabled(true);
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QSubtreeEnabler::createNodeCreationChange() const
+{
+ auto creationChange = QFrameGraphNodeCreatedChangePtr<QSubtreeEnablerData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QSubtreeEnabler);
+ data.enablement = d->m_enablement;
+ return creationChange;
+}
+
+} //Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/framegraph/qsubtreeenabler.h b/src/render/framegraph/qsubtreeenabler.h
new file mode 100644
index 000000000..558e3b8b7
--- /dev/null
+++ b/src/render/framegraph/qsubtreeenabler.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QSUBTREEENABLER_H
+#define QT3DRENDER_QSUBTREEENABLER_H
+
+#include <Qt3DRender/QFrameGraphNode>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender
+{
+
+class QSubtreeEnablerPrivate;
+
+class Q_3DRENDERSHARED_EXPORT QSubtreeEnabler : public QFrameGraphNode
+{
+ Q_OBJECT
+ Q_PROPERTY(Enablement enablement READ enablement WRITE setEnablement NOTIFY enablementChanged)
+public:
+ explicit QSubtreeEnabler(Qt3DCore::QNode *parent = nullptr);
+ ~QSubtreeEnabler();
+
+ enum Enablement {
+ Persistent,
+ SingleShot
+ };
+ Q_ENUM(Enablement)
+
+ Enablement enablement() const;
+ void setEnablement(Enablement enablement);
+
+ Q_INVOKABLE void requestUpdate();
+
+Q_SIGNALS:
+ void enablementChanged(Qt3DRender::QSubtreeEnabler::Enablement enablement);
+
+private:
+ Q_DECLARE_PRIVATE(QSubtreeEnabler)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
+};
+
+} //Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QSUBTREEENABLER_H
diff --git a/src/render/framegraph/qsubtreeenabler_p.h b/src/render/framegraph/qsubtreeenabler_p.h
new file mode 100644
index 000000000..72354fe89
--- /dev/null
+++ b/src/render/framegraph/qsubtreeenabler_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QSUBTREEENABLER_P_H
+#define QT3DRENDER_QSUBTREEENABLER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qsubtreeenabler.h"
+#include <private/qframegraphnode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QSubtreeEnablerPrivate : public QFrameGraphNodePrivate
+{
+public:
+ QSubtreeEnablerPrivate() = default;
+
+ QSubtreeEnabler::Enablement m_enablement = QSubtreeEnabler::Persistent;
+
+ Q_DECLARE_PUBLIC(QSubtreeEnabler)
+};
+
+struct QSubtreeEnablerData
+{
+ QSubtreeEnabler::Enablement enablement;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QSUBTREEENABLER_P_H
diff --git a/src/render/framegraph/qtechniquefilter.cpp b/src/render/framegraph/qtechniquefilter.cpp
index 404ad6991..c22e83381 100644
--- a/src/render/framegraph/qtechniquefilter.cpp
+++ b/src/render/framegraph/qtechniquefilter.cpp
@@ -41,9 +41,6 @@
#include "qtechniquefilter_p.h"
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/qparameter.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
QT_BEGIN_NAMESPACE
@@ -147,11 +144,7 @@ void QTechniqueFilter::addMatch(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey);
- change->setPropertyName("matchAll");
- d->notifyObservers(change);
- }
+ d->updateNode(filterKey, "matchAll", Qt3DCore::PropertyValueAdded);
}
}
@@ -162,11 +155,7 @@ void QTechniqueFilter::removeMatch(QFilterKey *filterKey)
{
Q_ASSERT(filterKey);
Q_D(QTechniqueFilter);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey);
- change->setPropertyName("matchAll");
- d->notifyObservers(change);
- }
+ d->updateNode(filterKey, "matchAll", Qt3DCore::PropertyValueRemoved);
d->m_matchList.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -192,11 +181,7 @@ void QTechniqueFilter::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -207,11 +192,7 @@ void QTechniqueFilter::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QTechniqueFilter);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
diff --git a/src/render/framegraph/qviewport.cpp b/src/render/framegraph/qviewport.cpp
index 539e02d65..34716c5b5 100644
--- a/src/render/framegraph/qviewport.cpp
+++ b/src/render/framegraph/qviewport.cpp
@@ -40,7 +40,6 @@
#include "qviewport.h"
#include "qviewport_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qframegraphnodecreatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/framegraph/qwaitfence.cpp b/src/render/framegraph/qwaitfence.cpp
index 5195653ce..737f4e54d 100644
--- a/src/render/framegraph/qwaitfence.cpp
+++ b/src/render/framegraph/qwaitfence.cpp
@@ -56,8 +56,8 @@ QWaitFencePrivate::QWaitFencePrivate()
}
/*!
- \class QWaitFence
-
+ \class Qt3DRender::QWaitFence
+ \inmodule Qt3DRender
\brief FrameGraphNode used to wait for a fence in the graphics command
stream to become signaled.
@@ -98,7 +98,7 @@ QWaitFence::~QWaitFence()
become signaled. This is false by default.
*/
/*!
- \property QWaitFence::waitOnCPU
+ \property Qt3DRender::QWaitFence::waitOnCPU
Specifies whether the CPU should be block while waiting for the fence to
become signaled. This is false by default.
@@ -125,7 +125,7 @@ void QWaitFence::setWaitOnCPU(bool waitOnCPU)
to become signaled.
*/
/*!
- \property QWaitFence::timeout
+ \property Qt3DRender::QWaitFence::timeout
Specifies the maximum amount of time in nanoseconds to wait for the fence
to become signaled.
@@ -157,7 +157,7 @@ QWaitFence::QWaitFence(QWaitFencePrivate &dd, Qt3DCore::QNode *parent)
are supported.
*/
/*!
- \property QWaitFence::handleType
+ \property Qt3DRender::QWaitFence::handleType
Specifies the type of handle being used. Currently only OpenGL Fence ids
are supported.
@@ -183,7 +183,7 @@ void QWaitFence::setHandleType(QWaitFence::HandleType type)
Holds the underlying fence handle wrapped in a variant.
*/
/*!
- \property QWaitFence::handle
+ \property Qt3DRender::QWaitFence::handle
Holds the underlying fence handle wrapped in a QVariant.
*/
diff --git a/src/render/framegraph/rendercapture.cpp b/src/render/framegraph/rendercapture.cpp
index 166294889..68d62b6a5 100644
--- a/src/render/framegraph/rendercapture.cpp
+++ b/src/render/framegraph/rendercapture.cpp
@@ -70,16 +70,23 @@ QRenderCaptureRequest RenderCapture::takeCaptureRequest()
return m_requestedCaptures.takeFirst();
}
-void RenderCapture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void RenderCapture::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("renderCaptureRequest")) {
- requestCapture(propertyChange->value().value<QRenderCaptureRequest>());
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
+ const QRenderCapture *node = qobject_cast<const QRenderCapture *>(frontEnd);
+ if (!node)
+ return;
+
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const QRenderCapturePrivate *d = static_cast<const QRenderCapturePrivate *>(QFrameGraphNodePrivate::get(node));
+ const auto newPendingsCaptures = std::move(d->m_pendingRequests);
+ if (newPendingsCaptures.size() > 0) {
+ m_requestedCaptures.append(newPendingsCaptures);
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
- FrameGraphNode::sceneChangeEvent(e);
+
+ if (firstTime)
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
// called by render thread
diff --git a/src/render/framegraph/rendercapture_p.h b/src/render/framegraph/rendercapture_p.h
index 71fa01ec1..4560c525d 100644
--- a/src/render/framegraph/rendercapture_p.h
+++ b/src/render/framegraph/rendercapture_p.h
@@ -68,8 +68,7 @@ public:
void addRenderCapture(int captureId, const QImage &image);
void sendRenderCaptures();
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
diff --git a/src/render/framegraph/renderpassfilternode.cpp b/src/render/framegraph/renderpassfilternode.cpp
index e3da1e36d..bcec38fb6 100644
--- a/src/render/framegraph/renderpassfilternode.cpp
+++ b/src/render/framegraph/renderpassfilternode.cpp
@@ -42,9 +42,6 @@
#include "qrenderpassfilter.h"
#include <Qt3DRender/private/qrenderpassfilter_p.h>
#include <Qt3DRender/qparameter.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -58,16 +55,33 @@ RenderPassFilter::RenderPassFilter()
{
}
-void RenderPassFilter::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void RenderPassFilter::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderPassFilterData>>(change);
- const auto &data = typedChange->data;
- m_filters = data.matchIds;
- m_parameterPack.clear();
- m_parameterPack.setParameters(data.parameterIds);
+ const QRenderPassFilter *node = qobject_cast<const QRenderPassFilter *>(frontEnd);
+ if (!node)
+ return;
+
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (firstTime)
+ m_parameterPack.clear();
+
+ auto parameters = qIdsForNodes(node->parameters());
+ std::sort(std::begin(parameters), std::end(parameters));
+ if (m_parameterPack.parameters() != parameters) {
+ m_parameterPack.setParameters(parameters);
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ auto filterIds = qIdsForNodes(node->matchAny());
+ std::sort(std::begin(filterIds), std::end(filterIds));
+ if (m_filters != filterIds) {
+ m_filters = filterIds;
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
}
+
QVector<Qt3DCore::QNodeId> RenderPassFilter::filters() const
{
return m_filters;
@@ -89,40 +103,6 @@ QVector<Qt3DCore::QNodeId> RenderPassFilter::parameters() const
return m_parameterPack.parameters();
}
-void RenderPassFilter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
-
- switch (e->type()) {
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("match")) {
- appendFilter(change->addedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (change->propertyName() == QByteArrayLiteral("parameter")) {
- m_parameterPack.appendParameter(change->addedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- break;
- }
-
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("match")) {
- removeFilter(change->removedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (change->propertyName() == QByteArrayLiteral("parameter")) {
- m_parameterPack.removeParameter(change->removedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- break;
- }
-
- default:
- break;
- }
- FrameGraphNode::sceneChangeEvent(e);
-}
-
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/framegraph/renderpassfilternode_p.h b/src/render/framegraph/renderpassfilternode_p.h
index 398d42049..157a162bb 100644
--- a/src/render/framegraph/renderpassfilternode_p.h
+++ b/src/render/framegraph/renderpassfilternode_p.h
@@ -76,11 +76,9 @@ public:
QVector<Qt3DCore::QNodeId> parameters() const;
void appendFilter(Qt3DCore::QNodeId criterionId);
void removeFilter(Qt3DCore::QNodeId criterionId);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DCore::QNodeId> m_filters;
ParameterPack m_parameterPack;
};
diff --git a/src/render/framegraph/rendersurfaceselector.cpp b/src/render/framegraph/rendersurfaceselector.cpp
index 16a1199b5..a1e639df5 100644
--- a/src/render/framegraph/rendersurfaceselector.cpp
+++ b/src/render/framegraph/rendersurfaceselector.cpp
@@ -40,7 +40,6 @@
#include "rendersurfaceselector_p.h"
#include <Qt3DRender/qrendersurfaceselector.h>
#include <Qt3DRender/private/qrendersurfaceselector_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <QtGui/qwindow.h>
#include <QtGui/qscreen.h>
@@ -73,6 +72,7 @@ namespace Render {
RenderSurfaceSelector::RenderSurfaceSelector()
: FrameGraphNode(FrameGraphNode::Surface)
+ , m_surfaceObj(nullptr)
, m_surface(nullptr)
, m_width(0)
, m_height(0)
@@ -80,57 +80,48 @@ RenderSurfaceSelector::RenderSurfaceSelector()
{
}
-void RenderSurfaceSelector::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void RenderSurfaceSelector::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderSurfaceSelectorData>>(change);
- const auto &data = typedChange->data;
- m_surface = surfaceFromQObject(data.surface);
- m_renderTargetSize = data.externalRenderTargetSize;
- m_devicePixelRatio = data.surfacePixelRatio;
+ const QRenderSurfaceSelector *node = qobject_cast<const QRenderSurfaceSelector *>(frontEnd);
+ if (!node)
+ return;
- if (m_surface && m_surface->surfaceClass() == QSurface::Window) {
- QWindow *window = static_cast<QWindow *>(m_surface);
- m_width = window->width();
- m_height = window->height();
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (node->surface() != m_surfaceObj) {
+ m_surfaceObj = node->surface();
+ m_surface = surfaceFromQObject(m_surfaceObj);
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
-}
-void RenderSurfaceSelector::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- qCDebug(Render::Framegraph) << Q_FUNC_INFO;
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("surface")) {
- m_surface = surfaceFromQObject(propertyChange->value().value<QObject *>());
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("externalRenderTargetSize")) {
- setRenderTargetSize(propertyChange->value().toSize());
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("width")) {
- m_width = propertyChange->value().toInt();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("height")) {
- m_height = propertyChange->value().toInt();
+ if (m_surface && m_surface->surfaceClass() == QSurface::Window) {
+ QWindow *window = static_cast<QWindow *>(m_surface);
+ if (window->width() != m_width) {
+ m_width = window->width();
markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("surfacePixelRatio")) {
- m_devicePixelRatio = propertyChange->value().toFloat();
+ }
+ if (window->height() != m_height) {
+ m_height = window->height();
markDirty(AbstractRenderer::FrameGraphDirty);
}
}
- FrameGraphNode::sceneChangeEvent(e);
+
+ if (node->externalRenderTargetSize() != m_renderTargetSize) {
+ m_renderTargetSize = node->externalRenderTargetSize();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ if (node->surfacePixelRatio() != m_devicePixelRatio) {
+ m_devicePixelRatio = node->surfacePixelRatio();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
}
QSize RenderSurfaceSelector::renderTargetSize() const
{
if (m_renderTargetSize.isValid())
return m_renderTargetSize;
- {
- SurfaceLocker lock(m_surface);
- if (lock.isSurfaceValid() && m_surface && m_surface->size().isValid())
- return m_surface->size();
- }
- return QSize();
+ return QSize(m_width, m_height);
}
} // namespace Render
diff --git a/src/render/framegraph/rendersurfaceselector_p.h b/src/render/framegraph/rendersurfaceselector_p.h
index 74863aa36..f1a139e84 100644
--- a/src/render/framegraph/rendersurfaceselector_p.h
+++ b/src/render/framegraph/rendersurfaceselector_p.h
@@ -68,7 +68,7 @@ public:
QSize renderTargetSize() const;
void setRenderTargetSize(const QSize &size) { m_renderTargetSize = size; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
QSurface *surface() const { return m_surface; }
inline int width() const Q_DECL_NOTHROW { return m_width; }
@@ -76,8 +76,7 @@ public:
inline float devicePixelRatio() const Q_DECL_NOTHROW { return m_devicePixelRatio; }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
+ QObject *m_surfaceObj;
QSurface *m_surface;
QSize m_renderTargetSize;
int m_width;
diff --git a/src/render/framegraph/rendertargetselectornode.cpp b/src/render/framegraph/rendertargetselectornode.cpp
index 615608bd2..614a749a5 100644
--- a/src/render/framegraph/rendertargetselectornode.cpp
+++ b/src/render/framegraph/rendertargetselectornode.cpp
@@ -43,7 +43,6 @@
#include <Qt3DRender/qrendertargetselector.h>
#include <Qt3DRender/private/qrendertargetselector_p.h>
#include <Qt3DRender/qrendertarget.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DRender/qrendertargetoutput.h>
@@ -59,29 +58,24 @@ RenderTargetSelector::RenderTargetSelector() :
{
}
-void RenderTargetSelector::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void RenderTargetSelector::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderTargetSelectorData>>(change);
- const auto &data = typedChange->data;
- m_renderTargetUuid = data.targetId;
- m_outputs = data.outputs;
-}
+ const QRenderTargetSelector *node = qobject_cast<const QRenderTargetSelector *>(frontEnd);
+ if (!node)
+ return;
-void RenderTargetSelector::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- qCDebug(Render::Framegraph) << Q_FUNC_INFO;
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("target")) {
- m_renderTargetUuid = propertyChange->value().value<QNodeId>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("outputs")) {
- m_outputs = propertyChange->value().value<QVector<Qt3DRender::QRenderTargetOutput::AttachmentPoint> >();
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const QNodeId renderTargetId = qIdForNode(node->target());
+ if (renderTargetId != m_renderTargetUuid) {
+ m_renderTargetUuid = renderTargetId;
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ if (node->outputs() != m_outputs) {
+ m_outputs = node->outputs();
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
- FrameGraphNode::sceneChangeEvent(e);
}
} // namespace Render
diff --git a/src/render/framegraph/rendertargetselectornode_p.h b/src/render/framegraph/rendertargetselectornode_p.h
index 81ac8a3d3..232ee9ecc 100644
--- a/src/render/framegraph/rendertargetselectornode_p.h
+++ b/src/render/framegraph/rendertargetselectornode_p.h
@@ -66,14 +66,12 @@ class RenderTargetSelector : public FrameGraphNode
public:
RenderTargetSelector();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
Qt3DCore::QNodeId renderTargetUuid() const { return m_renderTargetUuid; }
QVector<QRenderTargetOutput::AttachmentPoint> outputs() const { return m_outputs; }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_renderTargetUuid;
QVector<QRenderTargetOutput::AttachmentPoint> m_outputs;
};
diff --git a/src/render/framegraph/sortpolicy.cpp b/src/render/framegraph/sortpolicy.cpp
index b81d1f6cb..5c61966c0 100644
--- a/src/render/framegraph/sortpolicy.cpp
+++ b/src/render/framegraph/sortpolicy.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "sortpolicy_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/qsortpolicy_p.h>
QT_BEGIN_NAMESPACE
@@ -53,18 +52,19 @@ SortPolicy::SortPolicy()
{
}
-void SortPolicy::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void SortPolicy::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("sortTypes")) {
- auto sortTypesInt = propertyChange->value().value<QVector<int>>();
- m_sortTypes.clear();
- transformVector(sortTypesInt, m_sortTypes);
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
+ const QSortPolicy *node = qobject_cast<const QSortPolicy *>(frontEnd);
+ if (!node)
+ return;
+
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const auto sortTypes = node->sortTypes();
+ if (sortTypes != m_sortTypes) {
+ m_sortTypes = sortTypes;
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
- FrameGraphNode::sceneChangeEvent(e);
}
QVector<QSortPolicy::SortType> SortPolicy::sortTypes() const
@@ -72,14 +72,6 @@ QVector<QSortPolicy::SortType> SortPolicy::sortTypes() const
return m_sortTypes;
}
-void SortPolicy::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
-{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QSortPolicyData>>(change);
- const QSortPolicyData &data = typedChange->data;
- m_sortTypes = data.sortTypes;
-}
-
} // namepace Render
} // namespace Qt3DRender
diff --git a/src/render/framegraph/sortpolicy_p.h b/src/render/framegraph/sortpolicy_p.h
index ef928af7b..8d572ead7 100644
--- a/src/render/framegraph/sortpolicy_p.h
+++ b/src/render/framegraph/sortpolicy_p.h
@@ -65,13 +65,11 @@ class Q_AUTOTEST_EXPORT SortPolicy : public FrameGraphNode
public:
SortPolicy();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
QVector<Qt3DRender::QSortPolicy::SortType> sortTypes() const;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DRender::QSortPolicy::SortType> m_sortTypes;
};
diff --git a/src/render/framegraph/statesetnode.cpp b/src/render/framegraph/statesetnode.cpp
index 96551684e..c494c572b 100644
--- a/src/render/framegraph/statesetnode.cpp
+++ b/src/render/framegraph/statesetnode.cpp
@@ -43,9 +43,6 @@
#include <Qt3DRender/private/qrenderstateset_p.h>
#include <Qt3DRender/private/genericstate_p.h>
#include <Qt3DRender/private/renderstateset_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -68,40 +65,20 @@ QVector<QNodeId> StateSetNode::renderStates() const
return m_renderStates;
}
-void StateSetNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void StateSetNode::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderStateSetData>>(change);
- const auto &data = typedChange->data;
- for (const auto &stateId : qAsConst(data.renderStateIds))
- addRenderState(stateId);
-}
+ const QRenderStateSet *node = qobject_cast<const QRenderStateSet *>(frontEnd);
+ if (!node)
+ return;
-void StateSetNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("renderState")) {
- addRenderState(change->addedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- break;
- }
-
- case PropertyValueRemoved: {
- const auto propertyChange = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("renderState")) {
- removeRenderState(propertyChange->removedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- break;
- }
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
- default:
- break;
+ auto stateIds = qIdsForNodes(node->renderStates());
+ std::sort(std::begin(stateIds), std::end(stateIds));
+ if (m_renderStates != stateIds) {
+ m_renderStates = stateIds;
+ markDirty(AbstractRenderer::FrameGraphDirty);
}
- FrameGraphNode::sceneChangeEvent(e);
}
void StateSetNode::addRenderState(QNodeId renderStateId)
diff --git a/src/render/framegraph/statesetnode_p.h b/src/render/framegraph/statesetnode_p.h
index d33e118cb..5081f3215 100644
--- a/src/render/framegraph/statesetnode_p.h
+++ b/src/render/framegraph/statesetnode_p.h
@@ -68,13 +68,13 @@ public:
inline bool hasRenderStates() const { return !m_renderStates.empty(); }
QVector<Qt3DCore::QNodeId> renderStates() const;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+
protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
void addRenderState(Qt3DCore::QNodeId renderStateId);
void removeRenderState(Qt3DCore::QNodeId renderStateId);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
QVector<Qt3DCore::QNodeId> m_renderStates;
};
diff --git a/src/render/framegraph/subtreeenabler.cpp b/src/render/framegraph/subtreeenabler.cpp
new file mode 100644
index 000000000..4d912dc1d
--- /dev/null
+++ b/src/render/framegraph/subtreeenabler.cpp
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "subtreeenabler_p.h"
+#include <Qt3DRender/private/qsubtreeenabler_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+SubtreeEnabler::SubtreeEnabler()
+ : FrameGraphNode(FrameGraphNode::SubtreeEnabler, FrameGraphNode::ReadWrite)
+{
+}
+
+void SubtreeEnabler::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
+{
+ const QSubtreeEnabler *node = qobject_cast<const QSubtreeEnabler *>(frontEnd);
+ if (!node)
+ return;
+
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const auto enablement = node->enablement();
+ if (enablement != m_enablement) {
+ m_enablement = enablement;
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+}
+
+} //Render
+
+} //Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/core/qsceneobserverinterface_p.h b/src/render/framegraph/subtreeenabler_p.h
index 7ffc20742..2de8dfabf 100644
--- a/src/core/qsceneobserverinterface_p.h
+++ b/src/render/framegraph/subtreeenabler_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2019 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DCORE_QSCENEOBSERVERINTERFACE_P_H
-#define QT3DCORE_QSCENEOBSERVERINTERFACE_P_H
+#ifndef SUBTREEENABLER_P_H
+#define SUBTREEENABLER_P_H
//
// W A R N I N G
@@ -51,32 +51,32 @@
// We mean it.
//
-#include <Qt3DCore/qscenechange.h>
-
-#include <Qt3DCore/private/qt3dcore_global_p.h>
+#include <Qt3DRender/qsubtreeenabler.h>
+#include <Qt3DRender/private/framegraphnode_p.h>
QT_BEGIN_NAMESPACE
-namespace Qt3DCore {
+namespace Qt3DRender {
-class QChangeArbiter;
+namespace Render {
-class Q_3DCORE_PRIVATE_EXPORT QSceneObserverInterface
+class Q_AUTOTEST_EXPORT SubtreeEnabler : public FrameGraphNode
{
public:
- virtual ~QSceneObserverInterface();
+ SubtreeEnabler();
+ QSubtreeEnabler::Enablement enablement() const { return m_enablement; }
+ void sendDisableToFrontend();
-private:
- virtual void sceneNodeAdded(QSceneChangePtr &e) = 0;
- virtual void sceneNodeRemoved(QSceneChangePtr &e) = 0;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
- friend class QChangeArbiter;
+private:
+ QSubtreeEnabler::Enablement m_enablement = QSubtreeEnabler::Persistent;
};
-} // Qt3D
+} //Render
-QT_END_NAMESPACE
+} //Qt3DRender
-Q_DECLARE_METATYPE(Qt3DCore::QSceneObserverInterface *) // LCOV_EXCL_LINE
+QT_END_NAMESPACE
-#endif // QT3DCORE_QSCENEOBSERVERINTERFACE_P_H
+#endif // SUBTREEENABLER_P_H
diff --git a/src/render/framegraph/techniquefilternode.cpp b/src/render/framegraph/techniquefilternode.cpp
index 8816984ee..b3b70e9cb 100644
--- a/src/render/framegraph/techniquefilternode.cpp
+++ b/src/render/framegraph/techniquefilternode.cpp
@@ -43,9 +43,6 @@
#include <Qt3DRender/private/qtechniquefilter_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/qparameter.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -59,13 +56,30 @@ TechniqueFilter::TechniqueFilter()
{
}
-void TechniqueFilter::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void TechniqueFilter::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QTechniqueFilterData>>(change);
- const auto &data = typedChange->data;
- m_filters = data.matchIds;
- m_parameterPack.setParameters(data.parameterIds);
+ const QTechniqueFilter *node = qobject_cast<const QTechniqueFilter *>(frontEnd);
+ if (!node)
+ return;
+
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (firstTime)
+ m_parameterPack.clear();
+
+ auto parameters = qIdsForNodes(node->parameters());
+ std::sort(std::begin(parameters), std::end(parameters));
+ if (m_parameterPack.parameters() != parameters) {
+ m_parameterPack.setParameters(parameters);
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ auto filterIds = qIdsForNodes(node->matchAll());
+ std::sort(std::begin(filterIds), std::end(filterIds));
+ if (m_filters != filterIds) {
+ m_filters = filterIds;
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
}
QVector<Qt3DCore::QNodeId> TechniqueFilter::parameters() const
@@ -89,39 +103,6 @@ void TechniqueFilter::removeFilter(Qt3DCore::QNodeId criterionId)
m_filters.removeOne(criterionId);
}
-void TechniqueFilter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("matchAll")) {
- appendFilter(change->addedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (change->propertyName() == QByteArrayLiteral("parameter")) {
- m_parameterPack.appendParameter(change->addedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- break;
- }
-
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("matchAll")) {
- removeFilter(change->removedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (change->propertyName() == QByteArrayLiteral("parameter")) {
- m_parameterPack.removeParameter(change->removedNodeId());
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- break;
- }
-
- default:
- break;
- }
- FrameGraphNode::sceneChangeEvent(e);
-}
-
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/framegraph/techniquefilternode_p.h b/src/render/framegraph/techniquefilternode_p.h
index d7e6c1508..e424e37e5 100644
--- a/src/render/framegraph/techniquefilternode_p.h
+++ b/src/render/framegraph/techniquefilternode_p.h
@@ -79,11 +79,9 @@ public:
QVector<Qt3DCore::QNodeId> parameters() const;
QVector<Qt3DCore::QNodeId> filters() const;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
void appendFilter(Qt3DCore::QNodeId criterionId);
void removeFilter(Qt3DCore::QNodeId criterionId);
diff --git a/src/render/framegraph/viewportnode.cpp b/src/render/framegraph/viewportnode.cpp
index b3b53b0f9..5396d97e2 100644
--- a/src/render/framegraph/viewportnode.cpp
+++ b/src/render/framegraph/viewportnode.cpp
@@ -40,7 +40,6 @@
#include "viewportnode_p.h"
#include <Qt3DRender/qviewport.h>
#include <Qt3DRender/private/qviewport_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -59,16 +58,28 @@ ViewportNode::ViewportNode()
{
}
-void ViewportNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+
+void ViewportNode::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QViewportData>>(change);
- const auto &data = typedChange->data;
- m_xMin = data.normalizedRect.x();
- m_xMax = data.normalizedRect.width();
- m_yMin = data.normalizedRect.y();
- m_yMax = data.normalizedRect.height();
- m_gamma = data.gamma;
+ const QViewport *node = qobject_cast<const QViewport *>(frontEnd);
+ if (!node)
+ return;
+
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const QRectF oldRect(m_xMin, m_yMin, m_xMax, m_yMax);
+ if (oldRect != node->normalizedRect()) {
+ m_xMin = node->normalizedRect().x();
+ m_yMin = node->normalizedRect().y();
+ m_xMax = node->normalizedRect().width();
+ m_yMax = node->normalizedRect().height();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+
+ if (node->gamma() != m_gamma) {
+ m_gamma = node->gamma();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
}
float ViewportNode::xMin() const
@@ -118,25 +129,6 @@ void ViewportNode::setGamma(float gamma)
m_gamma = gamma;
}
-void ViewportNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("normalizedRect")) {
- QRectF normalizedRect = propertyChange->value().toRectF();
- setXMin(normalizedRect.x());
- setYMin(normalizedRect.y());
- setXMax(normalizedRect.width());
- setYMax(normalizedRect.height());
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("gamma")) {
- setGamma(propertyChange->value().toFloat());
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- }
- FrameGraphNode::sceneChangeEvent(e);
-}
-
QRectF ViewportNode::computeViewport(const QRectF &childViewport, const ViewportNode *parentViewport)
{
QRectF vp(parentViewport->xMin(),
diff --git a/src/render/framegraph/viewportnode_p.h b/src/render/framegraph/viewportnode_p.h
index 799b9b3dc..3e291a9da 100644
--- a/src/render/framegraph/viewportnode_p.h
+++ b/src/render/framegraph/viewportnode_p.h
@@ -84,13 +84,11 @@ public:
float gamma() const;
void setGamma(float gamma);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
static QRectF computeViewport(const QRectF &childViewport, const ViewportNode *parentViewport);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
float m_xMin;
float m_yMin;
float m_xMax;
diff --git a/src/render/framegraph/waitfence.cpp b/src/render/framegraph/waitfence.cpp
index 9480fb7a0..829730bbf 100644
--- a/src/render/framegraph/waitfence.cpp
+++ b/src/render/framegraph/waitfence.cpp
@@ -39,7 +39,6 @@
#include "waitfence_p.h"
#include <Qt3DRender/private/qwaitfence_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
//
// W A R N I N G
@@ -71,33 +70,30 @@ WaitFence::~WaitFence()
{
}
-void WaitFence::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void WaitFence::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("handle")) {
- m_data.handle = propertyChange->value();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("handleType")) {
- m_data.handleType = static_cast<QWaitFence::HandleType>(propertyChange->value().toInt());
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("timeout")) {
- m_data.timeout = propertyChange->value().value<quint64>();
- markDirty(AbstractRenderer::FrameGraphDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("waitOnCPU")) {
- m_data.waitOnCPU = propertyChange->value().toBool();
- markDirty(AbstractRenderer::FrameGraphDirty);
- }
- }
- FrameGraphNode::sceneChangeEvent(e);
-}
+ const QWaitFence *node = qobject_cast<const QWaitFence *>(frontEnd);
+ if (!node)
+ return;
-void WaitFence::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- FrameGraphNode::initializeFromPeer(change);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QWaitFenceData>>(change);
- const QWaitFenceData &data = typedChange->data;
- m_data = data;
+ FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (node->handleType() != m_data.handleType) {
+ m_data.handleType = node->handleType();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+ if (node->handle() != m_data.handle) {
+ m_data.handle = node->handle();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+ if (node->timeout() != m_data.timeout) {
+ m_data.timeout = node->timeout();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
+ if (node->waitOnCPU() != m_data.waitOnCPU) {
+ m_data.waitOnCPU = node->waitOnCPU();
+ markDirty(AbstractRenderer::FrameGraphDirty);
+ }
}
} // namespace Render
diff --git a/src/render/framegraph/waitfence_p.h b/src/render/framegraph/waitfence_p.h
index dd48e0efa..811fc80a2 100644
--- a/src/render/framegraph/waitfence_p.h
+++ b/src/render/framegraph/waitfence_p.h
@@ -68,11 +68,9 @@ public:
~WaitFence();
inline QWaitFenceData data() const { return m_data; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
-
QWaitFenceData m_data;
};
diff --git a/src/render/frontend/qcamera.cpp b/src/render/frontend/qcamera.cpp
index c2df23c6d..b0fd16182 100644
--- a/src/render/frontend/qcamera.cpp
+++ b/src/render/frontend/qcamera.cpp
@@ -235,7 +235,7 @@ void QCameraPrivate::updateViewMatrixAndTransform(bool doEmit)
* \qmlmethod void Qt3D.Render::Camera::viewEntity(Entity entity)
*
* Rotates and moves the camera so that it's viewCenter is the center of the entity's bounding volume
- * and the entire entity fits in the view port.
+ * and the entire \a entity fits in the view port.
*
* \note Only works if the lens is in perspective projection mode.
* \sa Qt3D.Render::Camera::projectionType
@@ -281,6 +281,18 @@ void QCameraPrivate::updateViewMatrixAndTransform(bool doEmit)
*/
/*!
+ * \qmlproperty Qt3DRender::QCameraLens QCamera::lens
+ * Holds the CameraLens component of the camera.
+ * \since 5.14
+ */
+
+/*!
+ * \qmlproperty Qt3DCore::QTransform QCamera::transform
+ * Holds the Transform component of the camera.
+ * \since 5.14
+ */
+
+/*!
* \qmlproperty real Qt3D.Render::Camera::fieldOfView
* Holds the current vertical field of view of the camera in degrees.
*
@@ -423,6 +435,18 @@ void QCameraPrivate::updateViewMatrixAndTransform(bool doEmit)
*/
/*!
+ * \property QCamera::lens
+ * Holds the Qt3DRender::QCameraLens component of the camera.
+ * \since 5.14
+ */
+
+/*!
+ * \property QCamera::transform
+ * Holds the Qt3DCore::QTransform component of the camera.
+ * \since 5.14
+ */
+
+/*!
* \property QCamera::fieldOfView
* Holds the current vertical field of view in degrees.
*
diff --git a/src/render/frontend/qcamera.h b/src/render/frontend/qcamera.h
index 7d717972e..b57f57957 100644
--- a/src/render/frontend/qcamera.h
+++ b/src/render/frontend/qcamera.h
@@ -80,6 +80,9 @@ class Q_3DRENDERSHARED_EXPORT QCamera : public Qt3DCore::QEntity
Q_PROPERTY(QVector3D viewVector READ viewVector NOTIFY viewVectorChanged)
Q_PROPERTY(QMatrix4x4 viewMatrix READ viewMatrix NOTIFY viewMatrixChanged)
+ Q_PROPERTY(Qt3DRender::QCameraLens *lens READ lens CONSTANT REVISION 14)
+ Q_PROPERTY(Qt3DCore::QTransform *transform READ transform CONSTANT REVISION 14)
+
public:
explicit QCamera(QNode *parent = nullptr);
~QCamera();
diff --git a/src/render/frontend/qcameralens.cpp b/src/render/frontend/qcameralens.cpp
index 6c3598fe2..cf30b714a 100644
--- a/src/render/frontend/qcameralens.cpp
+++ b/src/render/frontend/qcameralens.cpp
@@ -228,13 +228,17 @@ QCameraLensPrivate::QCameraLensPrivate()
{
}
+
void QCameraLens::viewAll(Qt3DCore::QNodeId cameraId)
{
Q_D(QCameraLens);
if (d->m_projectionType == PerspectiveProjection) {
QVariant v;
v.setValue(cameraId);
- d->m_pendingViewAllCommand = sendCommand(QLatin1Literal("QueryRootBoundingVolume"), v);
+ d->m_pendingViewAllCommand = {QLatin1String("QueryRootBoundingVolume"),
+ v,
+ id()};
+ d->update();
}
}
@@ -245,7 +249,10 @@ void QCameraLens::viewEntity(Qt3DCore::QNodeId entityId, Qt3DCore::QNodeId camer
QVector<Qt3DCore::QNodeId> ids = {entityId, cameraId};
QVariant v;
v.setValue(ids);
- d->m_pendingViewAllCommand = sendCommand(QLatin1Literal("QueryEntityBoundingVolume"), v);
+ d->m_pendingViewAllCommand = {QLatin1String("QueryEntityBoundingVolume"),
+ v,
+ id()};
+ d->update();
}
}
@@ -253,7 +260,7 @@ void QCameraLensPrivate::processViewAllCommand(Qt3DCore::QNodeCommand::CommandId
const QVariant &data)
{
Q_Q(QCameraLens);
- if (m_pendingViewAllCommand != commandId)
+ if (!m_pendingViewAllCommand || m_pendingViewAllCommand.commandId != commandId)
return;
QVector<float> boundingVolumeData = data.value< QVector<float> >();
@@ -262,7 +269,7 @@ void QCameraLensPrivate::processViewAllCommand(Qt3DCore::QNodeCommand::CommandId
QVector3D center(boundingVolumeData[0], boundingVolumeData[1], boundingVolumeData[2]);
float radius = boundingVolumeData[3];
Q_EMIT q->viewSphere(center, radius);
- m_pendingViewAllCommand = Qt3DCore::QNodeCommand::CommandId();
+ m_pendingViewAllCommand = {};
}
/*!
@@ -641,7 +648,7 @@ void QCameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
case Qt3DCore::CommandRequested: {
Qt3DCore::QNodeCommandPtr command = qSharedPointerCast<Qt3DCore::QNodeCommand>(change);
- if (command->name() == QLatin1Literal("ViewAll"))
+ if (command->name() == QLatin1String("ViewAll"))
d->processViewAllCommand(command->inReplyTo(), command->data());
}
break;
diff --git a/src/render/frontend/qcameralens_p.h b/src/render/frontend/qcameralens_p.h
index 111ab6522..5c5a6a42a 100644
--- a/src/render/frontend/qcameralens_p.h
+++ b/src/render/frontend/qcameralens_p.h
@@ -57,14 +57,31 @@
#include "qcameralens.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
-
#include <QtGui/qmatrix4x4.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+struct CameraLensCommand
+{
+ QString name;
+ QVariant data;
+ Qt3DCore::QNodeCommand::CommandId commandId;
+
+ inline operator bool() const { return !name.isEmpty(); }
+};
+
+inline bool operator ==(const CameraLensCommand &a, const CameraLensCommand &b) noexcept
+{
+ return a.name == b.name && a.data == b.data && a.commandId == b.commandId;
+}
+
+inline bool operator !=(const CameraLensCommand &a, const CameraLensCommand &b) noexcept
+{
+ return !(a == b);
+}
+
class Q_3DRENDERSHARED_PRIVATE_EXPORT QCameraLensPrivate : public Qt3DCore::QComponentPrivate
{
public:
@@ -106,7 +123,7 @@ public:
float m_exposure;
- Qt3DCore::QNodeCommand::CommandId m_pendingViewAllCommand;
+ CameraLensCommand m_pendingViewAllCommand;
void processViewAllCommand(Qt3DCore::QNodeCommand::CommandId commandId, const QVariant &data);
private:
diff --git a/src/render/frontend/qcomputecommand.cpp b/src/render/frontend/qcomputecommand.cpp
index e7acdd94a..dfd9c2033 100644
--- a/src/render/frontend/qcomputecommand.cpp
+++ b/src/render/frontend/qcomputecommand.cpp
@@ -39,7 +39,6 @@
#include "qcomputecommand.h"
#include "qcomputecommand_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -93,15 +92,15 @@ namespace Qt3DRender {
*/
/*!
- \qmlproperty QComputeCommand::runType
+ \qmlproperty enumeration ComputeCommand::runType
Specifies whether the compute command should be performed every frame or
manually triggered.
- \value Continuous Compute command is executed everyframe. This is the
+ \value ComputeCommand.Continuous Compute command is executed everyframe. This is the
default.
- \value Manual CompouteCommand is executed for a given number of frames and
+ \value ComputeCommand.Manual CompouteCommand is executed for a given number of frames and
then the component disables itself.
*/
@@ -156,10 +155,7 @@ QComputeCommandPrivate::QComputeCommandPrivate()
void QComputeCommandPrivate::setFrameCount(int frameCount)
{
m_frameCount = frameCount;
- const auto propertyChange = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id);
- propertyChange->setPropertyName("frameCount");
- propertyChange->setValue(m_frameCount);
- notifyObservers(propertyChange);
+ update();
}
/*!
diff --git a/src/render/frontend/qlevelofdetail.cpp b/src/render/frontend/qlevelofdetail.cpp
index a3596a518..52f5ea7c9 100644
--- a/src/render/frontend/qlevelofdetail.cpp
+++ b/src/render/frontend/qlevelofdetail.cpp
@@ -39,8 +39,8 @@
#include "qlevelofdetail.h"
#include "qlevelofdetail_p.h"
+#include "qlevelofdetailswitch.h"
#include "qcamera.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -55,6 +55,34 @@ QLevelOfDetailPrivate::QLevelOfDetailPrivate()
{
}
+void QLevelOfDetailPrivate::setCurrentIndex(int currentIndex)
+{
+ Q_Q(QLevelOfDetail);
+ if (m_currentIndex != currentIndex) {
+ m_currentIndex = currentIndex;
+ emit q->currentIndexChanged(m_currentIndex);
+
+ // TODO use derived pimpl
+ QLevelOfDetailSwitch *qswitch = qobject_cast<QLevelOfDetailSwitch *>(q);
+ if (qswitch) {
+ int entityIndex = 0;
+ const auto entities = q->entities();
+ if (entities.size()) {
+ // only work on the first entity, LOD should not be shared
+ Qt3DCore::QEntity *entity = entities.front();
+ const auto childNodes = entity->childNodes();
+ for (Qt3DCore::QNode *childNode : childNodes) {
+ Qt3DCore::QEntity *childEntity = qobject_cast<Qt3DCore::QEntity *>(childNode);
+ if (childEntity) {
+ childEntity->setEnabled(entityIndex == currentIndex);
+ entityIndex++;
+ }
+ }
+ }
+ }
+ }
+}
+
/*!
\class Qt3DRender::QLevelOfDetail
\inmodule Qt3DRender
@@ -317,18 +345,9 @@ Qt3DCore::QNodeCreatedChangeBasePtr QLevelOfDetail::createNodeCreationChange() c
return creationChange;
}
-/*! \internal */
-void QLevelOfDetail::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QLevelOfDetail::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- Q_D(QLevelOfDetail);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated) {
- if (e->propertyName() == QByteArrayLiteral("currentIndex")) {
- int ndx = e->value().value<int>();
- d->m_currentIndex = ndx;
- emit currentIndexChanged(ndx);
- }
- }
}
QCamera *QLevelOfDetail::camera() const
@@ -367,10 +386,7 @@ int QLevelOfDetail::currentIndex() const
void QLevelOfDetail::setCurrentIndex(int currentIndex)
{
Q_D(QLevelOfDetail);
- if (d->m_currentIndex != currentIndex) {
- d->m_currentIndex = currentIndex;
- emit currentIndexChanged(d->m_currentIndex);
- }
+ d->setCurrentIndex(currentIndex);
}
QLevelOfDetail::ThresholdType QLevelOfDetail::thresholdType() const
diff --git a/src/render/frontend/qlevelofdetail.h b/src/render/frontend/qlevelofdetail.h
index 308a4d3c0..81fcf3235 100644
--- a/src/render/frontend/qlevelofdetail.h
+++ b/src/render/frontend/qlevelofdetail.h
@@ -97,6 +97,7 @@ Q_SIGNALS:
protected:
explicit QLevelOfDetail(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr);
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/render/frontend/qlevelofdetail_p.h b/src/render/frontend/qlevelofdetail_p.h
index 7b409e4ca..429128427 100644
--- a/src/render/frontend/qlevelofdetail_p.h
+++ b/src/render/frontend/qlevelofdetail_p.h
@@ -72,6 +72,8 @@ public:
void _q_radiusChanged(float radius);
void _q_centerChanged(const QVector3D &center);
+ virtual void setCurrentIndex(int currentIndex);
+
QCamera *m_camera;
int m_currentIndex;
QLevelOfDetail::ThresholdType m_thresholdType;
diff --git a/src/render/frontend/qlevelofdetailswitch.cpp b/src/render/frontend/qlevelofdetailswitch.cpp
index 845fdd5a6..ec658b172 100644
--- a/src/render/frontend/qlevelofdetailswitch.cpp
+++ b/src/render/frontend/qlevelofdetailswitch.cpp
@@ -41,7 +41,6 @@
#include "qlevelofdetail_p.h"
#include "qglobal.h"
#include <Qt3DCore/QEntity>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -101,32 +100,9 @@ QLevelOfDetailSwitch::QLevelOfDetailSwitch(QLevelOfDetailPrivate &dd, QNode *par
{
}
-/*! \internal */
-void QLevelOfDetailSwitch::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QLevelOfDetailSwitch::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- Q_D(QLevelOfDetail);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated) {
- if (e->propertyName() == QByteArrayLiteral("currentIndex")) {
- int ndx = e->value().value<int>();
- d->m_currentIndex = ndx;
- emit currentIndexChanged(ndx);
-
- int entityIndex = 0;
- const auto entities = this->entities();
- for (Qt3DCore::QEntity *entity : entities) {
- const auto childNodes = entity->childNodes();
- for (Qt3DCore::QNode *childNode : childNodes) {
- Qt3DCore::QEntity *childEntity = qobject_cast<Qt3DCore::QEntity *>(childNode);
- if (childEntity) {
- childEntity->setEnabled(entityIndex == ndx);
- entityIndex++;
- }
- }
- break; // only work on the first entity, LOD should not be shared
- }
- }
- }
}
} // namespace Qt3DRender
diff --git a/src/render/frontend/qlevelofdetailswitch.h b/src/render/frontend/qlevelofdetailswitch.h
index 1615d16e6..a292f7eb3 100644
--- a/src/render/frontend/qlevelofdetailswitch.h
+++ b/src/render/frontend/qlevelofdetailswitch.h
@@ -56,6 +56,7 @@ public:
protected:
explicit QLevelOfDetailSwitch(QLevelOfDetailPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/render/frontend/qlevelofdetailswitch_p.h b/src/render/frontend/qlevelofdetailswitch_p.h
new file mode 100644
index 000000000..51321c986
--- /dev/null
+++ b/src/render/frontend/qlevelofdetailswitch_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QLEVELOFDETAILSWITCH_P_H
+#define QT3DRENDER_QLEVELOFDETAILSWITCH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qlevelofdetail_p.h>
+#include <Qt3DRender/qlevelofdetailswitch.h>
+
+#include <QVector3D>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class Q_3DRENDERSHARED_PRIVATE_EXPORT QLevelOfDetailSwitchPrivate : public QLevelOfDetailPrivate
+{
+public:
+ QLevelOfDetailSwitchPrivate();
+
+ Q_DECLARE_PUBLIC(QLevelOfDetailSwitch)
+
+ void setCurrentIndex(int currentIndex) override;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QLEVELOFDETAILSWITCH_P_H
diff --git a/src/render/frontend/qpickingsettings.cpp b/src/render/frontend/qpickingsettings.cpp
index 84e61e141..0c858aef2 100644
--- a/src/render/frontend/qpickingsettings.cpp
+++ b/src/render/frontend/qpickingsettings.cpp
@@ -199,7 +199,7 @@ void QPickingSettings::setPickMethod(QPickingSettings::PickMethod pickMethod)
* \value NearestPick Only the nearest entity to picking ray origin intersected by the picking ray
* is picked (default).
* \value AllPicks All entities that intersect the picking ray are picked.
- * \value PriorityPick Selects the entity whose object picker has the highest
+ * \value NearestPriorityPick Selects the entity whose object picker has the highest
* value. If several object pickers have the same priority, the closest one on
* the ray is selected.
*
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index c60488e16..72f114481 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -41,7 +41,6 @@
#include "qrenderaspect_p.h"
#include <Qt3DRender/private/nodemanagers_p.h>
-#include <Qt3DRender/private/texturedatamanager_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/scenemanager_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
@@ -67,6 +66,7 @@
#include <Qt3DRender/qshaderdata.h>
#include <Qt3DRender/qrenderstateset.h>
#include <Qt3DRender/qnodraw.h>
+#include <Qt3DRender/qnopicking.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/qbuffer.h>
@@ -90,10 +90,13 @@
#include <Qt3DRender/qblitframebuffer.h>
#include <Qt3DRender/qsetfence.h>
#include <Qt3DRender/qwaitfence.h>
+#include <Qt3DRender/qshaderimage.h>
+#include <Qt3DRender/qsubtreeenabler.h>
#include <Qt3DCore/qarmature.h>
#include <Qt3DCore/qjoint.h>
#include <Qt3DCore/qskeletonloader.h>
+#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/private/cameraselectornode_p.h>
#include <Qt3DRender/private/layerfilternode_p.h>
#include <Qt3DRender/private/cameralens_p.h>
@@ -112,10 +115,10 @@
#include <Qt3DRender/private/renderlogging_p.h>
#include <Qt3DRender/private/nodefunctor_p.h>
#include <Qt3DRender/private/framegraphnode_p.h>
-#include <Qt3DRender/private/loadtexturedatajob_p.h>
#include <Qt3DRender/private/textureimage_p.h>
#include <Qt3DRender/private/statesetnode_p.h>
#include <Qt3DRender/private/nodraw_p.h>
+#include <Qt3DRender/private/nopicking_p.h>
#include <Qt3DRender/private/vsyncframeadvanceservice_p.h>
#include <Qt3DRender/private/attribute_p.h>
#include <Qt3DRender/private/buffer_p.h>
@@ -147,6 +150,7 @@
#include <Qt3DRender/private/memorybarrier_p.h>
#include <Qt3DRender/private/shaderbuilder_p.h>
#include <Qt3DRender/private/blitframebuffer_p.h>
+#include <Qt3DRender/private/subtreeenabler_p.h>
#include <Qt3DRender/private/armature_p.h>
#include <Qt3DRender/private/skeleton_p.h>
#include <Qt3DRender/private/joint_p.h>
@@ -154,6 +158,7 @@
#include <Qt3DRender/private/proximityfilter_p.h>
#include <Qt3DRender/private/setfence_p.h>
#include <Qt3DRender/private/waitfence_p.h>
+#include <Qt3DRender/private/shaderimage_p.h>
#include <private/qrenderpluginfactory_p.h>
#include <private/qrenderplugin_p.h>
@@ -228,6 +233,12 @@ QRenderAspectPrivate *QRenderAspectPrivate::findPrivate(Qt3DCore::QAspectEngine
return nullptr;
}
+void QRenderAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const
+{
+ Render::BackendNode *renderBackend = static_cast<Render::BackendNode *>(backend);
+ renderBackend->syncFromFrontEnd(node, firstTime);
+}
+
/*! \internal */
void QRenderAspectPrivate::registerBackendTypes()
{
@@ -238,77 +249,80 @@ void QRenderAspectPrivate::registerBackendTypes()
qRegisterMetaType<Qt3DRender::QFrameGraphNode *>();
qRegisterMetaType<Qt3DRender::QCamera*>();
qRegisterMetaType<Qt3DRender::QShaderProgram*>();
+ qRegisterMetaType<Qt3DRender::QViewport*>();
qRegisterMetaType<Qt3DCore::QJoint*>();
- q->registerBackendType<Qt3DCore::QEntity>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers));
- q->registerBackendType<Qt3DCore::QTransform>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer));
+ registerBackendType<Qt3DCore::QEntity, true>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers));
+ registerBackendType<Qt3DCore::QTransform, true>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer));
- q->registerBackendType<Qt3DRender::QCameraLens>(QSharedPointer<Render::CameraLensFunctor>::create(m_renderer, q));
- q->registerBackendType<QLayer>(QSharedPointer<Render::NodeFunctor<Render::Layer, Render::LayerManager> >::create(m_renderer));
- q->registerBackendType<QLevelOfDetail>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
- q->registerBackendType<QLevelOfDetailSwitch>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
- q->registerBackendType<QSceneLoader>(QSharedPointer<Render::RenderSceneFunctor>::create(m_renderer, m_nodeManagers->sceneManager()));
- q->registerBackendType<QRenderTarget>(QSharedPointer<Render::NodeFunctor<Render::RenderTarget, Render::RenderTargetManager> >::create(m_renderer));
- q->registerBackendType<QRenderTargetOutput>(QSharedPointer<Render::NodeFunctor<Render::RenderTargetOutput, Render::AttachmentManager> >::create(m_renderer));
- q->registerBackendType<QRenderSettings>(QSharedPointer<Render::RenderSettingsFunctor>::create(m_renderer));
- q->registerBackendType<QRenderState>(QSharedPointer<Render::NodeFunctor<Render::RenderStateNode, Render::RenderStateManager> >::create(m_renderer));
+ registerBackendType<Qt3DRender::QCameraLens, true>(QSharedPointer<Render::CameraLensFunctor>::create(m_renderer, q));
+ registerBackendType<QLayer, true>(QSharedPointer<Render::NodeFunctor<Render::Layer, Render::LayerManager> >::create(m_renderer));
+ registerBackendType<QLevelOfDetail, true>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
+ registerBackendType<QLevelOfDetailSwitch, true>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
+ registerBackendType<QSceneLoader, true>(QSharedPointer<Render::RenderSceneFunctor>::create(m_renderer, m_nodeManagers->sceneManager()));
+ registerBackendType<QRenderTarget, true>(QSharedPointer<Render::NodeFunctor<Render::RenderTarget, Render::RenderTargetManager> >::create(m_renderer));
+ registerBackendType<QRenderTargetOutput, true>(QSharedPointer<Render::NodeFunctor<Render::RenderTargetOutput, Render::AttachmentManager> >::create(m_renderer));
+ registerBackendType<QRenderSettings, true>(QSharedPointer<Render::RenderSettingsFunctor>::create(m_renderer));
+ registerBackendType<QRenderState, true>(QSharedPointer<Render::NodeFunctor<Render::RenderStateNode, Render::RenderStateManager> >::create(m_renderer));
// Geometry + Compute
- q->registerBackendType<QAttribute>(QSharedPointer<Render::NodeFunctor<Render::Attribute, Render::AttributeManager> >::create(m_renderer));
- q->registerBackendType<QBuffer>(QSharedPointer<Render::BufferFunctor>::create(m_renderer, m_nodeManagers->bufferManager()));
- q->registerBackendType<QComputeCommand>(QSharedPointer<Render::NodeFunctor<Render::ComputeCommand, Render::ComputeCommandManager> >::create(m_renderer));
- q->registerBackendType<QGeometry>(QSharedPointer<Render::NodeFunctor<Render::Geometry, Render::GeometryManager> >::create(m_renderer));
- q->registerBackendType<QGeometryRenderer>(QSharedPointer<Render::GeometryRendererFunctor>::create(m_renderer, m_nodeManagers->geometryRendererManager()));
- q->registerBackendType<Qt3DCore::QArmature>(QSharedPointer<Render::NodeFunctor<Render::Armature, Render::ArmatureManager>>::create(m_renderer));
- q->registerBackendType<Qt3DCore::QAbstractSkeleton>(QSharedPointer<Render::SkeletonFunctor>::create(m_renderer, m_nodeManagers->skeletonManager(), m_nodeManagers->jointManager()));
- q->registerBackendType<Qt3DCore::QJoint>(QSharedPointer<Render::JointFunctor>::create(m_renderer, m_nodeManagers->jointManager(), m_nodeManagers->skeletonManager()));
+ registerBackendType<QAttribute, true>(QSharedPointer<Render::NodeFunctor<Render::Attribute, Render::AttributeManager> >::create(m_renderer));
+ registerBackendType<QBuffer, true>(QSharedPointer<Render::BufferFunctor>::create(m_renderer, m_nodeManagers->bufferManager()));
+ registerBackendType<QComputeCommand, true>(QSharedPointer<Render::NodeFunctor<Render::ComputeCommand, Render::ComputeCommandManager> >::create(m_renderer));
+ registerBackendType<QGeometry, true>(QSharedPointer<Render::NodeFunctor<Render::Geometry, Render::GeometryManager> >::create(m_renderer));
+ registerBackendType<QGeometryRenderer, true>(QSharedPointer<Render::GeometryRendererFunctor>::create(m_renderer, m_nodeManagers->geometryRendererManager()));
+ registerBackendType<Qt3DCore::QArmature, true>(QSharedPointer<Render::NodeFunctor<Render::Armature, Render::ArmatureManager>>::create(m_renderer));
+ registerBackendType<Qt3DCore::QAbstractSkeleton, true>(QSharedPointer<Render::SkeletonFunctor>::create(m_renderer, m_nodeManagers->skeletonManager(), m_nodeManagers->jointManager()));
+ registerBackendType<Qt3DCore::QJoint, true>(QSharedPointer<Render::JointFunctor>::create(m_renderer, m_nodeManagers->jointManager(), m_nodeManagers->skeletonManager()));
// Textures
- q->registerBackendType<QAbstractTexture>(QSharedPointer<Render::TextureFunctor>::create(m_renderer, m_nodeManagers->textureManager()));
- q->registerBackendType<QAbstractTextureImage>(QSharedPointer<Render::TextureImageFunctor>::create(m_renderer,
- m_nodeManagers->textureImageManager(),
- m_nodeManagers->textureImageDataManager()));
+ registerBackendType<QAbstractTexture, true>(QSharedPointer<Render::TextureFunctor>::create(m_renderer, m_nodeManagers->textureManager()));
+ registerBackendType<QAbstractTextureImage, true>(QSharedPointer<Render::TextureImageFunctor>::create(m_renderer,
+ m_nodeManagers->textureImageManager()));
// Material system
- q->registerBackendType<QEffect>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer));
- q->registerBackendType<QFilterKey>(QSharedPointer<Render::NodeFunctor<Render::FilterKey, Render::FilterKeyManager> >::create(m_renderer));
- q->registerBackendType<QAbstractLight>(QSharedPointer<Render::RenderLightFunctor>::create(m_renderer, m_nodeManagers));
- q->registerBackendType<QEnvironmentLight>(QSharedPointer<Render::NodeFunctor<Render::EnvironmentLight, Render::EnvironmentLightManager> >::create(m_renderer));
- q->registerBackendType<QMaterial>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer));
- q->registerBackendType<QParameter>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer));
- q->registerBackendType<QRenderPass>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer));
- q->registerBackendType<QShaderData>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers));
- q->registerBackendType<QShaderProgram>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer));
- q->registerBackendType<QShaderProgramBuilder>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer));
- q->registerBackendType<QTechnique>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers));
+ registerBackendType<QEffect, true>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer));
+ registerBackendType<QFilterKey, true>(QSharedPointer<Render::NodeFunctor<Render::FilterKey, Render::FilterKeyManager> >::create(m_renderer));
+ registerBackendType<QAbstractLight, true>(QSharedPointer<Render::RenderLightFunctor>::create(m_renderer, m_nodeManagers));
+ registerBackendType<QEnvironmentLight, true>(QSharedPointer<Render::NodeFunctor<Render::EnvironmentLight, Render::EnvironmentLightManager> >::create(m_renderer));
+ registerBackendType<QMaterial, true>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer));
+ registerBackendType<QParameter, true>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer));
+ registerBackendType<QRenderPass, true>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer));
+ registerBackendType<QShaderData, true>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers));
+ registerBackendType<QShaderProgram, true>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer));
+ registerBackendType<QShaderProgramBuilder, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer));
+ registerBackendType<QTechnique, true>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers));
+ registerBackendType<QShaderImage, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderImage, Render::ShaderImageManager>>::create(m_renderer));
// Framegraph
- q->registerBackendType<QFrameGraphNode>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrameGraphNode, QFrameGraphNode> >::create(m_renderer));
- q->registerBackendType<QCameraSelector>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::CameraSelector, QCameraSelector> >::create(m_renderer));
- q->registerBackendType<QClearBuffers>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ClearBuffers, QClearBuffers> >::create(m_renderer));
- q->registerBackendType<QDispatchCompute>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::DispatchCompute, QDispatchCompute> >::create(m_renderer));
- q->registerBackendType<QFrustumCulling>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrustumCulling, QFrustumCulling> >::create(m_renderer));
- q->registerBackendType<QLayerFilter>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::LayerFilterNode, QLayerFilter> >::create(m_renderer));
- q->registerBackendType<QNoDraw>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::NoDraw, QNoDraw> >::create(m_renderer));
- q->registerBackendType<QRenderPassFilter>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderPassFilter, QRenderPassFilter> >::create(m_renderer));
- q->registerBackendType<QRenderStateSet>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::StateSetNode, QRenderStateSet> >::create(m_renderer));
- q->registerBackendType<QRenderSurfaceSelector>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderSurfaceSelector, QRenderSurfaceSelector> >::create(m_renderer));
- q->registerBackendType<QRenderTargetSelector>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderTargetSelector, QRenderTargetSelector> >::create(m_renderer));
- q->registerBackendType<QSortPolicy>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SortPolicy, QSortPolicy> >::create(m_renderer));
- q->registerBackendType<QTechniqueFilter>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::TechniqueFilter, QTechniqueFilter> >::create(m_renderer));
- q->registerBackendType<QViewport>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ViewportNode, QViewport> >::create(m_renderer));
- q->registerBackendType<QRenderCapture>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderCapture, QRenderCapture> >::create(m_renderer));
- q->registerBackendType<QBufferCapture>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BufferCapture, QBufferCapture> >::create(m_renderer));
- q->registerBackendType<QMemoryBarrier>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::MemoryBarrier, QMemoryBarrier> >::create(m_renderer));
- q->registerBackendType<QProximityFilter>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ProximityFilter, QProximityFilter> >::create(m_renderer));
- q->registerBackendType<QBlitFramebuffer>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BlitFramebuffer, QBlitFramebuffer> >::create(m_renderer));
- q->registerBackendType<QSetFence>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SetFence, QSetFence> >::create(m_renderer));
- q->registerBackendType<QWaitFence>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::WaitFence, QWaitFence> >::create(m_renderer));
+ registerBackendType<QFrameGraphNode, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrameGraphNode, QFrameGraphNode> >::create(m_renderer));
+ registerBackendType<QCameraSelector, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::CameraSelector, QCameraSelector> >::create(m_renderer));
+ registerBackendType<QClearBuffers, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ClearBuffers, QClearBuffers> >::create(m_renderer));
+ registerBackendType<QDispatchCompute, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::DispatchCompute, QDispatchCompute> >::create(m_renderer));
+ registerBackendType<QFrustumCulling, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrustumCulling, QFrustumCulling> >::create(m_renderer));
+ registerBackendType<QLayerFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::LayerFilterNode, QLayerFilter> >::create(m_renderer));
+ registerBackendType<QNoDraw, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::NoDraw, QNoDraw> >::create(m_renderer));
+ registerBackendType<QRenderPassFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderPassFilter, QRenderPassFilter> >::create(m_renderer));
+ registerBackendType<QRenderStateSet, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::StateSetNode, QRenderStateSet> >::create(m_renderer));
+ registerBackendType<QRenderSurfaceSelector, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderSurfaceSelector, QRenderSurfaceSelector> >::create(m_renderer));
+ registerBackendType<QRenderTargetSelector, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderTargetSelector, QRenderTargetSelector> >::create(m_renderer));
+ registerBackendType<QSortPolicy, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SortPolicy, QSortPolicy> >::create(m_renderer));
+ registerBackendType<QTechniqueFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::TechniqueFilter, QTechniqueFilter> >::create(m_renderer));
+ registerBackendType<QViewport, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ViewportNode, QViewport> >::create(m_renderer));
+ registerBackendType<QRenderCapture, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::RenderCapture, QRenderCapture> >::create(m_renderer));
+ registerBackendType<QBufferCapture, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BufferCapture, QBufferCapture> >::create(m_renderer));
+ registerBackendType<QMemoryBarrier, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::MemoryBarrier, QMemoryBarrier> >::create(m_renderer));
+ registerBackendType<QProximityFilter, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::ProximityFilter, QProximityFilter> >::create(m_renderer));
+ registerBackendType<QBlitFramebuffer, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::BlitFramebuffer, QBlitFramebuffer> >::create(m_renderer));
+ registerBackendType<QSetFence, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SetFence, QSetFence> >::create(m_renderer));
+ registerBackendType<QWaitFence, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::WaitFence, QWaitFence> >::create(m_renderer));
+ registerBackendType<QNoPicking, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::NoPicking, QNoPicking> >::create(m_renderer));
+ registerBackendType<QSubtreeEnabler, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SubtreeEnabler, QSubtreeEnabler> >::create(m_renderer));
// Picking
- q->registerBackendType<QObjectPicker>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer));
- q->registerBackendType<QRayCaster>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer));
- q->registerBackendType<QScreenRayCaster>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer));
+ registerBackendType<QObjectPicker, true>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer));
+ registerBackendType<QRayCaster, true>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer));
+ registerBackendType<QScreenRayCaster, true>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer));
// Plugins
for (const QString &plugin : qAsConst(m_pluginConfig))
@@ -356,6 +370,7 @@ void QRenderAspectPrivate::unregisterBackendTypes()
unregisterBackendType<QShaderProgram>();
unregisterBackendType<QShaderProgramBuilder>();
unregisterBackendType<QTechnique>();
+ unregisterBackendType<QShaderImage>();
// Framegraph
unregisterBackendType<QCameraSelector>();
@@ -376,6 +391,7 @@ void QRenderAspectPrivate::unregisterBackendTypes()
unregisterBackendType<QMemoryBarrier>();
unregisterBackendType<QSetFence>();
unregisterBackendType<QWaitFence>();
+ unregisterBackendType<QSubtreeEnabler>();
// Picking
unregisterBackendType<QObjectPicker>();
@@ -387,13 +403,6 @@ void QRenderAspectPrivate::unregisterBackendTypes()
plugin->unregisterBackendTypes(q);
}
-void QRenderAspectPrivate::registerBackendType(const QMetaObject &obj,
- const QBackendNodeMapperPtr &functor)
-{
- Q_Q(QRenderAspect);
- q->registerBackendType(obj, functor);
-}
-
/*!
* The constructor creates a new QRenderAspect::QRenderAspect instance with the
* specified \a parent.
@@ -432,9 +441,9 @@ void QRenderAspectPrivate::renderInitialize(QOpenGLContext *context)
}
/*! \internal */
-void QRenderAspectPrivate::renderSynchronous(bool blocking)
+void QRenderAspectPrivate::renderSynchronous(bool swapBuffers)
{
- m_renderer->doRender(blocking);
+ m_renderer->doRender(swapBuffers);
}
/*
@@ -473,34 +482,16 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time)
if (d->m_renderer->isRunning() && d->m_renderer->settings()) {
Render::NodeManagers *manager = d->m_renderer->nodeManagers();
- QAspectJobPtr textureLoadingSync = d->m_renderer->syncTextureLoadingJob();
- textureLoadingSync->removeDependency(QWeakPointer<QAspectJob>());
-
- // Launch texture generator jobs
- const QVector<QTextureImageDataGeneratorPtr> pendingImgGen = manager->textureImageDataManager()->pendingGenerators();
- for (const QTextureImageDataGeneratorPtr &imgGen : pendingImgGen) {
- auto loadTextureJob = Render::LoadTextureDataJobPtr::create(imgGen);
- textureLoadingSync->addDependency(loadTextureJob);
- loadTextureJob->setNodeManagers(manager);
- jobs.append(loadTextureJob);
- }
- const QVector<QTextureGeneratorPtr> pendingTexGen = manager->textureDataManager()->pendingGenerators();
- for (const QTextureGeneratorPtr &texGen : pendingTexGen) {
- auto loadTextureJob = Render::LoadTextureDataJobPtr::create(texGen);
- textureLoadingSync->addDependency(loadTextureJob);
- loadTextureJob->setNodeManagers(manager);
- jobs.append(loadTextureJob);
- }
+ QAspectJobPtr loadingJobSync = d->m_renderer->syncLoadingJobs();
+ loadingJobSync->removeDependency(QWeakPointer<QAspectJob>());
- // Launch skeleton loader jobs. We join on the syncTextureLoadingJob for now
- // which should likely be renamed to something more generic or we introduce
- // another synchronizing job for skeleton loading
+ // Launch skeleton loader jobs once all loading jobs have completed.
const QVector<Render::HSkeleton> skeletonsToLoad =
manager->skeletonManager()->takeDirtySkeletons(Render::SkeletonManager::SkeletonDataDirty);
for (const auto &skeletonHandle : skeletonsToLoad) {
auto loadSkeletonJob = Render::LoadSkeletonJobPtr::create(skeletonHandle);
loadSkeletonJob->setNodeManagers(manager);
- textureLoadingSync->addDependency(loadSkeletonJob);
+ loadingJobSync->addDependency(loadSkeletonJob);
jobs.append(loadSkeletonJob);
}
@@ -551,7 +542,7 @@ void QRenderAspect::onEngineStartup()
Render::NodeManagers *managers = d->m_renderer->nodeManagers();
Render::Entity *rootEntity = managers->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
- d->m_renderer->setSceneRoot(d, rootEntity);
+ d->m_renderer->setSceneRoot(rootEntity);
}
void QRenderAspect::onRegistered()
diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h
index 28a9b2453..b4cb0812c 100644
--- a/src/render/frontend/qrenderaspect_p.h
+++ b/src/render/frontend/qrenderaspect_p.h
@@ -86,14 +86,15 @@ public:
static QRenderAspectPrivate* findPrivate(Qt3DCore::QAspectEngine *engine);
+ void syncDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QBackendNode *backend, bool firstTime) const override;
+
void registerBackendTypes();
void unregisterBackendTypes();
void loadSceneParsers();
void loadRenderPlugin(const QString &pluginName);
void renderInitialize(QOpenGLContext *context);
- void renderSynchronous(bool blocking = false);
+ void renderSynchronous(bool swapBuffers = true);
void renderShutdown();
- void registerBackendType(const QMetaObject &, const Qt3DCore::QBackendNodeMapperPtr &functor);
QVector<Qt3DCore::QAspectJobPtr> createGeometryRendererJobs();
Render::NodeManagers *m_nodeManagers;
diff --git a/src/render/frontend/qrenderplugin_p.h b/src/render/frontend/qrenderplugin_p.h
index c34dabefc..4aa0ec697 100644
--- a/src/render/frontend/qrenderplugin_p.h
+++ b/src/render/frontend/qrenderplugin_p.h
@@ -51,6 +51,7 @@
#include <private/qt3drender_global_p.h>
#include <Qt3DCore/qbackendnode.h>
+#include <Qt3DCore/private/qabstractaspect_p.h>
#include <Qt3DRender/qrenderaspect.h>
#include <QtCore/qobject.h>
@@ -75,6 +76,10 @@ protected:
{
aspect->registerBackendType(obj, functor);
}
+ void registerBackendType(QRenderAspect *aspect, const QMetaObject &obj, const Qt3DCore::QBackendNodeMapperPtr &functor, bool supportsSyncing)
+ {
+ Qt3DCore::QAbstractAspectPrivate::get(aspect)->registerBackendType(obj, functor, supportsSyncing);
+ }
void unregisterBackendType(QRenderAspect *aspect, const QMetaObject &obj)
{
aspect->unregisterBackendType(obj);
diff --git a/src/render/frontend/qrendersettings.cpp b/src/render/frontend/qrendersettings.cpp
index 23f88eb10..5916c4b73 100644
--- a/src/render/frontend/qrendersettings.cpp
+++ b/src/render/frontend/qrendersettings.cpp
@@ -96,28 +96,33 @@ void QRenderSettingsPrivate::init()
q, SLOT(_q_onWorldSpaceToleranceChanged(float)));
}
+void QRenderSettingsPrivate::invalidateFrame()
+{
+ update();
+}
+
/*! \internal */
void QRenderSettingsPrivate::_q_onPickingMethodChanged(QPickingSettings::PickMethod pickMethod)
{
- notifyPropertyChange("pickMethod", pickMethod);
+ notifyPropertyChange("pickMethod", pickMethod);// TODOSYNC
}
/*! \internal */
void QRenderSettingsPrivate::_q_onPickResultModeChanged(QPickingSettings::PickResultMode pickResultMode)
{
- notifyPropertyChange("pickResultMode", pickResultMode);
+ notifyPropertyChange("pickResultMode", pickResultMode);// TODOSYNC
}
/*! \internal */
void QRenderSettingsPrivate::_q_onFaceOrientationPickingModeChanged(QPickingSettings::FaceOrientationPickingMode faceOrientationPickingMode)
{
- notifyPropertyChange("faceOrientationPickingMode", faceOrientationPickingMode);
+ notifyPropertyChange("faceOrientationPickingMode", faceOrientationPickingMode);// TODOSYNC
}
/*! \internal */
void QRenderSettingsPrivate::_q_onWorldSpaceToleranceChanged(float worldSpaceTolerance)
{
- notifyPropertyChange("pickWorldSpaceTolerance", worldSpaceTolerance);
+ notifyPropertyChange("pickWorldSpaceTolerance", worldSpaceTolerance);// TODOSYNC
}
QRenderSettings::QRenderSettings(Qt3DCore::QNode *parent)
diff --git a/src/render/frontend/qrendersettings_p.h b/src/render/frontend/qrendersettings_p.h
index f91397bd2..88f91810a 100644
--- a/src/render/frontend/qrendersettings_p.h
+++ b/src/render/frontend/qrendersettings_p.h
@@ -71,6 +71,8 @@ public:
QFrameGraphNode *m_activeFrameGraph;
QRenderSettings::RenderPolicy m_renderPolicy;
+ void invalidateFrame();
+
void _q_onPickingMethodChanged(QPickingSettings::PickMethod pickMethod);
void _q_onPickResultModeChanged(QPickingSettings::PickResultMode pickResultMode);
void _q_onFaceOrientationPickingModeChanged(QPickingSettings::FaceOrientationPickingMode faceOrientationPickingMode);
diff --git a/src/render/frontend/qrendertarget.cpp b/src/render/frontend/qrendertarget.cpp
index 9aa9c8c41..57eecd795 100644
--- a/src/render/frontend/qrendertarget.cpp
+++ b/src/render/frontend/qrendertarget.cpp
@@ -40,9 +40,6 @@
#include "qrendertarget.h"
#include "qrendertarget_p.h"
#include "qrendertargetoutput.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -126,11 +123,7 @@ void QRenderTarget::addOutput(QRenderTargetOutput *output)
if (!output->parent())
output->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), output);
- change->setPropertyName("output");
- d->notifyObservers(change);
- }
+ d->updateNode(output, "output", Qt3DCore::PropertyValueAdded);
}
}
@@ -141,11 +134,7 @@ void QRenderTarget::removeOutput(QRenderTargetOutput *output)
{
Q_D(QRenderTarget);
- if (output && d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), output);
- change->setPropertyName("output");
- d->notifyObservers(change);
- }
+ d->updateNode(output, "output", Qt3DCore::PropertyValueRemoved);
d->m_outputs.removeOne(output);
// Remove bookkeeping connection
d->unregisterDestructionHelper(output);
diff --git a/src/render/frontend/qrendertargetoutput.cpp b/src/render/frontend/qrendertargetoutput.cpp
index 14ac9c817..8c0d86134 100644
--- a/src/render/frontend/qrendertargetoutput.cpp
+++ b/src/render/frontend/qrendertargetoutput.cpp
@@ -40,7 +40,6 @@
#include "qrendertargetoutput.h"
#include "qrendertargetoutput_p.h"
#include "qtexture.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/frontend/render-frontend.pri b/src/render/frontend/render-frontend.pri
index 1fafcc294..0153e9c97 100644
--- a/src/render/frontend/render-frontend.pri
+++ b/src/render/frontend/render-frontend.pri
@@ -9,6 +9,7 @@ HEADERS += \
$$PWD/qlevelofdetail.h \
$$PWD/qlevelofdetail_p.h \
$$PWD/qlevelofdetailswitch.h \
+ $$PWD/qlevelofdetailswitch_p.h \
$$PWD/qrendertarget.h \
$$PWD/qrendertarget_p.h \
$$PWD/sphere_p.h \
diff --git a/src/render/geometry/armature.cpp b/src/render/geometry/armature.cpp
index 15a26c9ec..6e417952b 100644
--- a/src/render/geometry/armature.cpp
+++ b/src/render/geometry/armature.cpp
@@ -36,7 +36,8 @@
#include "armature_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qarmature.h>
+#include <Qt3DCore/qabstractskeleton.h>
#include <Qt3DCore/private/qarmature_p.h>
@@ -52,32 +53,20 @@ Armature::Armature()
{
}
-void Armature::cleanup()
+void Armature::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- m_skeletonId = Qt3DCore::QNodeId();
- setEnabled(false);
-}
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QArmature *node = qobject_cast<const QArmature *>(frontEnd);
+ if (!node)
+ return;
-void Armature::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<QNodeCreatedChange<QArmatureData>>(change);
- m_skeletonId = typedChange->data.skeletonId;
+ m_skeletonId = node->skeleton() ? node->skeleton()->id() : QNodeId{};
}
-void Armature::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void Armature::cleanup()
{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("skeleton"))
- m_skeletonId = change->value().value<QNodeId>();
- break;
- }
-
- default:
- break;
- }
- QBackendNode::sceneChangeEvent(e);
+ m_skeletonId = Qt3DCore::QNodeId();
+ setEnabled(false);
}
} // namespace Render
diff --git a/src/render/geometry/armature_p.h b/src/render/geometry/armature_p.h
index 3e6e52a3f..39baa4a79 100644
--- a/src/render/geometry/armature_p.h
+++ b/src/render/geometry/armature_p.h
@@ -63,7 +63,7 @@ class Q_AUTOTEST_EXPORT Armature : public BackendNode
public:
Armature();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void cleanup();
Qt3DCore::QNodeId skeletonId() const { return m_skeletonId; }
@@ -73,8 +73,6 @@ public:
const UniformValue &skinningPaletteUniform() const { return m_skinningPaletteUniform; }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_skeletonId;
UniformValue m_skinningPaletteUniform;
};
diff --git a/src/render/geometry/attribute.cpp b/src/render/geometry/attribute.cpp
index bc6b27851..de44c5fe3 100644
--- a/src/render/geometry/attribute.cpp
+++ b/src/render/geometry/attribute.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "attribute_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/private/qattribute_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
@@ -83,78 +82,54 @@ void Attribute::cleanup()
m_nameId = 0;
}
-void Attribute::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Attribute::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAttributeData>>(change);
- const auto &data = typedChange->data;
- m_bufferId = data.bufferId;
- m_name = data.name;
- m_nameId = StringToInt::lookupId(m_name);
- m_vertexBaseType = data.vertexBaseType;
- m_vertexSize = data.vertexSize;
- m_count = data.count;
- m_byteStride = data.byteStride;
- m_byteOffset = data.byteOffset;
- m_divisor = data.divisor;
- m_attributeType = data.attributeType;
- m_attributeDirty = true;
-}
-
-/*!
- \fn Qt3DRender::QAttribute::dataSizeChanged(uint vertexSize)
-
- The signal is emitted with \a vertexSize when the dataSize changes.
-
-*/
-/*!
- \fn Qt3DRender::QAttribute::dataTypeChanged(Qt3DRender::QAttribute::VertexBaseType vertexBaseType)
-
- The signal is emitted with \a vertexBaseType when the dataType changed.
-*/
-void Attribute::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyUpdated: {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- QByteArray propertyName = propertyChange->propertyName();
-
- if (propertyName == QByteArrayLiteral("name")) {
- m_name = propertyChange->value().toString();
- m_nameId = StringToInt::lookupId(m_name);
- m_attributeDirty = true;
- } else if (propertyName == QByteArrayLiteral("vertexBaseType")) {
- m_vertexBaseType = static_cast<QAttribute::VertexBaseType>(propertyChange->value().value<int>());
- m_attributeDirty = true;
- } else if (propertyName == QByteArrayLiteral("vertexSize")) {
- m_vertexSize = propertyChange->value().value<uint>();
- m_attributeDirty = true;
- } else if (propertyName == QByteArrayLiteral("count")) {
- m_count = propertyChange->value().value<uint>();
- m_attributeDirty = true;
- } else if (propertyName == QByteArrayLiteral("byteStride")) {
- m_byteStride = propertyChange->value().value<uint>();
- m_attributeDirty = true;
- } else if (propertyName == QByteArrayLiteral("byteOffset")) {
- m_byteOffset = propertyChange->value().value<uint>();
- m_attributeDirty = true;
- } else if (propertyName == QByteArrayLiteral("divisor")) {
- m_divisor = propertyChange->value().value<uint>();
- m_attributeDirty = true;
- } else if (propertyName == QByteArrayLiteral("attributeType")) {
- m_attributeType = static_cast<QAttribute::AttributeType>(propertyChange->value().value<int>());
- m_attributeDirty = true;
- } else if (propertyName == QByteArrayLiteral("buffer")) {
- m_bufferId = propertyChange->value().value<QNodeId>();
- m_attributeDirty = true;
- }
- markDirty(AbstractRenderer::AllDirty);
- break;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAttribute *node = qobject_cast<const QAttribute *>(frontEnd);
+ if (!node)
+ return;
+
+ m_attributeDirty = firstTime;
+ if (m_name != node->name()) {
+ m_name = node->name();
+ m_nameId = StringToInt::lookupId(m_name);
+ m_attributeDirty = true;
}
-
- default:
- break;
+ if (m_vertexBaseType != node->vertexBaseType()) {
+ m_vertexBaseType = node->vertexBaseType();
+ m_attributeDirty = true;
}
- BackendNode::sceneChangeEvent(e);
+ if (m_vertexSize != node->vertexSize()) {
+ m_vertexSize = node->vertexSize();
+ m_attributeDirty = true;
+ }
+ if (m_count != node->count()) {
+ m_count = node->count();
+ m_attributeDirty = true;
+ }
+ if (m_byteStride != node->byteStride()) {
+ m_byteStride = node->byteStride();
+ m_attributeDirty = true;
+ }
+ if (m_byteOffset != node->byteOffset()) {
+ m_byteOffset = node->byteOffset();
+ m_attributeDirty = true;
+ }
+ if (m_divisor != node->divisor()) {
+ m_divisor = node->divisor();
+ m_attributeDirty = true;
+ }
+ if (m_attributeType != node->attributeType()) {
+ m_attributeType = node->attributeType();
+ m_attributeDirty = true;
+ }
+ const auto bufferId = node->buffer() ? node->buffer()->id() : QNodeId{};
+ if (bufferId != m_bufferId) {
+ m_bufferId = bufferId;
+ m_attributeDirty = true;
+ }
+
+ markDirty(AbstractRenderer::AllDirty);
}
void Attribute::unsetDirty()
diff --git a/src/render/geometry/attribute_p.h b/src/render/geometry/attribute_p.h
index e01537605..4b47146e1 100644
--- a/src/render/geometry/attribute_p.h
+++ b/src/render/geometry/attribute_p.h
@@ -68,7 +68,7 @@ public:
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
inline Qt3DCore::QNodeId bufferId() const { return m_bufferId; }
inline QString name() const { return m_name; }
@@ -84,8 +84,6 @@ public:
void unsetDirty();
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_bufferId;
QString m_name;
int m_nameId;
diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp
index d60f89c7d..6db3bab44 100644
--- a/src/render/geometry/buffer.cpp
+++ b/src/render/geometry/buffer.cpp
@@ -88,15 +88,6 @@ void Buffer::executeFunctor()
m_data = (*m_functor)();
// Request data to be loaded
forceDataUpload();
-
- if (m_syncData) {
- // Send data back to the frontend
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("data");
- e->setValue(QVariant::fromValue(m_data));
- notifyObservers(e);
- }
}
//Called from th sendBufferJob
@@ -105,34 +96,6 @@ void Buffer::updateDataFromGPUToCPU(QByteArray data)
// Note: when this is called, data is what's currently in GPU memory
// so m_data shouldn't be reuploaded
m_data = data;
- // Send data back to the frontend
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("downloadedData");
- e->setValue(QVariant::fromValue(m_data));
- notifyObservers(e);
-}
-
-void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QBufferData>>(change);
- const auto &data = typedChange->data;
- m_data = data.data;
- m_usage = data.usage;
- m_syncData = data.syncData;
- m_access = data.access;
- m_bufferDirty = true;
-
- if (!m_data.isEmpty())
- forceDataUpload();
-
- m_functor = data.functor;
- Q_ASSERT(m_manager);
- if (m_functor)
- m_manager->addDirtyBuffer(peerId());
-
- m_manager->addBufferReference(peerId());
- markDirty(AbstractRenderer::BuffersDirty);
}
void Buffer::forceDataUpload()
@@ -145,40 +108,63 @@ void Buffer::forceDataUpload()
m_bufferUpdates.push_back(updateNewData);
}
-void Buffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void Buffer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- QByteArray propertyName = propertyChange->propertyName();
- if (propertyName == QByteArrayLiteral("data")) {
- QByteArray newData = propertyChange->value().toByteArray();
- bool dirty = m_data != newData;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QBuffer *node = qobject_cast<const QBuffer *>(frontEnd);
+ if (!node)
+ return;
+
+ if (firstTime && m_manager != nullptr) {
+ m_manager->addBufferReference(peerId());
+ m_bufferDirty = true;
+ }
+
+ m_syncData = node->isSyncData();
+ m_access = node->accessType();
+ if (m_usage != node->usage()) {
+ m_usage = node->usage();
+ m_bufferDirty = true;
+ }
+ {
+ QBufferDataGeneratorPtr newGenerator = node->dataGenerator();
+ bool dirty = (newGenerator && m_functor && !(*newGenerator == *m_functor)) ||
+ (newGenerator.isNull() && !m_functor.isNull()) ||
+ (!newGenerator.isNull() && m_functor.isNull());
+ m_bufferDirty |= dirty;
+ m_functor = newGenerator;
+ if (m_functor && m_manager != nullptr)
+ m_manager->addDirtyBuffer(peerId());
+ }
+ {
+ const QVariant v = node->property("QT3D_updateData");
+
+ // Make sure we record data if it's the first time we are called
+ // or if we have no partial updates
+ if (firstTime || !v.isValid()){
+ const QByteArray newData = node->data();
+ const bool dirty = m_data != newData;
m_bufferDirty |= dirty;
m_data = newData;
- if (dirty)
+
+ // Since frontend applies partial updates to its m_data
+ // if we enter this code block, there's no problem in actually
+ // ignoring the partial updates
+ if (v.isValid())
+ const_cast<QBuffer *>(node)->setProperty("QT3D_updateData", {});
+
+ if (dirty && !m_data.isEmpty())
forceDataUpload();
- } else if (propertyName == QByteArrayLiteral("updateData")) {
- Qt3DRender::QBufferUpdate updateData = propertyChange->value().value<Qt3DRender::QBufferUpdate>();
+ } else if (v.isValid()) {
+ // Apply partial updates and record them to allow partial upload to the GPU
+ Qt3DRender::QBufferUpdate updateData = v.value<Qt3DRender::QBufferUpdate>();
m_data.replace(updateData.offset, updateData.data.size(), updateData.data);
m_bufferUpdates.push_back(updateData);
m_bufferDirty = true;
- } else if (propertyName == QByteArrayLiteral("usage")) {
- m_usage = static_cast<QBuffer::UsageType>(propertyChange->value().value<int>());
- m_bufferDirty = true;
- } else if (propertyName == QByteArrayLiteral("accessType")) {
- m_access = static_cast<QBuffer::AccessType>(propertyChange->value().value<int>());
- } else if (propertyName == QByteArrayLiteral("dataGenerator")) {
- QBufferDataGeneratorPtr newGenerator = propertyChange->value().value<QBufferDataGeneratorPtr>();
- m_bufferDirty |= !(newGenerator && m_functor && *newGenerator == *m_functor);
- m_functor = newGenerator;
- if (m_functor && m_manager != nullptr)
- m_manager->addDirtyBuffer(peerId());
- } else if (propertyName == QByteArrayLiteral("syncData")) {
- m_syncData = propertyChange->value().toBool();
+ const_cast<QBuffer *>(node)->setProperty("QT3D_updateData", {});
}
- markDirty(AbstractRenderer::BuffersDirty);
}
- BackendNode::sceneChangeEvent(e);
+ markDirty(AbstractRenderer::BuffersDirty);
}
// Called by Renderer once the buffer has been uploaded to OpenGL
diff --git a/src/render/geometry/buffer_p.h b/src/render/geometry/buffer_p.h
index 9a171599d..a3f52d1b3 100644
--- a/src/render/geometry/buffer_p.h
+++ b/src/render/geometry/buffer_p.h
@@ -73,7 +73,7 @@ public:
~Buffer();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void setManager(BufferManager *manager);
void executeFunctor();
@@ -88,7 +88,6 @@ public:
void unsetDirty();
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
void forceDataUpload();
QBuffer::UsageType m_usage;
diff --git a/src/render/geometry/buffermanager.cpp b/src/render/geometry/buffermanager.cpp
index 14b552879..92f87ab13 100644
--- a/src/render/geometry/buffermanager.cpp
+++ b/src/render/geometry/buffermanager.cpp
@@ -83,12 +83,12 @@ QVector<Qt3DCore::QNodeId> BufferManager::takeBuffersToRelease()
{
QMutexLocker lock(&m_mutex);
QVector<Qt3DCore::QNodeId> buffersToRelease;
- QMutableHashIterator<Qt3DCore::QNodeId, int> it(m_bufferReferences);
- while (it.hasNext()) {
- it.next();
+ for (auto it = m_bufferReferences.begin(), end = m_bufferReferences.end(); it != end; /*erasing*/) {
if (it.value() == 0) {
buffersToRelease.append(it.key());
- it.remove();
+ it = m_bufferReferences.erase(it);
+ } else {
+ ++it;
}
}
return buffersToRelease;
diff --git a/src/render/geometry/geometry.cpp b/src/render/geometry/geometry.cpp
index 4ee02a74d..56ea936be 100644
--- a/src/render/geometry/geometry.cpp
+++ b/src/render/geometry/geometry.cpp
@@ -42,8 +42,8 @@
#include <Qt3DRender/qgeometry.h>
#include <Qt3DRender/private/qgeometry_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
+
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -76,51 +76,29 @@ void Geometry::cleanup()
m_shouldNotifyMaxExtentChanged = false;
}
-void Geometry::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QGeometryData>>(change);
- const auto &data = typedChange->data;
- m_attributes = data.attributeIds;
- m_boundingPositionAttribute = data.boundingVolumePositionAttributeId;
- m_geometryDirty = true;
- markDirty(AbstractRenderer::GeometryDirty);
-}
-
-void Geometry::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void Geometry::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("attribute")) {
- m_attributes.push_back(change->addedNodeId());
- m_geometryDirty = true;
- }
- break;
- }
-
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("attribute")) {
- m_attributes.removeOne(change->removedNodeId());
- m_geometryDirty = true;
- }
- break;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QGeometry *node = qobject_cast<const QGeometry *>(frontEnd);
+ if (!node)
+ return;
+
+ m_geometryDirty |= firstTime;
+
+ QNodeIdVector attribs = qIdsForNodes(node->attributes());
+ std::sort(std::begin(attribs), std::end(attribs));
+ if (m_attributes != attribs) {
+ m_attributes = attribs;
+ m_geometryDirty = true;
}
- case PropertyUpdated: {
+ if ((node->boundingVolumePositionAttribute() && node->boundingVolumePositionAttribute()->id() != m_boundingPositionAttribute) ||
// Note: doesn't set dirtyness as this parameter changing doesn't need a new VAO update.
- const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("boundingVolumePositionAttribute")) {
- m_boundingPositionAttribute = change->value().value<QNodeId>();
- break;
- }
+ (!node->boundingVolumePositionAttribute() && !m_boundingPositionAttribute.isNull())) {
+ m_boundingPositionAttribute = node->boundingVolumePositionAttribute() ? node->boundingVolumePositionAttribute()->id() : QNodeId{};
}
- default:
- break;
- }
markDirty(AbstractRenderer::GeometryDirty);
- BackendNode::sceneChangeEvent(e);
}
void Geometry::unsetDirty()
diff --git a/src/render/geometry/geometry_p.h b/src/render/geometry/geometry_p.h
index e66524787..429a577b0 100644
--- a/src/render/geometry/geometry_p.h
+++ b/src/render/geometry/geometry_p.h
@@ -68,7 +68,7 @@ public:
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
inline QVector<Qt3DCore::QNodeId> attributes() const { return m_attributes; }
inline bool isDirty() const { return m_geometryDirty; }
@@ -82,8 +82,6 @@ public:
void notifyExtentChanged();
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DCore::QNodeId> m_attributes;
bool m_geometryDirty;
Qt3DCore::QNodeId m_boundingPositionAttribute;
diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp
index ea059c6ee..881c0f66b 100644
--- a/src/render/geometry/geometryrenderer.cpp
+++ b/src/render/geometry/geometryrenderer.cpp
@@ -43,8 +43,6 @@
#include <Qt3DRender/private/qgeometryrenderer_p.h>
#include <Qt3DRender/private/qmesh_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qtypedpropertyupdatechange_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
@@ -105,98 +103,58 @@ void GeometryRenderer::setManager(GeometryRendererManager *manager)
m_manager = manager;
}
-void GeometryRenderer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QGeometryRendererData>>(change);
- const auto &data = typedChange->data;
- m_geometryId = data.geometryId;
- m_instanceCount = data.instanceCount;
- m_vertexCount = data.vertexCount;
- m_indexOffset = data.indexOffset;
- m_firstInstance = data.firstInstance;
- m_firstVertex = data.firstVertex;
- m_indexBufferByteOffset = data.indexBufferByteOffset;
- m_restartIndexValue = data.restartIndexValue;
- m_verticesPerPatch = data.verticesPerPatch;
- m_primitiveRestartEnabled = data.primitiveRestart;
- m_primitiveType = data.primitiveType;
-
- Q_ASSERT(m_manager);
- m_geometryFactory = data.geometryFactory;
- if (m_geometryFactory)
- m_manager->addDirtyGeometryRenderer(peerId());
-
- m_dirty = true;
- markDirty(AbstractRenderer::GeometryDirty);
-}
-
-void GeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyUpdated: {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- QByteArray propertyName = propertyChange->propertyName();
-
- if (propertyName == QByteArrayLiteral("instanceCount")) {
- m_instanceCount = propertyChange->value().value<int>();
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("vertexCount")) {
- m_vertexCount = propertyChange->value().value<int>();
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("indexOffset")) {
- m_indexOffset = propertyChange->value().value<int>();
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("firstInstance")) {
- m_firstInstance = propertyChange->value().value<int>();
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("firstVertex")) {
- m_firstVertex = propertyChange->value().value<int>();
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("indexBufferByteOffset")) {
- m_indexBufferByteOffset = propertyChange->value().value<int>();
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("restartIndexValue")) {
- m_restartIndexValue = propertyChange->value().value<int>();
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("verticesPerPatch")) {
- m_verticesPerPatch = propertyChange->value().value<int>();
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("primitiveRestartEnabled")) {
- m_primitiveRestartEnabled = propertyChange->value().toBool();
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("primitiveType")) {
- m_primitiveType = static_cast<QGeometryRenderer::PrimitiveType>(propertyChange->value().value<int>());
- m_dirty = true;
- } else if (propertyName == QByteArrayLiteral("geometryFactory")) {
- QGeometryFactoryPtr newFunctor = propertyChange->value().value<QGeometryFactoryPtr>();
- const bool functorDirty = ((m_geometryFactory && !newFunctor)
- || (!m_geometryFactory && newFunctor)
- || (m_geometryFactory && newFunctor && !(*newFunctor == *m_geometryFactory)));
- m_dirty |= functorDirty;
- if (functorDirty) {
- m_geometryFactory = newFunctor;
- if (m_geometryFactory && m_manager != nullptr)
- m_manager->addDirtyGeometryRenderer(peerId());
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QGeometryRenderer *node = qobject_cast<const QGeometryRenderer *>(frontEnd);
+ if (!node)
+ return;
+
+ m_dirty |= m_instanceCount != node->instanceCount();
+ m_instanceCount = node->instanceCount();
+ m_dirty |= m_vertexCount != node->vertexCount();
+ m_vertexCount = node->vertexCount();
+ m_dirty |= m_indexOffset != node->indexOffset();
+ m_indexOffset = node->indexOffset();
+ m_dirty |= m_firstInstance != node->firstInstance();
+ m_firstInstance = node->firstInstance();
+ m_dirty |= m_firstVertex != node->firstVertex();
+ m_firstVertex = node->firstVertex();
+ m_dirty |= m_indexBufferByteOffset != node->indexBufferByteOffset();
+ m_indexBufferByteOffset = node->indexBufferByteOffset();
+ m_dirty |= m_restartIndexValue != node->restartIndexValue();
+ m_restartIndexValue = node->restartIndexValue();
+ m_dirty |= m_verticesPerPatch != node->verticesPerPatch();
+ m_verticesPerPatch = node->verticesPerPatch();
+ m_dirty |= m_primitiveRestartEnabled != node->primitiveRestartEnabled();
+ m_primitiveRestartEnabled = node->primitiveRestartEnabled();
+ m_dirty |= m_primitiveType != node->primitiveType();
+ m_primitiveType = node->primitiveType();
+ m_dirty |= (node->geometry() && m_geometryId != node->geometry()->id()) || (!node->geometry() && !m_geometryId.isNull());
+ m_geometryId = node->geometry() ? node->geometry()->id() : Qt3DCore::QNodeId();
+ QGeometryFactoryPtr newFunctor = node->geometryFactory();
+ const bool functorDirty = ((m_geometryFactory && !newFunctor)
+ || (!m_geometryFactory && newFunctor)
+ || (m_geometryFactory && newFunctor && !(*newFunctor == *m_geometryFactory)));
+ if (functorDirty) {
+ m_dirty = true;
+ m_geometryFactory = newFunctor;
+ if (m_geometryFactory && m_manager != nullptr) {
+ m_manager->addDirtyGeometryRenderer(peerId());
+
+ const bool isQMeshFunctor = m_geometryFactory->id() == Qt3DRender::functorTypeId<MeshLoaderFunctor>();
+ if (isQMeshFunctor) {
+ const QMesh *meshNode = static_cast<const QMesh *>(node);
+ QMeshPrivate *dmeshNode = QMeshPrivate::get(const_cast<QMesh *>(meshNode));
+ dmeshNode->setStatus(QMesh::Loading);
}
- } else if (propertyName == QByteArrayLiteral("geometry")) {
- m_geometryId = propertyChange->value().value<Qt3DCore::QNodeId>();
- m_dirty = true;
}
- break;
- }
-
- default:
- break;
}
markDirty(AbstractRenderer::GeometryDirty);
-
- BackendNode::sceneChangeEvent(e);
-
- // Add to dirty list in manager
}
-void GeometryRenderer::executeFunctor()
+GeometryFunctorResult GeometryRenderer::executeFunctor()
{
Q_ASSERT(m_geometryFactory);
@@ -217,7 +175,8 @@ void GeometryRenderer::executeFunctor()
}
// Load geometry
- std::unique_ptr<QGeometry> geometry((*m_geometryFactory)());
+ QGeometry *geometry = (*m_geometryFactory)();
+ QMesh::Status meshLoaderStatus = QMesh::None;
// If the geometry is null, then we were either unable to load it (Error)
// or the mesh is located at a remote url and needs to be downloaded first (Loading)
@@ -226,24 +185,15 @@ void GeometryRenderer::executeFunctor()
// corresponding QGeometryRenderer
const auto appThread = QCoreApplication::instance()->thread();
geometry->moveToThread(appThread);
-
- auto e = QGeometryChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- e->setPropertyName("geometry");
- e->data = std::move(geometry);
- notifyObservers(e);
}
// Send Status
if (isQMeshFunctor) {
QSharedPointer<MeshLoaderFunctor> meshLoader = qSharedPointerCast<MeshLoaderFunctor>(m_geometryFactory);
-
- auto e = QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- e->setPropertyName("status");
- e->setValue(meshLoader->status());
- notifyObservers(e);
+ meshLoaderStatus = meshLoader->status();
}
+
+ return { geometry, meshLoaderStatus };
}
void GeometryRenderer::unsetDirty()
diff --git a/src/render/geometry/geometryrenderer_p.h b/src/render/geometry/geometryrenderer_p.h
index 57d1ca0be..d2ddad4bb 100644
--- a/src/render/geometry/geometryrenderer_p.h
+++ b/src/render/geometry/geometryrenderer_p.h
@@ -54,6 +54,7 @@
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <Qt3DRender/qgeometryfactory.h>
+#include <Qt3DRender/qmesh.h>
QT_BEGIN_NAMESPACE
@@ -66,6 +67,12 @@ namespace Render {
class GeometryRendererManager;
+struct GeometryFunctorResult
+{
+ QGeometry *geometry;
+ QMesh::Status status;
+};
+
class Q_AUTOTEST_EXPORT GeometryRenderer : public BackendNode
{
public:
@@ -74,8 +81,8 @@ public:
void cleanup();
void setManager(GeometryRendererManager *manager);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
- void executeFunctor();
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+ GeometryFunctorResult executeFunctor();
inline Qt3DCore::QNodeId geometryId() const { return m_geometryId; }
inline int instanceCount() const { return m_instanceCount; }
@@ -98,8 +105,6 @@ public:
QVector<RayCasting::QBoundingVolume *> triangleData() const;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_geometryId;
int m_instanceCount;
int m_vertexCount;
diff --git a/src/render/geometry/joint.cpp b/src/render/geometry/joint.cpp
index c770564f9..9791f6c52 100644
--- a/src/render/geometry/joint.cpp
+++ b/src/render/geometry/joint.cpp
@@ -39,10 +39,10 @@
#include "joint_p.h"
#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DCore/QJoint>
#include <Qt3DCore/private/qjoint_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
+
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -69,62 +69,52 @@ void Joint::cleanup()
setEnabled(false);
}
-void Joint::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Joint::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- Q_ASSERT(m_jointManager);
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QJointData>>(change);
- const auto &data = typedChange->data;
- m_inverseBindMatrix = data.inverseBindMatrix;
- m_localPose.rotation = data.rotation;
- m_localPose.scale = data.scale;
- m_localPose.translation = data.translation;
- m_childJointIds = data.childJointIds;
- m_name = data.name;
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
-}
+ const Qt3DCore::QJoint *joint = qobject_cast<const Qt3DCore::QJoint *>(frontEnd);
+ if (!joint)
+ return;
+
+ bool jointDirty = firstTime;
+ if (m_localPose.scale != joint->scale()) {
+ m_localPose.scale = joint->scale();
+ jointDirty = true;
+ }
+ if (m_localPose.rotation != joint->rotation()) {
+ m_localPose.rotation = joint->rotation();
+ jointDirty = true;
+ }
+ if (m_localPose.translation != joint->translation()) {
+ m_localPose.translation = joint->translation();
+ jointDirty = true;
+ }
+ if (m_inverseBindMatrix != joint->inverseBindMatrix()) {
+ // Setting the inverse bind matrix should be a rare operation. Usually it is
+ // set once and then remains constant for the duration of the skeleton. So just
+ // trigger a rebuild of the skeleton's SkeletonData which will include obtaining
+ // the inverse bind matrix.
+ m_inverseBindMatrix = joint->inverseBindMatrix();
+ m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_owningSkeleton);
+ }
+ if (m_name != joint->name()) {
+ // Joint name doesn't affect anything in the render aspect so no need
+ // to mark anything as dirty.
+ m_name = joint->name();
-void Joint::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == PropertyUpdated) {
- const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("scale")) {
- m_localPose.scale = propertyChange->value().value<QVector3D>();
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
- } else if (propertyChange->propertyName() == QByteArrayLiteral("rotation")) {
- m_localPose.rotation = propertyChange->value().value<QQuaternion>();
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
- } else if (propertyChange->propertyName() == QByteArrayLiteral("translation")) {
- m_localPose.translation = propertyChange->value().value<QVector3D>();
- markDirty(AbstractRenderer::JointDirty);
- m_jointManager->addDirtyJoint(peerId());
- } else if (propertyChange->propertyName() == QByteArrayLiteral("inverseBindMatrix")) {
- // Setting the inverse bind matrix should be a rare operation. Usually it is
- // set once and then remains constant for the duration of the skeleton. So just
- // trigger a rebuild of the skeleton's SkeletonData which will include obtaining
- // the inverse bind matrix.
- m_inverseBindMatrix = propertyChange->value().value<QMatrix4x4>();
- m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_owningSkeleton);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("name")) {
- // Joint name doesn't affect anything in the render aspect so no need
- // to mark anything as dirty.
- m_name = propertyChange->value().toString();
-
- // TODO: Notify other aspects (animation) about the name change.
- }
- } else if (e->type() == PropertyValueAdded) {
- const auto addedChange = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (addedChange->propertyName() == QByteArrayLiteral("childJoint"))
- m_childJointIds.push_back(addedChange->addedNodeId());
- } else if (e->type() == PropertyValueRemoved) {
- const auto removedChange = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (removedChange->propertyName() == QByteArrayLiteral("childJoint"))
- m_childJointIds.removeOne(removedChange->removedNodeId());
+ // TODO: Notify other aspects (animation) about the name change.
+ }
+
+ Qt3DCore::QNodeIdVector childIds = qIdsForNodes(joint->childJoints());
+ std::sort(std::begin(childIds), std::end(childIds));
+ if (m_childJointIds != childIds)
+ m_childJointIds = childIds;
+
+ if (jointDirty) {
+ markDirty(AbstractRenderer::JointDirty);
+ m_jointManager->addDirtyJoint(peerId());
}
- BackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
}
diff --git a/src/render/geometry/joint_p.h b/src/render/geometry/joint_p.h
index e144ac489..de875459e 100644
--- a/src/render/geometry/joint_p.h
+++ b/src/render/geometry/joint_p.h
@@ -69,7 +69,7 @@ public:
Joint();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
Qt3DCore::Sqt localPose() const { return m_localPose; }
QMatrix4x4 inverseBindMatrix() const { return m_inverseBindMatrix; }
@@ -90,8 +90,6 @@ public:
SkeletonManager *skeletonManager() const { return m_skeletonManager; }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QMatrix4x4 m_inverseBindMatrix;
Qt3DCore::Sqt m_localPose;
QVector<Qt3DCore::QNodeId> m_childJointIds;
diff --git a/src/render/geometry/qattribute.cpp b/src/render/geometry/qattribute.cpp
index ca467fda9..84d14cfe1 100644
--- a/src/render/geometry/qattribute.cpp
+++ b/src/render/geometry/qattribute.cpp
@@ -41,8 +41,6 @@
#include "qattribute_p.h"
#include <Qt3DRender/qbuffer.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
@@ -505,6 +503,19 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAttribute::createNodeCreationChange() const
return creationChange;
}
+
+/*!
+\fn Qt3DRender::QAttribute::dataSizeChanged(uint vertexSize)
+
+The signal is emitted with \a vertexSize when the dataSize changes.
+*/
+/*!
+\fn Qt3DRender::QAttribute::dataTypeChanged(Qt3DRender::QAttribute::VertexBaseType vertexBaseType)
+
+The signal is emitted with \a vertexBaseType when the dataType changed.
+*/
+
+
} // Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/geometry/qbuffer.cpp b/src/render/geometry/qbuffer.cpp
index e0574a4c5..8399bdd7c 100644
--- a/src/render/geometry/qbuffer.cpp
+++ b/src/render/geometry/qbuffer.cpp
@@ -58,6 +58,15 @@ QBufferPrivate::QBufferPrivate()
{
}
+void QBufferPrivate::setData(const QByteArray &data)
+{
+ Q_Q(QBuffer);
+ const bool blocked = q->blockNotifications(true);
+ m_data = data;
+ emit q->dataChanged(data);
+ q->blockNotifications(blocked);
+}
+
/*!
* \qmltype Buffer
* \instantiates Qt3DRender::QBuffer
@@ -301,36 +310,14 @@ QBuffer::~QBuffer()
}
/*!
- * \internal
- */
-void QBuffer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- if (change->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change);
- const QByteArray propertyName = e->propertyName();
- if (propertyName == QByteArrayLiteral("data")) {
- const bool blocked = blockNotifications(true);
- setData(e->value().toByteArray());
- blockNotifications(blocked);
- } else if (propertyName == QByteArrayLiteral("downloadedData")) {
- const bool blocked = blockNotifications(true);
- setData(e->value().toByteArray());
- blockNotifications(blocked);
- Q_EMIT dataAvailable();
- }
- }
-}
-
-/*!
* Sets \a bytes as data.
*/
void QBuffer::setData(const QByteArray &bytes)
{
Q_D(QBuffer);
if (bytes != d->m_data) {
- d->m_data = bytes;
- Qt3DCore::QNodePrivate::get(this)->notifyPropertyChange("data", QVariant::fromValue(d->m_data));
- emit dataChanged(bytes);
+ d->setData(bytes);
+ d->update();
}
}
@@ -351,11 +338,8 @@ void QBuffer::updateData(int offset, const QByteArray &bytes)
QBufferUpdate updateData;
updateData.offset = offset;
updateData.data = bytes;
-
- auto e = QPropertyUpdatedChangePtr::create(id());
- e->setPropertyName("updateData");
- e->setValue(QVariant::fromValue(updateData));
- notifyObservers(e);
+ setProperty("QT3D_updateData", QVariant::fromValue(updateData));
+ d->update();
}
/*!
@@ -409,12 +393,7 @@ void QBuffer::setDataGenerator(const QBufferDataGeneratorPtr &functor)
if (functor && d->m_functor && *functor == *d->m_functor)
return;
d->m_functor = functor;
- if (d->m_changeArbiter != nullptr) {
- auto change = QPropertyUpdatedChangePtr::create(d->m_id);
- change->setPropertyName("dataGenerator");
- change->setValue(QVariant::fromValue(d->m_functor));
- d->notifyObservers(change);
- }
+ d->update();
}
/*!
@@ -454,6 +433,13 @@ void QBuffer::setAccessType(QBuffer::AccessType access)
}
}
+/*! \internal */
+void QBuffer::sceneChangeEvent(const QSceneChangePtr &change)
+{
+ // TODO Unused remove in Qt6
+ Q_UNUSED(change)
+}
+
bool QBuffer::isSyncData() const
{
Q_D(const QBuffer);
diff --git a/src/render/geometry/qbuffer.h b/src/render/geometry/qbuffer.h
index 1bd1aa8fd..aa6ebca66 100644
--- a/src/render/geometry/qbuffer.h
+++ b/src/render/geometry/qbuffer.h
@@ -118,9 +118,6 @@ public Q_SLOTS:
void setSyncData(bool syncData);
void setAccessType(AccessType access);
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
-
Q_SIGNALS:
void dataChanged(const QByteArray &bytes);
void typeChanged(BufferType type);
@@ -129,6 +126,10 @@ Q_SIGNALS:
void accessTypeChanged(AccessType access);
void dataAvailable();
+protected:
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+
private:
Q_DECLARE_PRIVATE(QBuffer)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
diff --git a/src/render/geometry/qbuffer_p.h b/src/render/geometry/qbuffer_p.h
index 7a0ffdfb9..6da28e88b 100644
--- a/src/render/geometry/qbuffer_p.h
+++ b/src/render/geometry/qbuffer_p.h
@@ -75,6 +75,8 @@ public:
QBufferDataGeneratorPtr m_functor;
bool m_syncData;
QBuffer::AccessType m_access;
+
+ void setData(const QByteArray &data);
};
struct QBufferData
diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp
index ec80e2657..48f054bce 100644
--- a/src/render/geometry/qgeometry.cpp
+++ b/src/render/geometry/qgeometry.cpp
@@ -43,8 +43,6 @@
#include <private/qnode_p.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -196,11 +194,7 @@ void QGeometry::addAttribute(QAttribute *attribute)
if (!attribute->parent())
attribute->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueAdded);
}
}
@@ -212,14 +206,10 @@ void QGeometry::removeAttribute(QAttribute *attribute)
{
Q_ASSERT(attribute);
Q_D(QGeometry);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
d->m_attributes.removeOne(attribute);
// Remove bookkeeping connection
d->unregisterDestructionHelper(attribute);
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved);
}
void QGeometry::setBoundingVolumePositionAttribute(QAttribute *boundingVolumePositionAttribute)
diff --git a/src/render/geometry/qgeometryrenderer.cpp b/src/render/geometry/qgeometryrenderer.cpp
index 6bff3462f..64f3e058e 100644
--- a/src/render/geometry/qgeometryrenderer.cpp
+++ b/src/render/geometry/qgeometryrenderer.cpp
@@ -41,9 +41,6 @@
#include "qgeometryrenderer_p.h"
#include <private/qcomponent_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -221,6 +218,11 @@ QGeometryRenderer::QGeometryRenderer(QGeometryRendererPrivate &dd, QNode *parent
{
}
+// TODO Unused remove in Qt6
+void QGeometryRenderer::sceneChangeEvent(const QSceneChangePtr &)
+{
+}
+
/*!
\property QGeometryRenderer::instanceCount
@@ -480,25 +482,7 @@ void QGeometryRenderer::setGeometryFactory(const QGeometryFactoryPtr &factory)
if (factory && d->m_geometryFactory && *factory == *d->m_geometryFactory)
return;
d->m_geometryFactory = factory;
- if (d->m_changeArbiter != nullptr) {
- auto change = QPropertyUpdatedChangePtr::create(d->m_id);
- change->setPropertyName("geometryFactory");
- change->setValue(QVariant::fromValue(d->m_geometryFactory));
- d->notifyObservers(change);
- }
-}
-
-/*!
- \internal
- */
-void QGeometryRenderer::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- auto change = qSharedPointerCast<QStaticPropertyUpdatedChangeBase>(e);
- if (change->type() == PropertyUpdated && change->propertyName() == QByteArrayLiteral("geometry")) {
- auto typedChange = qSharedPointerCast<QGeometryChange>(e);
- auto geometry = std::move(typedChange->data);
- setGeometry(geometry.release());
- }
+ d->update();
}
Qt3DCore::QNodeCreatedChangeBasePtr QGeometryRenderer::createNodeCreationChange() const
diff --git a/src/render/geometry/qgeometryrenderer.h b/src/render/geometry/qgeometryrenderer.h
index 81bd1ff67..14de40d0b 100644
--- a/src/render/geometry/qgeometryrenderer.h
+++ b/src/render/geometry/qgeometryrenderer.h
@@ -134,6 +134,7 @@ Q_SIGNALS:
protected:
explicit QGeometryRenderer(QGeometryRendererPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/render/geometry/qmesh.cpp b/src/render/geometry/qmesh.cpp
index 66c4a69bc..1f05a71f6 100644
--- a/src/render/geometry/qmesh.cpp
+++ b/src/render/geometry/qmesh.cpp
@@ -148,17 +148,6 @@ void QMeshPrivate::setStatus(QMesh::Status status)
*/
/*!
- \enum QMesh::Status
-
- This enum identifies the status of shader used.
-
- \value None A source mesh hasn't been assigned a source yet
- \value Loading The mesh geometry is loading
- \value Ready The mesh geometry was successfully loaded
- \value Error An error occurred while loading the mesh
-*/
-
-/*!
\qmlproperty enumeration Mesh::status
Holds the status of the mesh loading.
@@ -197,6 +186,17 @@ void QMeshPrivate::setStatus(QMesh::Status status)
*/
/*!
+ \enum Qt3DRender::QMesh::Status
+
+ This enum identifies the status of shader used.
+
+ \value None A source mesh hasn't been assigned a source yet
+ \value Loading The mesh geometry is loading
+ \value Ready The mesh geometry was successfully loaded
+ \value Error An error occurred while loading the mesh
+*/
+
+/*!
* Constructs a new QMesh with \a parent.
*/
QMesh::QMesh(QNode *parent)
@@ -215,16 +215,9 @@ QMesh::QMesh(QMeshPrivate &dd, QNode *parent)
{
}
-/*! \internal */
-void QMesh::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QMesh::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- Q_D(QMesh);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("status"))
- d->setStatus(e->value().value<QMesh::Status>());
- }
- Qt3DRender::QGeometryRenderer::sceneChangeEvent(change);
}
void QMesh::setSource(const QUrl& source)
diff --git a/src/render/geometry/qmesh.h b/src/render/geometry/qmesh.h
index 458a21fa4..e8ff52b35 100644
--- a/src/render/geometry/qmesh.h
+++ b/src/render/geometry/qmesh.h
@@ -88,6 +88,7 @@ Q_SIGNALS:
protected:
explicit QMesh(QMeshPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/render/geometry/skeleton.cpp b/src/render/geometry/skeleton.cpp
index 615b76c88..0452c020b 100644
--- a/src/render/geometry/skeleton.cpp
+++ b/src/render/geometry/skeleton.cpp
@@ -36,24 +36,19 @@
#include "skeleton_p.h"
-#include <Qt3DCore/qjoint.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
+#include <Qt3DCore/qjoint.h>
#include <Qt3DRender/private/abstractrenderer_p.h>
-#include <Qt3DRender/private/gltfskeletonloader_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/renderlogging_p.h>
-#include <Qt3DRender/private/qurlhelper_p.h>
#include <Qt3DCore/private/qskeletoncreatedchange_p.h>
#include <Qt3DCore/private/qskeleton_p.h>
#include <Qt3DCore/private/qskeletonloader_p.h>
#include <Qt3DCore/private/qmath3d_p.h>
-#include <Qt3DCore/private/qabstractnodefactory_p.h>
QT_BEGIN_NAMESPACE
@@ -65,6 +60,8 @@ namespace Render {
Skeleton::Skeleton()
: BackendNode(Qt3DCore::QBackendNode::ReadWrite)
, m_status(Qt3DCore::QSkeletonLoader::NotReady)
+ , m_createJoints(false)
+ , m_dataType(Unknown)
, m_skeletonManager(nullptr)
, m_jointManager(nullptr)
{
@@ -80,61 +77,48 @@ void Skeleton::cleanup()
setEnabled(false);
}
-void Skeleton::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Skeleton::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- Q_ASSERT(m_skeletonManager);
- m_skeletonHandle = m_skeletonManager->lookupHandle(peerId());
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAbstractSkeleton *node = qobject_cast<const QAbstractSkeleton *>(frontEnd);
+ if (!node)
+ return;
+ const QSkeleton *skeletonNode = qobject_cast<const QSkeleton *>(frontEnd);
+ const QSkeletonLoader *loaderNode = qobject_cast<const QSkeletonLoader *>(frontEnd);
- const auto skeletonCreatedChange = qSharedPointerCast<QSkeletonCreatedChangeBase>(change);
- switch (skeletonCreatedChange->type()) {
- case QSkeletonCreatedChangeBase::SkeletonLoader: {
- const auto loaderTypedChange = qSharedPointerCast<QSkeletonCreatedChange<QSkeletonLoaderData>>(change);
- const auto &data = loaderTypedChange->data;
- m_dataType = File;
- m_source = data.source;
- m_createJoints = data.createJoints;
- if (!m_source.isEmpty()) {
- markDirty(AbstractRenderer::SkeletonDataDirty);
- m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle);
+ if (firstTime) {
+ m_skeletonHandle = m_skeletonManager->lookupHandle(peerId());
+
+ if (skeletonNode) {
+ m_dataType = Data;
+ m_rootJointId = skeletonNode->rootJoint()->id();
+ if (!m_rootJointId.isNull()) {
+ markDirty(AbstractRenderer::SkeletonDataDirty);
+ m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle);
+ }
+ }
+
+ if (loaderNode) {
+ m_dataType = File;
+ m_source = loaderNode->source();
+ if (!m_source.isEmpty()) {
+ markDirty(AbstractRenderer::SkeletonDataDirty);
+ m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle);
+ }
}
- break;
}
- case QSkeletonCreatedChangeBase::Skeleton:
- const auto typedChange = qSharedPointerCast<QSkeletonCreatedChange<QSkeletonData>>(change);
- const auto &data = typedChange->data;
- m_dataType = Data;
- m_rootJointId = data.rootJointId;
- if (!m_rootJointId.isNull()) {
+ if (loaderNode) {
+ if (loaderNode->source() != m_source) {
+ m_source = loaderNode->source();
markDirty(AbstractRenderer::SkeletonDataDirty);
m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle);
}
- break;
- }
-}
+ m_createJoints = loaderNode->isCreateJointsEnabled();
-void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case Qt3DCore::PropertyUpdated: {
- const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("localPoses")) {
- // When the animation aspect sends us a new set of local poses, all we
- // need to do is copy them into place. The existing jobs will then update
- // the skinning matrix palette.
- m_skeletonData.localPoses = change->value().value<QVector<Qt3DCore::Sqt>>();
- } else if (change->propertyName() == QByteArrayLiteral("source")) {
- Q_ASSERT(m_dataType == File);
- const auto source = change->value().toUrl();
- if (source != m_source) {
- m_source = source;
- markDirty(AbstractRenderer::SkeletonDataDirty);
- m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle);
- }
- } else if (change->propertyName() == QByteArrayLiteral("createJointsEnabled")) {
- m_createJoints = change->value().toBool();
- } else if (change->propertyName() == QByteArrayLiteral("rootJoint")) {
- m_rootJointId = change->value().value<QNodeId>();
+ auto newJointId = Qt3DCore::qIdForNode(loaderNode->rootJoint());
+ if (newJointId != m_rootJointId) {
+ m_rootJointId = newJointId;
// If using a QSkeletonLoader to create frontend QJoints, when those joints are
// set on the skeleton, we end up here. In order to allow the subsequent call
@@ -146,228 +130,21 @@ void Skeleton::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
// If the joint changes, we need to rebuild our internal SkeletonData and
// the relationships between joints and skeleton. Mark the skeleton data as
// dirty so that we get a loadSkeletonJob executed to process this skeleton.
- markDirty(AbstractRenderer::SkeletonDataDirty);
- m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle);
+ if (!m_rootJointId.isNull()) {
+ markDirty(AbstractRenderer::SkeletonDataDirty);
+ m_skeletonManager->addDirtySkeleton(SkeletonManager::SkeletonDataDirty, m_skeletonHandle);
+ }
}
-
- break;
}
- default:
- break;
- }
- QBackendNode::sceneChangeEvent(e);
+ auto d = Qt3DCore::QAbstractSkeletonPrivate::get(node);
+ m_skeletonData.localPoses = d->m_localPoses;
}
void Skeleton::setStatus(QSkeletonLoader::Status status)
{
- if (status != m_status) {
+ if (status != m_status)
m_status = status;
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("status");
- e->setValue(QVariant::fromValue(m_status));
- notifyObservers(e);
- }
-}
-
-void Skeleton::notifyJointCount()
-{
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("jointCount");
- e->setValue(jointCount());
- notifyObservers(e);
-}
-
-void Skeleton::notifyJointNamesAndPoses()
-{
- auto e = QPropertyUpdatedChangePtr::create(peerId());
- JointNamesAndLocalPoses payload{m_skeletonData.jointNames, m_skeletonData.localPoses};
- e->setDeliveryFlags(Qt3DCore::QSceneChange::BackendNodes);
- e->setPropertyName("jointNamesAndLocalPoses");
- e->setValue(QVariant::fromValue(payload));
- notifyObservers(e);
-}
-
-void Skeleton::loadSkeleton()
-{
- qCDebug(Jobs) << Q_FUNC_INFO << m_source;
- clearData();
-
- // Load the data
- switch (m_dataType) {
- case File:
- loadSkeletonFromUrl();
- break;
-
- case Data:
- loadSkeletonFromData();
- break;
-
- default:
- Q_UNREACHABLE();
- }
-
- // If using a loader inform the frontend of the status change.
- // Don't bother if asked to create frontend joints though. When
- // the backend gets notified of those joints we'll update the
- // status at that point.
- if (m_dataType == File && !m_createJoints) {
- if (jointCount() == 0)
- setStatus(QSkeletonLoader::Error);
- else
- setStatus(QSkeletonLoader::Ready);
- }
- notifyJointCount();
- notifyJointNamesAndPoses();
-
- qCDebug(Jobs) << "Loaded skeleton data:" << *this;
-}
-
-void Skeleton::loadSkeletonFromUrl()
-{
- // TODO: Handle remote files
- QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_source);
- QFileInfo info(filePath);
- if (!info.exists()) {
- qWarning() << "Could not open skeleton file:" << filePath;
- setStatus(Qt3DCore::QSkeletonLoader::Error);
- return;
- }
-
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly)) {
- qWarning() << "Could not open skeleton file:" << filePath;
- setStatus(Qt3DCore::QSkeletonLoader::Error);
- return;
- }
-
- // TODO: Make plugin based for more file type support. For now gltf or native
- const QString ext = info.suffix();
- if (ext == QLatin1String("gltf")) {
- GLTFSkeletonLoader loader;
- loader.load(&file);
- m_skeletonData = loader.createSkeleton(m_name);
-
- // If the user has requested it, create the frontend nodes for the joints
- // and send them to the (soon to be owning) QSkeletonLoader.
- if (m_createJoints) {
- std::unique_ptr<QJoint> rootJoint(createFrontendJoints(m_skeletonData));
- if (!rootJoint) {
- qWarning() << "Failed to create frontend joints";
- setStatus(Qt3DCore::QSkeletonLoader::Error);
- return;
- }
-
- // Move the QJoint tree to the main thread and notify the
- // corresponding QSkeletonLoader
- const auto appThread = QCoreApplication::instance()->thread();
- rootJoint->moveToThread(appThread);
-
- auto e = QJointChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- e->setPropertyName("rootJoint");
- e->data = std::move(rootJoint);
- notifyObservers(e);
-
- // Clear the skeleton data. It will be recreated from the
- // frontend joints. A little bit inefficient but ensures
- // that joints created this way and via QSkeleton go through
- // the same code path.
- m_skeletonData = SkeletonData();
- }
- } else if (ext == QLatin1String("json")) {
- // TODO: Support native skeleton type
- } else {
- qWarning() << "Unknown skeleton file type:" << ext;
- setStatus(Qt3DCore::QSkeletonLoader::Error);
- return;
- }
- m_skinningPalette.resize(m_skeletonData.joints.size());
-}
-
-void Skeleton::loadSkeletonFromData()
-{
- // Recurse down through the joint hierarchy and process it into
- // the vector of joints used within SkeletonData. The recursion
- // ensures that a parent always appears before its children in
- // the vector of JointInfo objects.
- //
- // In addition, we set up a mapping from the joint ids to the
- // index of the corresponding JointInfo object in the vector.
- // This will allow us to easily update entries in the vector of
- // JointInfos when a Joint node marks itself as dirty.
- const int rootParentIndex = -1;
- processJointHierarchy(m_rootJointId, rootParentIndex, m_skeletonData);
- m_skinningPalette.resize(m_skeletonData.joints.size());
-}
-
-Qt3DCore::QJoint *Skeleton::createFrontendJoints(const SkeletonData &skeletonData) const
-{
- if (skeletonData.joints.isEmpty())
- return nullptr;
-
- // Create frontend joints from the joint info objects
- QVector<QJoint *> frontendJoints;
- const int jointCount = skeletonData.joints.size();
- frontendJoints.reserve(jointCount);
- for (int i = 0; i < jointCount; ++i) {
- const QMatrix4x4 &inverseBindMatrix = skeletonData.joints[i].inverseBindPose;
- const QString &jointName = skeletonData.jointNames[i];
- const Qt3DCore::Sqt &localPose = skeletonData.localPoses[i];
- frontendJoints.push_back(createFrontendJoint(jointName, localPose, inverseBindMatrix));
- }
-
- // Now go through and resolve the parent for each joint
- for (int i = 0; i < frontendJoints.size(); ++i) {
- const auto parentIndex = skeletonData.joints[i].parentIndex;
- if (parentIndex == -1)
- continue;
-
- // It's not enough to just set up the QObject parent-child relationship.
- // We need to explicitly add the child to the parent's list of joints so
- // that information is then propagated to the backend.
- frontendJoints[parentIndex]->addChildJoint(frontendJoints[i]);
- }
-
- return frontendJoints[0];
-}
-
-Qt3DCore::QJoint *Skeleton::createFrontendJoint(const QString &jointName,
- const Qt3DCore::Sqt &localPose,
- const QMatrix4x4 &inverseBindMatrix) const
-{
- auto joint = QAbstractNodeFactory::createNode<QJoint>("QJoint");
- joint->setTranslation(localPose.translation);
- joint->setRotation(localPose.rotation);
- joint->setScale(localPose.scale);
- joint->setInverseBindMatrix(inverseBindMatrix);
- joint->setName(jointName);
- return joint;
-}
-
-void Skeleton::processJointHierarchy(Qt3DCore::QNodeId jointId,
- int parentJointIndex,
- SkeletonData &skeletonData)
-{
- // Lookup the joint, create a JointInfo, and add an entry to the index map
- Joint *joint = m_renderer->nodeManagers()->jointManager()->lookupResource(jointId);
- Q_ASSERT(joint);
- joint->setOwningSkeleton(m_skeletonHandle);
- const JointInfo jointInfo(joint, parentJointIndex);
- skeletonData.joints.push_back(jointInfo);
- skeletonData.localPoses.push_back(joint->localPose());
- skeletonData.jointNames.push_back(joint->name());
-
- const int jointIndex = skeletonData.joints.size() - 1;
- const HJoint jointHandle = m_jointManager->lookupHandle(jointId);
- skeletonData.jointIndices.insert(jointHandle, jointIndex);
-
- // Recurse to the children
- const auto childIds = joint->childJointIds();
- for (const auto childJointId : childIds)
- processJointHierarchy(childJointId, jointIndex, skeletonData);
}
void Skeleton::clearData()
@@ -379,6 +156,12 @@ void Skeleton::clearData()
m_skeletonData.jointIndices.clear();
}
+void Skeleton::setSkeletonData(const SkeletonData &data)
+{
+ m_skeletonData = data;
+ m_skinningPalette.resize(m_skeletonData.joints.size());
+}
+
// Called from UpdateSkinningPaletteJob
void Skeleton::setLocalPose(HJoint jointHandle, const Qt3DCore::Sqt &localPose)
{
diff --git a/src/render/geometry/skeleton_p.h b/src/render/geometry/skeleton_p.h
index 4a14e5c1c..eb9551f07 100644
--- a/src/render/geometry/skeleton_p.h
+++ b/src/render/geometry/skeleton_p.h
@@ -75,6 +75,12 @@ class SkeletonManager;
class Q_AUTOTEST_EXPORT Skeleton : public BackendNode
{
public:
+ enum SkeletonDataType {
+ Unknown,
+ File,
+ Data
+ };
+
Skeleton();
void setSkeletonManager(SkeletonManager *skeletonManager) { m_skeletonManager = skeletonManager; }
@@ -84,52 +90,40 @@ public:
JointManager *jointManager() const { return m_jointManager; }
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void setStatus(Qt3DCore::QSkeletonLoader::Status status);
Qt3DCore::QSkeletonLoader::Status status() const { return m_status; }
QUrl source() const { return m_source; }
+ SkeletonDataType dataType() const { return m_dataType; }
+ bool createJoints() const { return m_createJoints; }
void setName(const QString &name) { m_name = name; }
QString name() const { return m_name; }
int jointCount() const { return m_skeletonData.joints.size(); }
- void notifyJointCount();
- void notifyJointNamesAndPoses();
QVector<JointInfo> joints() const { return m_skeletonData.joints; }
+ QVector<QString> jointNames() const { return m_skeletonData.jointNames; }
+ QVector<Qt3DCore::Sqt> localPoses() const { return m_skeletonData.localPoses; }
Qt3DCore::QNodeId rootJointId() const { return m_rootJointId; }
// Called from jobs
- void loadSkeleton();
void setLocalPose(HJoint jointHandle, const Qt3DCore::Sqt &localPose);
QVector<QMatrix4x4> calculateSkinningMatrixPalette();
+ void clearData();
+ void setSkeletonData(const SkeletonData &data);
+ const SkeletonData &skeletonData() const { return m_skeletonData; }
+ SkeletonData skeletonData() { return m_skeletonData; }
+
// Allow unit tests to set the data type
-#if !defined(QT_BUILD_INTERNAL)
-private:
-#endif
- enum SkeletonDataType {
- Unknown,
- File,
- Data
- };
#if defined(QT_BUILD_INTERNAL)
public:
void setDataType(SkeletonDataType dataType) { m_dataType = dataType; }
#endif
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
- void loadSkeletonFromUrl();
- void loadSkeletonFromData();
- Qt3DCore::QJoint *createFrontendJoints(const SkeletonData &skeletonData) const;
- Qt3DCore::QJoint *createFrontendJoint(const QString &jointName,
- const Qt3DCore::Sqt &localPose,
- const QMatrix4x4 &inverseBindMatrix) const;
- void processJointHierarchy(Qt3DCore::QNodeId jointId, int parentJointIndex, SkeletonData &skeletonData);
- void clearData();
-
QVector<QMatrix4x4> m_skinningPalette;
// QSkeletonLoader Properties
diff --git a/src/render/io/qsceneloader.cpp b/src/render/io/qsceneloader.cpp
index d66fe3080..2d53702f6 100644
--- a/src/render/io/qsceneloader.cpp
+++ b/src/render/io/qsceneloader.cpp
@@ -41,7 +41,6 @@
#include "qsceneloader_p.h"
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DRender/qgeometryrenderer.h>
@@ -219,6 +218,27 @@ void QSceneLoaderPrivate::setStatus(QSceneLoader::Status status)
}
}
+void QSceneLoaderPrivate::setSceneRoot(QEntity *root)
+{
+ // If we already have a scene sub tree, delete it
+ if (m_subTreeRoot) {
+ delete m_subTreeRoot;
+ m_subTreeRoot = nullptr;
+ }
+
+ // If we have successfully loaded a scene, graft it in
+ if (root) {
+ // Get the entity to which this component is attached
+ const Qt3DCore::QNodeIdVector entities = m_scene->entitiesForComponent(m_id);
+ Q_ASSERT(entities.size() == 1);
+ Qt3DCore::QNodeId parentEntityId = entities.first();
+ QEntity *parentEntity = qobject_cast<QEntity *>(m_scene->lookupNode(parentEntityId));
+ root->setParent(parentEntity);
+ m_subTreeRoot = root;
+ populateEntityMap(m_subTreeRoot);
+ }
+}
+
/*!
The constructor creates an instance with the specified \a parent.
*/
@@ -232,42 +252,15 @@ QSceneLoader::~QSceneLoader()
{
}
-/*! \internal */
-QSceneLoader::QSceneLoader(QSceneLoaderPrivate &dd, QNode *parent)
- : Qt3DCore::QComponent(dd, parent)
+// TODO Unused remove in Qt6
+void QSceneLoader::sceneChangeEvent(const QSceneChangePtr &)
{
}
-// Called in main thread
/*! \internal */
-void QSceneLoader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+QSceneLoader::QSceneLoader(QSceneLoaderPrivate &dd, QNode *parent)
+ : Qt3DCore::QComponent(dd, parent)
{
- Q_D(QSceneLoader);
- QPropertyUpdatedChangePtr e = qSharedPointerCast<QPropertyUpdatedChange>(change);
- if (e->type() == PropertyUpdated) {
- if (e->propertyName() == QByteArrayLiteral("scene")) {
- // If we already have a scene sub tree, delete it
- if (d->m_subTreeRoot) {
- delete d->m_subTreeRoot;
- d->m_subTreeRoot = nullptr;
- }
-
- // If we have successfully loaded a scene, graft it in
- auto *subTreeRoot = e->value().value<Qt3DCore::QEntity *>();
- if (subTreeRoot) {
- // Get the entity to which this component is attached
- const Qt3DCore::QNodeIdVector entities = d->m_scene->entitiesForComponent(d->m_id);
- Q_ASSERT(entities.size() == 1);
- Qt3DCore::QNodeId parentEntityId = entities.first();
- QEntity *parentEntity = qobject_cast<QEntity *>(d->m_scene->lookupNode(parentEntityId));
- subTreeRoot->setParent(parentEntity);
- d->m_subTreeRoot = subTreeRoot;
- d->populateEntityMap(d->m_subTreeRoot);
- }
- } else if (e->propertyName() == QByteArrayLiteral("status")) {
- d->setStatus(e->value().value<QSceneLoader::Status>());
- }
- }
}
QUrl QSceneLoader::source() const
@@ -324,7 +317,7 @@ QStringList QSceneLoader::entityNames() const
/*!
\qmlmethod Entity SceneLoader::component(string entityName, enumeration componentType)
- Returns a component matching \a componentType of a loaded entity with an \a objectName matching
+ Returns a component matching \a componentType of a loaded entity with an \e objectName matching
the \a entityName.
If the entity has multiple matching components, the first match in the component list of
the entity is returned.
diff --git a/src/render/io/qsceneloader.h b/src/render/io/qsceneloader.h
index 4cb743333..51ba42de7 100644
--- a/src/render/io/qsceneloader.h
+++ b/src/render/io/qsceneloader.h
@@ -60,6 +60,7 @@ public:
explicit QSceneLoader(Qt3DCore::QNode *parent = nullptr);
~QSceneLoader();
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
enum Status {
None = 0,
diff --git a/src/render/io/qsceneloader_p.h b/src/render/io/qsceneloader_p.h
index 50745c66f..213bc1104 100644
--- a/src/render/io/qsceneloader_p.h
+++ b/src/render/io/qsceneloader_p.h
@@ -67,6 +67,7 @@ public:
QSceneLoaderPrivate();
void setStatus(QSceneLoader::Status status);
+ void setSceneRoot(Qt3DCore::QEntity *root);
Q_DECLARE_PUBLIC(QSceneLoader)
diff --git a/src/render/io/scene.cpp b/src/render/io/scene.cpp
index d95f42a48..1a2000bbb 100644
--- a/src/render/io/scene.cpp
+++ b/src/render/io/scene.cpp
@@ -39,7 +39,6 @@
#include "scene_p.h"
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qdownloadhelperservice_p.h>
@@ -66,46 +65,23 @@ void Scene::cleanup()
m_source.clear();
}
-void Scene::setStatus(QSceneLoader::Status status)
+void Scene::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- // Send the new subtree to the frontend or notify failure
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("status");
- e->setValue(QVariant::fromValue(status));
- notifyObservers(e);
-}
+ const QSceneLoader *node = qobject_cast<const QSceneLoader *>(frontEnd);
+ if (!node)
+ return;
-void Scene::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QSceneLoaderData>>(change);
- const auto &data = typedChange->data;
- m_source = data.source;
- Q_ASSERT(m_sceneManager);
- if (Qt3DCore::QDownloadHelperService::isLocal(m_source))
- m_sceneManager->addSceneData(m_source, peerId());
- else
- m_sceneManager->startSceneDownload(m_source, peerId());
-}
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
-void Scene::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("source")) {
- m_source = propertyChange->value().toUrl();
-
- // If the source is empty -> we need to unload anything that was
- // previously loaded and reset the status accordingly. This means
- // we need to call addSceneData with the empty source to send a
- // change to the frontend that will trigger the removal of the
- // previous scene. The reason this scheme is employed is because
- // the backend also takes care of updating the status.
- if (m_source.isEmpty() || Qt3DCore::QDownloadHelperService::isLocal(m_source))
- m_sceneManager->addSceneData(m_source, peerId());
- else
- m_sceneManager->startSceneDownload(m_source, peerId());
- }
+ if (node->source() != m_source) {
+ m_source = node->source();
+ if (m_source.isEmpty() || Qt3DCore::QDownloadHelperService::isLocal(m_source))
+ m_sceneManager->addSceneData(m_source, peerId());
+ else
+ m_sceneManager->startSceneDownload(m_source, peerId());
+
+ const auto d = static_cast<const QSceneLoaderPrivate *>(Qt3DCore::QNodePrivate::get(node));
+ const_cast<QSceneLoaderPrivate *>(d)->setStatus(QSceneLoader::Loading);
}
markDirty(AbstractRenderer::AllDirty);
}
@@ -115,22 +91,6 @@ QUrl Scene::source() const
return m_source;
}
-void Scene::setSceneSubtree(Qt3DCore::QEntity *subTree)
-{
- if (subTree) {
- // Move scene sub tree to the application thread so that it can be grafted in.
- const auto appThread = QCoreApplication::instance()->thread();
- subTree->moveToThread(appThread);
- }
-
- // Send the new subtree to the frontend or notify failure
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("scene");
- e->setValue(QVariant::fromValue(subTree));
- notifyObservers(e);
-}
-
void Scene::setSceneManager(SceneManager *manager)
{
if (m_sceneManager != manager)
diff --git a/src/render/io/scene_p.h b/src/render/io/scene_p.h
index 631f23124..bf625b369 100644
--- a/src/render/io/scene_p.h
+++ b/src/render/io/scene_p.h
@@ -72,17 +72,14 @@ class Q_AUTOTEST_EXPORT Scene : public BackendNode
public:
Scene();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
QUrl source() const;
- void setSceneSubtree(Qt3DCore::QEntity *subTree);
void setSceneManager(SceneManager *manager);
void cleanup();
void setStatus(QSceneLoader::Status status);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
SceneManager *m_sceneManager;
QUrl m_source;
};
diff --git a/src/render/jobs/abstractpickingjob.cpp b/src/render/jobs/abstractpickingjob.cpp
index 74e6a7f80..092ab7d3b 100644
--- a/src/render/jobs/abstractpickingjob.cpp
+++ b/src/render/jobs/abstractpickingjob.cpp
@@ -58,13 +58,26 @@ namespace Qt3DRender {
namespace Render {
AbstractPickingJob::AbstractPickingJob()
- : m_manager(nullptr)
+ : Qt3DCore::QAspectJob()
+ , m_manager(nullptr)
, m_node(nullptr)
, m_frameGraphRoot(nullptr)
, m_renderSettings(nullptr)
+ , m_oneEnabledAtLeast(false)
{
}
+AbstractPickingJob::AbstractPickingJob(Qt3DCore::QAspectJobPrivate &dd)
+ : Qt3DCore::QAspectJob(dd)
+ , m_manager(nullptr)
+ , m_node(nullptr)
+ , m_frameGraphRoot(nullptr)
+ , m_renderSettings(nullptr)
+ , m_oneEnabledAtLeast(false)
+{
+
+}
+
void AbstractPickingJob::setRoot(Entity *root)
{
m_node = root;
diff --git a/src/render/jobs/abstractpickingjob_p.h b/src/render/jobs/abstractpickingjob_p.h
index 059c87aa7..c0c6ed7e9 100644
--- a/src/render/jobs/abstractpickingjob_p.h
+++ b/src/render/jobs/abstractpickingjob_p.h
@@ -90,6 +90,8 @@ public:
const QRect &viewport);
protected:
+ AbstractPickingJob(Qt3DCore::QAspectJobPrivate &dd);
+
void run() final;
NodeManagers *m_manager;
diff --git a/src/render/jobs/filterentitybycomponentjob_p.h b/src/render/jobs/filterentitybycomponentjob_p.h
index dd64e50a7..75e487d7f 100644
--- a/src/render/jobs/filterentitybycomponentjob_p.h
+++ b/src/render/jobs/filterentitybycomponentjob_p.h
@@ -97,10 +97,6 @@ private:
QVector<Entity *> m_filteredEntities;
};
-template<typename T, typename ... Ts>
-using FilterEntityByComponentJobPtr = QSharedPointer<FilterEntityByComponentJob<T, Ts...>>;
-
-
} // Render
} // Qt3DRender
diff --git a/src/render/jobs/filterproximitydistancejob.cpp b/src/render/jobs/filterproximitydistancejob.cpp
index a25e88508..02b712fc2 100644
--- a/src/render/jobs/filterproximitydistancejob.cpp
+++ b/src/render/jobs/filterproximitydistancejob.cpp
@@ -43,8 +43,10 @@ namespace Render {
FilterProximityDistanceJob::FilterProximityDistanceJob()
: m_manager(nullptr)
+ , m_targetEntity(nullptr)
+ , m_distanceThresholdSquared(0.)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::ProximityFiltering, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::ProximityFiltering, 0)
}
void FilterProximityDistanceJob::run()
@@ -55,9 +57,9 @@ void FilterProximityDistanceJob::run()
// Fill m_filteredEntities
// If no filtering needs to be done, this will be the output value
// otherwise it will be used as the base list of entities to filter
- selectAllEntities();
if (hasProximityFilter()) {
+ selectAllEntities();
QVector<Entity *> entitiesToFilter = std::move(m_filteredEntities);
FrameGraphManager *frameGraphManager = m_manager->frameGraphManager();
EntityManager *entityManager = m_manager->renderNodesManager();
diff --git a/src/render/jobs/framecleanupjob.cpp b/src/render/jobs/framecleanupjob.cpp
index ed01e73b4..17ca60bff 100644
--- a/src/render/jobs/framecleanupjob.cpp
+++ b/src/render/jobs/framecleanupjob.cpp
@@ -43,7 +43,6 @@
#include <private/entity_p.h>
#include <private/shaderdata_p.h>
#include <private/managers_p.h>
-#include <private/texturedatamanager_p.h>
#include <private/sphere_p.h>
#include <Qt3DRender/private/job_common_p.h>
diff --git a/src/render/jobs/genericlambdajob_p.h b/src/render/jobs/genericlambdajob_p.h
index d72975761..4d93f0f8d 100644
--- a/src/render/jobs/genericlambdajob_p.h
+++ b/src/render/jobs/genericlambdajob_p.h
@@ -84,6 +84,49 @@ private:
template<typename T>
using GenericLambdaJobPtr = QSharedPointer<GenericLambdaJob<T>>;
+template<typename T, typename U>
+class GenericLambdaJobAndPostFramePrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ explicit GenericLambdaJobAndPostFramePrivate(U postFrameCallable)
+ : m_postFrameCallable(postFrameCallable)
+ {}
+
+ ~GenericLambdaJobAndPostFramePrivate() override {}
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override
+ {
+ m_postFrameCallable(manager);
+ }
+
+private:
+ U m_postFrameCallable;
+};
+
+template<typename T, typename U>
+class GenericLambdaJobAndPostFrame : public Qt3DCore::QAspectJob
+{
+public:
+ explicit GenericLambdaJobAndPostFrame(T runCallable, U postFrameCallable, JobTypes::JobType type = JobTypes::GenericLambda)
+ : Qt3DCore::QAspectJob(*new GenericLambdaJobAndPostFramePrivate<T, U>(postFrameCallable))
+ , m_runCallable(runCallable)
+ {
+ SET_JOB_RUN_STAT_TYPE(this, type, 0);
+ }
+
+ // QAspectJob interface
+ void run() final
+ {
+ m_runCallable();
+ }
+
+private:
+ T m_runCallable;
+};
+
+template<typename T, typename U>
+using GenericLambdaJobAndPostFramePtr = QSharedPointer<GenericLambdaJobAndPostFrame<T, U>>;
+
} // Render
} // Qt3DRender
diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h
index 99bf99195..c3b581277 100644
--- a/src/render/jobs/job_common_p.h
+++ b/src/render/jobs/job_common_p.h
@@ -80,7 +80,7 @@ namespace JobTypes {
LayerFiltering,
EntityComponentTypeFiltering,
MaterialParameterGathering,
- RenderViewBuilder,
+ RenderCommandUpdater,
GenericLambda,
FrustumCulling,
LightGathering,
@@ -92,15 +92,15 @@ namespace JobTypes {
DirtyShaderGathering,
SendRenderCapture,
SendBufferCapture,
- SyncRenderViewCommandBuilding,
+ SyncRenderViewPreCommandUpdate,
SyncRenderViewInitialization,
- SyncRenderViewCommandBuilder,
+ SyncRenderViewPostCommandUpdate,
SyncFrustumCulling,
ClearBufferDrawIndex,
UpdateMeshTriangleList,
FilterCompatibleTechniques,
UpdateLevelOfDetail,
- SyncTextureLoading,
+ SyncLoadingJobs,
LoadSkeleton,
UpdateSkinningPalette,
ProximityFiltering,
@@ -109,7 +109,9 @@ namespace JobTypes {
UpdateLayerEntity,
SendTextureChangesToFrontend,
SendSetFenceHandlesToFrontend,
- UpdateEntityHierarchy,
+ SendDisablesToFrontend,
+ RenderViewCommandBuilder,
+ SyncRenderViewPreCommandBuilding
};
} // JobTypes
diff --git a/src/render/jobs/jobs.pri b/src/render/jobs/jobs.pri
index 0c326c0b5..2181e4a95 100644
--- a/src/render/jobs/jobs.pri
+++ b/src/render/jobs/jobs.pri
@@ -4,7 +4,6 @@ HEADERS += \
$$PWD/updateworldtransformjob_p.h \
$$PWD/loadscenejob_p.h \
$$PWD/framecleanupjob_p.h \
- $$PWD/loadtexturedatajob_p.h \
$$PWD/loadbufferjob_p.h \
$$PWD/loadgeometryjob_p.h \
$$PWD/calcboundingvolumejob_p.h \
@@ -31,14 +30,12 @@ HEADERS += \
$$PWD/filterproximitydistancejob_p.h \
$$PWD/abstractpickingjob_p.h \
$$PWD/raycastingjob_p.h \
- $$PWD/updateentityhierarchyjob_p.h \
$$PWD/updateentitylayersjob_p.h
SOURCES += \
$$PWD/updateworldtransformjob.cpp \
$$PWD/loadscenejob.cpp \
$$PWD/framecleanupjob.cpp \
- $$PWD/loadtexturedatajob.cpp \
$$PWD/loadbufferjob.cpp \
$$PWD/loadgeometryjob.cpp \
$$PWD/calcboundingvolumejob.cpp \
@@ -62,6 +59,5 @@ SOURCES += \
$$PWD/filterproximitydistancejob.cpp \
$$PWD/abstractpickingjob.cpp \
$$PWD/raycastingjob.cpp \
- $$PWD/updateentityhierarchyjob.cpp \
$$PWD/updateentitylayersjob.cpp
diff --git a/src/render/jobs/lightgatherer.cpp b/src/render/jobs/lightgatherer.cpp
index b76cd4d73..f4c8dfba8 100644
--- a/src/render/jobs/lightgatherer.cpp
+++ b/src/render/jobs/lightgatherer.cpp
@@ -58,6 +58,9 @@ LightGatherer::LightGatherer()
void LightGatherer::run()
{
+ m_lights.clear();
+ m_environmentLight = nullptr;
+
const QVector<HEntity> handles = m_manager->activeHandles();
int envLightCount = 0;
diff --git a/src/render/jobs/loadbufferjob.cpp b/src/render/jobs/loadbufferjob.cpp
index 49f271df5..68e92cfa7 100644
--- a/src/render/jobs/loadbufferjob.cpp
+++ b/src/render/jobs/loadbufferjob.cpp
@@ -39,9 +39,11 @@
#include "loadbufferjob_p.h"
#include <Qt3DRender/private/buffer_p.h>
+#include <Qt3DRender/private/qbuffer_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/job_common_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
QT_BEGIN_NAMESPACE
@@ -49,13 +51,24 @@ namespace Qt3DRender {
namespace Render {
+class LoadBufferJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ LoadBufferJobPrivate() {}
+ ~LoadBufferJobPrivate() {}
+
+ void postFrame(Qt3DCore::QAspectManager *aspectManager) override;
+
+ Buffer *m_bufferToUpdate = nullptr;
+};
+
LoadBufferJob::LoadBufferJob(const HBuffer &handle)
- : QAspectJob()
+ : QAspectJob(*new LoadBufferJobPrivate)
, m_handle(handle)
, m_nodeManagers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadBuffer, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadBuffer, 0)
}
LoadBufferJob::~LoadBufferJob()
@@ -64,10 +77,25 @@ LoadBufferJob::~LoadBufferJob()
void LoadBufferJob::run()
{
+ Q_DJOB(LoadBufferJob);
// Let's leave it for the moment until this has been properly tested
qCDebug(Jobs) << Q_FUNC_INFO;
Buffer *buffer = m_nodeManagers->data<Buffer, BufferManager>(m_handle);
buffer->executeFunctor();
+ if (buffer->isSyncData())
+ d->m_bufferToUpdate = buffer;
+}
+
+void LoadBufferJobPrivate::postFrame(Qt3DCore::QAspectManager *aspectManager)
+{
+ if (m_bufferToUpdate == nullptr)
+ return;
+ QBuffer *frontendBuffer = static_cast<decltype(frontendBuffer)>(aspectManager->lookupNode(m_bufferToUpdate->peerId()));
+ QBufferPrivate *dFrontend = static_cast<decltype(dFrontend)>(Qt3DCore::QNodePrivate::get(frontendBuffer));
+ // Calling frontendBuffer->setData would result in forcing a sync against the backend
+ // which isn't necessary
+ dFrontend->setData(m_bufferToUpdate->data());
+ m_bufferToUpdate = nullptr;
}
} // namespace Render
diff --git a/src/render/jobs/loadbufferjob_p.h b/src/render/jobs/loadbufferjob_p.h
index 6a221c7e0..884870a62 100644
--- a/src/render/jobs/loadbufferjob_p.h
+++ b/src/render/jobs/loadbufferjob_p.h
@@ -63,6 +63,7 @@ namespace Qt3DRender {
namespace Render {
class NodeManagers;
+class LoadBufferJobPrivate;
class Q_AUTOTEST_EXPORT LoadBufferJob : public Qt3DCore::QAspectJob
{
diff --git a/src/render/jobs/loadgeometryjob.cpp b/src/render/jobs/loadgeometryjob.cpp
index d28b15a7c..3d32f7d4e 100644
--- a/src/render/jobs/loadgeometryjob.cpp
+++ b/src/render/jobs/loadgeometryjob.cpp
@@ -41,6 +41,8 @@
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/private/job_common_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DRender/private/qmesh_p.h>
QT_BEGIN_NAMESPACE
@@ -48,8 +50,19 @@ namespace Qt3DRender {
namespace Render {
+class LoadGeometryJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ LoadGeometryJobPrivate() {}
+ ~LoadGeometryJobPrivate() {}
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ QVector<std::pair<Qt3DCore::QNodeId, GeometryFunctorResult>> m_updates;
+};
+
LoadGeometryJob::LoadGeometryJob(const HGeometryRenderer &handle)
- : QAspectJob()
+ : QAspectJob(*new LoadGeometryJobPrivate)
, m_handle(handle)
, m_nodeManagers(nullptr)
{
@@ -62,9 +75,27 @@ LoadGeometryJob::~LoadGeometryJob()
void LoadGeometryJob::run()
{
+ Q_DJOB(LoadGeometryJob);
GeometryRenderer *geometryRenderer = m_nodeManagers->geometryRendererManager()->data(m_handle);
if (geometryRenderer != nullptr)
- geometryRenderer->executeFunctor();
+ d->m_updates.push_back({ geometryRenderer->peerId(), geometryRenderer->executeFunctor() });
+}
+
+void LoadGeometryJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ const auto updates = std::move(m_updates);
+ for (const auto &update : updates) {
+ QGeometryRenderer *gR = static_cast<decltype(gR)>(manager->lookupNode(update.first));
+ const GeometryFunctorResult &result = update.second;
+ gR->setGeometry(result.geometry);
+
+ // Set status if gR is a QMesh instance
+ QMesh *mesh = qobject_cast<QMesh *>(gR);
+ if (mesh) {
+ QMeshPrivate *dMesh = static_cast<decltype(dMesh)>(Qt3DCore::QNodePrivate::get(mesh));
+ dMesh->setStatus(result.status);
+ }
+ }
}
} // namespace Render
diff --git a/src/render/jobs/loadgeometryjob_p.h b/src/render/jobs/loadgeometryjob_p.h
index c02739647..869abbe18 100644
--- a/src/render/jobs/loadgeometryjob_p.h
+++ b/src/render/jobs/loadgeometryjob_p.h
@@ -62,6 +62,7 @@ namespace Qt3DRender {
namespace Render {
class NodeManagers;
+class LoadGeometryJobPrivate;
class Q_AUTOTEST_EXPORT LoadGeometryJob : public Qt3DCore::QAspectJob
{
diff --git a/src/render/jobs/loadscenejob.cpp b/src/render/jobs/loadscenejob.cpp
index 9885d3225..22d5da887 100644
--- a/src/render/jobs/loadscenejob.cpp
+++ b/src/render/jobs/loadscenejob.cpp
@@ -42,10 +42,12 @@
#include <private/nodemanagers_p.h>
#include <private/scenemanager_p.h>
#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DRender/private/job_common_p.h>
#include <Qt3DRender/private/qsceneimporter_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>
#include <Qt3DRender/qsceneloader.h>
+#include <Qt3DRender/private/qsceneloader_p.h>
#include <Qt3DRender/private/renderlogging_p.h>
#include <QFileInfo>
#include <QMimeDatabase>
@@ -55,10 +57,10 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
namespace Render {
-LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId m_sceneComponent)
- : QAspectJob()
+LoadSceneJob::LoadSceneJob(const QUrl &source, Qt3DCore::QNodeId sceneComponent)
+ : QAspectJob(*new LoadSceneJobPrivate(this))
, m_source(source)
- , m_sceneComponent(m_sceneComponent)
+ , m_sceneComponent(sceneComponent)
, m_managers(nullptr)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadScene, 0);
@@ -97,7 +99,6 @@ void LoadSceneJob::run()
Q_ASSERT(scene);
// Reset status
- scene->setStatus(QSceneLoader::None);
QSceneLoader::Status finalStatus = QSceneLoader::None;
// Perform the loading only if the source wasn't explicitly set to empty
@@ -110,8 +111,7 @@ void LoadSceneJob::run()
qCDebug(SceneLoaders) << Q_FUNC_INFO << "Attempting to load" << finfo.filePath();
if (finfo.exists()) {
const QStringList extensions(finfo.suffix());
- sceneSubTree = tryLoadScene(scene,
- finalStatus,
+ sceneSubTree = tryLoadScene(finalStatus,
extensions,
[this] (QSceneImporter *importer) {
importer->setSource(m_source);
@@ -131,8 +131,7 @@ void LoadSceneJob::run()
const QString basePath = m_source.adjusted(QUrl::RemoveFilename).toString();
- sceneSubTree = tryLoadScene(scene,
- finalStatus,
+ sceneSubTree = tryLoadScene(finalStatus,
extensions,
[this, basePath] (QSceneImporter *importer) {
importer->setData(m_data, basePath);
@@ -140,19 +139,18 @@ void LoadSceneJob::run()
}
}
- // If the sceneSubTree is null it will trigger the frontend to unload
- // any subtree it may hold
- // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree
- // to the QCoreApplication thread which is where the frontend object tree lives.
- scene->setSceneSubtree(sceneSubTree);
+ Q_DJOB(LoadSceneJob);
+ d->m_sceneSubtree = sceneSubTree;
+ d->m_status = finalStatus;
- // Note: the status is set after the subtree so that bindinds depending on the status
- // in the frontend will be consistent
- scene->setStatus(finalStatus);
+ if (d->m_sceneSubtree) {
+ // Move scene sub tree to the application thread so that it can be grafted in.
+ const auto appThread = QCoreApplication::instance()->thread();
+ d->m_sceneSubtree->moveToThread(appThread);
+ }
}
-Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(Scene *scene,
- QSceneLoader::Status &finalStatus,
+Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(QSceneLoader::Status &finalStatus,
const QStringList &extensions,
const std::function<void (QSceneImporter *)> &importerSetupFunc)
{
@@ -165,9 +163,6 @@ Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(Scene *scene,
foundSuitableLoggerPlugin = true;
- // If the file type is supported -> enter Loading status
- scene->setStatus(QSceneLoader::Loading);
-
// Set source file or data on importer
importerSetupFunc(sceneImporter);
@@ -188,6 +183,27 @@ Qt3DCore::QEntity *LoadSceneJob::tryLoadScene(Scene *scene,
return sceneSubTree;
}
+void LoadSceneJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ Q_Q(LoadSceneJob);
+ QSceneLoader *node =
+ qobject_cast<QSceneLoader *>(manager->lookupNode(q->sceneComponentId()));
+ if (!node)
+ return;
+ Qt3DRender::QSceneLoaderPrivate *dNode =
+ static_cast<decltype(dNode)>(Qt3DCore::QNodePrivate::get(node));
+
+ // If the sceneSubTree is null it will trigger the frontend to unload
+ // any subtree it may hold
+ // Set clone of sceneTree in sceneComponent. This will move the sceneSubTree
+ // to the QCoreApplication thread which is where the frontend object tree lives.
+ dNode->setSceneRoot(m_sceneSubtree);
+
+ // Note: the status is set after the subtree so that bindinds depending on the status
+ // in the frontend will be consistent
+ dNode->setStatus(m_status);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/jobs/loadscenejob_p.h b/src/render/jobs/loadscenejob_p.h
index 0c77dc6e8..79c8a2935 100644
--- a/src/render/jobs/loadscenejob_p.h
+++ b/src/render/jobs/loadscenejob_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DCore/private/qaspectjob_p.h>
#include <Qt3DCore/qnodeid.h>
#include <Qt3DRender/qsceneloader.h>
#include <QSharedPointer>
@@ -69,6 +70,24 @@ namespace Render {
class Scene;
class NodeManagers;
+class LoadSceneJob;
+
+class Q_AUTOTEST_EXPORT LoadSceneJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ explicit LoadSceneJobPrivate(LoadSceneJob *q): q_ptr(q) {}
+ ~LoadSceneJobPrivate() override {}
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ Qt3DCore::QEntity *m_sceneSubtree = nullptr;
+ QSceneLoader::Status m_status = QSceneLoader::None;
+
+ Q_DECLARE_PUBLIC(LoadSceneJob)
+private:
+ LoadSceneJob *q_ptr;
+};
+
class Q_AUTOTEST_EXPORT LoadSceneJob : public Qt3DCore::QAspectJob
{
public:
@@ -91,8 +110,7 @@ private:
NodeManagers *m_managers;
QList<QSceneImporter *> m_sceneImporters;
- Qt3DCore::QEntity *tryLoadScene(Scene *scene,
- QSceneLoader::Status &finalStatus,
+ Qt3DCore::QEntity *tryLoadScene(QSceneLoader::Status &finalStatus,
const QStringList &extensions,
const std::function<void (QSceneImporter *)> &importerSetupFunc);
};
diff --git a/src/render/jobs/loadskeletonjob.cpp b/src/render/jobs/loadskeletonjob.cpp
index 413afc5b5..6f7bcd9b7 100644
--- a/src/render/jobs/loadskeletonjob.cpp
+++ b/src/render/jobs/loadskeletonjob.cpp
@@ -35,32 +35,263 @@
****************************************************************************/
#include "loadskeletonjob_p.h"
-#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DCore/qjoint.h>
+#include <Qt3DCore/qabstractskeleton.h>
+#include <Qt3DCore/qskeletonloader.h>
+#include <Qt3DCore/private/qabstractskeleton_p.h>
+#include <Qt3DCore/private/qabstractnodefactory_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qskeletonloader_p.h>
#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/job_common_p.h>
+#include <Qt3DRender/private/qurlhelper_p.h>
+#include <Qt3DRender/private/gltfskeletonloader_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
namespace Render {
+class LoadSkeletonJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ LoadSkeletonJobPrivate() : m_backendSkeleton(nullptr), m_loadedRootJoint(nullptr) { }
+ ~LoadSkeletonJobPrivate() override { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ Skeleton *m_backendSkeleton;
+ Qt3DCore::QJoint* m_loadedRootJoint;
+};
+
LoadSkeletonJob::LoadSkeletonJob(const HSkeleton &handle)
- : QAspectJob()
+ : QAspectJob(*new LoadSkeletonJobPrivate)
, m_handle(handle)
, m_nodeManagers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadSkeleton, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadSkeleton, 0)
}
-LoadSkeletonJob::~LoadSkeletonJob()
+void LoadSkeletonJob::run()
{
+ Q_DJOB(LoadSkeletonJob);
+ d->m_backendSkeleton = nullptr;
+
+ Skeleton *skeleton = m_nodeManagers->skeletonManager()->data(m_handle);
+ if (skeleton != nullptr) {
+ d->m_backendSkeleton = skeleton;
+ loadSkeleton(skeleton);
+ }
}
-void LoadSkeletonJob::run()
+void LoadSkeletonJob::loadSkeleton(Skeleton *skeleton)
{
- Skeleton *skeleton = m_nodeManagers->skeletonManager()->data(m_handle);
- if (skeleton != nullptr)
- skeleton->loadSkeleton();
+ qCDebug(Jobs) << Q_FUNC_INFO << skeleton->source();
+ skeleton->clearData();
+
+ // Load the data
+ switch (skeleton->dataType()) {
+ case Skeleton::File:
+ loadSkeletonFromUrl(skeleton);
+ break;
+
+ case Skeleton::Data:
+ loadSkeletonFromData(skeleton);
+ break;
+
+ default:
+ Q_UNREACHABLE();
+ }
+
+ // If using a loader inform the frontend of the status change.
+ // Don't bother if asked to create frontend joints though. When
+ // the backend gets notified of those joints we'll update the
+ // status at that point.
+ if (skeleton->dataType() == Skeleton::File && !skeleton->createJoints()) {
+ if (skeleton->jointCount() == 0)
+ skeleton->setStatus(Qt3DCore::QSkeletonLoader::Error);
+ else
+ skeleton->setStatus(Qt3DCore::QSkeletonLoader::Ready);
+ }
+
+ qCDebug(Jobs) << "Loaded skeleton data:" << *skeleton;
+}
+
+void LoadSkeletonJob::loadSkeletonFromUrl(Skeleton *skeleton)
+{
+ Q_DJOB(LoadSkeletonJob);
+
+ using namespace Qt3DCore;
+
+ // TODO: Handle remote files
+ QString filePath = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(skeleton->source());
+ QFileInfo info(filePath);
+ if (!info.exists()) {
+ qWarning() << "Could not open skeleton file:" << filePath;
+ skeleton->setStatus(Qt3DCore::QSkeletonLoader::Error);
+ return;
+ }
+
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "Could not open skeleton file:" << filePath;
+ skeleton->setStatus(QSkeletonLoader::Error);
+ return;
+ }
+
+ // TODO: Make plugin based for more file type support. For now gltf or native
+ const QString ext = info.suffix();
+ SkeletonData skeletonData;
+ if (ext == QLatin1String("gltf")) {
+ GLTFSkeletonLoader loader;
+ loader.load(&file);
+ skeletonData = loader.createSkeleton(skeleton->name());
+
+ // If the user has requested it, create the frontend nodes for the joints
+ // and send them to the (soon to be owning) QSkeletonLoader.
+ if (skeleton->createJoints()) {
+ QJoint *rootJoint = createFrontendJoints(skeletonData);
+ if (!rootJoint) {
+ qWarning() << "Failed to create frontend joints";
+ skeleton->setStatus(QSkeletonLoader::Error);
+ return;
+ }
+
+ // Move the QJoint tree to the main thread and notify the
+ // corresponding QSkeletonLoader
+ const auto appThread = QCoreApplication::instance()->thread();
+ rootJoint->moveToThread(appThread);
+
+ d->m_loadedRootJoint = rootJoint;
+
+ // Clear the skeleton data. It will be recreated from the
+ // frontend joints. A little bit inefficient but ensures
+ // that joints created this way and via QSkeleton go through
+ // the same code path.
+ skeletonData = SkeletonData();
+ }
+ } else if (ext == QLatin1String("json")) {
+ // TODO: Support native skeleton type
+ } else {
+ qWarning() << "Unknown skeleton file type:" << ext;
+ skeleton->setStatus(QSkeletonLoader::Error);
+ return;
+ }
+
+ skeleton->setSkeletonData(skeletonData);
+}
+
+void LoadSkeletonJob::loadSkeletonFromData(Skeleton *skeleton)
+{
+ // Recurse down through the joint hierarchy and process it into
+ // the vector of joints used within SkeletonData. The recursion
+ // ensures that a parent always appears before its children in
+ // the vector of JointInfo objects.
+ //
+ // In addition, we set up a mapping from the joint ids to the
+ // index of the corresponding JointInfo object in the vector.
+ // This will allow us to easily update entries in the vector of
+ // JointInfos when a Joint node marks itself as dirty.
+ const int rootParentIndex = -1;
+ auto skeletonData = skeleton->skeletonData();
+ processJointHierarchy(skeleton->rootJointId(), rootParentIndex, skeletonData);
+ skeleton->setSkeletonData(skeletonData);
+}
+
+Qt3DCore::QJoint *LoadSkeletonJob::createFrontendJoints(const SkeletonData &skeletonData) const
+{
+ if (skeletonData.joints.isEmpty())
+ return nullptr;
+
+ // Create frontend joints from the joint info objects
+ QVector<Qt3DCore::QJoint *> frontendJoints;
+ const int jointCount = skeletonData.joints.size();
+ frontendJoints.reserve(jointCount);
+ for (int i = 0; i < jointCount; ++i) {
+ const QMatrix4x4 &inverseBindMatrix = skeletonData.joints[i].inverseBindPose;
+ const QString &jointName = skeletonData.jointNames[i];
+ const Qt3DCore::Sqt &localPose = skeletonData.localPoses[i];
+ frontendJoints.push_back(createFrontendJoint(jointName, localPose, inverseBindMatrix));
+ }
+
+ // Now go through and resolve the parent for each joint
+ for (int i = 0; i < frontendJoints.size(); ++i) {
+ const auto parentIndex = skeletonData.joints[i].parentIndex;
+ if (parentIndex == -1)
+ continue;
+
+ // It's not enough to just set up the QObject parent-child relationship.
+ // We need to explicitly add the child to the parent's list of joints so
+ // that information is then propagated to the backend.
+ frontendJoints[parentIndex]->addChildJoint(frontendJoints[i]);
+ }
+
+ return frontendJoints[0];
+}
+
+Qt3DCore::QJoint *LoadSkeletonJob::createFrontendJoint(const QString &jointName,
+ const Qt3DCore::Sqt &localPose,
+ const QMatrix4x4 &inverseBindMatrix) const
+{
+ auto joint = Qt3DCore::QAbstractNodeFactory::createNode<Qt3DCore::QJoint>("QJoint");
+ joint->setTranslation(localPose.translation);
+ joint->setRotation(localPose.rotation);
+ joint->setScale(localPose.scale);
+ joint->setInverseBindMatrix(inverseBindMatrix);
+ joint->setName(jointName);
+ return joint;
+}
+
+void LoadSkeletonJob::processJointHierarchy(Qt3DCore::QNodeId jointId,
+ int parentJointIndex,
+ SkeletonData &skeletonData)
+{
+ // Lookup the joint, create a JointInfo, and add an entry to the index map
+ Joint *joint = m_nodeManagers->jointManager()->lookupResource(jointId);
+ Q_ASSERT(joint);
+ joint->setOwningSkeleton(m_handle);
+ const JointInfo jointInfo(joint, parentJointIndex);
+ skeletonData.joints.push_back(jointInfo);
+ skeletonData.localPoses.push_back(joint->localPose());
+ skeletonData.jointNames.push_back(joint->name());
+
+ const int jointIndex = skeletonData.joints.size() - 1;
+ const HJoint jointHandle = m_nodeManagers->jointManager()->lookupHandle(jointId);
+ skeletonData.jointIndices.insert(jointHandle, jointIndex);
+
+ // Recurse to the children
+ const auto childIds = joint->childJointIds();
+ for (const auto &childJointId : childIds)
+ processJointHierarchy(childJointId, jointIndex, skeletonData);
+}
+
+void LoadSkeletonJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ if (!m_backendSkeleton)
+ return;
+
+ using namespace Qt3DCore;
+ QAbstractSkeleton *node = qobject_cast<QAbstractSkeleton *>(manager->lookupNode(m_backendSkeleton->peerId()));
+ if (!node)
+ return;
+
+ QAbstractSkeletonPrivate *dnode = QAbstractSkeletonPrivate::get(node);
+ dnode->m_jointCount = m_backendSkeleton->jointCount();
+ dnode->m_jointNames = m_backendSkeleton->jointNames();
+ dnode->m_localPoses = m_backendSkeleton->localPoses();
+ dnode->update();
+
+ QSkeletonLoader *loaderNode = qobject_cast<QSkeletonLoader *>(node);
+ if (loaderNode) {
+ QSkeletonLoaderPrivate *dloaderNode = static_cast<QSkeletonLoaderPrivate *>(QSkeletonLoaderPrivate::get(loaderNode));
+ dloaderNode->setStatus(m_backendSkeleton->status());
+
+ if (m_loadedRootJoint) {
+ dloaderNode->setRootJoint(m_loadedRootJoint);
+ m_loadedRootJoint = nullptr;
+ }
+ }
}
} // namespace Render
diff --git a/src/render/jobs/loadskeletonjob_p.h b/src/render/jobs/loadskeletonjob_p.h
index 2cd9fa8bf..5ea4912ee 100644
--- a/src/render/jobs/loadskeletonjob_p.h
+++ b/src/render/jobs/loadskeletonjob_p.h
@@ -51,26 +51,41 @@
#include <Qt3DCore/qaspectjob.h>
#include <QtCore/qsharedpointer.h>
-
+#include <Qt3DRender/private/skeletondata_p.h>
#include <Qt3DRender/private/handle_types_p.h>
QT_BEGIN_NAMESPACE
+namespace Qt3DCore {
+class QJoint;
+}
+
namespace Qt3DRender {
namespace Render {
class NodeManagers;
+class LoadSkeletonJobPrivate;
class LoadSkeletonJob : public Qt3DCore::QAspectJob
{
public:
explicit LoadSkeletonJob(const HSkeleton &handle);
- ~LoadSkeletonJob();
void setNodeManagers(NodeManagers *nodeManagers) { m_nodeManagers = nodeManagers; }
protected:
void run() override;
+ void loadSkeleton(Skeleton *skeleton);
+ void loadSkeletonFromUrl(Skeleton *skeleton);
+ void loadSkeletonFromData(Skeleton *skeleton);
+ Qt3DCore::QJoint *createFrontendJoints(const SkeletonData &skeletonData) const;
+ Qt3DCore::QJoint *createFrontendJoint(const QString &jointName,
+ const Qt3DCore::Sqt &localPose,
+ const QMatrix4x4 &inverseBindMatrix) const;
+ void processJointHierarchy(Qt3DCore::QNodeId jointId,
+ int parentJointIndex,
+ SkeletonData &skeletonData);
+
HSkeleton m_handle;
NodeManagers *m_nodeManagers;
};
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp
index 1a6cd7ba4..ae0cb2350 100644
--- a/src/render/jobs/pickboundingvolumejob.cpp
+++ b/src/render/jobs/pickboundingvolumejob.cpp
@@ -41,7 +41,11 @@
#include "qpicktriangleevent.h"
#include "qpicklineevent.h"
#include "qpickpointevent.h"
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DRender/qobjectpicker.h>
+#include <Qt3DRender/qviewport.h>
#include <Qt3DRender/qgeometryrenderer.h>
+#include <Qt3DRender/private/qobjectpicker_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/entity_p.h>
@@ -65,6 +69,82 @@ using namespace Qt3DRender::RayCasting;
namespace Render {
+class PickBoundingVolumeJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ PickBoundingVolumeJobPrivate() = default;
+ ~PickBoundingVolumeJobPrivate() override = default;
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ enum CustomEventType {
+ MouseButtonClick = QEvent::User,
+ };
+
+ struct EventDetails {
+ Qt3DCore::QNodeId pickerId;
+ int sourceEventType;
+ QPickEventPtr resultingEvent;
+ Qt3DCore::QNodeId viewportNodeId;
+ };
+
+ QVector<EventDetails> dispatches;
+};
+
+
+void PickBoundingVolumeJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ using namespace Qt3DCore;
+ QNodeId previousId;
+ QObjectPicker *node = nullptr;
+
+ for (auto res: qAsConst(dispatches)) {
+ if (previousId != res.pickerId) {
+ node = qobject_cast<QObjectPicker *>(manager->lookupNode(res.pickerId));
+ previousId = res.pickerId;
+ }
+ if (!node)
+ continue;
+
+ QObjectPickerPrivate *dnode = static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node));
+
+ // resolve front end details
+ QPickEvent *pickEvent = res.resultingEvent.data();
+ if (pickEvent) {
+ QPickEventPrivate *dpickEvent = QPickEventPrivate::get(pickEvent);
+ dpickEvent->m_viewport = static_cast<QViewport *>(manager->lookupNode(res.viewportNodeId));
+ dpickEvent->m_entityPtr = static_cast<QEntity *>(manager->lookupNode(dpickEvent->m_entity));
+ }
+
+ // dispatch event
+ switch (res.sourceEventType) {
+ case QEvent::MouseButtonPress:
+ dnode->pressedEvent(pickEvent);
+ break;
+ case QEvent::MouseButtonRelease:
+ dnode->releasedEvent(pickEvent);
+ break;
+ case MouseButtonClick:
+ dnode->clickedEvent(pickEvent);
+ break;
+ case QEvent::MouseMove:
+ dnode->movedEvent(pickEvent);
+ break;
+ case QEvent::Enter:
+ emit node->entered();
+ dnode->setContainsMouse(true);
+ break;
+ case QEvent::Leave:
+ dnode->setContainsMouse(false);
+ emit node->exited();
+ break;
+ default: Q_UNREACHABLE();
+ }
+ }
+
+ dispatches.clear();
+}
+
namespace {
void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &eventButton, int &eventButtons, int &eventModifiers)
@@ -109,10 +189,10 @@ void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &e
} // anonymous
PickBoundingVolumeJob::PickBoundingVolumeJob()
- : AbstractPickingJob()
+ : AbstractPickingJob(*new PickBoundingVolumeJobPrivate)
, m_pickersDirty(true)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0)
}
void PickBoundingVolumeJob::setRoot(Entity *root)
@@ -236,7 +316,8 @@ bool PickBoundingVolumeJob::runHelper()
// has moved out of the viewport In case of a button released
// outside of the viewport, we still want to notify the
// lastCurrent entity about this.
- dispatchPickEvents(event.second, PickingUtils::HitList(), eventButton, eventButtons, eventModifiers, m_renderSettings->pickResultMode());
+ dispatchPickEvents(event.second, PickingUtils::HitList(), eventButton, eventButtons, eventModifiers, m_renderSettings->pickResultMode(),
+ vca.viewportNodeId);
continue;
}
@@ -278,7 +359,8 @@ bool PickBoundingVolumeJob::runHelper()
}
// Dispatch events based on hit results
- dispatchPickEvents(event.second, sphereHits, eventButton, eventButtons, eventModifiers, m_renderSettings->pickResultMode());
+ dispatchPickEvents(event.second, sphereHits, eventButton, eventButtons, eventModifiers, m_renderSettings->pickResultMode(),
+ vca.viewportNodeId);
}
}
@@ -295,8 +377,11 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
QPickEvent::Buttons eventButton,
int eventButtons,
int eventModifiers,
- bool allHitsRequested)
+ bool allHitsRequested,
+ Qt3DCore::QNodeId viewportNodeId)
{
+ Q_DJOB(PickBoundingVolumeJob);
+
ObjectPicker *lastCurrentPicker = m_manager->objectPickerManager()->data(m_currentPicker);
// If we have hits
if (!sphereHits.isEmpty()) {
@@ -380,37 +465,43 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
// Store pressed object handle
m_currentPicker = objectPickerHandle;
// Send pressed event to m_currentPicker
- objectPicker->onPressed(pickEvent);
+ d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId});
+ objectPicker->setPressed(true);
break;
}
case QEvent::MouseButtonRelease: {
// Only send the release event if it was pressed
- if (objectPicker->isPressed())
- objectPicker->onReleased(pickEvent);
+ if (objectPicker->isPressed()) {
+ d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId});
+ objectPicker->setPressed(false);
+ }
if (lastCurrentPicker != nullptr && m_currentPicker == objectPickerHandle) {
- objectPicker->onClicked(pickEvent);
+ d->dispatches.push_back({objectPicker->peerId(),
+ PickBoundingVolumeJobPrivate::MouseButtonClick,
+ pickEvent, viewportNodeId});
m_currentPicker = HObjectPicker();
}
break;
}
#if QT_CONFIG(gestures)
case QEvent::Gesture: {
- objectPicker->onClicked(pickEvent);
+ d->dispatches.push_back({objectPicker->peerId(),
+ PickBoundingVolumeJobPrivate::MouseButtonClick,
+ pickEvent, viewportNodeId});
break;
}
#endif
case QEvent::MouseMove: {
- if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled()) {
- objectPicker->onMoved(pickEvent);
- }
+ if ((objectPicker->isPressed() || objectPicker->isHoverEnabled()) && objectPicker->isDragEnabled())
+ d->dispatches.push_back({objectPicker->peerId(), event.type(), pickEvent, viewportNodeId});
Q_FALLTHROUGH(); // fallthrough
}
case QEvent::HoverMove: {
if (!m_hoveredPickers.contains(objectPickerHandle)) {
if (objectPicker->isHoverEnabled()) {
// Send entered event to objectPicker
- objectPicker->onEntered();
+ d->dispatches.push_back({objectPicker->peerId(), QEvent::Enter, pickEvent, viewportNodeId});
// and save it in the hoveredPickers
m_hoveredPickers.push_back(objectPickerHandle);
}
@@ -437,7 +528,8 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
if (lastCurrentPicker != nullptr) {
m_currentPicker = HObjectPicker();
QPickEventPtr pickEvent(new QPickEvent);
- lastCurrentPicker->onReleased(pickEvent);
+ lastCurrentPicker->setPressed(false);
+ d->dispatches.push_back({lastCurrentPicker->peerId(), event.type(), pickEvent, viewportNodeId});
}
break;
}
@@ -449,12 +541,15 @@ void PickBoundingVolumeJob::dispatchPickEvents(const QMouseEvent &event,
void PickBoundingVolumeJob::clearPreviouslyHoveredPickers()
{
+ Q_DJOB(PickBoundingVolumeJob);
+
for (const HObjectPicker &pickHandle : qAsConst(m_hoveredPickersToClear)) {
ObjectPicker *pick = m_manager->objectPickerManager()->data(pickHandle);
if (pick)
- pick->onExited();
+ d->dispatches.push_back({pick->peerId(), QEvent::Leave, {}, {}});
m_hoveredPickers.removeAll(pickHandle);
}
+
m_hoveredPickersToClear.clear();
}
diff --git a/src/render/jobs/pickboundingvolumejob_p.h b/src/render/jobs/pickboundingvolumejob_p.h
index 2c38c400b..751d0be7b 100644
--- a/src/render/jobs/pickboundingvolumejob_p.h
+++ b/src/render/jobs/pickboundingvolumejob_p.h
@@ -66,7 +66,11 @@
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+
+class QViewport;
+
namespace Render {
+class PickBoundingVolumeJobPrivate;
namespace PickingUtils {
typedef QVector<RayCasting::QCollisionQueryResult::Hit> HitList;
@@ -94,7 +98,8 @@ protected:
QPickEvent::Buttons eventButton,
int eventButtons,
int eventModifiers,
- bool allHitsRequested);
+ bool allHitsRequested,
+ Qt3DCore::QNodeId viewportNodeId);
private:
void clearPreviouslyHoveredPickers();
diff --git a/src/render/jobs/pickboundingvolumeutils.cpp b/src/render/jobs/pickboundingvolumeutils.cpp
index abc54482a..1d22e8645 100644
--- a/src/render/jobs/pickboundingvolumeutils.cpp
+++ b/src/render/jobs/pickboundingvolumeutils.cpp
@@ -86,15 +86,25 @@ ViewportCameraAreaDetails ViewportCameraAreaGatherer::gatherUpViewportCameraArea
case FrameGraphNode::CameraSelector:
vca.cameraId = static_cast<const CameraSelector *>(node)->cameraUuid();
break;
- case FrameGraphNode::Viewport:
- vca.viewport = ViewportNode::computeViewport(vca.viewport, static_cast<const ViewportNode *>(node));
+ case FrameGraphNode::Viewport: {
+ auto vnode = static_cast<const ViewportNode *>(node);
+ // we want the leaf viewport so if we have a viewport node already don't override it with its parent
+ if (!vca.viewportNodeId)
+ vca.viewportNodeId = vnode->peerId();
+ vca.viewport = ViewportNode::computeViewport(vca.viewport, vnode);
break;
+ }
case FrameGraphNode::Surface: {
auto selector = static_cast<const RenderSurfaceSelector *>(node);
vca.area = selector->renderTargetSize();
vca.surface = selector->surface();
break;
}
+ case FrameGraphNode::NoPicking: {
+ // Return an empty/invalid ViewportCameraAreaDetails which will
+ // prevent picking in the presence of a NoPicking node
+ return {};
+ }
default:
break;
}
diff --git a/src/render/jobs/pickboundingvolumeutils_p.h b/src/render/jobs/pickboundingvolumeutils_p.h
index 923a49317..fa3e701c2 100644
--- a/src/render/jobs/pickboundingvolumeutils_p.h
+++ b/src/render/jobs/pickboundingvolumeutils_p.h
@@ -79,6 +79,7 @@ namespace PickingUtils {
struct Q_AUTOTEST_EXPORT ViewportCameraAreaDetails
{
Qt3DCore::QNodeId cameraId;
+ Qt3DCore::QNodeId viewportNodeId;
QRectF viewport;
QSize area;
QSurface *surface = nullptr;
diff --git a/src/render/jobs/raycastingjob.cpp b/src/render/jobs/raycastingjob.cpp
index f3571c210..a6f172b86 100644
--- a/src/render/jobs/raycastingjob.cpp
+++ b/src/render/jobs/raycastingjob.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "raycastingjob_p.h"
+#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/geometryrenderer_p.h>
@@ -51,6 +52,7 @@
#include <Qt3DRender/private/rendersettings_p.h>
#include <Qt3DRender/private/trianglesvisitor_p.h>
#include <Qt3DRender/private/entityvisitor_p.h>
+#include <Qt3DRender/private/qabstractraycaster_p.h>
QT_BEGIN_NAMESPACE
@@ -82,11 +84,43 @@ public:
} // anonymous
+class Qt3DRender::Render::RayCastingJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ RayCastingJobPrivate() { }
+ ~RayCastingJobPrivate() override { Q_ASSERT(dispatches.isEmpty()); }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ QVector<QPair<RayCaster *, QAbstractRayCaster::Hits>> dispatches;
+};
+
+
+void RayCastingJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ for (auto res: qAsConst(dispatches)) {
+ QAbstractRayCaster *node = qobject_cast<QAbstractRayCaster *>(manager->lookupNode(res.first->peerId()));
+ if (!node)
+ continue;
+
+ QAbstractRayCasterPrivate *d = QAbstractRayCasterPrivate::get(node);
+ d->dispatchHits(res.second);
+
+ if (node->runMode() == QAbstractRayCaster::SingleShot) {
+ node->setEnabled(false);
+ res.first->setEnabled(false);
+ }
+ }
+
+ dispatches.clear();
+}
+
+
RayCastingJob::RayCastingJob()
- : AbstractPickingJob()
+ : AbstractPickingJob(*new RayCastingJobPrivate())
, m_castersDirty(true)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::RayCasting, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::RayCasting, 0)
}
void RayCastingJob::markCastersDirty()
@@ -239,7 +273,8 @@ void RayCastingJob::dispatchHits(RayCaster *rayCaster, const PickingUtils::HitLi
};
}
- rayCaster->dispatchHits(hits);
+ Q_DJOB(RayCastingJob);
+ d->dispatches.push_back({rayCaster, hits});
}
QT_END_NAMESPACE
diff --git a/src/render/jobs/raycastingjob_p.h b/src/render/jobs/raycastingjob_p.h
index 0bd8d445a..ba0e2f309 100644
--- a/src/render/jobs/raycastingjob_p.h
+++ b/src/render/jobs/raycastingjob_p.h
@@ -68,6 +68,8 @@ namespace PickingUtils {
typedef QVector<RayCasting::QCollisionQueryResult::Hit> HitList;
}
+class RayCastingJobPrivate;
+
class Q_AUTOTEST_EXPORT RayCastingJob : public AbstractPickingJob
{
public:
diff --git a/src/render/jobs/sendbuffercapturejob.cpp b/src/render/jobs/sendbuffercapturejob.cpp
index 8683ea9f2..889a86c68 100644
--- a/src/render/jobs/sendbuffercapturejob.cpp
+++ b/src/render/jobs/sendbuffercapturejob.cpp
@@ -39,11 +39,12 @@
#include "sendbuffercapturejob_p.h"
-
-#include "Qt3DRender/private/renderer_p.h"
-#include "Qt3DRender/private/nodemanagers_p.h"
+#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/job_common_p.h>
#include <Qt3DRender/private/buffer_p.h>
+#include <Qt3DRender/private/buffermanager_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DRender/private/qbuffer_p.h>
QT_BEGIN_NAMESPACE
@@ -51,36 +52,75 @@ namespace Qt3DRender {
namespace Render {
+class SendBufferCaptureJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ SendBufferCaptureJobPrivate() {}
+ ~SendBufferCaptureJobPrivate() {}
+
+ void postFrame(Qt3DCore::QAspectManager *aspectManager) override;
+
+ mutable QMutex m_mutex;
+ QVector<QPair<Qt3DCore::QNodeId, QByteArray>> m_buffersToCapture;
+ QVector<QPair<Qt3DCore::QNodeId, QByteArray>> m_buffersToNotify;
+};
+
SendBufferCaptureJob::SendBufferCaptureJob()
- : Qt3DCore::QAspectJob()
+ : Qt3DCore::QAspectJob(*new SendBufferCaptureJobPrivate)
+ , m_nodeManagers(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendBufferCapture, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::SendBufferCapture, 0)
}
SendBufferCaptureJob::~SendBufferCaptureJob()
{
}
-void SendBufferCaptureJob::addRequest(QPair<Buffer *, QByteArray> request)
+// Called from SubmitRenderView while rendering
+void SendBufferCaptureJob::addRequest(QPair<Qt3DCore::QNodeId, QByteArray> request)
{
- QMutexLocker locker(&m_mutex);
- m_pendingSendBufferCaptures.push_back(request);
+ Q_DJOB(SendBufferCaptureJob);
+ QMutexLocker locker(&d->m_mutex);
+ d->m_buffersToCapture.push_back(request);
}
-// Called by aspect thread jobs to execute (no concurrency at that point)
+// Called by aspect thread jobs to execute (we may still be rendering at this point)
bool SendBufferCaptureJob::hasRequests() const
{
- return m_pendingSendBufferCaptures.size() > 0;
+ Q_DJOB(const SendBufferCaptureJob);
+ QMutexLocker locker(&d->m_mutex);
+ return d->m_buffersToCapture.size() > 0;
}
void SendBufferCaptureJob::run()
{
- QMutexLocker locker(&m_mutex);
- for (const QPair<Buffer*, QByteArray> &pendingCapture : qAsConst(m_pendingSendBufferCaptures)) {
- pendingCapture.first->updateDataFromGPUToCPU(pendingCapture.second);
+ Q_ASSERT(m_nodeManagers);
+ Q_DJOB(SendBufferCaptureJob);
+ QMutexLocker locker(&d->m_mutex);
+ for (const QPair<Qt3DCore::QNodeId, QByteArray> &pendingCapture : qAsConst(d->m_buffersToCapture)) {
+ Buffer *buffer = m_nodeManagers->bufferManager()->lookupResource(pendingCapture.first);
+ // Buffer might have been destroyed between the time addRequest is made and this job gets run
+ // If it exists however, it cannot be destroyed before this job is done running
+ if (buffer != nullptr)
+ buffer->updateDataFromGPUToCPU(pendingCapture.second);
}
+ d->m_buffersToNotify = std::move(d->m_buffersToCapture);
+}
- m_pendingSendBufferCaptures.clear();
+void SendBufferCaptureJobPrivate::postFrame(Qt3DCore::QAspectManager *aspectManager)
+{
+ QMutexLocker locker(&m_mutex);
+ const QVector<QPair<Qt3DCore::QNodeId, QByteArray>> pendingSendBufferCaptures = std::move(m_buffersToNotify);
+ for (const auto &bufferDataPair : pendingSendBufferCaptures) {
+ QBuffer *frontendBuffer = static_cast<decltype(frontendBuffer)>(aspectManager->lookupNode(bufferDataPair.first));
+ if (!frontendBuffer)
+ continue;
+ QBufferPrivate *dFrontend = static_cast<decltype(dFrontend)>(Qt3DCore::QNodePrivate::get(frontendBuffer));
+ // Calling frontendBuffer->setData would result in forcing a sync against the backend
+ // which isn't necessary
+ dFrontend->setData(bufferDataPair.second);
+ Q_EMIT frontendBuffer->dataAvailable();
+ }
}
} // Render
diff --git a/src/render/jobs/sendbuffercapturejob_p.h b/src/render/jobs/sendbuffercapturejob_p.h
index f47c556df..ce797f0a9 100644
--- a/src/render/jobs/sendbuffercapturejob_p.h
+++ b/src/render/jobs/sendbuffercapturejob_p.h
@@ -52,6 +52,7 @@
//
#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DCore/qnodeid.h>
#include <Qt3DRender/qt3drender_global.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
#include <QMutex>
@@ -67,6 +68,7 @@ class NodeManagers;
class Entity;
class Renderer;
class Buffer;
+class SendBufferCaptureJobPrivate;
class Q_3DRENDERSHARED_PRIVATE_EXPORT SendBufferCaptureJob : public Qt3DCore::QAspectJob
{
@@ -74,15 +76,14 @@ public:
explicit SendBufferCaptureJob();
~SendBufferCaptureJob();
- void addRequest(QPair<Buffer*, QByteArray> request);
+ void setManagers(NodeManagers *nodeManagers) { m_nodeManagers = nodeManagers; }
+ void addRequest(QPair<Qt3DCore::QNodeId, QByteArray> request);
bool hasRequests() const;
void run() final;
private:
- QMutex m_mutex;
-
- QVector<QPair<Buffer*, QByteArray> > m_pendingSendBufferCaptures;
+ NodeManagers *m_nodeManagers;
};
typedef QSharedPointer<SendBufferCaptureJob> SendBufferCaptureJobPtr;
diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp
index b5349a2c1..9ac923d8b 100644
--- a/src/render/jobs/updatelevelofdetailjob.cpp
+++ b/src/render/jobs/updatelevelofdetailjob.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "updatelevelofdetailjob_p.h"
+#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DRender/QLevelOfDetail>
#include <Qt3DRender/private/entityvisitor_p.h>
#include <Qt3DRender/private/job_common_p.h>
@@ -66,9 +67,11 @@ public:
, m_filterValue(filterValue)
, m_frameGraphRoot(frameGraphRoot)
{
+ m_updatedIndices.reserve(manager->levelOfDetailManager()->count());
}
double filterValue() const { return m_filterValue; }
+ const QVector<QPair<Qt3DCore::QNodeId, int>> &updatedIndices() const { return m_updatedIndices; }
Operation visit(Qt3DRender::Render::Entity *entity = nullptr) override {
using namespace Qt3DRender;
@@ -102,6 +105,7 @@ public:
private:
double m_filterValue = 0.;
Qt3DRender::Render::FrameGraphNode *m_frameGraphRoot;
+ QVector<QPair<Qt3DCore::QNodeId, int>> m_updatedIndices;
void updateEntityLodByDistance(Qt3DRender::Render::Entity *entity, Qt3DRender::Render::LevelOfDetail *lod)
{
@@ -128,8 +132,10 @@ private:
if (dist <= thresholds[i] || i == n -1) {
m_filterValue = approxRollingAverage<30>(m_filterValue, i);
i = qBound(0, static_cast<int>(qRound(m_filterValue)), n - 1);
- if (lod->currentIndex() != i)
+ if (lod->currentIndex() != i) {
lod->setCurrentIndex(i);
+ m_updatedIndices.push_back({lod->peerId(), i});
+ }
break;
}
}
@@ -172,8 +178,10 @@ private:
if (thresholds[i] < area || i == n -1) {
m_filterValue = approxRollingAverage<30>(m_filterValue, i);
i = qBound(0, static_cast<int>(qRound(m_filterValue)), n - 1);
- if (lod->currentIndex() != i)
+ if (lod->currentIndex() != i) {
lod->setCurrentIndex(i);
+ m_updatedIndices.push_back({lod->peerId(), i});
+ }
break;
}
}
@@ -199,13 +207,24 @@ private:
namespace Qt3DRender {
namespace Render {
+class UpdateLevelOfDetailJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ UpdateLevelOfDetailJobPrivate() { }
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ QVector<QPair<Qt3DCore::QNodeId, int>> m_updatedIndices;
+};
+
UpdateLevelOfDetailJob::UpdateLevelOfDetailJob()
- : m_manager(nullptr)
+ : Qt3DCore::QAspectJob(*new UpdateLevelOfDetailJobPrivate)
+ , m_manager(nullptr)
, m_frameGraphRoot(nullptr)
, m_root(nullptr)
, m_filterValue(0.)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLevelOfDetail, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateLevelOfDetail, 0)
}
UpdateLevelOfDetailJob::~UpdateLevelOfDetailJob()
@@ -229,23 +248,32 @@ void UpdateLevelOfDetailJob::setFrameGraphRoot(FrameGraphNode *frameGraphRoot)
void UpdateLevelOfDetailJob::run()
{
+ Q_DJOB(UpdateLevelOfDetailJob);
+
Q_ASSERT(m_frameGraphRoot && m_root && m_manager);
// short-circuit if no LoDs exist
if (m_manager->levelOfDetailManager()->count() == 0)
return;
-
- if (m_manager->levelOfDetailManager()->count() == 0)
- return; // no LODs, lets bail out early
-
LODUpdateVisitor visitor(m_filterValue, m_frameGraphRoot, m_manager);
visitor.apply(m_root);
m_filterValue = visitor.filterValue();
+ d->m_updatedIndices = visitor.updatedIndices();
}
-} // Render
+void UpdateLevelOfDetailJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ for (const auto &updatedNode: qAsConst(m_updatedIndices)) {
+ QLevelOfDetail *node = qobject_cast<QLevelOfDetail *>(manager->lookupNode(updatedNode.first));
+ if (!node)
+ continue;
+ node->setCurrentIndex(updatedNode.second);
+ }
+}
+
+} // Render
} // Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/jobs/updatelevelofdetailjob_p.h b/src/render/jobs/updatelevelofdetailjob_p.h
index 3c7d00d2c..e0f9bd064 100644
--- a/src/render/jobs/updatelevelofdetailjob_p.h
+++ b/src/render/jobs/updatelevelofdetailjob_p.h
@@ -65,6 +65,7 @@ class Entity;
class NodeManagers;
class LevelOfDetail;
class FrameGraphNode;
+class UpdateLevelOfDetailJobPrivate;
class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateLevelOfDetailJob : public Qt3DCore::QAspectJob
{
diff --git a/src/render/jobs/updatetreeenabledjob.cpp b/src/render/jobs/updatetreeenabledjob.cpp
index e97fc6414..5c6f2b378 100644
--- a/src/render/jobs/updatetreeenabledjob.cpp
+++ b/src/render/jobs/updatetreeenabledjob.cpp
@@ -71,6 +71,7 @@ void updateTreeEnabled(NodeManagers *manager, Entity *node, bool parentEnabled)
UpdateTreeEnabledJob::UpdateTreeEnabledJob()
: Qt3DCore::QAspectJob()
, m_node(nullptr)
+ , m_manager(nullptr)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateTreeEnabled, 0);
}
diff --git a/src/render/jobs/updateworldtransformjob.cpp b/src/render/jobs/updateworldtransformjob.cpp
index 1a9697843..e3487e68b 100644
--- a/src/render/jobs/updateworldtransformjob.cpp
+++ b/src/render/jobs/updateworldtransformjob.cpp
@@ -39,6 +39,9 @@
#include "updateworldtransformjob_p.h"
+#include <Qt3DCore/qtransform.h>
+#include <Qt3DCore/private/qtransform_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/transform_p.h>
@@ -56,28 +59,50 @@ namespace Render {
namespace {
-void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform)
+struct TransformUpdate
+{
+ Qt3DCore::QNodeId peerId;
+ QMatrix4x4 worldTransformMatrix;
+};
+
+void updateWorldTransformAndBounds(NodeManagers *manager, Entity *node, const Matrix4x4 &parentTransform, QVector<TransformUpdate> &updatedTransforms)
{
Matrix4x4 worldTransform(parentTransform);
Transform *nodeTransform = node->renderComponent<Transform>();
- if (nodeTransform != nullptr && nodeTransform->isEnabled())
+ const bool hasTransformComponent = nodeTransform != nullptr && nodeTransform->isEnabled();
+ if (hasTransformComponent)
worldTransform = worldTransform * nodeTransform->transformMatrix();
- *(node->worldTransform()) = worldTransform;
+ if (*(node->worldTransform()) != worldTransform) {
+ *(node->worldTransform()) = worldTransform;
+ if (hasTransformComponent)
+ updatedTransforms.push_back({nodeTransform->peerId(), convertToQMatrix4x4(worldTransform)});
+ }
const auto childrenHandles = node->childrenHandles();
for (const HEntity &handle : childrenHandles) {
Entity *child = manager->renderNodesManager()->data(handle);
if (child)
- updateWorldTransformAndBounds(manager, child, worldTransform);
+ updateWorldTransformAndBounds(manager, child, worldTransform, updatedTransforms);
}
}
}
+class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateWorldTransformJobPrivate : public Qt3DCore::QAspectJobPrivate
+{
+public:
+ UpdateWorldTransformJobPrivate() {}
+ ~UpdateWorldTransformJobPrivate() override {}
+
+ void postFrame(Qt3DCore::QAspectManager *manager) override;
+
+ QVector<TransformUpdate> m_updatedTransforms;
+};
+
UpdateWorldTransformJob::UpdateWorldTransformJob()
- : Qt3DCore::QAspectJob()
+ : Qt3DCore::QAspectJob(*new UpdateWorldTransformJobPrivate())
, m_node(nullptr)
, m_manager(nullptr)
{
@@ -103,17 +128,32 @@ void UpdateWorldTransformJob::run()
// TODO: Parallelise this on each level using a parallel_for
// implementation.
+ Q_DJOB(UpdateWorldTransformJob);
qCDebug(Jobs) << "Entering" << Q_FUNC_INFO << QThread::currentThread();
Matrix4x4 parentTransform;
Entity *parent = m_node->parent();
if (parent != nullptr)
parentTransform = *(parent->worldTransform());
- updateWorldTransformAndBounds(m_manager, m_node, parentTransform);
+ updateWorldTransformAndBounds(m_manager, m_node, parentTransform, d->m_updatedTransforms);
qCDebug(Jobs) << "Exiting" << Q_FUNC_INFO << QThread::currentThread();
}
+void UpdateWorldTransformJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
+{
+ const QVector<TransformUpdate> updatedTransforms = std::move(m_updatedTransforms);
+ for (const TransformUpdate &t : updatedTransforms) {
+ Qt3DCore::QTransform *node =
+ qobject_cast<Qt3DCore::QTransform *>(manager->lookupNode(t.peerId));
+ if (!node)
+ continue;
+ Qt3DCore::QTransformPrivate *dNode =
+ static_cast<Qt3DCore::QTransformPrivate *>(Qt3DCore::QNodePrivate::get(node));
+ dNode->setWorldMatrix(t.worldTransformMatrix);
+ }
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/jobs/updateworldtransformjob_p.h b/src/render/jobs/updateworldtransformjob_p.h
index 2689fe45a..ded501a07 100644
--- a/src/render/jobs/updateworldtransformjob_p.h
+++ b/src/render/jobs/updateworldtransformjob_p.h
@@ -63,6 +63,7 @@ namespace Render {
class Entity;
class NodeManagers;
+class UpdateWorldTransformJobPrivate;
class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateWorldTransformJob : public Qt3DCore::QAspectJob
{
diff --git a/src/render/lights/environmentlight.cpp b/src/render/lights/environmentlight.cpp
index d4245fb6e..20364fdfa 100644
--- a/src/render/lights/environmentlight.cpp
+++ b/src/render/lights/environmentlight.cpp
@@ -53,11 +53,17 @@ QNodeId EnvironmentLight::shaderData() const
return m_shaderDataId;
}
-void EnvironmentLight::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
+void EnvironmentLight::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QEnvironmentLightData>>(change);
- const auto &data = typedChange->data;
- m_shaderDataId = data.shaderDataId;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QEnvironmentLight *node = qobject_cast<const QEnvironmentLight *>(frontEnd);
+ if (!node)
+ return;
+
+ if (firstTime) {
+ QEnvironmentLightPrivate *d = static_cast<QEnvironmentLightPrivate *>(QEnvironmentLightPrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd)));
+ m_shaderDataId = d->m_shaderData ? d->m_shaderData->id() : QNodeId{};
+ }
}
} // namespace Render
diff --git a/src/render/lights/environmentlight_p.h b/src/render/lights/environmentlight_p.h
index 00d49d298..92f6ce100 100644
--- a/src/render/lights/environmentlight_p.h
+++ b/src/render/lights/environmentlight_p.h
@@ -63,10 +63,9 @@ class Q_AUTOTEST_EXPORT EnvironmentLight : public BackendNode
{
public:
Qt3DCore::QNodeId shaderData() const;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_shaderDataId;
};
diff --git a/src/render/lights/light.cpp b/src/render/lights/light.cpp
index e8474b728..3bdab0457 100644
--- a/src/render/lights/light.cpp
+++ b/src/render/lights/light.cpp
@@ -40,7 +40,6 @@
#include "light_p.h"
#include "qabstractlight.h"
#include "qabstractlight_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <private/abstractrenderer_p.h>
#include <private/nodemanagers_p.h>
#include <private/qbackendnode_p.h>
@@ -58,14 +57,18 @@ QNodeId Light::shaderData() const
return m_shaderDataId;
}
-void Light::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
+void Light::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractLightData>>(change);
- const auto &data = typedChange->data;
- m_shaderDataId = data.shaderDataId;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAbstractLight *node = qobject_cast<const QAbstractLight *>(frontEnd);
+ if (!node)
+ return;
- Q_ASSERT(m_renderer);
- BackendNode::markDirty(AbstractRenderer::LightsDirty);
+ if (firstTime) {
+ QAbstractLightPrivate *d = static_cast<QAbstractLightPrivate *>(QAbstractLightPrivate::get(const_cast<Qt3DCore::QNode *>(frontEnd)));
+ m_shaderDataId = d->m_shaderData ? d->m_shaderData->id() : QNodeId{};
+ BackendNode::markDirty(AbstractRenderer::LightsDirty);
+ }
}
RenderLightFunctor::RenderLightFunctor(AbstractRenderer *renderer, NodeManagers *managers)
diff --git a/src/render/lights/light_p.h b/src/render/lights/light_p.h
index 8ecc87585..5f5f8140e 100644
--- a/src/render/lights/light_p.h
+++ b/src/render/lights/light_p.h
@@ -66,9 +66,9 @@ class Q_AUTOTEST_EXPORT Light : public BackendNode
public:
Qt3DCore::QNodeId shaderData() const;
-private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+private:
Qt3DCore::QNodeId m_shaderDataId;
};
diff --git a/src/render/lights/qdirectionallight.cpp b/src/render/lights/qdirectionallight.cpp
index 9b6e580de..13fb78843 100644
--- a/src/render/lights/qdirectionallight.cpp
+++ b/src/render/lights/qdirectionallight.cpp
@@ -39,7 +39,6 @@
#include "qdirectionallight.h"
#include "qdirectionallight_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/lights/qspotlight.cpp b/src/render/lights/qspotlight.cpp
index c4deaf817..eddafbe61 100644
--- a/src/render/lights/qspotlight.cpp
+++ b/src/render/lights/qspotlight.cpp
@@ -40,7 +40,6 @@
#include "qspotlight.h"
#include "qspotlight_p.h"
#include "shaderdata_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/materialsystem/effect.cpp b/src/render/materialsystem/effect.cpp
index 29d05ed01..035cf4746 100644
--- a/src/render/materialsystem/effect.cpp
+++ b/src/render/materialsystem/effect.cpp
@@ -43,11 +43,8 @@
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/private/qeffect_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-
#include <QVariant>
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -73,41 +70,25 @@ void Effect::cleanup()
m_techniques.clear();
}
-void Effect::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QEffectData>>(change);
- const auto &data = typedChange->data;
- m_techniques = data.techniqueIds;
- m_parameterPack.setParameters(data.parameterIds);
-}
-
-void Effect::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void Effect::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- switch (e->type()) {
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("technique"))
- appendRenderTechnique(change->addedNodeId());
- else if (change->propertyName() == QByteArrayLiteral("parameter"))
- m_parameterPack.appendParameter(change->addedNodeId());
- break;
- }
-
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("technique"))
- m_techniques.removeOne(change->removedNodeId());
- else if (change->propertyName() == QByteArrayLiteral("parameter"))
- m_parameterPack.removeParameter(change->removedNodeId());
- break;
- }
-
- default:
- break;
- }
-
- markDirty(AbstractRenderer::AllDirty);
- BackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QEffect *node = qobject_cast<const QEffect *>(frontEnd);
+ if (!node)
+ return;
+
+ auto parameters = qIdsForNodes(node->parameters());
+ std::sort(std::begin(parameters), std::end(parameters));
+ if (m_parameterPack.parameters() != parameters)
+ m_parameterPack.setParameters(parameters);
+
+ auto techniques = qIdsForNodes(node->techniques());
+ std::sort(std::begin(techniques), std::end(techniques));
+ if (m_techniques != techniques)
+ m_techniques = techniques;
+
+ if (!firstTime)
+ markDirty(AbstractRenderer::AllDirty);
}
void Effect::appendRenderTechnique(Qt3DCore::QNodeId technique)
diff --git a/src/render/materialsystem/effect_p.h b/src/render/materialsystem/effect_p.h
index 87ff4a803..e81be2b8d 100644
--- a/src/render/materialsystem/effect_p.h
+++ b/src/render/materialsystem/effect_p.h
@@ -70,15 +70,13 @@ public:
~Effect();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void appendRenderTechnique(Qt3DCore::QNodeId t);
QVector<Qt3DCore::QNodeId> techniques() const;
QVector<Qt3DCore::QNodeId> parameters() const;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<Qt3DCore::QNodeId> m_techniques;
ParameterPack m_parameterPack;
};
diff --git a/src/render/materialsystem/filterkey.cpp b/src/render/materialsystem/filterkey.cpp
index 167413451..e6c37b241 100644
--- a/src/render/materialsystem/filterkey.cpp
+++ b/src/render/materialsystem/filterkey.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "filterkey_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/qfilterkey_p.h>
QT_BEGIN_NAMESPACE
@@ -65,31 +64,23 @@ void FilterKey::cleanup()
m_value.clear();
}
-void FilterKey::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void FilterKey::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QFilterKeyData>>(change);
- const auto &data = typedChange->data;
- m_name = data.name;
- m_value = data.value;
-}
+ const QFilterKey *node = qobject_cast<const QFilterKey *>(frontEnd);
+ if (!node)
+ return;
-void FilterKey::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyUpdated: {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("value"))
- m_value = propertyChange->value();
- else if (propertyChange->propertyName() == QByteArrayLiteral("name"))
- m_name = propertyChange->value().toString();
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ if (node->name() != m_name) {
+ m_name = node->name();
markDirty(AbstractRenderer::AllDirty);
}
- default:
- break;
+ if (node->value() != m_value) {
+ m_value = node->value();
+ markDirty(AbstractRenderer::AllDirty);
}
- BackendNode::sceneChangeEvent(e);
}
bool FilterKey::operator ==(const FilterKey &other)
diff --git a/src/render/materialsystem/filterkey_p.h b/src/render/materialsystem/filterkey_p.h
index 69d298503..f4fb2c3d0 100644
--- a/src/render/materialsystem/filterkey_p.h
+++ b/src/render/materialsystem/filterkey_p.h
@@ -71,13 +71,11 @@ public:
const QVariant &value() const { return m_value; }
const QString &name() const { return m_name; }
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
bool operator ==(const FilterKey &other);
bool operator !=(const FilterKey &other);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVariant m_value;
QString m_name;
};
diff --git a/src/render/materialsystem/material.cpp b/src/render/materialsystem/material.cpp
index 723dbfd31..6fda17ccd 100644
--- a/src/render/materialsystem/material.cpp
+++ b/src/render/materialsystem/material.cpp
@@ -46,10 +46,6 @@
#include "qeffect.h"
#include <Qt3DRender/private/qmaterial_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-
using namespace Qt3DCore;
QT_BEGIN_NAMESPACE
@@ -73,45 +69,26 @@ void Material::cleanup()
m_parameterPack.clear();
}
-void Material::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Material::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QMaterialData>>(change);
- const auto &data = typedChange->data;
- m_effectUuid = data.effectId;
- m_parameterPack.setParameters(data.parameterIds);
-}
-
-void Material::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
-
- switch (e->type()) {
- case PropertyUpdated: {
- const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("effect"))
- m_effectUuid = change->value().value<QNodeId>();
- break;
- }
-
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("parameter"))
- m_parameterPack.appendParameter(change->addedNodeId());
- break;
- }
-
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("parameter"))
- m_parameterPack.removeParameter(change->removedNodeId());
- break;
- }
-
- default:
- break;
- }
- markDirty(AbstractRenderer::AllDirty);
-
- BackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QMaterial *node = qobject_cast<const QMaterial *>(frontEnd);
+ if (!node)
+ return;
+
+ auto parameters = qIdsForNodes(node->parameters());
+ std::sort(std::begin(parameters), std::end(parameters));
+ if (m_parameterPack.parameters() != parameters)
+ m_parameterPack.setParameters(parameters);
+
+ const auto effectId = node->effect() ? node->effect()->id() : QNodeId{};
+ if (effectId != m_effectUuid)
+ m_effectUuid = effectId;
+
+ if (firstTime)
+ markDirty(AbstractRenderer::MaterialDirty);
+ else
+ markDirty(AbstractRenderer::AllDirty);
}
QVector<Qt3DCore::QNodeId> Material::parameters() const
diff --git a/src/render/materialsystem/material_p.h b/src/render/materialsystem/material_p.h
index 3b55dc657..7a02c6691 100644
--- a/src/render/materialsystem/material_p.h
+++ b/src/render/materialsystem/material_p.h
@@ -79,14 +79,12 @@ public:
~Material();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
QVector<Qt3DCore::QNodeId> parameters() const;
Qt3DCore::QNodeId effect() const;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
ParameterPack m_parameterPack;
Qt3DCore::QNodeId m_effectUuid;
};
diff --git a/src/render/materialsystem/materialsystem.pri b/src/render/materialsystem/materialsystem.pri
index c464d6b99..ae3d2f78c 100644
--- a/src/render/materialsystem/materialsystem.pri
+++ b/src/render/materialsystem/materialsystem.pri
@@ -17,6 +17,8 @@ HEADERS += \
$$PWD/qrenderpass.h \
$$PWD/qshaderdata.h \
$$PWD/qshaderdata_p.h \
+ $$PWD/qshaderimage.h \
+ $$PWD/qshaderimage_p.h \
$$PWD/qshaderprogram.h \
$$PWD/qshaderprogram_p.h \
$$PWD/qshaderprogrambuilder.h \
@@ -27,6 +29,7 @@ HEADERS += \
$$PWD/shader_p.h \
$$PWD/shaderbuilder_p.h \
$$PWD/shaderdata_p.h \
+ $$PWD/shaderimage_p.h \
$$PWD/technique_p.h \
$$PWD/qgraphicsapifilter.h \
$$PWD/qgraphicsapifilter_p.h \
@@ -44,6 +47,7 @@ SOURCES += \
$$PWD/qparameter.cpp \
$$PWD/qrenderpass.cpp \
$$PWD/qshaderdata.cpp \
+ $$PWD/qshaderimage.cpp \
$$PWD/qshaderprogram.cpp \
$$PWD/qshaderprogrambuilder.cpp \
$$PWD/qtechnique.cpp \
@@ -51,6 +55,7 @@ SOURCES += \
$$PWD/shader.cpp \
$$PWD/shaderbuilder.cpp \
$$PWD/shaderdata.cpp \
+ $$PWD/shaderimage.cpp \
$$PWD/technique.cpp \
$$PWD/qgraphicsapifilter.cpp \
$$PWD/shadercache.cpp \
diff --git a/src/render/materialsystem/parameter.cpp b/src/render/materialsystem/parameter.cpp
index f00df3c90..3360aebef 100644
--- a/src/render/materialsystem/parameter.cpp
+++ b/src/render/materialsystem/parameter.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "parameter_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/private/qparameter_p.h>
#include <Qt3DRender/qtexture.h>
@@ -68,35 +67,36 @@ void Parameter::cleanup()
m_nameId = -1;
m_name.clear();
m_uniformValue = UniformValue();
+ m_backendValue = {};
}
-void Parameter::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Parameter::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QParameterData>>(change);
- const auto &data = typedChange->data;
- m_name = data.name;
- m_nameId = StringToInt::lookupId(m_name);
- m_uniformValue = UniformValue::fromVariant(data.backendValue);
-}
+ const QParameter *node = qobject_cast<const QParameter *>(frontEnd);
+ if (!node)
+ return;
-void Parameter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
-
- if (e->type() == PropertyUpdated) {
- if (propertyChange->propertyName() == QByteArrayLiteral("name")) {
- m_name = propertyChange->value().toString();
- m_nameId = StringToInt::lookupId(m_name);
- markDirty(AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("value")) {
- m_uniformValue = UniformValue::fromVariant(propertyChange->value());
- markDirty(AbstractRenderer::ParameterDirty);
- } else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) {
- markDirty(AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty);
- }
+ AbstractRenderer::BackendNodeDirtySet dirty = firstTime ? AbstractRenderer::ParameterDirty : static_cast<AbstractRenderer::BackendNodeDirtyFlag>(0);
+ if (node->isEnabled() != isEnabled())
+ dirty |= (AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty);
+
+ if (node->name() != m_name) {
+ m_name = node->name();
+ m_nameId = StringToInt::lookupId(m_name);
+ dirty |= (AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty);
}
- BackendNode::sceneChangeEvent(e);
+ QParameterPrivate* d = static_cast<QParameterPrivate *>(QParameterPrivate::get(const_cast<QParameter *>(node)));
+ if (d->m_backendValue != m_backendValue) {
+ m_backendValue = d->m_backendValue;
+ m_uniformValue = UniformValue::fromVariant(m_backendValue);
+ dirty |= (AbstractRenderer::ParameterDirty);
+ }
+
+ if (dirty)
+ markDirty(dirty);
+
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
}
QString Parameter::name() const
diff --git a/src/render/materialsystem/parameter_p.h b/src/render/materialsystem/parameter_p.h
index 4ab04bc8e..258834ff3 100644
--- a/src/render/materialsystem/parameter_p.h
+++ b/src/render/materialsystem/parameter_p.h
@@ -71,16 +71,16 @@ public:
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
QString name() const;
int nameId() const Q_DECL_NOTHROW { return m_nameId; }
const UniformValue &uniformValue() const { return m_uniformValue; }
+ QVariant backendValue() const { return m_backendValue; }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QString m_name;
+ QVariant m_backendValue;
UniformValue m_uniformValue;
int m_nameId;
};
diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp
index ba19154fd..8637a92d4 100644
--- a/src/render/materialsystem/qeffect.cpp
+++ b/src/render/materialsystem/qeffect.cpp
@@ -42,10 +42,6 @@
#include "qtechnique.h"
#include "qparameter.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
@@ -176,7 +172,7 @@ QEffect::QEffect(QEffectPrivate &dd, QNode *parent)
*/
/*!
- * Adds \a parameter to the effect. It sends a QPropertyNodeAddedChange to the backend.
+ * Adds \a parameter to the effect. It sends an update to the backend.
* The \a parameter will be used to set a corresponding uniform value in the shader used
* by this effect.
*/
@@ -196,11 +192,7 @@ void QEffect::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -211,14 +203,10 @@ void QEffect::removeParameter(QParameter *parameter)
{
Q_D(QEffect);
- if (parameter && d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
}
/*!
@@ -231,7 +219,7 @@ QVector<QParameter *> QEffect::parameters() const
}
/*!
- * Adds a new technique \a t to the effect. It sends a QPropertyNodeAddedChange to the backend.
+ * Adds a new technique \a t to the effect. It sends an update to the backend.
*/
void QEffect::addTechnique(QTechnique *t)
{
@@ -250,11 +238,7 @@ void QEffect::addTechnique(QTechnique *t)
if (!t->parent())
t->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), t);
- change->setPropertyName("technique");
- d->notifyObservers(change);
- }
+ d->updateNode(t, "technique", Qt3DCore::PropertyValueAdded);
}
}
@@ -264,11 +248,8 @@ void QEffect::addTechnique(QTechnique *t)
void QEffect::removeTechnique(QTechnique *t)
{
Q_D(QEffect);
- if (t && d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), t);
- change->setPropertyName("technique");
- d->notifyObservers(change);
- }
+ if (t)
+ d->updateNode(t, "technique", Qt3DCore::PropertyValueRemoved);
d->m_techniques.removeOne(t);
// Remove bookkeeping connection
d->unregisterDestructionHelper(t);
diff --git a/src/render/materialsystem/qfilterkey.cpp b/src/render/materialsystem/qfilterkey.cpp
index 0cffde7c1..2105da987 100644
--- a/src/render/materialsystem/qfilterkey.cpp
+++ b/src/render/materialsystem/qfilterkey.cpp
@@ -40,7 +40,6 @@
#include "qfilterkey.h"
#include "qfilterkey_p.h"
#include <private/qnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/materialsystem/qgraphicsapifilter.cpp b/src/render/materialsystem/qgraphicsapifilter.cpp
index 70f329172..9b5557930 100644
--- a/src/render/materialsystem/qgraphicsapifilter.cpp
+++ b/src/render/materialsystem/qgraphicsapifilter.cpp
@@ -107,6 +107,11 @@ QGraphicsApiFilterPrivate *QGraphicsApiFilterPrivate::get(QGraphicsApiFilter *q)
return q->d_func();
}
+const QGraphicsApiFilterPrivate *QGraphicsApiFilterPrivate::get(const QGraphicsApiFilter *q)
+{
+ return q->d_func();
+}
+
/*!
\class Qt3DRender::QGraphicsApiFilter
\inmodule Qt3DRender
diff --git a/src/render/materialsystem/qgraphicsapifilter_p.h b/src/render/materialsystem/qgraphicsapifilter_p.h
index 3961d4f93..435451c27 100644
--- a/src/render/materialsystem/qgraphicsapifilter_p.h
+++ b/src/render/materialsystem/qgraphicsapifilter_p.h
@@ -84,6 +84,7 @@ public:
}
static QGraphicsApiFilterPrivate *get(QGraphicsApiFilter *q);
+ static const QGraphicsApiFilterPrivate *get(const QGraphicsApiFilter *q);
Q_DECLARE_PUBLIC(QGraphicsApiFilter)
GraphicsApiFilterData m_data;
diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp
index c6913441e..edd227500 100644
--- a/src/render/materialsystem/qmaterial.cpp
+++ b/src/render/materialsystem/qmaterial.cpp
@@ -43,9 +43,6 @@
#include "qeffect.h"
#include <Qt3DRender/private/renderlogging_p.h>
#include "qparameter.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
/*!
\qmltype Material
@@ -275,11 +272,7 @@ void QMaterial::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -290,11 +283,7 @@ void QMaterial::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QMaterial);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
}
diff --git a/src/render/materialsystem/qparameter.cpp b/src/render/materialsystem/qparameter.cpp
index 92f3cf0c2..969882564 100644
--- a/src/render/materialsystem/qparameter.cpp
+++ b/src/render/materialsystem/qparameter.cpp
@@ -40,7 +40,6 @@
#include "qparameter.h"
#include "qparameter_p.h"
#include <Qt3DRender/private/renderlogging_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qtexture.h>
diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp
index 111bb7b5f..dcb831b13 100644
--- a/src/render/materialsystem/qrenderpass.cpp
+++ b/src/render/materialsystem/qrenderpass.cpp
@@ -43,9 +43,6 @@
#include "qparameter.h"
#include "qfilterkey.h"
#include "qrenderstate.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnode_p.h>
QT_BEGIN_NAMESPACE
@@ -231,12 +228,6 @@ void QRenderPass::setShaderProgram(QShaderProgram *shaderProgram)
Q_D(QRenderPass);
if (d->m_shader != shaderProgram) {
- if (d->m_shader != nullptr && d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), d->m_shader);
- change->setPropertyName("shaderProgram");
- d->notifyObservers(change);
- }
-
if (d->m_shader)
d->unregisterDestructionHelper(d->m_shader);
@@ -283,11 +274,7 @@ void QRenderPass::addFilterKey(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey);
- change->setPropertyName("filterKeys");
- d->notifyObservers(change);
- }
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueAdded);
}
}
@@ -298,11 +285,7 @@ void QRenderPass::removeFilterKey(QFilterKey *filterKey)
{
Q_ASSERT(filterKey);
Q_D(QRenderPass);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey);
- change->setPropertyName("filterKeys");
- d->notifyObservers(change);
- }
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueRemoved);
d->m_filterKeyList.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -339,11 +322,7 @@ void QRenderPass::addRenderState(QRenderState *state)
if (!state->parent())
state->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), state);
- change->setPropertyName("renderState");
- d->notifyObservers(change);
- }
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueAdded);
}
}
@@ -354,11 +333,7 @@ void QRenderPass::removeRenderState(QRenderState *state)
{
Q_ASSERT(state);
Q_D(QRenderPass);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), state);
- change->setPropertyName("renderState");
- d->notifyObservers(change);
- }
+ d->updateNode(state, "renderState", Qt3DCore::PropertyValueRemoved);
d->m_renderStates.removeOne(state);
// Remove bookkeeping connection
d->unregisterDestructionHelper(state);
@@ -394,11 +369,7 @@ void QRenderPass::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -409,11 +380,7 @@ void QRenderPass::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QRenderPass);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
diff --git a/src/render/materialsystem/qshaderimage.cpp b/src/render/materialsystem/qshaderimage.cpp
new file mode 100644
index 000000000..508cf44f2
--- /dev/null
+++ b/src/render/materialsystem/qshaderimage.cpp
@@ -0,0 +1,991 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshaderimage.h"
+#include "qshaderimage_p.h"
+#include <Qt3DRender/qabstracttexture.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+QShaderImagePrivate::QShaderImagePrivate()
+ : Qt3DCore::QNodePrivate()
+ , m_texture(nullptr)
+ , m_mipLevel(0)
+ , m_layer(0)
+ , m_access(QShaderImage::ReadWrite)
+ , m_format(QShaderImage::Automatic)
+ , m_layered(false)
+{
+}
+
+QShaderImagePrivate::~QShaderImagePrivate()
+{
+}
+
+/*!
+ \qmltype ShaderImage
+ \instantiates Qt3DRender::QShaderImage
+ \inqmlmodule Qt3D.Render
+ \since 5.14
+ \brief Provides Image access to shader programs.
+
+ To make the content of textures available for read and write operations in
+ a shader, they need to exposed as ShaderImage. Textures can be composed of
+ several mip levels, layers and faces. Additionally declaring a ShaderImage
+ allows specifying which level, layer or face of the texture content we want
+ to access.
+
+ ShaderImage has to be assigned as a Parameter's value and reference a valid
+ Qt3D.Render.AbstractTexture to work properly.
+
+ If the referenced texture is a one-dimensional array, two-dimensional array,
+ three-dimensional, cube map, cube map array, or two-dimensional multisample
+ array texture, it is possible to bind either the entire texture level or a
+ single layer or face of the texture level. This can be controlled with the
+ \l layered property.
+
+ Support for ShaderImage is only supported with OpenGL 4 and partially with
+ OpenGL ES 3.1 and 3.2.
+
+ OpenGL 4 supports the following image types:
+ \table
+ \header
+ \li GLSL Type
+ \li OpenGL Type Enum
+ \li Texture Type
+ \row
+ \li image1D
+ \li GL_IMAGE_1D
+ \li Texture1D
+ \row
+ \li image2D
+ \li GL_IMAGE_2D
+ \li Texture2D
+ \row
+ \li image3D
+ \li GL_IMAGE_3D
+ \li Texture3D
+ \row
+ \li image2DRect
+ \li GL_IMAGE_2D_RECT
+ \li TextureRectangle
+ \row
+ \li imageCube
+ \li GL_IMAGE_CUBE
+ \li TextureCubeMap
+ \row
+ \li imageBuffer
+ \li GL_IMAGE_BUFFER
+ \li TextureBuffer
+ \row
+ \li image1DArray
+ \li GL_IMAGE_1D_ARRAY
+ \li Texture1DArray
+ \row
+ \li image2DArray
+ \li GL_IMAGE_2D_ARRAY
+ \li Texture2DArray
+ \row
+ \li imageCubeArray
+ \li GL_IMAGE_CUBE_MAP_ARRAY
+ \li TextureCubeMapArray
+ \row
+ \li image2DMS
+ \li GL_IMAGE_2D_MULTISAMPLE
+ \li Texture2DMultisample
+ \row
+ \li image2DMSArray
+ \li GL_IMAGE_2D_MULTISAMPLE_ARRAY
+ \li Texture2DMultisampleArray
+ \row
+ \li iimage1D
+ \li GL_INT_IMAGE_1D
+ \li Texture1D
+ \row
+ \li iimage2D
+ \li GL_INT_IMAGE_2D
+ \li Texture2D
+ \row
+ \li iimage3D
+ \li GL_INT_IMAGE_3D
+ \li Texture3D
+ \row
+ \li iimage2DRect
+ \li GL_INT_IMAGE_2D_RECT
+ \li TextureRectangle
+ \row
+ \li iimageCube
+ \li GL_INT_IMAGE_CUBE
+ \li TextureCubeMap
+ \row
+ \li iimageBuffer
+ \li GL_INT_IMAGE_BUFFER
+ \li TextureBuffer
+ \row
+ \li iimage1DArray
+ \li GL_INT_IMAGE_1D_ARRAY
+ \li Texture1DArray
+ \row
+ \li iimage2DArray
+ \li GL_INT_IMAGE_2D_ARRAY
+ \li Texture2DArray
+ \row
+ \li iimageCubeArray
+ \li GL_INT_IMAGE_CUBE_MAP_ARRAY
+ \li TextureCubeMapArray
+ \row
+ \li iimage2DMS
+ \li GL_INT_IMAGE_2D_MULTISAMPLE
+ \li Texture2DMultisample
+ \row
+ \li iimage2DMSArray
+ \li GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY
+ \li Texture2DMultisampleArray
+ \row
+ \li uimage1D
+ \li GL_UNSIGNED_INT_IMAGE_1D
+ \li Texture1D
+ \row
+ \li uimage2D
+ \li GL_UNSIGNED_INT_IMAGE_2D
+ \li Texture2D
+ \row
+ \li uimage3D
+ \li GL_UNSIGNED_INT_IMAGE_3D
+ \li Texture3D
+ \row
+ \li uimage2DRect
+ \li GL_UNSIGNED_INT_IMAGE_2D_RECT
+ \li TextureRectangle
+ \row
+ \li uimageCube
+ \li GL_UNSIGNED_INT_IMAGE_CUBE
+ \li TextureCubeMap
+ \row
+ \li uimageBuffer
+ \li GL_UNSIGNED_INT_IMAGE_BUFFER
+ \li TextureBuffer
+ \row
+ \li uimage1DArray
+ \li GL_UNSIGNED_INT_IMAGE_1D_ARRAY
+ \li Texture1DArray
+ \row
+ \li uimage2DArray
+ \li GL_UNSIGNED_INT_IMAGE_2D_ARRAY
+ \li Texture2DArray
+ \row
+ \li uimageCubeArray
+ \li GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY
+ \li TextureCubeMapArray
+ \row
+ \li uimage2DMS
+ \li GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE
+ \li Texture2DMultisample
+ \row
+ \li uimage2DMSArray
+ \li GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY
+ \li Texture2DMultisampleArray
+ \endtable
+
+ OpenGL ES 3.1 supports the following image types:
+ \table
+ \header
+ \li GLSL Type
+ \li OpenGL Type Enum
+ \li Texture Type
+ \row
+ \li image2D
+ \li GL_IMAGE_2D
+ \li Texture2D
+ \row
+ \li image3D
+ \li GL_IMAGE_3D
+ \li Texture3D
+ \row
+ \li imageCube
+ \li GL_IMAGE_CUBE
+ \li TextureCubeMap
+ \row
+ \li image2DArray
+ \li GL_IMAGE_2D_ARRAY
+ \li Texture2DArray
+ \row
+ \li iimage2D
+ \li GL_INT_IMAGE_2D
+ \li Texture2D
+ \row
+ \li iimage3D
+ \li GL_INT_IMAGE_3D
+ \li Texture3D
+ \row
+ \li iimageCube
+ \li GL_INT_IMAGE_CUBE
+ \li TextureCubeMap
+ \row
+ \li iimage2DArray
+ \li GL_INT_IMAGE_2D_ARRAY
+ \li Texture2DArray
+ \row
+ \li uimage2D
+ \li GL_UNSIGNED_INT_IMAGE_2D
+ \li Texture2D
+ \row
+ \li uimage3D
+ \li GL_UNSIGNED_INT_IMAGE_3D
+ \li Texture3D
+ \row
+ \li uimageCube
+ \li GL_UNSIGNED_INT_IMAGE_CUBE
+ \li TextureCubeMap
+ \row
+ \li uimage2DArray
+ \li GL_UNSIGNED_INT_IMAGE_2D_ARRAY
+ \li Texture2DArray
+ \endtable
+
+ OpenGL ES 3.2 supports all of the OpenGL ES 3.1 image types as well as the
+ following:
+ \table
+ \header
+ \li GLSL Type
+ \li OpenGL Type Enum
+ \li Texture Type
+ \row
+ \li imageBuffer
+ \li GL_IMAGE_BUFFER
+ \li TextureBuffer
+ \row
+ \li imageCubeArray
+ \li GL_IMAGE_CUBE_MAP_ARRAY
+ \li TextureCubeMapArray
+ \row
+ \li iimageBuffer
+ \li GL_IMAGE_BUFFER
+ \li TextureBuffer
+ \row
+ \li iimageCubeArray
+ \li GL_INT_IMAGE_CUBE_MAP_ARRAY
+ \li TextureCubeMapArray
+ \row
+ \li uimageBuffer
+ \li GL_UNSIGNED_INT_IMAGE_BUFFER
+ \li TextureBuffer
+ \row
+ \li uimageCubeArray
+ \li GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY
+ \li TextureCubeMapArray
+ \endtable
+
+ Expected use would look like:
+
+ \badcode
+
+ import Qt3D.Render 2.14
+
+ Entity {
+ ...
+ Texture2D {
+ id: tex2D
+ ...
+ }
+
+ Material {
+ parameters: Parameter {
+ name: "imageUniformName"
+ value: ShaderImage {
+ texture: tex2D
+ }
+ }
+ ...
+ }
+ ...
+ }
+ \endcode
+ */
+
+/*!
+ \qmlproperty int Qt3D.Render::ShaderImage::mipLevel
+
+ Holds which mipLevel out of the referenced texture should be used for the
+ ShaderImage.
+
+ \default 0
+ */
+
+/*!
+ \qmlproperty int Qt3D.Render::ShaderImage::layer
+
+ Holds which layer out of the referenced texture should be used for the
+ ShaderImage. This property does nothing if \a layered is set to true or if
+ the reference texture's type isn't compatible with layers.
+
+ \note When the referenced texture is of type cube map or cube map array and
+ \a ĺayered is set to false, the face and layer are retrieved in the
+ following manner:
+ \badcode
+ cubeMapLayer = layer / 6
+ cubeMapFace = layer - (cubeMapLayer * 6)
+ \endcode
+
+ Default value is 0.
+ */
+
+/*!
+ * \qmlproperty bool Qt3D.Render::ShaderImage::layered
+
+ If set to true, if the referenced texture is a one-dimensional array,
+ two-dimensional array, three-dimensional, cube map, cube map array, or
+ two-dimensional multisample array texture, the entire level will be bound
+ for all layers. If set to false, only the single layer specified by the \a
+ layer property will be bound.
+
+ Default value is \c false.
+ */
+
+/*!
+ \qmlproperty enumeration Qt3D.Render::ShaderImage::access
+
+ Specifies the type of access we want to allow from our shader instances to
+ the image. If a shader tries to write or read from an image that has
+ incompatible access, the behavior is undefined.
+
+ \value ShaderImage.ReadOnly
+ Read-only access.
+ \value ShaderImage.WriteOnly
+ Write-only access.
+ \value ShaderImage.ReadWrite
+ Read-write access.
+
+ Default value is ShaderImage.ReadWrite.
+ */
+
+/*!
+ \qmlproperty enumeration Qt3D.Render::ShaderImage::format
+
+ Specifies the image format, which is essentially important when storing values
+ in the ShaderImage from a shader.
+
+ The format doesn't have to be the same as the referenced texture's format.
+ It however has to be compatible (matching in size but not necessarily by
+ class type). For instance a texture of format R32F (size 32bits, class
+ 1x32) could be used with an image of format RGBA8I (size 32bits, class
+ 4x8). Table 8.27 of the
+ \l{https://www.khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf}{OpenGL specifications}
+ shows the size and class for all supported image formats.
+
+ By default Qt3D will try to set the image format to match that of the
+ referenced texture.
+
+ Default value is ShaderImage.Automatic.
+ */
+
+/*!
+ \class Qt3DRender::QShaderImage
+ \inmodule Qt3DRender
+ \since 5.14
+ \brief Provides Image access to shader programs.
+
+ To make the content of textures available for read and write operations in
+ a shader, they need to exposed as QShaderImage. Textures can be composed of
+ several mip levels, layers and faces. Additionally declaring a QShaderImage
+ allows specifying which level, layer or face of the texture content we want
+ to access.
+
+ QShaderImage has to be assigned as a QParameter's value and reference a valid
+ Qt3DRender::QAbstractTexture to work properly.
+
+ If the referenced texture is a one-dimensional array, two-dimensional array,
+ three-dimensional, cube map, cube map array, or two-dimensional multisample
+ array texture, it is possible to bind either the entire texture level or a
+ single layer or face of the texture level. This can be controlled with the
+ \l layered property.
+
+ Support for QShaderImage is only supported with OpenGL 4 and partially with
+ OpenGL ES 3.1 and 3.2.
+
+ OpenGL 4 supports the following image types:
+ \table
+ \header
+ \li GLSL Type
+ \li OpenGL Type Enum
+ \li Texture Type
+ \row
+ \li image1D
+ \li GL_IMAGE_1D
+ \li QTexture1D
+ \row
+ \li image2D
+ \li GL_IMAGE_2D
+ \li QTexture2D
+ \row
+ \li image3D
+ \li GL_IMAGE_3D
+ \li QTexture3D
+ \row
+ \li image2DRect
+ \li GL_IMAGE_2D_RECT
+ \li QTextureRectangle
+ \row
+ \li imageCube
+ \li GL_IMAGE_CUBE
+ \li QTextureCubeMap
+ \row
+ \li imageBuffer
+ \li GL_IMAGE_BUFFER
+ \li QTextureBuffer
+ \row
+ \li image1DArray
+ \li GL_IMAGE_1D_ARRAY
+ \li QTexture1DArray
+ \row
+ \li image2DArray
+ \li GL_IMAGE_2D_ARRAY
+ \li QTexture2DArray
+ \row
+ \li imageCubeArray
+ \li GL_IMAGE_CUBE_MAP_ARRAY
+ \li QTextureCubeMapArray
+ \row
+ \li image2DMS
+ \li GL_IMAGE_2D_MULTISAMPLE
+ \li QTexture2DMultisample
+ \row
+ \li image2DMSArray
+ \li GL_IMAGE_2D_MULTISAMPLE_ARRAY
+ \li QTexture2DMultisampleArray
+ \row
+ \li iimage1D
+ \li GL_INT_IMAGE_1D
+ \li QTexture1D
+ \row
+ \li iimage2D
+ \li GL_INT_IMAGE_2D
+ \li QTexture2D
+ \row
+ \li iimage3D
+ \li GL_INT_IMAGE_3D
+ \li QTexture3D
+ \row
+ \li iimage2DRect
+ \li GL_INT_IMAGE_2D_RECT
+ \li QTextureRectangle
+ \row
+ \li iimageCube
+ \li GL_INT_IMAGE_CUBE
+ \li QTextureCubeMap
+ \row
+ \li iimageBuffer
+ \li GL_INT_IMAGE_BUFFER
+ \li QTextureBuffer
+ \row
+ \li iimage1DArray
+ \li GL_INT_IMAGE_1D_ARRAY
+ \li QTexture1DArray
+ \row
+ \li iimage2DArray
+ \li GL_INT_IMAGE_2D_ARRAY
+ \li QTexture2DArray
+ \row
+ \li iimageCubeArray
+ \li GL_INT_IMAGE_CUBE_MAP_ARRAY
+ \li QTextureCubeMapArray
+ \row
+ \li iimage2DMS
+ \li GL_INT_IMAGE_2D_MULTISAMPLE
+ \li QTexture2DMultisample
+ \row
+ \li iimage2DMSArray
+ \li GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY
+ \li QTexture2DMultisampleArray
+ \row
+ \li uimage1D
+ \li GL_UNSIGNED_INT_IMAGE_1D
+ \li QTexture1D
+ \row
+ \li uimage2D
+ \li GL_UNSIGNED_INT_IMAGE_2D
+ \li QTexture2D
+ \row
+ \li uimage3D
+ \li GL_UNSIGNED_INT_IMAGE_3D
+ \li QTexture3D
+ \row
+ \li uimage2DRect
+ \li GL_UNSIGNED_INT_IMAGE_2D_RECT
+ \li QTextureRectangle
+ \row
+ \li uimageCube
+ \li GL_UNSIGNED_INT_IMAGE_CUBE
+ \li QTextureCubeMap
+ \row
+ \li uimageBuffer
+ \li GL_UNSIGNED_INT_IMAGE_BUFFER
+ \li QTextureBuffer
+ \row
+ \li uimage1DArray
+ \li GL_UNSIGNED_INT_IMAGE_1D_ARRAY
+ \li QTexture1DArray
+ \row
+ \li uimage2DArray
+ \li GL_UNSIGNED_INT_IMAGE_2D_ARRAY
+ \li QTexture2DArray
+ \row
+ \li uimageCubeArray
+ \li GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY
+ \li QTextureCubeMapArray
+ \row
+ \li uimage2DMS
+ \li GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE
+ \li QTexture2DMultisample
+ \row
+ \li uimage2DMSArray
+ \li GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY
+ \li QTexture2DMultisampleArray
+ \endtable
+
+ OpenGL ES 3.1 supports the following image types:
+ \table
+ \header
+ \li GLSL Type
+ \li OpenGL Type Enum
+ \li Texture Type
+ \row
+ \li image2D
+ \li GL_IMAGE_2D
+ \li QTexture2D
+ \row
+ \li image3D
+ \li GL_IMAGE_3D
+ \li QTexture3D
+ \row
+ \li imageCube
+ \li GL_IMAGE_CUBE
+ \li QTextureCubeMap
+ \row
+ \li image2DArray
+ \li GL_IMAGE_2D_ARRAY
+ \li QTexture2DArray
+ \row
+ \li iimage2D
+ \li GL_INT_IMAGE_2D
+ \li QTexture2D
+ \row
+ \li iimage3D
+ \li GL_INT_IMAGE_3D
+ \li QTexture3D
+ \row
+ \li iimageCube
+ \li GL_INT_IMAGE_CUBE
+ \li QTextureCubeMap
+ \row
+ \li iimage2DArray
+ \li GL_INT_IMAGE_2D_ARRAY
+ \li QTexture2DArray
+ \row
+ \li uimage2D
+ \li GL_UNSIGNED_INT_IMAGE_2D
+ \li QTexture2D
+ \row
+ \li uimage3D
+ \li GL_UNSIGNED_INT_IMAGE_3D
+ \li QTexture3D
+ \row
+ \li uimageCube
+ \li GL_UNSIGNED_INT_IMAGE_CUBE
+ \li QTextureCubeMap
+ \row
+ \li uimage2DArray
+ \li GL_UNSIGNED_INT_IMAGE_2D_ARRAY
+ \li QTexture2DArray
+ \endtable
+
+ OpenGL ES 3.2 supports all of the OpenGL ES 3.1 image types as well as the
+ following:
+ \table
+ \header
+ \li GLSL Type
+ \li OpenGL Type Enum
+ \li Texture Type
+ \row
+ \li imageBuffer
+ \li GL_IMAGE_BUFFER
+ \li QTextureBuffer
+ \row
+ \li imageCubeArray
+ \li GL_IMAGE_CUBE_MAP_ARRAY
+ \li QTextureCubeMapArray
+ \row
+ \li iimageBuffer
+ \li GL_IMAGE_BUFFER
+ \li QTextureBuffer
+ \row
+ \li iimageCubeArray
+ \li GL_INT_IMAGE_CUBE_MAP_ARRAY
+ \li QTextureCubeMapArray
+ \row
+ \li uimageBuffer
+ \li GL_UNSIGNED_INT_IMAGE_BUFFER
+ \li QTextureBuffer
+ \row
+ \li uimageCubeArray
+ \li GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY
+ \li QTextureCubeMapArray
+ \endtable
+
+ Expected use would look like:
+
+ \badcode
+ Qt3DRender::QTexture2D *tex2D = new Qt3DRender::QTexture2D();
+ ...
+ Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial();
+ ...
+ Qt3DRender::QParameter *imageParameter = new Qt3DRender::QParameter();
+ Qt3DRender::QShaderImage *shaderImage = new Qt3DRender::QShaderImage();
+
+ shaderImage->setTexture(tex2D);
+
+ imageParameter->setName("imageUniformName");
+ imageParameter->setValue(QVariant::fromValue(shaderImage));
+
+ material->addParameter(imageParamenter);
+ \endcode
+ */
+
+/*!
+ \property Qt3DRender::QShaderImage::mipLevel
+
+ Holds which mipLevel out of the referenced texture should be used for the
+ QShaderImage.
+
+ \default 0
+ */
+
+/*!
+ \property Qt3DRender::QShaderImage::layer
+
+ Holds which layer out of the referenced texture should be used for the
+ QShaderImage. This property does nothing if \a layered is set to true or if the
+ reference texture's type isn't compatible with layers.
+
+ \note When the referenced texture is of type cube map or cube map array and
+ \a ĺayered is set to false, the face and layer are retrieved in the
+ following manner:
+ \badcode
+ cubeMapLayer = layer / 6
+ cubeMapFace = layer - (cubeMapLayer * 6)
+ \endcode
+
+ \default 0
+ */
+
+/*!
+ * \property Qt3DRender::QShaderImage::layered
+
+ If set to true, if the referenced texture is a one-dimensional array,
+ two-dimensional array, three-dimensional, cube map, cube map array, or
+ two-dimensional multisample array texture, the entire level will be bound
+ for all layers. If set to false, only the single layer specified by the \a
+ layer property will be bound.
+
+ \default false
+ */
+
+/*!
+ \property Qt3DRender::QShaderImage::access
+
+ Specifies the type of access we want to allow from our shader instances to
+ the image. If a shader tries to write or read from an image that has
+ incompatible access, the behavior is undefined.
+
+ \default QShaderImage::ReadWrite
+ */
+
+/*!
+ \property Qt3DRender::QShaderImage::format
+
+ Specifies the image format, which is essentially important when storing values
+ in the Image from a shader.
+
+ The format doesn't have to be the same as the referenced texture's format.
+ It however has to be compatible (matching in size but not necessarily by
+ class type). For instance a texture of format R32F (size 32bits, class
+ 1x32) could be used with an image of format RGBA8I (size 32bits, class
+ 4x8). Table 8.27 of the
+ \l{https://www.khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf}{OpenGL specifications}
+ shows the size and class for all supported Image formats.
+
+ By default Qt3D will try to set the image format to match that of the
+ referenced texture.
+
+ \default QShaderImage::Automatic
+ */
+
+/*!
+ \enum Qt3DRender::QShaderImage::Access
+
+ \value ReadOnly
+ Image will only be read from in shaders
+ \value WriteOnly
+ Image will only be written into from shaders
+ \value ReadWrite
+ Image will only be read and written into from shaders
+*/
+
+/*!
+ \enum Qt3DRender::QShaderImage::ImageFormat
+
+ This list describes all possible image formats
+
+ \value NoFormat
+ GL_NONE
+ \value Automatic
+ Qt 3D will try to determine the format automatically based on
+ the referenced texture.
+ \value R8_UNorm
+ GL_R8 (GLSL type r8, supported by OpenGL 4.2+)
+ \value RG8_UNorm
+ GL_RG8 (GLSL type rg8, supported by OpenGL 4.2+)
+ \value RGBA8_UNorm
+ GL_RGBA8 (GLSL type rgba8, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value R16_UNorm
+ GL_R16 (GLSL type r16, supported by OpenGL 4.2+)
+ \value RG16_UNorm
+ GL_RG16 (GLSL type rg16, supported by OpenGL 4.2+)
+ \value RGBA16_UNorm
+ GL_RGBA16 (GLSL type rgba16, supported by OpenGL 4.2+)
+ \value R8_SNorm
+ GL_R8_SNORM (GLSL type r8_snorm, supported by OpenGL 4.2+)
+ \value RG8_SNorm
+ GL_RG8_SNORM (GLSL type rg8_snorm, supported by OpenGL 4.2+)
+ \value RGBA8_SNorm
+ GL_RGBA8_SNORM (GLSL type rgba8_snorm, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value R16_SNorm
+ GL_R16_SNORM (GLSL type r16_snorm, supported by OpenGL 4.2+)
+ \value RG16_SNorm
+ GL_RG16_SNORM (GLSL type rg16_snorm, supported by OpenGL 4.2+)
+ \value RGBA16_SNorm
+ GL_RGBA16_SNORM (GLSL type rgba16_snorm, supported by OpenGL 4.2+)
+ \value R8U
+ GL_R8UI (GLSL type r8ui, supported by OpenGL 4.2+)
+ \value RG8U
+ GL_RG8UI (GLSL type rg8ui, supported by OpenGL 4.2+)
+ \value RGBA8U
+ GL_RGBA8UI (GLSL type rgba8ui, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value R16U
+ GL_R16UI (GLSL type r16ui, supported by OpenGL 4.2+)
+ \value RG16U
+ GL_RG16UI (GLSL type rg16ui, supported by OpenGL 4.2+)
+ \value RGBA16U
+ GL_RGBA16UI (GLSL type rgba16ui, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value R32U
+ GL_R32UI (GLSL type r32ui, supported by OpenGL 4.2+, OpenGL ES 3.1)
+ \value RG32U
+ GL_RG32UI (GLSL type rg32ui, supported by OpenGL 4.2+)
+ \value RGBA32U
+ GL_RGBA32UI (GLSL type rgba32ui, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value R8I
+ GL_R8I (GLSL type r8i, supported by OpenGL 4.2+)
+ \value RG8I
+ GL_RG8I (GLSL type rg8i, supported by OpenGL 4.2+)
+ \value RGBA8I
+ GL_RGBA8I (GLSL type rgba8i, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value R16I
+ GL_R16I (GLSL type r16i, supported by OpenGL 4.2+)
+ \value RG16I
+ GL_RG16I (GLSL type rg16i, supported by OpenGL 4.2+)
+ \value RGBA16I
+ GL_RGBA16I (GLSL type rgba16i, supported by OpenGL 4.2+, OpenGL ES 3.1)
+ \value R32I
+ GL_R32I (GLSL type r32i, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value RG32I
+ GL_RG32I (GLSL type rg32i, supported by OpenGL 4.2+)
+ \value RGBA32I
+ GL_RGBA32I (GLSL type rgba32i, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value R16F
+ GL_R16F (GLSL type r16f, supported by OpenGL 4.2+)
+ \value RG16F
+ GL_RG16F (GLSL type rg16f, supported by OpenGL 4.2+)
+ \value RGBA16F
+ GL_RGBA16F (GLSL type rgba16f, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value R32F
+ GL_R32F (GLSL type r32f, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value RG32F
+ GL_RG32F (GLSL type rg32f, supported by OpenGL 4.2+)
+ \value RGBA32F
+ GL_RGBA32F (GLSL type rgba32f, supported by OpenGL 4.2+, OpenGL ES 3.1+)
+ \value RG11B10F
+ GL_R11F_G11F_B10F (GLSL type r11f_g11f_b10f, supported by OpenGL 4.2+)
+ \value RGB10A2
+ GL_RGB10_A2 (GLSL type rgb10_a2, supported by OpenGL 4.2+)
+ \value RGB10A2U
+ GL_RGB10_A2UI (GLSL type rgb10_a2ui, supported by OpenGL 4.2+)
+*/
+
+
+QShaderImage::QShaderImage(Qt3DCore::QNode *parent)
+ : Qt3DCore::QNode(*new QShaderImagePrivate, parent)
+{
+}
+
+QShaderImage::~QShaderImage()
+{
+
+}
+
+QAbstractTexture *QShaderImage::texture() const
+{
+ Q_D(const QShaderImage);
+ return d->m_texture;
+}
+
+bool QShaderImage::layered() const
+{
+ Q_D(const QShaderImage);
+ return d->m_layered;
+}
+
+int QShaderImage::mipLevel() const
+{
+ Q_D(const QShaderImage);
+ return d->m_mipLevel;
+}
+
+int QShaderImage::layer() const
+{
+ Q_D(const QShaderImage);
+ return d->m_layer;
+}
+
+QShaderImage::Access QShaderImage::access() const
+{
+ Q_D(const QShaderImage);
+ return d->m_access;
+}
+
+QShaderImage::ImageFormat QShaderImage::format() const
+{
+ Q_D(const QShaderImage);
+ return d->m_format;
+}
+
+void QShaderImage::setTexture(QAbstractTexture *texture)
+{
+ Q_D(QShaderImage);
+ if (texture == d->m_texture)
+ return;
+
+ if (d->m_texture)
+ d->unregisterDestructionHelper(d->m_texture);
+
+ if (texture && !texture->parent())
+ texture->setParent(this);
+
+ d->m_texture = texture;
+
+ if (d->m_texture)
+ d->registerDestructionHelper(d->m_texture, &QShaderImage::setTexture, d->m_texture);
+
+ Q_EMIT textureChanged(texture);
+}
+
+void QShaderImage::setLayered(bool layered)
+{
+ Q_D(QShaderImage);
+ if (layered == d->m_layered)
+ return;
+ d->m_layered = layered;
+ Q_EMIT layeredChanged(layered);
+}
+
+void QShaderImage::setMipLevel(int mipLevel)
+{
+ Q_D(QShaderImage);
+ if (mipLevel == d->m_mipLevel)
+ return;
+ d->m_mipLevel = mipLevel;
+ Q_EMIT mipLevelChanged(mipLevel);
+}
+
+void QShaderImage::setLayer(int layer)
+{
+ Q_D(QShaderImage);
+ if (layer == d->m_layer)
+ return;
+ d->m_layer = layer;
+ Q_EMIT layerChanged(layer);
+}
+
+void QShaderImage::setAccess(QShaderImage::Access access)
+{
+ Q_D(QShaderImage);
+ if (access == d->m_access)
+ return;
+ d->m_access = access;
+ Q_EMIT accessChanged(access);
+}
+
+void QShaderImage::setFormat(QShaderImage::ImageFormat format)
+{
+ Q_D(QShaderImage);
+ if (format == d->m_format)
+ return;
+ d->m_format = format;
+ Q_EMIT formatChanged(format);
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr Qt3DRender::QShaderImage::createNodeCreationChange() const
+{
+ auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QShaderImageData>::create(this);
+ QShaderImageData &data = creationChange->data;
+ Q_D(const QShaderImage);
+ data.textureId = Qt3DCore::qIdForNode(d->m_texture);
+ data.layer = d->m_layer;
+ data.mipLevel = d->m_mipLevel;
+ data.access = d->m_access;
+ data.format = d->m_format;
+ data.layered = d->m_layered;
+ return creationChange;
+
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/materialsystem/qshaderimage.h b/src/render/materialsystem/qshaderimage.h
new file mode 100644
index 000000000..e1f5459d2
--- /dev/null
+++ b/src/render/materialsystem/qshaderimage.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QSHADERIMAGE_H
+#define QT3DRENDER_QSHADERIMAGE_H
+
+#include <Qt3DCore/qnode.h>
+#include <Qt3DRender/qt3drender_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QAbstractTexture;
+class QShaderImagePrivate;
+
+class Q_3DRENDERSHARED_EXPORT QShaderImage : public Qt3DCore::QNode
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt3DRender::QAbstractTexture *texture READ texture WRITE setTexture NOTIFY textureChanged)
+ Q_PROPERTY(bool layered READ layered WRITE setLayered NOTIFY layeredChanged)
+ Q_PROPERTY(int mipLevel READ mipLevel WRITE setMipLevel NOTIFY mipLevelChanged)
+ Q_PROPERTY(int layer READ layer WRITE setLayer NOTIFY layerChanged)
+ Q_PROPERTY(Access access READ access WRITE setAccess NOTIFY accessChanged)
+ Q_PROPERTY(ImageFormat format READ format WRITE setFormat NOTIFY formatChanged)
+
+public:
+ enum Access {
+ ReadOnly = 0,
+ WriteOnly,
+ ReadWrite
+ };
+ Q_ENUM(Access)
+
+ enum ImageFormat {
+ NoFormat = 0, // GL_NONE
+ Automatic = 1, // The Qt3D engine automatically determines the best format
+
+ // Unsigned normalized formats
+ R8_UNorm = 0x8229, // GL_R8
+ RG8_UNorm = 0x822B, // GL_RG8
+ RGBA8_UNorm = 0x8058, // GL_RGBA8
+
+ R16_UNorm = 0x822A, // GL_R16
+ RG16_UNorm = 0x822C, // GL_RG16
+ RGBA16_UNorm = 0x805B, // GL_RGBA16
+
+ // Signed normalized formats
+ R8_SNorm = 0x8F94, // GL_R8_SNORM
+ RG8_SNorm = 0x8F95, // GL_RG8_SNORM
+ RGBA8_SNorm = 0x8F97, // GL_RGBA8_SNORM
+
+ R16_SNorm = 0x8F98, // GL_R16_SNORM
+ RG16_SNorm = 0x8F99, // GL_RG16_SNORM
+ RGBA16_SNorm = 0x8F9B, // GL_RGBA16_SNORM
+
+ // Unsigned integer formats
+ R8U = 0x8232, // GL_R8UI
+ RG8U = 0x8238, // GL_RG8UI
+ RGBA8U = 0x8D7C, // GL_RGBA8UI
+
+ R16U = 0x8234, // GL_R16UI
+ RG16U = 0x823A, // GL_RG16UI
+ RGBA16U = 0x8D76, // GL_RGBA16UI
+
+ R32U = 0x8236, // GL_R32UI
+ RG32U = 0x823C, // GL_RG32UI
+ RGBA32U = 0x8D70, // GL_RGBA32UI
+
+ // Signed integer formats
+ R8I = 0x8231, // GL_R8I
+ RG8I = 0x8237, // GL_RG8I
+ RGBA8I = 0x8D8E, // GL_RGBA8I
+
+ R16I = 0x8233, // GL_R16I
+ RG16I = 0x8239, // GL_RG16I
+ RGBA16I = 0x8D88, // GL_RGBA16I
+
+ R32I = 0x8235, // GL_R32I
+ RG32I = 0x823B, // GL_RG32I
+ RGBA32I = 0x8D82, // GL_RGBA32I
+
+ // Floating point formats
+ R16F = 0x822D, // GL_R16F
+ RG16F = 0x822F, // GL_RG16F
+ RGBA16F = 0x881A, // GL_RGBA16F
+
+ R32F = 0x822E, // GL_R32F
+ RG32F = 0x8230, // GL_RG32F
+ RGBA32F = 0x8814, // GL_RGBA32F
+
+ // Packed formats
+ RG11B10F = 0x8C3A, // GL_R11F_G11F_B10F
+ RGB10A2 = 0x8059, // GL_RGB10_A2
+ RGB10A2U = 0x906F, // GL_RGB10_A2_UI
+ };
+ Q_ENUM(ImageFormat)
+
+ explicit QShaderImage(Qt3DCore::QNode *parent = nullptr);
+ ~QShaderImage();
+
+ Qt3DRender::QAbstractTexture *texture() const;
+ bool layered() const;
+ int mipLevel() const;
+ int layer() const;
+ Access access() const;
+ ImageFormat format() const;
+
+public Q_SLOTS:
+ void setTexture(Qt3DRender::QAbstractTexture *texture);
+ void setLayered(bool layered);
+ void setMipLevel(int mipLevel);
+ void setLayer(int layer);
+ void setAccess(Access access);
+ void setFormat(ImageFormat format);
+
+Q_SIGNALS:
+ void textureChanged(Qt3DRender::QAbstractTexture *texture);
+ void layeredChanged(bool layered);
+ void mipLevelChanged(int mipLevel);
+ void layerChanged(int layer);
+ void accessChanged(Access access);
+ void formatChanged(ImageFormat format);
+
+private:
+ Q_DECLARE_PRIVATE(QShaderImage)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QSHADERIMAGE_H
diff --git a/src/render/materialsystem/qshaderimage_p.h b/src/render/materialsystem/qshaderimage_p.h
new file mode 100644
index 000000000..33cffb84a
--- /dev/null
+++ b/src/render/materialsystem/qshaderimage_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QSHADERIMAGE_P_H
+#define QT3DRENDER_QSHADERIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DRender/qshaderimage.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QAbstractTexture;
+
+class QShaderImagePrivate : public Qt3DCore::QNodePrivate
+{
+public:
+ QShaderImagePrivate();
+ ~QShaderImagePrivate();
+
+ Q_DECLARE_PUBLIC(QShaderImage)
+
+ Qt3DRender::QAbstractTexture *m_texture;
+ int m_mipLevel;
+ int m_layer;
+ QShaderImage::Access m_access;
+ QShaderImage::ImageFormat m_format;
+ bool m_layered;
+};
+
+struct QShaderImageData
+{
+ Qt3DCore::QNodeId textureId;
+ int mipLevel;
+ int layer;
+ QShaderImage::Access access;
+ QShaderImage::ImageFormat format;
+ bool layered;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QSHADERIMAGE_P_H
diff --git a/src/render/materialsystem/qshaderprogrambuilder.cpp b/src/render/materialsystem/qshaderprogrambuilder.cpp
index 84dd33372..7f98fbf5e 100644
--- a/src/render/materialsystem/qshaderprogrambuilder.cpp
+++ b/src/render/materialsystem/qshaderprogrambuilder.cpp
@@ -79,6 +79,47 @@ QShaderProgramBuilderPrivate::QShaderProgramBuilderPrivate()
{
}
+void QShaderProgramBuilderPrivate::setShaderCode(const QByteArray &code, QShaderProgram::ShaderType type)
+{
+ Q_Q(QShaderProgramBuilder);
+ const bool blocked = q->blockNotifications(true);
+
+ switch (type) {
+ case QShaderProgram::Vertex: {
+ m_vertexShaderCode = code;
+ emit q->vertexShaderCodeChanged(m_vertexShaderCode);
+ break;
+ }
+ case QShaderProgram::Fragment:{
+ m_fragmentShaderCode = code;
+ emit q->fragmentShaderCodeChanged(m_fragmentShaderCode);
+ break;
+ }
+ case QShaderProgram::Geometry: {
+ m_geometryShaderCode = code;
+ emit q->geometryShaderCodeChanged(m_geometryShaderCode);
+ break;
+ }
+ case QShaderProgram::Compute: {
+ m_computeShaderCode = code;
+ emit q->computeShaderCodeChanged(m_computeShaderCode);
+ break;
+ }
+ case QShaderProgram::TessellationControl: {
+ m_tessControlShaderCode = code;
+ emit q->tessellationControlShaderCodeChanged(m_tessControlShaderCode);
+ break;
+ }
+ case QShaderProgram::TessellationEvaluation: {
+ m_tessEvalShaderCode = code;
+ emit q->tessellationEvaluationShaderCodeChanged(m_tessEvalShaderCode);
+ break;
+ }
+ }
+
+ q->blockNotifications(blocked);
+}
+
QShaderProgramBuilder::QShaderProgramBuilder(QNode *parent)
: QNode(*new QShaderProgramBuilderPrivate, parent)
{
@@ -94,51 +135,9 @@ QShaderProgramBuilder::QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Q
{
}
-void QShaderProgramBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+// TODO Unused remove in Qt6
+void QShaderProgramBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
{
- Q_D(QShaderProgramBuilder);
- if (change->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->propertyName() == QByteArrayLiteral("generatedShaderCode")) {
- const bool blocked = blockNotifications(true);
- const QPair<int, QByteArray> data = e->value().value<QPair<int, QByteArray>>();
-
- switch (data.first) {
- case QShaderProgram::Vertex: {
- d->m_vertexShaderCode = data.second;
- emit vertexShaderCodeChanged(d->m_vertexShaderCode);
- break;
- }
- case QShaderProgram::Fragment:{
- d->m_fragmentShaderCode = data.second;
- emit fragmentShaderCodeChanged(d->m_fragmentShaderCode);
- break;
- }
- case QShaderProgram::Geometry: {
- d->m_geometryShaderCode = data.second;
- emit geometryShaderCodeChanged(d->m_geometryShaderCode);
- break;
- }
- case QShaderProgram::Compute: {
- d->m_computeShaderCode = data.second;
- emit computeShaderCodeChanged(d->m_computeShaderCode);
- break;
- }
- case QShaderProgram::TessellationControl: {
- d->m_tessControlShaderCode = data.second;
- emit tessellationControlShaderCodeChanged(d->m_tessControlShaderCode);
- break;
- }
- case QShaderProgram::TessellationEvaluation: {
- d->m_tessEvalShaderCode = data.second;
- emit tessellationEvaluationShaderCodeChanged(d->m_tessEvalShaderCode);
- break;
- }
- }
-
- blockNotifications(blocked);
- }
- }
}
/*!
@@ -359,13 +358,13 @@ QUrl QShaderProgramBuilder::computeShaderGraph() const
}
/*!
- \qmlproperty string ShaderProgramBuilder:vertexShaderCode
+ \qmlproperty string ShaderProgramBuilder::vertexShaderCode
Holds the generated vertex shader code
\since 2.13
*/
/*!
- \property QShaderProgram:Builder:vertexShaderCode
+ \property QShaderProgramBuilder::vertexShaderCode
Holds the generate vertex shader code.
\since 5.13
@@ -377,13 +376,13 @@ QByteArray QShaderProgramBuilder::vertexShaderCode() const
}
/*!
- \qmlproperty string ShaderProgramBuilder:tessellationControlShaderCode
+ \qmlproperty string ShaderProgramBuilder::tessellationControlShaderCode
Holds the generated tessellation control shader code
\since 2.13
*/
/*!
- \property QShaderProgram:Builder:tessellationControlShaderCode
+ \property QShaderProgramBuilder::tessellationControlShaderCode
Holds the generate tessellation control shader code.
\since 5.13
@@ -395,13 +394,13 @@ QByteArray QShaderProgramBuilder::tessellationControlShaderCode() const
}
/*!
- \qmlproperty string ShaderProgramBuilder:tessellationEvaluationShaderCode
+ \qmlproperty string ShaderProgramBuilder::tessellationEvaluationShaderCode
Holds the generated tessellation evaluation shader code
\since 2.13
*/
/*!
- \property QShaderProgram:Builder:tessellationEvaluationShaderCode
+ \property QShaderProgramBuilder::tessellationEvaluationShaderCode
Holds the generate tessellation evaluation shader code.
\since 5.13
@@ -413,13 +412,13 @@ QByteArray QShaderProgramBuilder::tessellationEvaluationShaderCode() const
}
/*!
- \qmlproperty string ShaderProgramBuilder:geometryShaderCode
+ \qmlproperty string ShaderProgramBuilder::geometryShaderCode
Holds the generated geometry shader code
\since 2.13
*/
/*!
- \property QShaderProgram:Builder:geometryShaderCode
+ \property QShaderProgramBuilder::geometryShaderCode
Holds the generate geometry shader code.
\since 5.13
@@ -437,7 +436,7 @@ QByteArray QShaderProgramBuilder::geometryShaderCode() const
\since 2.13
*/
/*!
- \property QShaderProgram:Builder:fragmentShaderCode
+ \property QShaderProgramBuilder::fragmentShaderCode
Holds the generate fragment shader code.
\since 5.13
@@ -455,7 +454,7 @@ QByteArray QShaderProgramBuilder::fragmentShaderCode() const
\since 2.13
*/
/*!
- \property QShaderProgram:Builder:computeShaderCode
+ \property QShaderProgramBuilder::computeShaderCode
Holds the generate compute shader code.
\since 5.13
diff --git a/src/render/materialsystem/qshaderprogrambuilder.h b/src/render/materialsystem/qshaderprogrambuilder.h
index 184093730..48e189c8c 100644
--- a/src/render/materialsystem/qshaderprogrambuilder.h
+++ b/src/render/materialsystem/qshaderprogrambuilder.h
@@ -117,6 +117,7 @@ Q_SIGNALS:
protected:
explicit QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+ // TODO Unused remove in Qt6
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
private:
diff --git a/src/render/materialsystem/qshaderprogrambuilder_p.h b/src/render/materialsystem/qshaderprogrambuilder_p.h
index 2ac765a1d..22f8e6e58 100644
--- a/src/render/materialsystem/qshaderprogrambuilder_p.h
+++ b/src/render/materialsystem/qshaderprogrambuilder_p.h
@@ -52,6 +52,8 @@
//
#include <private/qnode_p.h>
+#include <Qt3DRender/private/qt3drender_global_p.h>
+#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/qshaderprogrambuilder.h>
#include <QtCore/qurl.h>
@@ -60,7 +62,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QShaderProgramBuilderPrivate : public Qt3DCore::QNodePrivate
+class Q_3DRENDERSHARED_PRIVATE_EXPORT QShaderProgramBuilderPrivate : public Qt3DCore::QNodePrivate
{
public:
QShaderProgramBuilderPrivate();
@@ -80,6 +82,8 @@ public:
QByteArray m_geometryShaderCode;
QByteArray m_fragmentShaderCode;
QByteArray m_computeShaderCode;
+
+ void setShaderCode(const QByteArray &code, QShaderProgram::ShaderType type);
};
struct QShaderProgramBuilderData
diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp
index e5f109d46..a9b7ca82b 100644
--- a/src/render/materialsystem/qtechnique.cpp
+++ b/src/render/materialsystem/qtechnique.cpp
@@ -41,9 +41,6 @@
#include "qtechnique_p.h"
#include "qparameter.h"
#include "qgraphicsapifilter.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -238,12 +235,7 @@ QTechnique::QTechnique(QTechniquePrivate &dd, QNode *parent)
/*! \internal */
void QTechniquePrivate::_q_graphicsApiFilterChanged()
{
- if (m_changeArbiter != nullptr) {
- auto change = QPropertyUpdatedChangePtr::create(m_id);
- change->setPropertyName("graphicsApiFilterData");
- change->setValue(QVariant::fromValue(QGraphicsApiFilterPrivate::get(const_cast<QGraphicsApiFilter *>(&m_graphicsApiFilter))->m_data));
- notifyObservers(change);
- }
+ update();
}
/*!
@@ -266,11 +258,7 @@ void QTechnique::addFilterKey(QFilterKey *filterKey)
if (!filterKey->parent())
filterKey->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), filterKey);
- change->setPropertyName("filterKeys");
- d->notifyObservers(change);
- }
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueAdded);
}
}
@@ -281,11 +269,7 @@ void QTechnique::removeFilterKey(QFilterKey *filterKey)
{
Q_ASSERT(filterKey);
Q_D(QTechnique);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), filterKey);
- change->setPropertyName("filterKeys");
- d->notifyObservers(change);
- }
+ d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueRemoved);
d->m_filterKeys.removeOne(filterKey);
// Remove bookkeeping connection
d->unregisterDestructionHelper(filterKey);
@@ -321,11 +305,7 @@ void QTechnique::addParameter(QParameter *parameter)
if (!parameter->parent())
parameter->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueAdded);
}
}
@@ -336,11 +316,7 @@ void QTechnique::removeParameter(QParameter *parameter)
{
Q_ASSERT(parameter);
Q_D(QTechnique);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), parameter);
- change->setPropertyName("parameter");
- d->notifyObservers(change);
- }
+ d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved);
d->m_parameters.removeOne(parameter);
// Remove bookkeeping connection
d->unregisterDestructionHelper(parameter);
@@ -366,11 +342,7 @@ void QTechnique::addRenderPass(QRenderPass *pass)
if (!pass->parent())
pass->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), pass);
- change->setPropertyName("pass");
- d->notifyObservers(change);
- }
+ d->updateNode(pass, "pass", Qt3DCore::PropertyValueAdded);
}
}
@@ -381,11 +353,7 @@ void QTechnique::removeRenderPass(QRenderPass *pass)
{
Q_ASSERT(pass);
Q_D(QTechnique);
- if (d->m_changeArbiter) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), pass);
- change->setPropertyName("pass");
- d->notifyObservers(change);
- }
+ d->updateNode(pass, "pass", Qt3DCore::PropertyValueAdded);
d->m_renderPasses.removeOne(pass);
// Remove bookkeeping connection
d->unregisterDestructionHelper(pass);
@@ -415,6 +383,12 @@ QGraphicsApiFilter *QTechnique::graphicsApiFilter()
return &d->m_graphicsApiFilter;
}
+const QGraphicsApiFilter *QTechnique::graphicsApiFilter() const
+{
+ Q_D(const QTechnique);
+ return &d->m_graphicsApiFilter;
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QTechnique::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QTechniqueData>::create(this);
diff --git a/src/render/materialsystem/qtechnique.h b/src/render/materialsystem/qtechnique.h
index 7711cd67f..b9887b6a2 100644
--- a/src/render/materialsystem/qtechnique.h
+++ b/src/render/materialsystem/qtechnique.h
@@ -77,6 +77,7 @@ public:
QVector<QRenderPass *> renderPasses() const;
QGraphicsApiFilter *graphicsApiFilter();
+ const QGraphicsApiFilter *graphicsApiFilter() const;
protected:
explicit QTechnique(QTechniquePrivate &dd, Qt3DCore::QNode *parent = nullptr);
diff --git a/src/render/materialsystem/renderpass.cpp b/src/render/materialsystem/renderpass.cpp
index e0fadddd9..19e2a427e 100644
--- a/src/render/materialsystem/renderpass.cpp
+++ b/src/render/materialsystem/renderpass.cpp
@@ -48,9 +48,7 @@
#include <Qt3DRender/private/renderstates_p.h>
#include <Qt3DRender/private/renderstateset_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
+#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -77,58 +75,33 @@ void RenderPass::cleanup()
m_shaderUuid = Qt3DCore::QNodeId();
}
-void RenderPass::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void RenderPass::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderPassData>>(change);
- const auto &data = typedChange->data;
- m_filterKeyList = data.filterKeyIds;
- m_parameterPack.setParameters(data.parameterIds);
- for (const auto &renderStateId : qAsConst(data.renderStateIds))
- addRenderState(renderStateId);
- m_shaderUuid = data.shaderId;
-}
-
-void RenderPass::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("filterKeys"))
- appendFilterKey(change->addedNodeId());
- else if (change->propertyName() == QByteArrayLiteral("shaderProgram"))
- m_shaderUuid = change->addedNodeId();
- else if (change->propertyName() == QByteArrayLiteral("renderState"))
- addRenderState(change->addedNodeId());
- else if (change->propertyName() == QByteArrayLiteral("parameter"))
- m_parameterPack.appendParameter(change->addedNodeId());
- break;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QRenderPass *node = qobject_cast<const QRenderPass *>(frontEnd);
+ if (!node)
+ return;
+
+ if ((node->shaderProgram() && node->shaderProgram()->id() != m_shaderUuid) ||
+ (!node->shaderProgram() && !m_shaderUuid.isNull())) {
+ m_shaderUuid = node->shaderProgram() ? node->shaderProgram()->id() : QNodeId{};
}
- case PropertyUpdated: {
- const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("shaderProgram"))
- m_shaderUuid = change->value().value<Qt3DCore::QNodeId>();
- break;
- }
+ auto filterList = qIdsForNodes(node->filterKeys());
+ std::sort(std::begin(filterList), std::end(filterList));
+ if (m_filterKeyList != filterList)
+ m_filterKeyList = filterList;
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("filterKeys"))
- removeFilterKey(change->removedNodeId());
- else if (change->propertyName() == QByteArrayLiteral("shaderProgram"))
- m_shaderUuid = QNodeId();
- else if (change->propertyName() == QByteArrayLiteral("renderState"))
- removeRenderState(change->removedNodeId());
- else if (change->propertyName() == QByteArrayLiteral("parameter"))
- m_parameterPack.removeParameter(change->removedNodeId());
- break;
- }
+ auto parameters = qIdsForNodes(node->parameters());
+ std::sort(std::begin(parameters), std::end(parameters));
+ if (m_parameterPack.parameters() != parameters)
+ m_parameterPack.setParameters(parameters);
- default:
- break;
- }
+ auto renderStates = qIdsForNodes(node->renderStates());
+ std::sort(std::begin(renderStates), std::end(renderStates));
+ if (m_renderStates != renderStates)
+ m_renderStates = renderStates;
- BackendNode::sceneChangeEvent(e);
markDirty(AbstractRenderer::AllDirty);
}
diff --git a/src/render/materialsystem/renderpass_p.h b/src/render/materialsystem/renderpass_p.h
index 1ca02b1ad..314386ad1 100644
--- a/src/render/materialsystem/renderpass_p.h
+++ b/src/render/materialsystem/renderpass_p.h
@@ -79,7 +79,7 @@ public:
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
Qt3DCore::QNodeId shaderProgram() const;
QVector<Qt3DCore::QNodeId> filterKeys() const;
@@ -95,8 +95,6 @@ private:
void addRenderState(Qt3DCore::QNodeId renderStateId);
void removeRenderState(Qt3DCore::QNodeId renderStateId);
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
Qt3DCore::QNodeId m_shaderUuid;
QVector<Qt3DCore::QNodeId> m_filterKeyList;
ParameterPack m_parameterPack;
diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp
index d42b0dda7..300a71b84 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -62,8 +62,10 @@ Shader::Shader()
: BackendNode(ReadWrite)
, m_isLoaded(false)
, m_dna(0)
+ , m_oldDna(0)
, m_graphicsContext(nullptr)
, m_status(QShaderProgram::NotReady)
+ , m_requiresFrontendSync(false)
{
m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1);
}
@@ -101,23 +103,24 @@ void Shader::cleanup()
m_status = QShaderProgram::NotReady;
}
-void Shader::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Shader::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderProgramData>>(change);
- const auto &data = typedChange->data;
-
- for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i)
- m_shaderCode[i].clear();
-
- m_shaderCode[QShaderProgram::Vertex] = data.vertexShaderCode;
- m_shaderCode[QShaderProgram::TessellationControl] = data.tessellationControlShaderCode;
- m_shaderCode[QShaderProgram::TessellationEvaluation] = data.tessellationEvaluationShaderCode;
- m_shaderCode[QShaderProgram::Geometry] = data.geometryShaderCode;
- m_shaderCode[QShaderProgram::Fragment] = data.fragmentShaderCode;
- m_shaderCode[QShaderProgram::Compute] = data.computeShaderCode;
- m_isLoaded = false;
- updateDNA();
- markDirty(AbstractRenderer::ShadersDirty);
+ const QShaderProgram *node = qobject_cast<const QShaderProgram *>(frontEnd);
+ if (!node)
+ return;
+
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (firstTime)
+ for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i)
+ m_shaderCode[i].clear();
+
+ for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i) {
+ const QShaderProgram::ShaderType shaderType = static_cast<QShaderProgram::ShaderType>(i);
+ const QByteArray code = node->shaderCode(shaderType);
+ if (code != m_shaderCode.value(shaderType))
+ setShaderCode(shaderType, code);
+ }
}
void Shader::setGraphicsContext(GraphicsContext *context)
@@ -169,34 +172,12 @@ void Shader::setShaderCode(QShaderProgram::ShaderType type, const QByteArray &co
m_shaderCode[type] = code;
m_isLoaded = false;
- setStatus(QShaderProgram::NotReady);
+ m_status = QShaderProgram::NotReady;
updateDNA();
+ m_requiresFrontendSync = true;
markDirty(AbstractRenderer::ShadersDirty);
}
-void Shader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = e.staticCast<QPropertyUpdatedChange>();
- QVariant propertyValue = propertyChange->value();
-
- if (propertyChange->propertyName() == QByteArrayLiteral("vertexShaderCode"))
- setShaderCode(QShaderProgram::Vertex, propertyValue.toByteArray());
- else if (propertyChange->propertyName() == QByteArrayLiteral("fragmentShaderCode"))
- setShaderCode(QShaderProgram::Fragment, propertyValue.toByteArray());
- else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationControlShaderCode"))
- setShaderCode(QShaderProgram::TessellationControl, propertyValue.toByteArray());
- else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationEvaluationShaderCode"))
- setShaderCode(QShaderProgram::TessellationEvaluation, propertyValue.toByteArray());
- else if (propertyChange->propertyName() == QByteArrayLiteral("geometryShaderCode"))
- setShaderCode(QShaderProgram::Geometry, propertyValue.toByteArray());
- else if (propertyChange->propertyName() == QByteArrayLiteral("computeShaderCode"))
- setShaderCode(QShaderProgram::Compute, propertyValue.toByteArray());
- }
-
- BackendNode::sceneChangeEvent(e);
-}
-
QHash<QString, ShaderUniform> Shader::activeUniformsForUniformBlock(int blockIndex) const
{
return m_uniformBlockIndexToShaderUniforms.value(blockIndex);
@@ -259,24 +240,17 @@ ShaderStorageBlock Shader::storageBlockForBlockName(const QString &blockName)
return ShaderStorageBlock();
}
-// To be called from a worker thread
-void Shader::submitPendingNotifications()
-{
- const QVector<Qt3DCore::QPropertyUpdatedChangePtr> notifications = std::move(m_pendingNotifications);
- for (const Qt3DCore::QPropertyUpdatedChangePtr &notification : notifications)
- notifyObservers(notification);
-}
-
void Shader::prepareUniforms(ShaderParameterPack &pack)
{
const PackUniformHash &values = pack.uniforms();
- auto it = values.cbegin();
- const auto end = values.cend();
+ auto it = values.keys.cbegin();
+ const auto end = values.keys.cend();
+
while (it != end) {
// Find if there's a uniform with the same name id
for (const ShaderUniform &uniform : qAsConst(m_uniforms)) {
- if (uniform.m_nameId == it.key()) {
+ if (uniform.m_nameId == *it) {
pack.setSubmissionUniform(uniform);
break;
}
@@ -434,32 +408,21 @@ void Shader::initializeFromReference(const Shader &other)
m_shaderStorageBlockNames = other.m_shaderStorageBlockNames;
m_shaderStorageBlocks = other.m_shaderStorageBlocks;
m_isLoaded = other.m_isLoaded;
- setStatus(other.status());
- setLog(other.log());
+ m_status = other.m_status;
+ m_log = other.m_log;
+ m_requiresFrontendSync = true;
}
void Shader::setLog(const QString &log)
{
- if (log != m_log) {
- m_log = log;
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("log");
- e->setValue(QVariant::fromValue(m_log));
- m_pendingNotifications.push_back(e);
- }
+ m_log = log;
+ m_requiresFrontendSync = true;
}
void Shader::setStatus(QShaderProgram::Status status)
{
- if (status != m_status) {
- m_status = status;
- Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("status");
- e->setValue(QVariant::fromValue(m_status));
- m_pendingNotifications.push_back(e);
- }
+ m_status = status;
+ m_requiresFrontendSync = true;
}
} // namespace Render
diff --git a/src/render/materialsystem/shader_p.h b/src/render/materialsystem/shader_p.h
index 9eb24904c..fe1a401d9 100644
--- a/src/render/materialsystem/shader_p.h
+++ b/src/render/materialsystem/shader_p.h
@@ -99,7 +99,7 @@ public:
QVector<QByteArray> shaderCode() const;
void setShaderCode(QShaderProgram::ShaderType type, const QByteArray &code);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
bool isLoaded() const { QMutexLocker lock(&m_mutex); return m_isLoaded; }
void setLoaded(bool loaded) { QMutexLocker lock(&m_mutex); m_isLoaded = loaded; }
ProgramDNA dna() const Q_DECL_NOTHROW { return m_dna; }
@@ -122,12 +122,10 @@ public:
inline QString log() const { return m_log; }
inline QShaderProgram::Status status() const { return m_status; }
- void submitPendingNotifications();
- inline bool hasPendingNotifications() const { return !m_pendingNotifications.empty(); }
+ inline bool requiresFrontendSync() const { return m_requiresFrontendSync; }
+ inline void unsetRequiresFrontendSync() { m_requiresFrontendSync = false; }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
QVector<QString> m_uniformsNames;
QVector<int> m_uniformsNamesIds;
QVector<ShaderUniform> m_uniforms;
@@ -157,8 +155,7 @@ private:
QMetaObject::Connection m_contextConnection;
QString m_log;
QShaderProgram::Status m_status;
-
- QVector<Qt3DCore::QPropertyUpdatedChangePtr> m_pendingNotifications;
+ bool m_requiresFrontendSync;
void updateDNA();
diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp
index c1ec7f75a..23f1400c9 100644
--- a/src/render/materialsystem/shaderbuilder.cpp
+++ b/src/render/materialsystem/shaderbuilder.cpp
@@ -39,6 +39,8 @@
#include "shaderbuilder_p.h"
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
#include <Qt3DRender/private/qshaderprogrambuilder_p.h>
#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/private/qshaderprogram_p.h>
@@ -113,31 +115,6 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
-
-namespace {
-
-QShaderProgram::ShaderType toQShaderProgramType(ShaderBuilder::ShaderType type)
-{
- switch (type) {
- case ShaderBuilder::ShaderType::Vertex:
- return QShaderProgram::Vertex;
- case ShaderBuilder::ShaderType::TessellationControl:
- return QShaderProgram::TessellationControl;
- case ShaderBuilder::ShaderType::TessellationEvaluation:
- return QShaderProgram::TessellationEvaluation;
- case ShaderBuilder::ShaderType::Geometry:
- return QShaderProgram::Geometry;
- case ShaderBuilder::ShaderType::Fragment:
- return QShaderProgram::Fragment;
- case ShaderBuilder::ShaderType::Compute:
- return QShaderProgram::Compute;
- default:
- Q_UNREACHABLE();
- }
-}
-
-} // anonymous
-
QString ShaderBuilder::getPrototypesFile()
{
return qt3dGlobalShaderPrototypes->prototypesFile();
@@ -168,6 +145,7 @@ void ShaderBuilder::cleanup()
m_enabledLayers.clear();
m_graphs.clear();
m_dirtyTypes.clear();
+ m_pendingUpdates.clear();
QBackendNode::setEnabled(false);
}
@@ -189,7 +167,7 @@ void ShaderBuilder::setEnabledLayers(const QStringList &layers)
m_enabledLayers = layers;
- for (QHash<ShaderType, QUrl>::const_iterator it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
+ for (auto it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
if (!it.value().isEmpty())
m_dirtyTypes.insert(it.key());
}
@@ -206,18 +184,18 @@ void ShaderBuilder::setGraphicsApi(const GraphicsApiFilterData &graphicsApi)
return;
m_graphicsApi = graphicsApi;
- for (QHash<ShaderType, QUrl>::const_iterator it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
+ for (auto it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) {
if (!it.value().isEmpty())
m_dirtyTypes.insert(it.key());
}
}
-QUrl ShaderBuilder::shaderGraph(ShaderBuilder::ShaderType type) const
+QUrl ShaderBuilder::shaderGraph(QShaderProgram::ShaderType type) const
{
return m_graphs.value(type);
}
-void ShaderBuilder::setShaderGraph(ShaderBuilder::ShaderType type, const QUrl &url)
+void ShaderBuilder::setShaderGraph(QShaderProgram::ShaderType type, const QUrl &url)
{
if (url != m_graphs.value(type)) {
m_graphs.insert(type, url);
@@ -225,17 +203,17 @@ void ShaderBuilder::setShaderGraph(ShaderBuilder::ShaderType type, const QUrl &u
}
}
-QByteArray ShaderBuilder::shaderCode(ShaderBuilder::ShaderType type) const
+QByteArray ShaderBuilder::shaderCode(QShaderProgram::ShaderType type) const
{
return m_codes.value(type);
}
-bool ShaderBuilder::isShaderCodeDirty(ShaderBuilder::ShaderType type) const
+bool ShaderBuilder::isShaderCodeDirty(QShaderProgram::ShaderType type) const
{
return m_dirtyTypes.contains(type);
}
-void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type)
+void ShaderBuilder::generateCode(QShaderProgram::ShaderType type)
{
const auto graphPath = QUrlHelper::urlToLocalFileOrQrc(shaderGraph(type));
QFile file(graphPath);
@@ -271,55 +249,51 @@ void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type)
m_codes.insert(type, QShaderProgramPrivate::deincludify(code, graphPath + QStringLiteral(".glsl")));
m_dirtyTypes.remove(type);
- // Send notification to the frontend
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- propertyChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- propertyChange->setPropertyName("generatedShaderCode");
- propertyChange->setValue(QVariant::fromValue(qMakePair(int(toQShaderProgramType(type)), m_codes.value(type))));
- notifyObservers(propertyChange);
+ m_pendingUpdates.push_back({ peerId(),
+ type,
+ m_codes.value(type) });
}
-void ShaderBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = e.staticCast<QPropertyUpdatedChange>();
- QVariant propertyValue = propertyChange->value();
-
- if (propertyChange->propertyName() == QByteArrayLiteral("shaderProgram"))
- m_shaderProgramId = propertyValue.value<Qt3DCore::QNodeId>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("enabledLayers"))
- setEnabledLayers(propertyValue.toStringList());
- else if (propertyChange->propertyName() == QByteArrayLiteral("vertexShaderGraph"))
- setShaderGraph(Vertex, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationControlShaderGraph"))
- setShaderGraph(TessellationControl, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationEvaluationShaderGraph"))
- setShaderGraph(TessellationEvaluation, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("geometryShaderGraph"))
- setShaderGraph(Geometry, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("fragmentShaderGraph"))
- setShaderGraph(Fragment, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("computeShaderGraph"))
- setShaderGraph(Compute, propertyValue.toUrl());
+ const QShaderProgramBuilder *node = qobject_cast<const QShaderProgramBuilder *>(frontEnd);
+ if (!node)
+ return;
+
+ const bool oldEnabled = isEnabled();
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ if (oldEnabled != isEnabled()) {
markDirty(AbstractRenderer::ShadersDirty);
}
- BackendNode::sceneChangeEvent(e);
-}
-void ShaderBuilder::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderProgramBuilderData>>(change);
- const auto &data = typedChange->data;
-
- m_shaderProgramId = data.shaderProgramId;
- m_enabledLayers = data.enabledLayers;
- setShaderGraph(Vertex, data.vertexShaderGraph);
- setShaderGraph(TessellationControl, data.tessellationControlShaderGraph);
- setShaderGraph(TessellationEvaluation, data.tessellationEvaluationShaderGraph);
- setShaderGraph(Geometry, data.geometryShaderGraph);
- setShaderGraph(Fragment, data.fragmentShaderGraph);
- setShaderGraph(Compute, data.computeShaderGraph);
+ const Qt3DCore::QNodeId shaderProgramId = Qt3DCore::qIdForNode(node->shaderProgram());
+ if (shaderProgramId != m_shaderProgramId) {
+ m_shaderProgramId = shaderProgramId;
+ markDirty(AbstractRenderer::ShadersDirty);
+ }
+
+ if (node->enabledLayers() != m_enabledLayers) {
+ setEnabledLayers(node->enabledLayers());
+ markDirty(AbstractRenderer::ShadersDirty);
+ }
+
+ static const std::pair<QShaderProgram::ShaderType, QUrl (QShaderProgramBuilder::*)() const> shaderTypesToGetters[] = {
+ {QShaderProgram::Vertex, &QShaderProgramBuilder::vertexShaderGraph},
+ {QShaderProgram::TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph},
+ {QShaderProgram::TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph},
+ {QShaderProgram::Geometry, &QShaderProgramBuilder::geometryShaderGraph},
+ {QShaderProgram::Fragment, &QShaderProgramBuilder::fragmentShaderGraph},
+ {QShaderProgram::Compute, &QShaderProgramBuilder::computeShaderGraph},
+ };
+
+ for (auto it = std::cbegin(shaderTypesToGetters), end = std::cend(shaderTypesToGetters); it != end; ++it) {
+ const QUrl url = (node->*(it->second))();
+ if (url != m_graphs.value(it->first)) {
+ setShaderGraph(it->first, url);
+ markDirty(AbstractRenderer::ShadersDirty);
+ }
+ }
}
} // namespace Render
diff --git a/src/render/materialsystem/shaderbuilder_p.h b/src/render/materialsystem/shaderbuilder_p.h
index 00c4e1c28..0a799afaa 100644
--- a/src/render/materialsystem/shaderbuilder_p.h
+++ b/src/render/materialsystem/shaderbuilder_p.h
@@ -51,9 +51,9 @@
// We mean it.
//
+#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/private/qgraphicsapifilter_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -61,18 +61,16 @@ namespace Qt3DRender {
namespace Render {
+struct ShaderBuilderUpdate
+{
+ Qt3DCore::QNodeId builderId;
+ Qt3DRender::QShaderProgram::ShaderType shaderType;
+ QByteArray shaderCode;
+};
+
class Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderBuilder : public BackendNode
{
public:
- enum ShaderType {
- Vertex = 0,
- TessellationControl,
- TessellationEvaluation,
- Geometry,
- Fragment,
- Compute
- };
-
static QString getPrototypesFile();
static void setPrototypesFile(const QString &file);
static QStringList getPrototypeNames();
@@ -87,26 +85,28 @@ public:
GraphicsApiFilterData graphicsApi() const;
void setGraphicsApi(const GraphicsApiFilterData &graphicsApi);
- QUrl shaderGraph(ShaderType type) const;
- void setShaderGraph(ShaderType type, const QUrl &url);
+ QUrl shaderGraph(QShaderProgram::ShaderType type) const;
+ void setShaderGraph(QShaderProgram::ShaderType type, const QUrl &url);
+
+ QByteArray shaderCode(QShaderProgram::ShaderType type) const;
+ bool isShaderCodeDirty(QShaderProgram::ShaderType type) const;
- QByteArray shaderCode(ShaderType type) const;
- bool isShaderCodeDirty(ShaderType type) const;
+ void generateCode(QShaderProgram::ShaderType type);
- void generateCode(ShaderType type);
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ QVector<ShaderBuilderUpdate> takePendingUpdates() { return std::move(m_pendingUpdates); }
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
void setEnabledLayers(const QStringList &layers);
GraphicsApiFilterData m_graphicsApi;
Qt3DCore::QNodeId m_shaderProgramId;
QStringList m_enabledLayers;
- QHash<ShaderType, QUrl> m_graphs;
- QHash<ShaderType, QByteArray> m_codes;
- QSet<ShaderType> m_dirtyTypes;
+ QHash<QShaderProgram::ShaderType, QUrl> m_graphs;
+ QHash<QShaderProgram::ShaderType, QByteArray> m_codes;
+ QSet<QShaderProgram::ShaderType> m_dirtyTypes;
+ QVector<ShaderBuilderUpdate> m_pendingUpdates;
};
} // namespace Render
diff --git a/src/render/materialsystem/shaderdata.cpp b/src/render/materialsystem/shaderdata.cpp
index 130333898..34d4641e9 100644
--- a/src/render/materialsystem/shaderdata.cpp
+++ b/src/render/materialsystem/shaderdata.cpp
@@ -64,8 +64,6 @@ const int qNodeIdTypeId = qMetaTypeId<Qt3DCore::QNodeId>();
}
-QVector<Qt3DCore::QNodeId> ShaderData::m_updatedShaderData;
-
ShaderData::ShaderData()
: m_managers(nullptr)
{
@@ -80,51 +78,82 @@ void ShaderData::setManagers(NodeManagers *managers)
m_managers = managers;
}
-void ShaderData::initializeFromPeer(const QNodeCreatedChangeBasePtr &change)
+void ShaderData::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderDataData>>(change);
- const QShaderDataData &data = typedChange->data;
-
- m_propertyReader = data.propertyReader;
-
- for (const QPair<QByteArray, QVariant> &entry : data.properties) {
- if (entry.first == QByteArrayLiteral("data") ||
- entry.first == QByteArrayLiteral("childNodes")) // We don't handle default Node properties
- continue;
- const QVariant &propertyValue = entry.second;
- const QString propertyName = QString::fromLatin1(entry.first);
-
- m_originalProperties.insert(propertyName, propertyValue);
-
- // We check if the property is a QNodeId or QVector<QNodeId> so that we can
- // check nested QShaderData for update
- if (propertyValue.userType() == qNodeIdTypeId) {
- m_nestedShaderDataProperties.insert(propertyName, propertyValue);
- } else if (propertyValue.userType() == QMetaType::QVariantList) {
- QVariantList list = propertyValue.value<QVariantList>();
- if (list.count() > 0 && list.at(0).userType() == qNodeIdTypeId)
- m_nestedShaderDataProperties.insert(propertyName, propertyValue);
- }
- }
+ const QShaderData *node = qobject_cast<const QShaderData *>(frontEnd);
+ if (!node)
+ return;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (firstTime) {
+ m_propertyReader = node->propertyReader();
+
+ const QMetaObject *metaObj = node->metaObject();
+ const int propertyOffset = QShaderData::staticMetaObject.propertyOffset();
+ const int propertyCount = metaObj->propertyCount();
+ // Dynamic properties names
+ const auto dynamicPropertyNames = node->dynamicPropertyNames();
- // We look for transformed properties once the complete hash of
- // originalProperties is available
- QHash<QString, QVariant>::iterator it = m_originalProperties.begin();
- const QHash<QString, QVariant>::iterator end = m_originalProperties.end();
-
- while (it != end) {
- if (it.value().type() == QVariant::Vector3D) {
- // if there is a matching QShaderData::TransformType propertyTransformed
- QVariant value = m_originalProperties.value(it.key() + QLatin1String("Transformed"));
- // if that's the case, we apply a space transformation to the property
- if (value.isValid() && value.type() == QVariant::Int)
- m_transformedProperties.insert(it.key(), static_cast<TransformType>(value.toInt()));
+ QVector<QString> propertyNames;
+ propertyNames.reserve(propertyCount - propertyOffset + dynamicPropertyNames.size());
+
+ // Statiically defined properties
+ for (int i = propertyOffset; i < propertyCount; ++i) {
+ const QMetaProperty pro = metaObj->property(i);
+ if (pro.isWritable())
+ propertyNames.push_back(QString::fromLatin1(pro.name()));
+ }
+ // Dynamic properties
+ for (const QByteArray &propertyName : dynamicPropertyNames)
+ propertyNames.push_back(QString::fromLatin1(propertyName));
+
+ for (const QString &propertyName : propertyNames) {
+ if (propertyName == QStringLiteral("data") ||
+ propertyName == QStringLiteral("childNodes")) // We don't handle default Node properties
+ continue;
+
+ const QVariant &propertyValue = m_propertyReader->readProperty(node->property(propertyName.toLatin1()));
+ bool isNested = false;
+ bool isTransformed = false;
+
+ // We check if the property is a QNodeId
+ isNested = (propertyValue.userType() == qNodeIdTypeId);
+ // We check if QVector<QNodeId>
+ if (propertyValue.userType() == QMetaType::QVariantList) {
+ QVariantList list = propertyValue.value<QVariantList>();
+ if (list.count() > 0 && list.at(0).userType() == qNodeIdTypeId)
+ isNested = true;
+ }
+
+ // We check if property is a Transformed property
+ if (propertyValue.userType() == QVariant::Vector3D) {
+ // if there is a matching QShaderData::TransformType propertyTransformed
+ isTransformed = propertyNames.contains(propertyName + QLatin1String("Transformed"));
+ }
+ m_originalProperties.insert(propertyName, { propertyValue, isNested, isTransformed });
+ }
+ BackendNode::markDirty(AbstractRenderer::ParameterDirty);
+ } else {
+ // Updates
+ if (!m_propertyReader.isNull()) {
+ auto it = m_originalProperties.begin();
+ const auto end = m_originalProperties.end();
+
+ while (it != end) {
+ const QVariant newValue = m_propertyReader->readProperty(node->property(it.key().toLatin1()));
+ PropertyValue &propValue = it.value();
+ if (propValue.value != newValue) {
+ // Note we aren't notified about nested QShaderData in this call
+ // only scalar / vec properties
+ propValue.value = newValue;
+ BackendNode::markDirty(AbstractRenderer::ParameterDirty);
+ }
+ ++it;
+ }
}
- ++it;
}
}
-
ShaderData *ShaderData::lookupResource(NodeManagers *managers, QNodeId id)
{
return managers->shaderDataManager()->lookupResource(id);
@@ -135,120 +164,62 @@ ShaderData *ShaderData::lookupResource(QNodeId id)
return ShaderData::lookupResource(m_managers, id);
}
-// Call by cleanup job (single thread)
-void ShaderData::clearUpdatedProperties()
-{
- // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7
- // const QHash<QString, QVariant>::const_iterator end = m_nestedShaderDataProperties.end();
- // QHash<QString, QVariant>::const_iterator it = m_nestedShaderDataProperties.begin();
-
- // while (it != end) {
- // if (it.value().userType() == QMetaType::QVariantList) {
- // const auto values = it.value().value<QVariantList>();
- // for (const QVariant &v : values) {
- // ShaderData *nested = lookupResource(v.value<QNodeId>());
- // if (nested != nullptr)
- // nested->clearUpdatedProperties();
- // }
- // } else {
- // ShaderData *nested = lookupResource(it.value().value<QNodeId>());
- // if (nested != nullptr)
- // nested->clearUpdatedProperties();
- // }
- // ++it;
- // }
-}
-
void ShaderData::cleanup(NodeManagers *managers)
{
Q_UNUSED(managers)
- // DISABLED: Is only useful when building UBO from a ShaderData, which is disable since 5.7
- // for (Qt3DCore::QNodeId id : qAsConst(m_updatedShaderData)) {
- // ShaderData *shaderData = ShaderData::lookupResource(managers, id);
- // if (shaderData)
- // shaderData->clearUpdatedProperties();
- // }
- m_updatedShaderData.clear();
}
+// RenderCommand updater jobs
QVariant ShaderData::getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix)
{
// Note protecting m_worldMatrix at this point as we assume all world updates
// have been performed when reaching this point
- auto it = m_transformedProperties.find(name);
- if (it != m_transformedProperties.end()) {
- const TransformType transformType = it.value();
- switch (transformType) {
- case ModelToEye:
- return QVariant::fromValue(viewMatrix * m_worldMatrix * Vector3D(m_originalProperties.value(name).value<QVector3D>()));
- case ModelToWorld:
- return QVariant::fromValue(m_worldMatrix * Vector3D(m_originalProperties.value(it.key()).value<QVector3D>()));
- case ModelToWorldDirection:
- return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(m_originalProperties.value(it.key()).value<QVector3D>(), 0.0f)));
- case NoTransform:
- break;
+ const auto it = m_originalProperties.constFind(name);
+ if (it != m_originalProperties.constEnd()) {
+ const PropertyValue &propertyValue = it.value();
+ if (propertyValue.isTransformed) {
+ const auto transformedIt = m_originalProperties.constFind(name + QLatin1String("Transformed"));
+ if (transformedIt != m_originalProperties.constEnd()) {
+ const PropertyValue &transformedValue = transformedIt.value();
+ const TransformType transformType = static_cast<TransformType>(transformedValue.value.toInt());
+ switch (transformType) {
+ case ModelToEye:
+ return QVariant::fromValue(viewMatrix * m_worldMatrix * Vector3D(propertyValue.value.value<QVector3D>()));
+ case ModelToWorld:
+ return QVariant::fromValue(m_worldMatrix * Vector3D(propertyValue.value.value<QVector3D>()));
+ case ModelToWorldDirection:
+ return QVariant::fromValue(Vector3D(m_worldMatrix * Vector4D(propertyValue.value.value<QVector3D>(), 0.0f)));
+ case NoTransform:
+ break;
+ }
+ }
}
+ return propertyValue.value;
}
return QVariant();
}
-// Called by FramePreparationJob or by RenderView when dealing with lights
-void ShaderData::updateWorldTransform(const Matrix4x4 &worldMatrix)
-{
- QMutexLocker lock(&m_mutex);
- if (m_worldMatrix != worldMatrix) {
- m_worldMatrix = worldMatrix;
- }
-}
-
-// This will add the ShaderData to be cleared from updates at the end of the frame
-// by the cleanup job
-// Called by renderview jobs (several concurrent threads)
-void ShaderData::markDirty()
-{
- QMutexLocker lock(&m_mutex);
- if (!ShaderData::m_updatedShaderData.contains(peerId()))
- ShaderData::m_updatedShaderData.append(peerId());
-}
-
-/*!
- \internal
- Lookup if the current ShaderData or a nested ShaderData has updated properties.
- UpdateProperties contains either the value of the propertie of a QNodeId if it's another ShaderData.
- Transformed properties are updated for all of ShaderData that have ones at the point.
-
- \note This needs to be performed for every top level ShaderData every time it is used.
- As we don't know if the transformed properties use the same viewMatrix for all RenderViews.
- */
-
+// Unit tests only
ShaderData::TransformType ShaderData::propertyTransformType(const QString &name) const
{
- return m_transformedProperties.value(name, TransformType::NoTransform);
+ const auto it = m_originalProperties.constFind(name);
+ if (it != m_originalProperties.constEnd()) {
+ const PropertyValue &propertyValue = it.value();
+ if (propertyValue.isTransformed) {
+ auto transformedIt = m_originalProperties.constFind(name + QLatin1String("Transformed"));
+ if (transformedIt != m_originalProperties.end())
+ return static_cast<TransformType>(transformedIt.value().value.toInt());
+ }
+ }
+ return NoTransform;
}
-void ShaderData::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+// Called by FramePreparationJob or by RenderView when dealing with lights
+void ShaderData::updateWorldTransform(const Matrix4x4 &worldMatrix)
{
- if (!m_propertyReader.isNull() && e->type() == PropertyUpdated) {
- QString propertyName;
- QVariant propertyValue;
-
- if (auto propertyChange = qSharedPointerDynamicCast<QPropertyUpdatedChange>(e)) {
- propertyName = QString::fromLatin1(propertyChange->propertyName());
- propertyValue = m_propertyReader->readProperty(propertyChange->value());
- } else if (auto propertyChange = qSharedPointerDynamicCast<QDynamicPropertyUpdatedChange>(e)) {
- propertyName = QString::fromLatin1(propertyChange->propertyName());
- propertyValue = m_propertyReader->readProperty(propertyChange->value());
- } else {
- Q_UNREACHABLE();
- }
-
- // Note we aren't notified about nested QShaderData in this call
- // only scalar / vec properties
- m_originalProperties.insert(propertyName, propertyValue);
- BackendNode::markDirty(AbstractRenderer::ParameterDirty);
+ if (m_worldMatrix != worldMatrix) {
+ m_worldMatrix = worldMatrix;
}
-
- BackendNode::sceneChangeEvent(e);
}
RenderShaderDataFunctor::RenderShaderDataFunctor(AbstractRenderer *renderer, NodeManagers *managers)
diff --git a/src/render/materialsystem/shaderdata_p.h b/src/render/materialsystem/shaderdata_p.h
index f9c3ecc79..c9cc22939 100644
--- a/src/render/materialsystem/shaderdata_p.h
+++ b/src/render/materialsystem/shaderdata_p.h
@@ -76,49 +76,42 @@ public:
ModelToWorld,
ModelToWorldDirection
};
+ struct PropertyValue {
+ QVariant value;
+ bool isNested;
+ bool isTransformed;
+ };
ShaderData();
~ShaderData();
- QHash<QString, QVariant> properties() const { return m_originalProperties; }
+ QHash<QString, PropertyValue> properties() const { return m_originalProperties; }
// Called by FramePreparationJob
void updateWorldTransform(const Matrix4x4 &worldMatrix);
- // Call by RenderViewJob
- void markDirty();
+ QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix);
+ // Unit tests purposes only
TransformType propertyTransformType(const QString &name) const;
- QVariant getTransformedProperty(const QString &name, const Matrix4x4 &viewMatrix);
// Called by FrameCleanupJob
static void cleanup(NodeManagers *managers);
void setManagers(NodeManagers *managers);
-protected:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override;
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+protected:
PropertyReaderInterfacePtr m_propertyReader;
- // 1 to 1 match with frontend properties, modified only by sceneChangeEvent
- QHash<QString, QVariant> m_originalProperties;
-
- // Contains properties thar are of type ShaderData
- QHash<QString, QVariant> m_nestedShaderDataProperties;
-
- // Contains property that are defined like: postionTransformed: ModelToEye
- QHash<QString, TransformType> m_transformedProperties;
+ // 1 to 1 match with frontend properties
+ QHash<QString, PropertyValue> m_originalProperties;
- QMutex m_mutex;
- static QVector<Qt3DCore::QNodeId> m_updatedShaderData;
Matrix4x4 m_worldMatrix;
- Matrix4x4 m_viewMatrix;
NodeManagers *m_managers;
- void clearUpdatedProperties();
static ShaderData *lookupResource(NodeManagers *managers, Qt3DCore::QNodeId id);
ShaderData *lookupResource(Qt3DCore::QNodeId id);
diff --git a/src/render/materialsystem/shaderimage.cpp b/src/render/materialsystem/shaderimage.cpp
new file mode 100644
index 000000000..65a4cf761
--- /dev/null
+++ b/src/render/materialsystem/shaderimage.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shaderimage_p.h"
+#include <Qt3DRender/private/qshaderimage_p.h>
+#include <Qt3DRender/qabstracttexture.h>
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+ShaderImage::ShaderImage()
+ : BackendNode(BackendNode::ReadOnly)
+ , m_textureId()
+ , m_mipLevel(0)
+ , m_layer(0)
+ , m_layered(false)
+ , m_access(QShaderImage::ReadWrite)
+ , m_format(QShaderImage::NoFormat)
+{
+}
+
+void ShaderImage::cleanup()
+{
+ QBackendNode::setEnabled(false);
+ m_textureId = Qt3DCore::QNodeId();
+ m_mipLevel = 0;
+ m_layer = 0;
+ m_layered = false;
+ m_access = QShaderImage::ReadWrite;
+ m_format = QShaderImage::NoFormat;
+}
+
+void ShaderImage::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
+{
+ const QShaderImage *node = qobject_cast<const QShaderImage *>(frontEnd);
+ if (!node)
+ return;
+
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ const Qt3DCore::QNodeId textureNodeId = Qt3DCore::qIdForNode(node->texture());
+ if (textureNodeId != m_textureId) {
+ m_textureId = textureNodeId;
+ markDirty(AbstractRenderer::ParameterDirty);
+ }
+
+ if (node->mipLevel() != m_mipLevel) {
+ m_mipLevel = node->mipLevel();
+ markDirty(AbstractRenderer::ParameterDirty);
+ }
+
+ if (node->layer() != m_layer) {
+ m_layer = node->layer();
+ markDirty(AbstractRenderer::ParameterDirty);
+ }
+
+ if (node->layered() != m_layered) {
+ m_layered = node->layered();
+ markDirty(AbstractRenderer::ParameterDirty);
+ }
+
+ if (node->format() != m_format) {
+ m_format = node->format();
+ markDirty(AbstractRenderer::ParameterDirty);
+ }
+
+ if (node->access() != m_access) {
+ m_access = node->access();
+ markDirty(AbstractRenderer::ParameterDirty);
+ }
+
+}
+
+} // namespace Render
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/materialsystem/shaderimage_p.h b/src/render/materialsystem/shaderimage_p.h
new file mode 100644
index 000000000..1a1294a21
--- /dev/null
+++ b/src/render/materialsystem/shaderimage_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_SHADERIMAGE_P_H
+#define QT3DRENDER_RENDER_SHADERIMAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/backendnode_p.h>
+#include <Qt3DRender/qshaderimage.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class Q_AUTOTEST_EXPORT ShaderImage : public BackendNode
+{
+public:
+ ShaderImage();
+
+ void cleanup();
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+
+ Qt3DCore::QNodeId textureId() const { return m_textureId; }
+ int mipLevel() const { return m_mipLevel; }
+ int layer() const { return m_layer; }
+ bool layered() const { return m_layered; }
+ QShaderImage::Access access() const { return m_access; }
+ QShaderImage::ImageFormat format() const { return m_format; }
+
+ // For Unit Test purposes only
+#ifdef QT_BUILD_INTERNAL
+ void setTextureId(Qt3DCore::QNodeId id) { m_textureId = id; }
+ void setMipLevel(int level) { m_mipLevel = level; }
+ void setLayer(int layer) { m_layer = layer; }
+ void setLayered(bool layered) { m_layered = layered; }
+ void setAccess(QShaderImage::Access access) { m_access = access; }
+ void setFormat(QShaderImage::ImageFormat format) { m_format = format; }
+#endif
+
+private:
+ Qt3DCore::QNodeId m_textureId;
+ int m_mipLevel;
+ int m_layer;
+ bool m_layered;
+ QShaderImage::Access m_access;
+ QShaderImage::ImageFormat m_format;
+};
+
+} // namespace Render
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_SHADERIMAGE_P_H
diff --git a/src/render/materialsystem/technique.cpp b/src/render/materialsystem/technique.cpp
index 5438fa9c8..10e9af990 100644
--- a/src/render/materialsystem/technique.cpp
+++ b/src/render/materialsystem/technique.cpp
@@ -48,9 +48,6 @@
#include <Qt3DRender/private/qtechnique_p.h>
#include <Qt3DRender/private/shader_p.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/techniquemanager_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
@@ -85,71 +82,48 @@ void Technique::cleanup()
m_isCompatibleWithRenderer = false;
}
-void Technique::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void Technique::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QTechniqueData>>(change);
- const QTechniqueData &data = typedChange->data;
-
- m_graphicsApiFilterData = data.graphicsApiFilterData;
- m_filterKeyList = data.filterKeyIds;
- m_parameterPack.setParameters(data.parameterIds);
- m_renderPasses = data.renderPassIds;
- m_nodeManager->techniqueManager()->addDirtyTechnique(peerId());
-}
+ const QTechnique *node = qobject_cast<const QTechnique *>(frontEnd);
-void Technique::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyUpdated: {
- const auto change = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("enabled")) {
- markDirty(AbstractRenderer::TechniquesDirty);
- } else if (change->propertyName() == QByteArrayLiteral("graphicsApiFilterData")) {
- GraphicsApiFilterData filterData = change->value().value<GraphicsApiFilterData>();
- m_graphicsApiFilterData = filterData;
- // Notify the manager that our graphicsApiFilterData has changed
- // and that we therefore need to be check for compatibility again
- m_isCompatibleWithRenderer = false;
- m_nodeManager->techniqueManager()->addDirtyTechnique(peerId());
- markDirty(AbstractRenderer::TechniquesDirty);
- }
- break;
+ if (!node)
+ return;
+
+ bool dirty = isEnabled() != frontEnd->isEnabled();
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ auto renderPasses = qIdsForNodes(node->renderPasses());
+ std::sort(std::begin(renderPasses), std::end(renderPasses));
+ if (m_renderPasses != renderPasses) {
+ m_renderPasses = renderPasses;
+ dirty = true;
}
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("pass")) {
- appendRenderPass(change->addedNodeId());
- markDirty(AbstractRenderer::TechniquesDirty);
- } else if (change->propertyName() == QByteArrayLiteral("parameter")) {
- m_parameterPack.appendParameter(change->addedNodeId());
- markDirty(AbstractRenderer::TechniquesDirty);
- } else if (change->propertyName() == QByteArrayLiteral("filterKeys")) {
- appendFilterKey(change->addedNodeId());
- markDirty(AbstractRenderer::TechniquesDirty);
- }
- break;
+ auto parameters = qIdsForNodes(node->parameters());
+ std::sort(std::begin(parameters), std::end(parameters));
+ if (m_parameterPack.parameters() != parameters) {
+ m_parameterPack.setParameters(parameters);
+ dirty = true;
}
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("pass")) {
- removeRenderPass(change->removedNodeId());
- markDirty(AbstractRenderer::TechniquesDirty);
- } else if (change->propertyName() == QByteArrayLiteral("parameter")) {
- m_parameterPack.removeParameter(change->removedNodeId());
- markDirty(AbstractRenderer::TechniquesDirty);
- } else if (change->propertyName() == QByteArrayLiteral("filterKeys")) {
- removeFilterKey(change->removedNodeId());
- markDirty(AbstractRenderer::TechniquesDirty);
- }
- break;
+ auto filterKeys = qIdsForNodes(node->filterKeys());
+ std::sort(std::begin(filterKeys), std::end(filterKeys));
+ if (m_filterKeyList != filterKeys) {
+ m_filterKeyList = filterKeys;
+ dirty = true;
+ }
+
+ auto graphicsApiFilterData = QGraphicsApiFilterPrivate::get(node->graphicsApiFilter())->m_data;
+ if (m_graphicsApiFilterData != graphicsApiFilterData) {
+ m_graphicsApiFilterData = graphicsApiFilterData;
+ m_isCompatibleWithRenderer = false;
+ dirty = true;
}
- default:
- break;
+ if (dirty) {
+ m_nodeManager->techniqueManager()->addDirtyTechnique(peerId());
+ markDirty(AbstractRenderer::TechniquesDirty);
}
- BackendNode::sceneChangeEvent(e);
}
QVector<Qt3DCore::QNodeId> Technique::parameters() const
diff --git a/src/render/materialsystem/technique_p.h b/src/render/materialsystem/technique_p.h
index d885c1b87..1d0d0a9dd 100644
--- a/src/render/materialsystem/technique_p.h
+++ b/src/render/materialsystem/technique_p.h
@@ -80,7 +80,8 @@ public:
~Technique();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
+
QVector<Qt3DCore::QNodeId> parameters() const;
void appendRenderPass(Qt3DCore::QNodeId renderPassId);
@@ -102,7 +103,6 @@ public:
NodeManagers *nodeManager() const;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
GraphicsApiFilterData m_graphicsApiFilterData;
ParameterPack m_parameterPack;
diff --git a/src/render/picking/objectpicker.cpp b/src/render/picking/objectpicker.cpp
index 43e308d20..84169586e 100644
--- a/src/render/picking/objectpicker.cpp
+++ b/src/render/picking/objectpicker.cpp
@@ -43,7 +43,6 @@
#include <Qt3DRender/private/qobjectpicker_p.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/private/pickboundingvolumejob_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
@@ -75,40 +74,37 @@ void ObjectPicker::cleanup()
notifyJob();
}
-void ObjectPicker::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void ObjectPicker::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QObjectPickerData>>(change);
- const auto &data = typedChange->data;
- m_hoverEnabled = data.hoverEnabled;
- m_dragEnabled = data.dragEnabled;
- m_priority = data.priority;
- notifyJob();
-}
+ const QObjectPicker *node = qobject_cast<const QObjectPicker *>(frontEnd);
+ if (!node)
+ return;
-void ObjectPicker::notifyJob()
-{
- if (m_renderer && m_renderer->pickBoundingVolumeJob())
- qSharedPointerCast<PickBoundingVolumeJob>(m_renderer->pickBoundingVolumeJob())->markPickersDirty();
-}
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
-void ObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- const Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
+ if (node->isHoverEnabled() != m_hoverEnabled) {
+ m_hoverEnabled = node->isHoverEnabled();
+ markDirty(AbstractRenderer::AllDirty);
+ notifyJob();
+ }
- if (propertyChange->propertyName() == QByteArrayLiteral("hoverEnabled")) {
- m_hoverEnabled = propertyChange->value().toBool();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("dragEnabled")) {
- m_dragEnabled = propertyChange->value().toBool();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("priority")) {
- m_priority = propertyChange->value().toInt();
- }
+ if (node->isDragEnabled() != m_dragEnabled) {
+ m_dragEnabled = node->isDragEnabled();
+ markDirty(AbstractRenderer::AllDirty);
+ notifyJob();
+ }
+ if (node->priority() != m_priority) {
+ m_priority = node->priority();
markDirty(AbstractRenderer::AllDirty);
notifyJob();
}
+}
- BackendNode::sceneChangeEvent(e);
+void ObjectPicker::notifyJob()
+{
+ if (m_renderer && m_renderer->pickBoundingVolumeJob())
+ qSharedPointerCast<PickBoundingVolumeJob>(m_renderer->pickBoundingVolumeJob())->markPickersDirty();
}
bool ObjectPicker::isPressed() const
@@ -126,58 +122,9 @@ bool ObjectPicker::isDragEnabled() const
return m_dragEnabled;
}
-void ObjectPicker::onClicked(QPickEventPtr event)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("clicked");
- e->setValue(QVariant::fromValue(event));
- notifyObservers(e);
-}
-
-void ObjectPicker::onMoved(QPickEventPtr event)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("moved");
- e->setValue(QVariant::fromValue(event));
- notifyObservers(e);
-}
-
-void ObjectPicker::onPressed(QPickEventPtr event)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("pressed");
- e->setValue(QVariant::fromValue(event));
- m_isPressed = true;
- notifyObservers(e);
-}
-
-void ObjectPicker::onReleased(QPickEventPtr event)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("released");
- e->setValue(QVariant::fromValue(event));
- m_isPressed = false;
- notifyObservers(e);
-}
-
-void ObjectPicker::onEntered()
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("entered");
- notifyObservers(e);
-}
-
-void ObjectPicker::onExited()
+void ObjectPicker::setPressed(bool pressed)
{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("exited");
- notifyObservers(e);
+ m_isPressed = pressed;
}
void ObjectPicker::setPriority(int priority)
diff --git a/src/render/picking/objectpicker_p.h b/src/render/picking/objectpicker_p.h
index 7389a4b53..49c8de770 100644
--- a/src/render/picking/objectpicker_p.h
+++ b/src/render/picking/objectpicker_p.h
@@ -69,24 +69,18 @@ public:
~ObjectPicker();
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
bool isPressed() const;
bool isHoverEnabled() const;
bool isDragEnabled() const;
- void onClicked(QPickEventPtr event);
- void onMoved(QPickEventPtr event);
- void onPressed(QPickEventPtr event);
- void onReleased(QPickEventPtr event);
- void onEntered();
- void onExited();
+ void setPressed(bool pressed);
// Needed for unit tests
void setPriority(int priority);
int priority() const;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
void notifyJob();
int m_priority;
diff --git a/src/render/picking/picking.pri b/src/render/picking/picking.pri
index 89c549de0..189d64bb6 100644
--- a/src/render/picking/picking.pri
+++ b/src/render/picking/picking.pri
@@ -7,6 +7,7 @@ HEADERS += \
$$PWD/qpicklineevent.h \
$$PWD/qpickpointevent.h \
$$PWD/qpicktriangleevent.h \
+ $$PWD/qpicktriangleevent_p.h \
$$PWD/objectpicker_p.h \
$$PWD/pickeventfilter_p.h \
$$PWD/qobjectpicker_p.h \
diff --git a/src/render/picking/qabstractraycaster.cpp b/src/render/picking/qabstractraycaster.cpp
index ecec7a628..5f4c4c490 100644
--- a/src/render/picking/qabstractraycaster.cpp
+++ b/src/render/picking/qabstractraycaster.cpp
@@ -58,10 +58,6 @@ QAbstractRayCasterPrivate::QAbstractRayCasterPrivate()
m_shareable = false;
}
-/*!
- \property Qt3DRender::QAbstractRayCaster::Hits
-*/
-
QAbstractRayCasterPrivate *QAbstractRayCasterPrivate::get(QAbstractRayCaster *obj)
{
return obj->d_func();
@@ -117,7 +113,8 @@ void QAbstractRayCasterPrivate::dispatchHits(const QAbstractRayCaster::Hits &hit
\note Components derived from QAbstractRayCaster should not be shared amount multiple entities.
- \sa Qt3DRender::QRayCaster, Qt3DRender::QScreenRayCaster, Qt3DRender::QObjectPicker, Qt3DRender::QPickingSettings
+ \sa Qt3DRender::QRayCaster, Qt3DRender::QScreenRayCaster, Qt3DRender::QObjectPicker,
+ Qt3DRender::QPickingSettings, Qt3DRender::QNoPicking
*/
/*!
\qmltype AbstractRayCaster
@@ -148,7 +145,8 @@ void QAbstractRayCasterPrivate::dispatchHits(const QAbstractRayCaster::Hits &hit
Note: components derived from AbstractRayCaster should not be shared amount multiple entities.
- \sa Qt3D.Render::RayCaster, Qt3D.Render::ScreenRayCaster, Qt3D.Render::ObjectPicker, Qt3D.Render::PickingSettings
+ \sa Qt3D.Render::RayCaster, Qt3D.Render::ScreenRayCaster, Qt3D.Render::ObjectPicker,
+ Qt3D.Render::PickingSettings, Qt3D.Render::NoPicking
*/
/*!
diff --git a/src/render/picking/qobjectpicker.cpp b/src/render/picking/qobjectpicker.cpp
index d1a246c27..4f039b361 100644
--- a/src/render/picking/qobjectpicker.cpp
+++ b/src/render/picking/qobjectpicker.cpp
@@ -41,8 +41,10 @@
#include "qobjectpicker_p.h"
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/private/qcomponent_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DRender/qpickevent.h>
+#include <Qt3DRender/QViewport>
+#include <Qt3DRender/private/qpickevent_p.h>
QT_BEGIN_NAMESPACE
@@ -75,7 +77,7 @@ namespace Qt3DRender {
For generalised ray casting queries, see Qt3DRender::QRayCaster and Qt3DRender::QScreenRayCaster.
\sa Qt3DRender::QPickingSettings, Qt3DRender::QGeometry, Qt3DRender::QAttribute,
- Qt3DRender::QPickEvent, Qt3DRender::QPickTriangleEvent
+ Qt3DRender::QPickEvent, Qt3DRender::QPickTriangleEvent, Qt3DRender::QNoPicking
\note Instances of this component shouldn't be shared, not respecting that
condition will most likely result in undefined behavior.
@@ -110,7 +112,7 @@ namespace Qt3DRender {
If drag is enabled, queries also happen on each mouse move while any button is pressed.
If hover is enabled, queries happen on every mouse move even if no button is pressed.
- \sa PickingSettings, Geometry, Attribute, PickEvent, PickTriangleEvent
+ \sa PickingSettings, Geometry, Attribute, PickEvent, PickTriangleEvent, NoPicking
\note To receive hover events in QtQuick, the hoverEnabled property of Scene3D must also be set.
@@ -150,7 +152,7 @@ namespace Qt3DRender {
This signal is emitted when the bounding volume defined by the
pickAttribute property intersects with a ray on a mouse click. Intersection
- information are accessible through the pick \a parameter.
+ information are accessible through the \a pick parameter.
*/
/*!
@@ -290,6 +292,11 @@ void QObjectPicker::setPriority(int priority)
}
}
+// TODO Unused remove in Qt6
+void QObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
+{
+}
+
/*!
\qmlproperty bool Qt3D.Render::ObjectPicker::dragEnabled
*/
@@ -356,37 +363,6 @@ int QObjectPicker::priority() const
return d->m_priority;
}
-/*! \internal */
-void QObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
-{
- Q_D(QObjectPicker);
- Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change);
- if (e->type() == Qt3DCore::PropertyUpdated) {
- // TO DO: Complete this part
- // to emit the correct signals
- const QByteArray propertyName = e->propertyName();
- if (propertyName == QByteArrayLiteral("pressed")) {
- QPickEventPtr ev = e->value().value<QPickEventPtr>();
- d->pressedEvent(ev.data());
- } else if (propertyName == QByteArrayLiteral("released")) {
- QPickEventPtr ev = e->value().value<QPickEventPtr>();
- d->releasedEvent(ev.data());
- } else if (propertyName == QByteArrayLiteral("clicked")) {
- QPickEventPtr ev = e->value().value<QPickEventPtr>();
- d->clickedEvent(ev.data());
- } else if (propertyName == QByteArrayLiteral("moved")) {
- QPickEventPtr ev = e->value().value<QPickEventPtr>();
- d->movedEvent(ev.data());
- } else if (propertyName == QByteArrayLiteral("entered")) {
- emit entered();
- d->setContainsMouse(true);
- } else if (propertyName == QByteArrayLiteral("exited")) {
- d->setContainsMouse(false);
- emit exited();
- }
- }
-}
-
/*!
\internal
*/
diff --git a/src/render/picking/qobjectpicker.h b/src/render/picking/qobjectpicker.h
index 8866c99a9..ea65040ba 100644
--- a/src/render/picking/qobjectpicker.h
+++ b/src/render/picking/qobjectpicker.h
@@ -77,6 +77,10 @@ public Q_SLOTS:
void setDragEnabled(bool dragEnabled);
Q_REVISION(13) void setPriority(int priority);
+protected:
+ // TODO Unused remove in Qt6
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+
Q_SIGNALS:
void pressed(Qt3DRender::QPickEvent *pick);
void released(Qt3DRender::QPickEvent *pick);
@@ -90,9 +94,6 @@ Q_SIGNALS:
void containsMouseChanged(bool containsMouse);
Q_REVISION(13) void priorityChanged(int priority);
-protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
-
private:
Q_DECLARE_PRIVATE(QObjectPicker)
Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
diff --git a/src/render/picking/qobjectpicker_p.h b/src/render/picking/qobjectpicker_p.h
index b95183ab5..61f8a3d94 100644
--- a/src/render/picking/qobjectpicker_p.h
+++ b/src/render/picking/qobjectpicker_p.h
@@ -51,6 +51,7 @@
#include <Qt3DCore/private/qcomponent_p.h>
#include <Qt3DCore/qnodeid.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
+#include <Qt3DRender/private/objectpicker_p.h>
QT_BEGIN_NAMESPACE
@@ -107,8 +108,16 @@ struct QObjectPickerData
int priority;
};
+struct QObjectPickerEvent
+{
+ QPickEventPtr event;
+ Qt3DCore::QNodeId viewportNodeId;
+};
+
} // namespace Qt3DRender
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(Qt3DRender::QObjectPickerEvent);
+
#endif // QT3DRENDER_QOBJECTPICKER_P_H
diff --git a/src/render/picking/qpickevent.cpp b/src/render/picking/qpickevent.cpp
index 9230cc5e5..ae5748082 100644
--- a/src/render/picking/qpickevent.cpp
+++ b/src/render/picking/qpickevent.cpp
@@ -88,7 +88,8 @@ QPickEventPrivate *QPickEventPrivate::get(QPickEvent *object)
Constructs a new QPickEvent with the given parameters: \a position, \a intersection, \a localIntersection and \a distance
*/
// NOTE: remove in Qt6
-QPickEvent::QPickEvent(const QPointF &position, const QVector3D &worldIntersection, const QVector3D &localIntersection, float distance)
+QPickEvent::QPickEvent(const QPointF &position, const QVector3D &worldIntersection, const QVector3D &localIntersection,
+ float distance)
: QObject(*new QPickEventPrivate())
{
Q_D(QPickEvent);
@@ -101,7 +102,8 @@ QPickEvent::QPickEvent(const QPointF &position, const QVector3D &worldIntersecti
/*!
Constructs a new QPickEvent with the given parameters: \a position, \a worldIntersection, \a localIntersection, \a distance, \a button, \a buttons and \a modifiers
*/
-QPickEvent::QPickEvent(const QPointF &position, const QVector3D &worldIntersection, const QVector3D &localIntersection, float distance, QPickEvent::Buttons button, int buttons, int modifiers)
+QPickEvent::QPickEvent(const QPointF &position, const QVector3D &worldIntersection, const QVector3D &localIntersection,
+ float distance, QPickEvent::Buttons button, int buttons, int modifiers)
: QObject(*new QPickEventPrivate())
{
Q_D(QPickEvent);
@@ -302,6 +304,51 @@ int QPickEvent::modifiers() const
return d->m_modifiers;
}
+/*!
+ * \qmlproperty Viewport Qt3D.Render::PickEvent::viewport
+ * The viewport in which this event originated. A null value means the event originated from a frame graph branch without a Viewport.
+ * If a frame graph branch has a Viewport inside a Viewport the property will contain the leaf viewport.
+ *
+ * \since 5.14
+ */
+/*!
+ * \property Qt3DRender::QPickEvent::viewport
+ * The viewport in which this event originated. A null value means the event originated from a frame graph branch without a QViewport.
+ * If a frame graph branch has a Viewport inside a Viewport the property will contain the leaf viewport.
+ *
+ * \since 5.14
+ */
+QViewport *QPickEvent::viewport() const
+{
+ Q_D(const QPickEvent);
+ return d->m_viewport;
+}
+
+
+/*!
+ * \qmlproperty Entity Qt3D.Render::PickEvent::entity
+ * The entity that the picked geometry belongs to.
+ *
+ * If the object picker is not attached to a leaf node in the scene graph,
+ * this is useful to find which child entity was actually picked.
+ *
+ * \since 5.14
+ */
+/*!
+ * \property Qt3DRender::QPickEvent::entity
+ * The entity that the picked geometry belongs to.
+ *
+ * If the object picker is not attached to a leaf node in the scene graph,
+ * this is useful to find which child entity was actually picked.
+ *
+ * \since 5.14
+ */
+Qt3DCore::QEntity *QPickEvent::entity() const
+{
+ Q_D(const QPickEvent);
+ return d->m_entityPtr;
+}
+
} // Qt3DRender
QT_END_NAMESPACE
diff --git a/src/render/picking/qpickevent.h b/src/render/picking/qpickevent.h
index 5b354efb7..854008aaf 100644
--- a/src/render/picking/qpickevent.h
+++ b/src/render/picking/qpickevent.h
@@ -47,8 +47,13 @@
QT_BEGIN_NAMESPACE
+namespace Qt3DCore {
+class QEntity;
+}
+
namespace Qt3DRender {
+class QViewport;
class QPickEventPrivate;
class QPickEvent;
@@ -65,6 +70,8 @@ class Q_3DRENDERSHARED_EXPORT QPickEvent : public QObject
Q_PROPERTY(Qt3DRender::QPickEvent::Buttons button READ button CONSTANT)
Q_PROPERTY(int buttons READ buttons CONSTANT)
Q_PROPERTY(int modifiers READ modifiers CONSTANT)
+ Q_PROPERTY(Qt3DRender::QViewport *viewport READ viewport CONSTANT REVISION 14)
+ Q_PROPERTY(Qt3DCore::QEntity *entity READ entity CONSTANT REVISION 14)
public:
enum Buttons {
LeftButton = Qt::LeftButton,
@@ -87,7 +94,8 @@ public:
QPickEvent();
QPickEvent(const QPointF &position, const QVector3D& worldIntersection, const QVector3D& localIntersection, float distance);
- QPickEvent(const QPointF &position, const QVector3D& worldIntersection, const QVector3D& localIntersection, float distance, Buttons button, int buttons, int modifiers);
+ QPickEvent(const QPointF &position, const QVector3D& worldIntersection, const QVector3D& localIntersection, float distance, Buttons button,
+ int buttons, int modifiers);
~QPickEvent();
bool isAccepted() const;
@@ -103,6 +111,8 @@ public:
Buttons button() const;
int buttons() const;
int modifiers() const;
+ QViewport *viewport() const;
+ Qt3DCore::QEntity *entity() const;
Q_SIGNALS:
void acceptedChanged(bool accepted);
@@ -112,6 +122,8 @@ protected:
private:
Q_DECLARE_PRIVATE(QPickEvent)
+
+ friend class QObjectPickerPrivate;
};
} // Qt3DRender
diff --git a/src/render/picking/qpickevent_p.h b/src/render/picking/qpickevent_p.h
index e27ee51e2..15eeb04b8 100644
--- a/src/render/picking/qpickevent_p.h
+++ b/src/render/picking/qpickevent_p.h
@@ -37,6 +37,9 @@
**
****************************************************************************/
+#ifndef QT3DRENDER_QPICKEVENT_P_H
+#define QT3DRENDER_QPICKEVENT_P_H
+
//
// W A R N I N G
// -------------
@@ -59,6 +62,7 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
class QPickEvent;
+class QViewport;
class Q_3DRENDERSHARED_PRIVATE_EXPORT QPickEventPrivate : public QObjectPrivate
{
@@ -70,6 +74,8 @@ public:
, m_button(QPickEvent::NoButton)
, m_buttons(QPickEvent::NoButton)
, m_modifiers(QPickEvent::NoModifier)
+ , m_entityPtr(nullptr)
+ , m_viewport(nullptr)
{
}
@@ -82,6 +88,8 @@ public:
int m_buttons;
int m_modifiers;
Qt3DCore::QNodeId m_entity;
+ Qt3DCore::QEntity *m_entityPtr;
+ QViewport *m_viewport;
static QPickEventPrivate *get(QPickEvent *object);
};
@@ -90,3 +98,4 @@ public:
QT_END_NAMESPACE
+#endif // QT3DRENDER_QPICKEVENT_P_H
diff --git a/src/render/picking/qpicktriangleevent.cpp b/src/render/picking/qpicktriangleevent.cpp
index 3e8e8c72c..c077d412f 100644
--- a/src/render/picking/qpicktriangleevent.cpp
+++ b/src/render/picking/qpicktriangleevent.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qpicktriangleevent.h"
+#include "qpicktriangleevent_p.h"
#include "qpickevent_p.h"
#include <private/qobject_p.h>
@@ -45,24 +46,42 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-class QPickTriangleEventPrivate : public QPickEventPrivate
+
+Qt3DRender::QPickTriangleEventPrivate::QPickTriangleEventPrivate()
+ : QPickEventPrivate()
+ , m_triangleIndex(0)
+ , m_vertex1Index(0)
+ , m_vertex2Index(0)
+ , m_vertex3Index(0)
+{
+}
+
+const QPickTriangleEventPrivate *QPickTriangleEventPrivate::get(const QPickTriangleEvent *ev)
{
-public:
- QPickTriangleEventPrivate()
- : QPickEventPrivate()
- , m_triangleIndex(0)
- , m_vertex1Index(0)
- , m_vertex2Index(0)
- , m_vertex3Index(0)
- {
- }
+ return ev->d_func();
+}
+
+QPickTriangleEvent *QPickTriangleEventPrivate::clone() const
+{
+ auto res = new QPickTriangleEvent();
+ res->d_func()->m_accepted = m_accepted;
+ res->d_func()->m_position = m_position;
+ res->d_func()->m_worldIntersection = m_worldIntersection;
+ res->d_func()->m_localIntersection = m_localIntersection;
+ res->d_func()->m_distance = m_distance;
+ res->d_func()->m_button = m_button;
+ res->d_func()->m_buttons = m_buttons;
+ res->d_func()->m_modifiers = m_modifiers;
+ res->d_func()->m_entity = m_entity;
+ res->d_func()->m_entityPtr = m_entityPtr;
+ res->d_func()->m_viewport = m_viewport;
+ res->d_func()->m_triangleIndex = m_triangleIndex;
+ res->d_func()->m_vertex1Index = m_vertex1Index;
+ res->d_func()->m_vertex2Index = m_vertex2Index;
+ res->d_func()->m_vertex3Index = m_vertex3Index;
+ return res;
+}
- uint m_triangleIndex;
- uint m_vertex1Index;
- uint m_vertex2Index;
- uint m_vertex3Index;
- QVector3D m_uvw;
-};
/*!
\class Qt3DRender::QPickTriangleEvent
diff --git a/src/render/picking/qpicktriangleevent_p.h b/src/render/picking/qpicktriangleevent_p.h
new file mode 100644
index 000000000..d646ac2bb
--- /dev/null
+++ b/src/render/picking/qpicktriangleevent_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QPICKTRIANGLEEVENT_P_H
+#define QT3DRENDER_QPICKTRIANGLEEVENT_P_H
+
+#include <Qt3DRender/private/qpickevent_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+class QPickTriangleEvent;
+
+class Q_3DRENDERSHARED_PRIVATE_EXPORT QPickTriangleEventPrivate : public QPickEventPrivate
+{
+public:
+ QPickTriangleEventPrivate();
+
+ static const QPickTriangleEventPrivate *get(const QPickTriangleEvent *ev);
+ QPickTriangleEvent *clone() const;
+
+ uint m_triangleIndex;
+ uint m_vertex1Index;
+ uint m_vertex2Index;
+ uint m_vertex3Index;
+ QVector3D m_uvw;
+};
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QPICKTRIANGLEEVENT_P_H
diff --git a/src/render/picking/qraycaster.cpp b/src/render/picking/qraycaster.cpp
index cfe5bce1b..f32ea32f1 100644
--- a/src/render/picking/qraycaster.cpp
+++ b/src/render/picking/qraycaster.cpp
@@ -40,7 +40,6 @@
#include "qraycaster.h"
#include "qabstractraycaster_p.h"
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qcomponent_p.h>
#include <Qt3DCore/private/qscene_p.h>
@@ -63,7 +62,7 @@ namespace Qt3DRender {
Ray casting tests will be performed every frame as long as the component is enabled.
The hits property will be updated with the list of intersections.
- \sa QAbstractRayCaster, QScreenRayCaster
+ \sa QAbstractRayCaster, QScreenRayCaster, QNoPicking
*/
/*!
\qmltype RayCaster
@@ -78,7 +77,7 @@ namespace Qt3DRender {
Ray casting tests will be performed every frame as long as the component is enabled.
The hits property will be updated with the list of intersections.
- \sa AbstractRayCaster, ScreenRayCaster
+ \sa AbstractRayCaster, ScreenRayCaster, NoPicking
*/
/*!
diff --git a/src/render/picking/qscreenraycaster.cpp b/src/render/picking/qscreenraycaster.cpp
index 95df8e4c1..3e47c2a01 100644
--- a/src/render/picking/qscreenraycaster.cpp
+++ b/src/render/picking/qscreenraycaster.cpp
@@ -40,7 +40,6 @@
#include "qscreenraycaster.h"
#include "qabstractraycaster_p.h"
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qcomponent_p.h>
#include <Qt3DCore/private/qscene_p.h>
@@ -59,7 +58,7 @@ namespace Qt3DRender {
screen space, which will be used to construct an actual 3D ray between the near and
far planes.
- \sa QRayCaster
+ \sa QRayCaster, QNoPicking
*/
/*!
\qmltype ScreenRayCaster
@@ -72,7 +71,7 @@ namespace Qt3DRender {
screen space, which will be used to construct an actual 3D ray between the near and
far planes.
- \sa RayCaster
+ \sa RayCaster, NoPicking
*/
/*!
diff --git a/src/render/picking/raycaster.cpp b/src/render/picking/raycaster.cpp
index a5fbf1206..8d3456595 100644
--- a/src/render/picking/raycaster.cpp
+++ b/src/render/picking/raycaster.cpp
@@ -41,11 +41,9 @@
#include "qpickevent.h"
#include <Qt3DRender/private/abstractrenderer_p.h>
#include <Qt3DRender/qabstractraycaster.h>
+#include <Qt3DRender/qlayer.h>
#include <Qt3DRender/private/qabstractraycaster_p.h>
#include <Qt3DRender/private/raycastingjob_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
QT_BEGIN_NAMESPACE
@@ -119,87 +117,62 @@ void RayCaster::cleanup()
notifyJob();
}
-void RayCaster::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void RayCaster::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractRayCasterData>>(change);
- const auto &data = typedChange->data;
- m_type = data.casterType;
- m_runMode = data.runMode;
- m_origin = data.origin;
- m_direction = data.direction;
- m_length = data.length;
- m_position = data.position;
- m_filterMode = data.filterMode;
- m_layerIds = data.layerIds;
-}
+ const QAbstractRayCaster *node = qobject_cast<const QAbstractRayCaster *>(frontEnd);
+ if (!node)
+ return;
-void RayCaster::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- switch (e->type()) {
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("layer")) {
- m_layerIds.append(change->addedNodeId());
- markDirty(AbstractRenderer::LayersDirty);
- notifyJob();
- }
- break;
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (node->runMode() != m_runMode) {
+ m_runMode = node->runMode();
+ notifyJob();
+ markDirty(AbstractRenderer::AllDirty);
}
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("layer")) {
- m_layerIds.removeOne(change->removedNodeId());
- markDirty(AbstractRenderer::LayersDirty);
- notifyJob();
- }
- break;
+ if (node->filterMode() != m_filterMode) {
+ m_filterMode = node->filterMode();
+ notifyJob();
+ markDirty(AbstractRenderer::AllDirty);
}
- case PropertyUpdated: {
- const Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
-
- if (propertyChange->propertyName() == QByteArrayLiteral("origin")) {
- m_origin = propertyChange->value().value<QVector3D>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("direction")) {
- m_direction = propertyChange->value().value<QVector3D>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("length")) {
- m_length = propertyChange->value().toFloat();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("position")) {
- m_position = propertyChange->value().toPoint();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("runMode")) {
- m_runMode = propertyChange->value().value<QAbstractRayCaster::RunMode>();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("filterMode")) {
- m_filterMode = propertyChange->value().value<QAbstractRayCaster::FilterMode>();
- }
+ const Qt3DCore::QNodeIdVector layerIds = Qt3DCore::qIdsForNodes(node->layers());
+ if (layerIds != m_layerIds) {
+ m_layerIds = layerIds;
+ markDirty(AbstractRenderer::LayersDirty);
+ notifyJob();
+ }
+
+ const QAbstractRayCasterPrivate *d = static_cast<const QAbstractRayCasterPrivate *>(QNodePrivate::get(node));
+ if (d->m_direction != m_direction) {
+ m_direction = d->m_direction;
+ notifyJob();
+ markDirty(AbstractRenderer::AllDirty);
+ }
+ if (!qFuzzyCompare(d->m_length, m_length)) {
+ m_length = d->m_length;
notifyJob();
markDirty(AbstractRenderer::AllDirty);
- break;
}
- default:
- break;
+ if (d->m_origin != m_origin) {
+ m_origin = d->m_origin;
+ notifyJob();
+ markDirty(AbstractRenderer::AllDirty);
}
- BackendNode::sceneChangeEvent(e);
-}
+ if (d->m_position != m_position) {
+ m_position = d->m_position;
+ notifyJob();
+ markDirty(AbstractRenderer::AllDirty);
+ }
-void RayCaster::dispatchHits(const QAbstractRayCaster::Hits &hits)
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("hits");
- e->setValue(QVariant::fromValue(hits));
- notifyObservers(e);
-
- if (m_runMode == QAbstractRayCaster::SingleShot) {
- setEnabled(false);
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- e->setPropertyName("enabled");
- e->setValue(false);
- notifyObservers(e);
+ if (d->m_rayCasterType != m_type) {
+ m_type = d->m_rayCasterType;
+ notifyJob();
+ markDirty(AbstractRenderer::AllDirty);
}
}
diff --git a/src/render/picking/raycaster_p.h b/src/render/picking/raycaster_p.h
index 6fe6ee322..865d40365 100644
--- a/src/render/picking/raycaster_p.h
+++ b/src/render/picking/raycaster_p.h
@@ -80,13 +80,10 @@ public:
Qt3DCore::QNodeIdVector layerIds() const;
QAbstractRayCaster::FilterMode filterMode() const;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final;
-
- void dispatchHits(const QAbstractRayCaster::Hits &hits);
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
void notifyJob();
QAbstractRayCasterPrivate::RayCasterType m_type = QAbstractRayCasterPrivate::WorldSpaceRayCaster;
diff --git a/src/render/raycasting/qcollisionqueryresult.cpp b/src/render/raycasting/qcollisionqueryresult.cpp
index 9d1e484b6..d2a443691 100644
--- a/src/render/raycasting/qcollisionqueryresult.cpp
+++ b/src/render/raycasting/qcollisionqueryresult.cpp
@@ -46,6 +46,7 @@ namespace RayCasting {
QCollisionQueryResultPrivate::QCollisionQueryResultPrivate()
: QSharedData()
+ , m_handle(0)
{
}
diff --git a/src/render/raycasting/qcollisionqueryresult_p.h b/src/render/raycasting/qcollisionqueryresult_p.h
index 67f6a34d0..d8e2056eb 100644
--- a/src/render/raycasting/qcollisionqueryresult_p.h
+++ b/src/render/raycasting/qcollisionqueryresult_p.h
@@ -86,8 +86,10 @@ public:
Hit(Qt3DCore::QNodeId entity, const Vector3D &intersection, float distance, const Vector3D &uvw)
: m_entityId(entity)
+ , m_type(Entity)
, m_intersection(intersection)
, m_distance(distance)
+ , m_primitiveIndex(0U)
, m_uvw(uvw)
{
}
diff --git a/src/render/raycasting/qraycastingservice.cpp b/src/render/raycasting/qraycastingservice.cpp
index a0f21aa41..bdb1557f7 100644
--- a/src/render/raycasting/qraycastingservice.cpp
+++ b/src/render/raycasting/qraycastingservice.cpp
@@ -43,7 +43,6 @@
#include <Qt3DRender/private/sphere_p.h>
#include <Qt3DRender/private/qboundingvolumeprovider_p.h>
-#include <QMap>
#include <QtConcurrent>
#include "math.h"
diff --git a/src/render/render.pro b/src/render/render.pro
index ea5ce7dc5..55303fa83 100644
--- a/src/render/render.pro
+++ b/src/render/render.pro
@@ -20,9 +20,6 @@ include (services/services.pri)
include (texture/texture.pri)
include (renderers/renderers.pri)
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
index be8f861e3..333453ac7 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
@@ -92,6 +92,10 @@ QT_BEGIN_NAMESPACE
#define GL_DRAW_FRAMEBUFFER 0x8CA9
#endif
+#ifndef GL_MAX_IMAGE_UNITS
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#endif
+
namespace {
QOpenGLShader::ShaderType shaderType(Qt3DRender::QShaderProgram::ShaderType type)
@@ -125,6 +129,7 @@ GraphicsContext::GraphicsContext()
: m_initialized(false)
, m_supportsVAO(false)
, m_maxTextureUnits(0)
+ , m_maxImageUnits(0)
, m_defaultFBO(0)
, m_gl(nullptr)
, m_glHelper(nullptr)
@@ -152,6 +157,8 @@ void GraphicsContext::initialize()
m_gl->functions()->glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &m_maxTextureUnits);
qCDebug(Backend) << "context supports" << m_maxTextureUnits << "texture units";
+ m_gl->functions()->glGetIntegerv(GL_MAX_IMAGE_UNITS, &m_maxImageUnits);
+ qCDebug(Backend) << "context supports" << m_maxImageUnits << "image units";
if (m_gl->format().majorVersion() >= 3) {
m_supportsVAO = true;
@@ -272,7 +279,7 @@ void GraphicsContext::introspectShaderInterface(Shader *shader, QOpenGLShaderPro
}
-// Called by GL Command Thread
+// Called by Renderer::updateGLResources
void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager)
{
bool wasPresent = false;
@@ -310,7 +317,8 @@ void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager)
shader->setGraphicsContext(this);
shader->setLoaded(true);
- shader->markDirty(AbstractRenderer::AllDirty);
+ // Will force notifications to be sent to frontend at next frame
+ shader->markDirty(AbstractRenderer::ShadersDirty);
}
}
@@ -335,6 +343,11 @@ void GraphicsContext::activateDrawBuffers(const AttachmentPack &attachments)
}
}
+void GraphicsContext::rasterMode(GLenum faceMode, GLenum rasterMode)
+{
+ m_glHelper->rasterMode(faceMode, rasterMode);
+}
+
/*!
* \internal
* Finds the highest supported opengl version and internally use the most optimized
@@ -555,6 +568,11 @@ void GraphicsContext::bindFramebuffer(GLuint fbo, GraphicsHelperInterface::FBOBi
m_glHelper->bindFrameBufferObject(fbo, mode);
}
+void GraphicsContext::depthRange(GLdouble nearValue, GLdouble farValue)
+{
+ m_glHelper->depthRange(nearValue, farValue);
+}
+
void GraphicsContext::depthTest(GLenum mode)
{
m_glHelper->depthTest(mode);
@@ -577,6 +595,19 @@ void GraphicsContext::bindFragOutputs(GLuint shader, const QHash<QString, int> &
m_glHelper->bindFragDataLocation(shader, outputs);
}
+void GraphicsContext::bindImageTexture(GLuint imageUnit, GLuint texture,
+ GLint mipLevel, GLboolean layered,
+ GLint layer, GLenum access, GLenum format)
+{
+ m_glHelper->bindImageTexture(imageUnit,
+ texture,
+ mipLevel,
+ layered,
+ layer,
+ access,
+ format);
+}
+
void GraphicsContext::bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
m_glHelper->bindUniformBlock(programId, uniformBlockIndex, uniformBlockBinding);
@@ -652,11 +683,17 @@ GLint GraphicsContext::maxClipPlaneCount()
return m_glHelper->maxClipPlaneCount();
}
-GLint GraphicsContext::maxTextureUnitsCount()
+GLint GraphicsContext::maxTextureUnitsCount() const
{
return m_maxTextureUnits;
}
+GLint GraphicsContext::maxImageUnitsCount() const
+{
+ return m_maxImageUnits;
+}
+
+
void GraphicsContext::enablePrimitiveRestart(int restartIndex)
{
if (m_glHelper->supportsFeature(GraphicsHelperInterface::PrimitiveRestart))
@@ -759,6 +796,7 @@ void GraphicsContext::applyUniform(const ShaderUniform &description, const Unifo
break;
case UniformType::Sampler:
+ case UniformType::Image:
case UniformType::Int:
applyUniformHelper<UniformType::Int>(description, v);
break;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h b/src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h
index 73d1f316c..2f4df2e22 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h
@@ -123,6 +123,7 @@ public:
void bindFramebuffer(GLuint fbo, GraphicsHelperInterface::FBOBindMode mode);
void bindBufferBase(GLenum target, GLuint bindingIndex, GLuint buffer);
void bindFragOutputs(GLuint shader, const QHash<QString, int> &outputs);
+ void bindImageTexture(GLuint imageUnit, GLuint texture, GLint mipLevel, GLboolean layered, GLint layer, GLenum access, GLenum format);
void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding);
void blendEquation(GLenum mode);
@@ -134,6 +135,7 @@ public:
void clearColor(const QColor &color);
void clearDepthValue(float depth);
void clearStencilValue(int stencil);
+ void depthRange(GLdouble nearValue, GLdouble farValue);
void depthMask(GLenum mode);
void depthTest(GLenum mode);
void disableClipPlane(int clipPlane);
@@ -154,7 +156,8 @@ public:
void enablePrimitiveRestart(int restartIndex);
void frontFace(GLenum mode);
GLint maxClipPlaneCount();
- GLint maxTextureUnitsCount();
+ GLint maxTextureUnitsCount() const;
+ GLint maxImageUnitsCount() const;
void pointSize(bool programmable, GLfloat value);
void readBuffer(GLenum mode);
void drawBuffer(GLenum mode);
@@ -166,6 +169,7 @@ public:
void setVerticesPerPatch(GLint verticesPerPatch);
void memoryBarrier(QMemoryBarrier::Operations barriers);
void activateDrawBuffers(const AttachmentPack &attachments);
+ void rasterMode(GLenum faceMode, GLenum rasterMode);
// Helper methods
static GLint elementType(GLint type);
@@ -183,6 +187,7 @@ public:
bool m_initialized;
bool m_supportsVAO;
GLint m_maxTextureUnits;
+ GLint m_maxImageUnits;
GLuint m_defaultFBO;
QOpenGLContext *m_gl;
GraphicsHelperInterface *m_glHelper;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp
index 71540b1ad..5f77dd376 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp
@@ -345,6 +345,13 @@ void GraphicsHelperES2::deleteSync(void *)
qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)";
}
+void GraphicsHelperES2::rasterMode(GLenum faceMode, GLenum rasterMode)
+{
+ Q_UNUSED(faceMode);
+ Q_UNUSED(rasterMode);
+ qWarning() << "glPolyonMode is not supported with OpenGL ES";
+}
+
void GraphicsHelperES2::blendEquation(GLenum mode)
{
m_funcs->glBlendEquation(mode);
@@ -394,6 +401,11 @@ void GraphicsHelperES2::depthMask(GLenum mode)
m_funcs->glDepthMask(mode);
}
+void GraphicsHelperES2::depthRange(GLdouble nearValue, GLdouble farValue)
+{
+ m_funcs->glDepthRangef(static_cast<float>(nearValue), static_cast<float>(farValue));
+}
+
void GraphicsHelperES2::frontFace(GLenum mode)
{
m_funcs->glFrontFace(mode);
@@ -435,6 +447,21 @@ void GraphicsHelperES2::bindFrameBufferObject(GLuint frameBufferId, FBOBindMode
m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, frameBufferId);
}
+void GraphicsHelperES2::bindImageTexture(GLuint imageUnit, GLuint texture,
+ GLint mipLevel, GLboolean layered,
+ GLint layer, GLenum access, GLenum format)
+{
+ Q_UNUSED(imageUnit)
+ Q_UNUSED(texture)
+ Q_UNUSED(mipLevel)
+ Q_UNUSED(layered)
+ Q_UNUSED(layer)
+ Q_UNUSED(access)
+ Q_UNUSED(format)
+ qWarning() << "Shader Images are not supported by ES 2.0 (since ES 3.1)";
+
+}
+
GLuint GraphicsHelperES2::boundFrameBufferObject()
{
GLint id = 0;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h
index 8c8dd34e9..882931ad9 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h
@@ -76,6 +76,7 @@ public:
void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) override;
void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) override;
void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) override;
+ void bindImageTexture(GLuint imageUnit, GLuint texture, GLint mipLevel, GLboolean layered, GLint layer, GLenum access, GLenum format) override;
void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) override;
void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
void blendEquation(GLenum mode) override;
@@ -88,6 +89,7 @@ public:
void clearBufferf(GLint drawbuffer, const QVector4D &values) override;
GLuint createFrameBufferObject() override;
void depthMask(GLenum mode) override;
+ void depthRange(GLdouble nearValue, GLdouble farValue) override;
void depthTest(GLenum mode) override;
void disableClipPlane(int clipPlane) override;
void disablei(GLenum cap, GLuint index) override;
@@ -131,6 +133,7 @@ public:
void vertexAttributePointer(GLenum shaderDataType, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) override;
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void rasterMode(GLenum faceMode, GLenum rasterMode) override;
void *fenceSync() override;
void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp
index a555b67ef..9c424d962 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1.cpp
@@ -110,6 +110,42 @@ QT_BEGIN_NAMESPACE
#ifndef GL_SHADER_STORAGE_BARRIER_BIT
#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
#endif
+#ifndef GL_IMAGE_2D
+#define GL_IMAGE_2D 0x904D
+#endif
+#ifndef GL_IMAGE_3D
+#define GL_IMAGE_3D 0x904E
+#endif
+#ifndef GL_IMAGE_CUBE
+#define GL_IMAGE_CUBE 0x9050
+#endif
+#ifndef GL_IMAGE_2D_ARRAY
+#define GL_IMAGE_2D_ARRAY 0x9053
+#endif
+#ifndef GL_INT_IMAGE_2D
+#define GL_INT_IMAGE_2D 0x9058
+#endif
+#ifndef GL_INT_IMAGE_3D
+#define GL_INT_IMAGE_3D 0x9059
+#endif
+#ifndef GL_INT_IMAGE_CUBE
+#define GL_INT_IMAGE_CUBE 0x905B
+#endif
+#ifndef GL_INT_IMAGE_2D_ARRAY
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#endif
+#ifndef GL_UNSIGNED_INT_IMAGE_2D
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#endif
+#ifndef GL_UNSIGNED_INT_IMAGE_3D
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#endif
+#ifndef GL_UNSIGNED_INT_IMAGE_CUBE
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#endif
+#ifndef GL_UNSIGNED_INT_IMAGE_2D_ARRAY
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#endif
namespace Qt3DRender {
@@ -175,6 +211,7 @@ bool GraphicsHelperES3_1::supportsFeature(GraphicsHelperInterface::Feature featu
case GraphicsHelperInterface::Compute:
case GraphicsHelperInterface::ShaderStorageObject:
case GraphicsHelperInterface::IndirectDrawing:
+ case GraphicsHelperInterface::ShaderImage:
return true;
default:
break;
@@ -182,6 +219,19 @@ bool GraphicsHelperES3_1::supportsFeature(GraphicsHelperInterface::Feature featu
return GraphicsHelperES3::supportsFeature(feature);
}
+void GraphicsHelperES3_1::bindImageTexture(GLuint imageUnit, GLuint texture,
+ GLint mipLevel, GLboolean layered,
+ GLint layer, GLenum access, GLenum format)
+{
+ m_extraFuncs->glBindImageTexture(imageUnit,
+ texture,
+ mipLevel,
+ layered,
+ layer,
+ access,
+ format);
+}
+
void GraphicsHelperES3_1::dispatchCompute(GLuint wx, GLuint wy, GLuint wz)
{
m_extraFuncs->glDispatchCompute(wx, wy, wz);
@@ -240,6 +290,19 @@ UniformType GraphicsHelperES3_1::uniformTypeFromGLType(GLenum glType)
case GL_INT_SAMPLER_2D_MULTISAMPLE:
case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
return UniformType::Sampler;
+ case GL_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_IMAGE_CUBE:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_2D:
+ case GL_INT_IMAGE_3D:
+ case GL_INT_IMAGE_CUBE:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ return UniformType::Image;
default:
return GraphicsHelperES3::uniformTypeFromGLType(glType);
@@ -254,6 +317,18 @@ uint GraphicsHelperES3_1::uniformByteSize(const ShaderUniform &description)
case GL_SAMPLER_2D_MULTISAMPLE:
case GL_INT_SAMPLER_2D_MULTISAMPLE:
case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_IMAGE_CUBE:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_2D:
+ case GL_INT_IMAGE_3D:
+ case GL_INT_IMAGE_CUBE:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
rawByteSize = 4;
break;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1_p.h
index 2c130fbf5..43d9ae7dd 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_1_p.h
@@ -65,6 +65,7 @@ public:
~GraphicsHelperES3_1();
bool supportsFeature(Feature feature) const override;
+ void bindImageTexture(GLuint imageUnit, GLuint texture, GLint mipLevel, GLboolean layered, GLint layer, GLenum access, GLenum format) override;
void dispatchCompute(GLuint wx, GLuint wy, GLuint wz) override;
void memoryBarrier(QMemoryBarrier::Operations barriers) override;
void drawArraysIndirect(GLenum mode,void *indirect) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp
index 56da249f2..9d0988410 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2.cpp
@@ -56,6 +56,25 @@ QT_BEGIN_NAMESPACE
#define GL_PATCH_VERTICES 36466
#endif
+#ifndef GL_IMAGE_BUFFER
+#define GL_IMAGE_BUFFER 0x9051
+#endif
+#ifndef GL_IMAGE_CUBE_MAP_ARRAY
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#endif
+#ifndef GL_INT_IMAGE_BUFFER
+#define GL_INT_IMAGE_BUFFER 0x905C
+#endif
+#ifndef GL_INT_IMAGE_CUBE_MAP_ARRAY
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#endif
+#ifndef GL_UNSIGNED_INT_IMAGE_BUFFER
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#endif
+#ifndef GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#endif
+
namespace Qt3DRender {
namespace Render {
@@ -130,6 +149,44 @@ void GraphicsHelperES3_2::drawElementsInstancedBaseVertexBaseInstance(GLenum pri
baseVertex);
}
+UniformType GraphicsHelperES3_2::uniformTypeFromGLType(GLenum glType)
+{
+ switch (glType) {
+ case GL_IMAGE_BUFFER:
+ case GL_IMAGE_CUBE_MAP_ARRAY:
+ case GL_INT_IMAGE_BUFFER:
+ case GL_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_BUFFER:
+ case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY:
+ return UniformType::Image;
+
+ default:
+ return GraphicsHelperES3_1::uniformTypeFromGLType(glType);
+ }
+}
+
+uint GraphicsHelperES3_2::uniformByteSize(const ShaderUniform &description)
+{
+ uint rawByteSize = 0;
+
+ switch (description.m_type) {
+ case GL_IMAGE_BUFFER:
+ case GL_IMAGE_CUBE_MAP_ARRAY:
+ case GL_INT_IMAGE_BUFFER:
+ case GL_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_BUFFER:
+ case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY:
+ rawByteSize = 4;
+ break;
+
+ default:
+ rawByteSize = GraphicsHelperES3_1::uniformByteSize(description);
+ break;
+ }
+
+ return rawByteSize;
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h
index 259864379..6b1a893d4 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_2_p.h
@@ -71,6 +71,9 @@ public:
bool frameBufferNeedsRenderBuffer(const Attachment &attachment) override;
void setVerticesPerPatch(GLint verticesPerPatch) override;
void drawElementsInstancedBaseVertexBaseInstance(GLenum primitiveType, GLsizei primitiveCount, GLint indexType, void *indices, GLsizei instances, GLint baseVertex = 0, GLint baseInstance = 0) override;
+ UniformType uniformTypeFromGLType(GLenum glType) override;
+ uint uniformByteSize(const ShaderUniform &description) override;
+
};
} // namespace Render
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp
index b6f3412b2..b9ee16acb 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp
@@ -299,6 +299,11 @@ void GraphicsHelperGL2::deleteSync(void *)
qWarning() << "Fences are not supported by OpenGL 2.0 (since OpenGL 3.2)";
}
+void GraphicsHelperGL2::rasterMode(GLenum faceMode, GLenum rasterMode)
+{
+ m_funcs->glPolygonMode(faceMode, rasterMode);
+}
+
void GraphicsHelperGL2::blendEquation(GLenum mode)
{
m_funcs->glBlendEquation(mode);
@@ -341,6 +346,11 @@ void GraphicsHelperGL2::depthMask(GLenum mode)
m_funcs->glDepthMask(mode);
}
+void GraphicsHelperGL2::depthRange(GLdouble nearValue, GLdouble farValue)
+{
+ m_funcs->glDepthRange(nearValue, farValue);
+}
+
void GraphicsHelperGL2::frontFace(GLenum mode)
{
m_funcs->glFrontFace(mode);
@@ -480,6 +490,21 @@ void GraphicsHelperGL2::bindFrameBufferObject(GLuint frameBufferId, FBOBindMode
}
}
+void GraphicsHelperGL2::bindImageTexture(GLuint imageUnit, GLuint texture,
+ GLint mipLevel, GLboolean layered,
+ GLint layer, GLenum access, GLenum format)
+{
+ Q_UNUSED(imageUnit)
+ Q_UNUSED(texture)
+ Q_UNUSED(mipLevel)
+ Q_UNUSED(layered)
+ Q_UNUSED(layer)
+ Q_UNUSED(access)
+ Q_UNUSED(format)
+ qWarning() << "Shader Images are not supported by OpenGL 2.0 (since OpenGL 4.2)";
+
+}
+
GLuint GraphicsHelperGL2::boundFrameBufferObject()
{
GLint id = 0;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h
index b142b2623..eb85b8537 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h
@@ -76,6 +76,7 @@ public:
void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) override;
void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) override;
void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) override;
+ void bindImageTexture(GLuint imageUnit, GLuint texture, GLint mipLevel, GLboolean layered, GLint layer, GLenum access, GLenum format) override;
void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) override;
void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
void blendEquation(GLenum mode) override;
@@ -88,6 +89,7 @@ public:
void clearBufferf(GLint drawbuffer, const QVector4D &values) override;
GLuint createFrameBufferObject() override;
void depthMask(GLenum mode) override;
+ void depthRange(GLdouble nearValue, GLdouble farValue) override;
void depthTest(GLenum mode) override;
void disableClipPlane(int clipPlane) override;
void disablei(GLenum cap, GLuint index) override;
@@ -131,6 +133,7 @@ public:
void vertexAttributePointer(GLenum shaderDataType, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) override;
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void rasterMode(GLenum faceMode, GLenum rasterMode) override;
void *fenceSync() override;
void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp
index 5ff1a2ba5..f20491358 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp
@@ -365,6 +365,11 @@ void GraphicsHelperGL3_2::deleteSync(void *sync)
m_funcs->glDeleteSync(static_cast<GLsync>(sync));
}
+void GraphicsHelperGL3_2::rasterMode(GLenum faceMode, GLenum rasterMode)
+{
+ m_funcs->glPolygonMode(faceMode, rasterMode);
+}
+
void GraphicsHelperGL3_2::blendEquation(GLenum mode)
{
m_funcs->glBlendEquation(mode);
@@ -406,6 +411,11 @@ void GraphicsHelperGL3_2::depthMask(GLenum mode)
m_funcs->glDepthMask(mode);
}
+void GraphicsHelperGL3_2::depthRange(GLdouble nearValue, GLdouble farValue)
+{
+ m_funcs->glDepthRange(nearValue, farValue);
+}
+
void GraphicsHelperGL3_2::frontFace(GLenum mode)
{
m_funcs->glFrontFace(mode);
@@ -452,6 +462,21 @@ void GraphicsHelperGL3_2::bindFrameBufferObject(GLuint frameBufferId, FBOBindMod
}
}
+void GraphicsHelperGL3_2::bindImageTexture(GLuint imageUnit, GLuint texture,
+ GLint mipLevel, GLboolean layered,
+ GLint layer, GLenum access, GLenum format)
+{
+ Q_UNUSED(imageUnit)
+ Q_UNUSED(texture)
+ Q_UNUSED(mipLevel)
+ Q_UNUSED(layered)
+ Q_UNUSED(layer)
+ Q_UNUSED(access)
+ Q_UNUSED(format)
+ qWarning() << "Shader Images are not supported by OpenGL 3.2 (since OpenGL 4.2)";
+
+}
+
GLuint GraphicsHelperGL3_2::boundFrameBufferObject()
{
GLint id = 0;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h
index 9e81345ad..914afc9ff 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h
@@ -78,6 +78,7 @@ public:
void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) override;
void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) override;
void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) override;
+ void bindImageTexture(GLuint imageUnit, GLuint texture, GLint mipLevel, GLboolean layered, GLint layer, GLenum access, GLenum format) override;
void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) override;
void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
void blendEquation(GLenum mode) override;
@@ -90,6 +91,7 @@ public:
void clearBufferf(GLint drawbuffer, const QVector4D &values) override;
GLuint createFrameBufferObject() override;
void depthMask(GLenum mode) override;
+ void depthRange(GLdouble nearValue, GLdouble farValue) override;
void depthTest(GLenum mode) override;
void disableClipPlane(int clipPlane) override;
void disablei(GLenum cap, GLuint index) override;
@@ -133,6 +135,7 @@ public:
void vertexAttributePointer(GLenum shaderDataType, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) override;
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void rasterMode(GLenum faceMode, GLenum rasterMode) override;
void *fenceSync() override;
void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp
index 81081943d..ddffb38e2 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp
@@ -361,6 +361,11 @@ void GraphicsHelperGL3_3::deleteSync(void *sync)
m_funcs->glDeleteSync(static_cast<GLsync>(sync));
}
+void GraphicsHelperGL3_3::rasterMode(GLenum faceMode, GLenum rasterMode)
+{
+ m_funcs->glPolygonMode(faceMode, rasterMode);
+}
+
void GraphicsHelperGL3_3::blendEquation(GLenum mode)
{
m_funcs->glBlendEquation(mode);
@@ -402,6 +407,11 @@ void GraphicsHelperGL3_3::depthMask(GLenum mode)
m_funcs->glDepthMask(mode);
}
+void GraphicsHelperGL3_3::depthRange(GLdouble nearValue, GLdouble farValue)
+{
+ m_funcs->glDepthRange(nearValue, farValue);
+}
+
void GraphicsHelperGL3_3::frontFace(GLenum mode)
{
m_funcs->glFrontFace(mode);
@@ -546,6 +556,20 @@ void GraphicsHelperGL3_3::bindShaderStorageBlock(GLuint programId, GLuint shader
qWarning() << "SSBO are not supported by OpenGL 3.3 (since OpenGL 4.3)";
}
+void GraphicsHelperGL3_3::bindImageTexture(GLuint imageUnit, GLuint texture,
+ GLint mipLevel, GLboolean layered,
+ GLint layer, GLenum access, GLenum format)
+{
+ Q_UNUSED(imageUnit)
+ Q_UNUSED(texture)
+ Q_UNUSED(mipLevel)
+ Q_UNUSED(layered)
+ Q_UNUSED(layer)
+ Q_UNUSED(access)
+ Q_UNUSED(format)
+ qWarning() << "Shader Images are not supported by OpenGL 3.3 (since OpenGL 4.2)";
+}
+
void GraphicsHelperGL3_3::bindBufferBase(GLenum target, GLuint index, GLuint buffer)
{
m_funcs->glBindBufferBase(target, index, buffer);
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h
index c480e5258..4dbf6fe7b 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h
@@ -79,6 +79,7 @@ public:
void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) override;
void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) override;
void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) override;
+ void bindImageTexture(GLuint imageUnit, GLuint texture, GLint mipLevel, GLboolean layered, GLint layer, GLenum access, GLenum format) override;
void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
void blendEquation(GLenum mode) override;
void blendFunci(GLuint buf, GLenum sfactor, GLenum dfactor) override;
@@ -90,6 +91,7 @@ public:
void clearBufferf(GLint drawbuffer, const QVector4D &values) override;
GLuint createFrameBufferObject() override;
void depthMask(GLenum mode) override;
+ void depthRange(GLdouble nearValue, GLdouble farValue) override;
void depthTest(GLenum mode) override;
void disableClipPlane(int clipPlane) override;
void disablei(GLenum cap, GLuint index) override;
@@ -133,6 +135,7 @@ public:
void vertexAttributePointer(GLenum shaderDataType, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) override;
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void rasterMode(GLenum faceMode, GLenum rasterMode) override;
void *fenceSync() override;
void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp
index 22cbf7428..60caed273 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp
@@ -79,6 +79,39 @@
# define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
# define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
# define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+# define GL_IMAGE_1D 0x904C
+# define GL_IMAGE_2D 0x904D
+# define GL_IMAGE_3D 0x904E
+# define GL_IMAGE_2D_RECT 0x904F
+# define GL_IMAGE_CUBE 0x9050
+# define GL_IMAGE_BUFFER 0x9051
+# define GL_IMAGE_1D_ARRAY 0x9052
+# define GL_IMAGE_2D_ARRAY 0x9053
+# define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+# define GL_IMAGE_2D_MULTISAMPLE 0x9055
+# define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+# define GL_INT_IMAGE_1D 0x9057
+# define GL_INT_IMAGE_2D 0x9058
+# define GL_INT_IMAGE_3D 0x9059
+# define GL_INT_IMAGE_2D_RECT 0x905A
+# define GL_INT_IMAGE_CUBE 0x905B
+# define GL_INT_IMAGE_BUFFER 0x905C
+# define GL_INT_IMAGE_1D_ARRAY 0x905D
+# define GL_INT_IMAGE_2D_ARRAY 0x905E
+# define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+# define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+# define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+# define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+# define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+# define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+# define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+# define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+# define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+# define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+# define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+# define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+# define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+# define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
# endif
QT_BEGIN_NAMESPACE
@@ -433,6 +466,11 @@ void GraphicsHelperGL4::deleteSync(void *sync)
m_funcs->glDeleteSync(static_cast<GLsync>(sync));
}
+void GraphicsHelperGL4::rasterMode(GLenum faceMode, GLenum rasterMode)
+{
+ m_funcs->glPolygonMode(faceMode, rasterMode);
+}
+
void GraphicsHelperGL4::glUniform1fv(GLint location, GLsizei count, const GLfloat *values)
{
m_funcs->glUniform1fv(location, count, values);
@@ -630,6 +668,42 @@ UniformType GraphicsHelperGL4::uniformTypeFromGLType(GLenum type)
case GL_UNSIGNED_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY:
return UniformType::Sampler;
+
+ case GL_IMAGE_1D:
+ case GL_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_IMAGE_2D_RECT:
+ case GL_IMAGE_CUBE:
+ case GL_IMAGE_BUFFER:
+ case GL_IMAGE_1D_ARRAY:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE_MAP_ARRAY:
+ case GL_IMAGE_2D_MULTISAMPLE:
+ case GL_IMAGE_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_IMAGE_1D:
+ case GL_INT_IMAGE_2D:
+ case GL_INT_IMAGE_3D:
+ case GL_INT_IMAGE_2D_RECT:
+ case GL_INT_IMAGE_CUBE:
+ case GL_INT_IMAGE_BUFFER:
+ case GL_INT_IMAGE_1D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_INT_IMAGE_2D_MULTISAMPLE:
+ case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_1D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_2D_RECT:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_BUFFER:
+ case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
+ return UniformType::Image;
+
default:
// TO DO: Add support for Doubles and Images
Q_UNREACHABLE();
@@ -668,6 +742,11 @@ void GraphicsHelperGL4::depthMask(GLenum mode)
m_funcs->glDepthMask(mode);
}
+void GraphicsHelperGL4::depthRange(GLdouble nearValue, GLdouble farValue)
+{
+ m_funcs->glDepthRange(nearValue, farValue);
+}
+
void GraphicsHelperGL4::frontFace(GLenum mode)
{
m_funcs->glFrontFace(mode);
@@ -714,6 +793,19 @@ void GraphicsHelperGL4::bindFrameBufferObject(GLuint frameBufferId, FBOBindMode
}
}
+void GraphicsHelperGL4::bindImageTexture(GLuint imageUnit, GLuint texture,
+ GLint mipLevel, GLboolean layered,
+ GLint layer, GLenum access, GLenum format)
+{
+ m_funcs->glBindImageTexture(imageUnit,
+ texture,
+ mipLevel,
+ layered,
+ layer,
+ access,
+ format);
+}
+
GLuint GraphicsHelperGL4::boundFrameBufferObject()
{
GLint id = 0;
@@ -781,6 +873,7 @@ bool GraphicsHelperGL4::supportsFeature(GraphicsHelperInterface::Feature feature
case IndirectDrawing:
case MapBuffer:
case Fences:
+ case ShaderImage:
return true;
default:
return false;
@@ -1009,7 +1102,40 @@ void GraphicsHelperGL4::buildUniformBuffer(const QVariant &v, const ShaderUnifor
case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
- case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: {
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_IMAGE_1D:
+ case GL_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_IMAGE_2D_RECT:
+ case GL_IMAGE_CUBE:
+ case GL_IMAGE_BUFFER:
+ case GL_IMAGE_1D_ARRAY:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE_MAP_ARRAY:
+ case GL_IMAGE_2D_MULTISAMPLE:
+ case GL_IMAGE_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_IMAGE_1D:
+ case GL_INT_IMAGE_2D:
+ case GL_INT_IMAGE_3D:
+ case GL_INT_IMAGE_2D_RECT:
+ case GL_INT_IMAGE_CUBE:
+ case GL_INT_IMAGE_BUFFER:
+ case GL_INT_IMAGE_1D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_INT_IMAGE_2D_MULTISAMPLE:
+ case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_1D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_2D_RECT:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_BUFFER:
+ case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY: {
Q_ASSERT(description.m_size == 1);
int value = v.toInt();
QGraphicsUtils::fillDataArray<GLint>(bufferData, &value, description, 1);
@@ -1139,8 +1265,47 @@ uint GraphicsHelperGL4::uniformByteSize(const ShaderUniform &description)
case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_IMAGE_1D:
+ case GL_IMAGE_2D:
+ case GL_IMAGE_3D:
+ case GL_IMAGE_2D_RECT:
+ case GL_IMAGE_CUBE:
+ case GL_IMAGE_BUFFER:
+ case GL_IMAGE_1D_ARRAY:
+ case GL_IMAGE_2D_ARRAY:
+ case GL_IMAGE_CUBE_MAP_ARRAY:
+ case GL_IMAGE_2D_MULTISAMPLE:
+ case GL_IMAGE_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_IMAGE_1D:
+ case GL_INT_IMAGE_2D:
+ case GL_INT_IMAGE_3D:
+ case GL_INT_IMAGE_2D_RECT:
+ case GL_INT_IMAGE_CUBE:
+ case GL_INT_IMAGE_BUFFER:
+ case GL_INT_IMAGE_1D_ARRAY:
+ case GL_INT_IMAGE_2D_ARRAY:
+ case GL_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_INT_IMAGE_2D_MULTISAMPLE:
+ case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_1D:
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ case GL_UNSIGNED_INT_IMAGE_3D:
+ case GL_UNSIGNED_INT_IMAGE_2D_RECT:
+ case GL_UNSIGNED_INT_IMAGE_CUBE:
+ case GL_UNSIGNED_INT_IMAGE_BUFFER:
+ case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY:
+ case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
rawByteSize = 4;
break;
+
+ default: {
+ qWarning() << Q_FUNC_INFO << "unable to deduce rawByteSize for uniform type:" << description.m_type << "for uniform" << description.m_name;
+ break;
+ }
+
}
return arrayStride ? rawByteSize * arrayStride : rawByteSize;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h
index da62f4212..d3ce0d079 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h
@@ -76,6 +76,7 @@ public:
void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) override;
void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) override;
void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) override;
+ void bindImageTexture(GLuint imageUnit, GLuint texture, GLint mipLevel, GLboolean layered, GLint layer, GLenum access, GLenum format) override;
void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) override;
void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
void blendEquation(GLenum mode) override;
@@ -88,6 +89,7 @@ public:
void clearBufferf(GLint drawbuffer, const QVector4D &values) override;
GLuint createFrameBufferObject() override;
void depthMask(GLenum mode) override;
+ void depthRange(GLdouble nearValue, GLdouble farValue) override;
void depthTest(GLenum mode) override;
void disableClipPlane(int clipPlane) override;
void disablei(GLenum cap, GLuint index) override;
@@ -131,6 +133,7 @@ public:
void vertexAttributePointer(GLenum shaderDataType, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) override;
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void rasterMode(GLenum faceMode, GLenum rasterMode) override;
void *fenceSync() override;
void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h
index 2a1688b7f..21146c32b 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h
@@ -83,7 +83,8 @@ public:
BlitFramebuffer,
IndirectDrawing,
MapBuffer,
- Fences
+ Fences,
+ ShaderImage
};
enum FBOBindMode {
@@ -100,6 +101,7 @@ public:
virtual void bindFrameBufferAttachment(QOpenGLTexture *texture, const Attachment &attachment) = 0;
virtual void bindFrameBufferAttachment(RenderBuffer *renderBuffer, const Attachment &attachment) = 0;
virtual void bindFrameBufferObject(GLuint frameBufferId, FBOBindMode mode) = 0;
+ virtual void bindImageTexture(GLuint imageUnit, GLuint texture, GLint mipLevel, GLboolean layered, GLint layer, GLenum access, GLenum format) = 0;
virtual void bindShaderStorageBlock(GLuint programId, GLuint shaderStorageBlockIndex, GLuint shaderStorageBlockBinding) = 0;
virtual void bindUniformBlock(GLuint programId, GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0;
virtual void blendEquation(GLenum mode) = 0;
@@ -111,6 +113,7 @@ public:
virtual bool checkFrameBufferComplete() = 0;
virtual void clearBufferf(GLint drawbuffer, const QVector4D &values) = 0;
virtual GLuint createFrameBufferObject() = 0;
+ virtual void depthRange(GLdouble nearValue, GLdouble farValue) = 0;
virtual void depthMask(GLenum mode) = 0;
virtual void depthTest(GLenum mode) = 0;
virtual void disableClipPlane(int clipPlane) = 0;
@@ -155,6 +158,7 @@ public:
virtual void vertexAttributePointer(GLenum shaderDataType, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) = 0;
virtual void readBuffer(GLenum mode) = 0;
virtual void drawBuffer(GLenum mode) = 0;
+ virtual void rasterMode(GLenum faceMode, GLenum rasterMode) = 0;
virtual void *fenceSync() = 0;
virtual void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) = 0;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri b/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri
index ad08038c9..f2f7274d7 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri
@@ -14,6 +14,7 @@ HEADERS += \
$$PWD/graphicshelpergl3_3_p.h \
$$PWD/graphicshelpergl4_p.h \
$$PWD/graphicshelpergl3_2_p.h \
+ $$PWD/imagesubmissioncontext_p.h \
$$PWD/submissioncontext_p.h \
$$PWD/texturesubmissioncontext_p.h
@@ -27,5 +28,6 @@ SOURCES += \
$$PWD/graphicshelpergl3_3.cpp \
$$PWD/graphicshelpergl4.cpp \
$$PWD/graphicshelpergl3_2.cpp \
+ $$PWD/imagesubmissioncontext.cpp \
$$PWD/submissioncontext.cpp \
$$PWD/texturesubmissioncontext.cpp
diff --git a/src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext.cpp
new file mode 100644
index 000000000..ca600f994
--- /dev/null
+++ b/src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "imagesubmissioncontext_p.h"
+#include <Qt3DRender/private/graphicscontext_p.h>
+#include <Qt3DRender/private/gltexture_p.h>
+#include <Qt3DRender/private/shaderimage_p.h>
+#include <Qt3DRender/qshaderimage.h>
+
+QT_BEGIN_NAMESPACE
+
+// ES 3.1+ or GL 4.2+
+#ifndef GL_READ_ONLY
+#define GL_READ_ONLY 0x88B8
+#endif
+#ifndef GL_WRITE_ONLY
+#define GL_WRITE_ONLY 0x88B9
+#endif
+#ifndef GL_READ_WRITE
+#define GL_READ_WRITE 0x88BA
+#endif
+
+namespace Qt3DRender {
+namespace Render {
+
+class GraphicsContext;
+class GLTexture;
+
+namespace {
+
+GLenum glAccessEnumForShaderImageAccess(QShaderImage::Access access)
+{
+ switch (access) {
+ case QShaderImage::ReadOnly:
+ return GL_READ_ONLY;
+ case QShaderImage::WriteOnly:
+ return GL_WRITE_ONLY;
+ case QShaderImage::ReadWrite:
+ default:
+ break;
+ }
+ return GL_READ_WRITE;
+}
+
+GLenum glImageFormatToGL(QShaderImage::ImageFormat format)
+{
+ // Right now we can abuse from the fact that the ImageFormat enum values
+ // have been assigned the same value as the GL enum
+ return GLenum(format);
+}
+
+GLenum glImageFormatForShaderImageFormat(QShaderImage::ImageFormat format,
+ QAbstractTexture::TextureFormat textureFormat)
+{
+ Q_ASSERT_X(format != QShaderImage::NoFormat, Q_FUNC_INFO, "Valid image format or Automatic expected");
+
+ if (format != QShaderImage::Automatic)
+ return glImageFormatToGL(format);
+
+ // Otherwise try to mind to best texture format
+ switch (textureFormat) {
+ case QAbstractTexture::R8_UNorm:
+ return glImageFormatToGL(QShaderImage::R8_UNorm);
+ case QAbstractTexture::RG8_UNorm:
+ return glImageFormatToGL(QShaderImage::RG8_UNorm);
+ case QAbstractTexture::RGBA8_UNorm:
+ return glImageFormatToGL(QShaderImage::RGBA8_UNorm);
+
+ case QAbstractTexture::R16_UNorm:
+ return glImageFormatToGL(QShaderImage::R16_UNorm);
+ case QAbstractTexture::RG16_UNorm:
+ return glImageFormatToGL(QShaderImage::RG16_UNorm);
+ case QAbstractTexture::RGBA16_UNorm:
+ return glImageFormatToGL(QShaderImage::RGBA16_UNorm);
+
+ case QAbstractTexture::R8_SNorm:
+ return glImageFormatToGL(QShaderImage::R8_SNorm);
+ case QAbstractTexture::RG8_SNorm:
+ return glImageFormatToGL(QShaderImage::RG8_SNorm);
+ case QAbstractTexture::RGBA8_SNorm:
+ return glImageFormatToGL(QShaderImage::RGBA8_SNorm);
+
+ case QAbstractTexture::R16_SNorm:
+ return glImageFormatToGL(QShaderImage::R16_SNorm);
+ case QAbstractTexture::RG16_SNorm:
+ return glImageFormatToGL(QShaderImage::RG16_SNorm);
+ case QAbstractTexture::RGBA16_SNorm:
+ return glImageFormatToGL(QShaderImage::RGBA16_SNorm);
+
+ case QAbstractTexture::R8U:
+ return glImageFormatToGL(QShaderImage::R8U);
+ case QAbstractTexture::RG8U:
+ return glImageFormatToGL(QShaderImage::RG8U);
+ case QAbstractTexture::RGBA8U:
+ return glImageFormatToGL(QShaderImage::RGBA8U);
+
+ case QAbstractTexture::R16U:
+ return glImageFormatToGL(QShaderImage::R16U);
+ case QAbstractTexture::RG16U:
+ return glImageFormatToGL(QShaderImage::RG16U);
+ case QAbstractTexture::RGBA16U:
+ return glImageFormatToGL(QShaderImage::RGBA16U);
+
+ case QAbstractTexture::R32U:
+ return glImageFormatToGL(QShaderImage::R32U);
+ case QAbstractTexture::RG32U:
+ return glImageFormatToGL(QShaderImage::RG32U);
+ case QAbstractTexture::RGBA32U:
+ return glImageFormatToGL(QShaderImage::RGBA32U);
+
+ case QAbstractTexture::R8I:
+ return glImageFormatToGL(QShaderImage::R8I);
+ case QAbstractTexture::RG8I:
+ return glImageFormatToGL(QShaderImage::RG8I);
+ case QAbstractTexture::RGBA8I:
+ return glImageFormatToGL(QShaderImage::RGBA8I);
+
+ case QAbstractTexture::R16I:
+ return glImageFormatToGL(QShaderImage::R16I);
+ case QAbstractTexture::RG16I:
+ return glImageFormatToGL(QShaderImage::RG16I);
+ case QAbstractTexture::RGBA16I:
+ return glImageFormatToGL(QShaderImage::RGBA16I);
+
+ case QAbstractTexture::R32I:
+ return glImageFormatToGL(QShaderImage::R32I);
+ case QAbstractTexture::RG32I:
+ return glImageFormatToGL(QShaderImage::RG32I);
+ case QAbstractTexture::RGBA32I:
+ return glImageFormatToGL(QShaderImage::RGBA32I);
+
+ case QAbstractTexture::R16F:
+ return glImageFormatToGL(QShaderImage::R16F);
+ case QAbstractTexture::RG16F:
+ return glImageFormatToGL(QShaderImage::RG16F);
+ case QAbstractTexture::RGBA16F:
+ return glImageFormatToGL(QShaderImage::RGBA16F);
+
+ case QAbstractTexture::R32F:
+ return glImageFormatToGL(QShaderImage::R32F);
+ case QAbstractTexture::RG32F:
+ return glImageFormatToGL(QShaderImage::RG32F);
+ case QAbstractTexture::RGBA32F:
+ return glImageFormatToGL(QShaderImage::RGBA32F);
+
+ case QAbstractTexture::RG11B10F:
+ return glImageFormatToGL(QShaderImage::RG11B10F);
+ case QAbstractTexture::RGB10A2:
+ return glImageFormatToGL(QShaderImage::RGB10A2);
+ case QAbstractTexture::RGB10A2U:
+ return glImageFormatToGL(QShaderImage::RGB10A2U);
+
+ default:
+ qWarning() << "Cannot map Texture format" << textureFormat << "to a valid Image Format";
+ Q_UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+} // anonymous
+
+ImageSubmissionContext::ImageSubmissionContext()
+ : m_ctx(nullptr)
+{
+}
+
+void ImageSubmissionContext::initialize(GraphicsContext *context)
+{
+ m_ctx = context;
+ m_activeImages.resize(m_ctx->maxImageUnitsCount());
+}
+
+void ImageSubmissionContext::endDrawing()
+{
+ // Reduce score of all active Images
+ decayImageScores();
+}
+
+// Return Image Unit for Image
+// If Image was used previously and recently, it will return the last used unit
+// for that image. Otherwise it will try to return the image unit the least used.
+int ImageSubmissionContext::activateImage(ShaderImage *image, GLTexture *tex)
+{
+ const int onUnit = assignUnitForImage(image->peerId());
+
+ if (onUnit < 0) {
+ qWarning() << "Unable to find available image unit";
+ return -1;
+ }
+
+ QOpenGLTexture *glTex = tex->getGLTexture();
+ if (glTex == nullptr) {
+ qWarning() << "Unable to retrieve valid texture for Image";
+ return -1;
+ }
+
+ // Bind Image against Texture and resolve Image Format
+ m_ctx->bindImageTexture(onUnit,
+ glTex->textureId(),
+ image->mipLevel(),
+ image->layered(),
+ image->layer(),
+ glAccessEnumForShaderImageAccess(image->access()),
+ glImageFormatForShaderImageFormat(image->format(),
+ tex->properties().format));
+
+ // Store information about the Texture/Image on ActiveImage for given
+ // image unit
+ m_activeImages[onUnit].shaderImageId = image->peerId();
+ m_activeImages[onUnit].texture = tex;
+ m_activeImages[onUnit].score = 200;
+ m_activeImages[onUnit].pinned = true;
+
+ return onUnit;
+}
+
+// Unset pinned Active Image and reduce their score
+void ImageSubmissionContext::deactivateImages()
+{
+ for (int u = 0, m = m_activeImages.size(); u < m; ++u) {
+ if (m_activeImages[u].pinned) {
+ m_activeImages[u].pinned = false;
+ m_activeImages[u].score = qMax(m_activeImages[u].score - 1, 0);
+ return;
+ }
+ }
+}
+
+// Reduce score of all active images (pinned or not)
+void ImageSubmissionContext::decayImageScores()
+{
+ for (int u = 0, m = m_activeImages.size(); u < m; ++u)
+ m_activeImages[u].score = qMax(m_activeImages[u].score - 1, 0);
+}
+
+int ImageSubmissionContext::assignUnitForImage(Qt3DCore::QNodeId shaderImageId)
+{
+ int lowestScoredUnit = -1;
+ int lowestScore = 0xfffffff;
+
+ const int m = m_activeImages.size();
+ for (int u = 0; u < m; ++u) {
+ if (m_activeImages[u].shaderImageId == shaderImageId)
+ return u;
+ }
+
+ for (int u = 0; u < m; ++u) {
+ // No image is currently active on the image unit
+ // we save the image unit with the texture that has been on there
+ // the longest time while not being used
+ if (!m_activeImages[u].pinned) {
+ const int score = m_activeImages[u].score;
+ if (score < lowestScore) {
+ lowestScore = score;
+ lowestScoredUnit = u;
+ }
+ }
+ }
+
+ if (lowestScoredUnit == -1)
+ qCWarning(Backend) << Q_FUNC_INFO << "No free image units!";
+
+ return lowestScoredUnit;
+}
+
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/jobs/loadtexturedatajob_p.h b/src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext_p.h
index 607068712..6d39f469b 100644
--- a/src/render/jobs/loadtexturedatajob_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DRENDER_RENDER_LOADTEXTUREDATAJOB_H
-#define QT3DRENDER_RENDER_LOADTEXTUREDATAJOB_H
+#ifndef QT3DRENDER_RENDER_IMAGESUBMISSIONCONTEXT_P_H
+#define QT3DRENDER_RENDER_IMAGESUBMISSIONCONTEXT_P_H
//
// W A R N I N G
@@ -51,44 +51,45 @@
// We mean it.
//
-#include <Qt3DCore/qnodeid.h>
-#include <Qt3DCore/qaspectjob.h>
-#include <Qt3DRender/qtexturegenerator.h>
-#include <Qt3DRender/qtextureimagedatagenerator.h>
+#include <Qt3DCore/QNodeId>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-
namespace Render {
-class NodeManagers;
+class GraphicsContext;
+class GLTexture;
+class ShaderImage;
-class LoadTextureDataJob : public Qt3DCore::QAspectJob
+class Q_AUTOTEST_EXPORT ImageSubmissionContext
{
public:
- LoadTextureDataJob(const QTextureGeneratorPtr &texGen);
- LoadTextureDataJob(const QTextureImageDataGeneratorPtr &imgDataGen);
- ~LoadTextureDataJob();
-
- inline void setNodeManagers(NodeManagers *manager) { m_manager = manager; }
+ ImageSubmissionContext();
-protected:
- void run() final;
+ void initialize(GraphicsContext *context);
+ void endDrawing();
+ int activateImage(ShaderImage *image, GLTexture *tex);
+ void deactivateImages();
private:
- QTextureGeneratorPtr m_texGen;
- QTextureImageDataGeneratorPtr m_imgDataGen;
-
- NodeManagers *m_manager;
+ void decayImageScores();
+ int assignUnitForImage(Qt3DCore::QNodeId shaderImageId);
+
+ struct ActiveImage
+ {
+ Qt3DCore::QNodeId shaderImageId;
+ GLTexture *texture = nullptr;
+ int score = 0;
+ bool pinned = false;
+ };
+ QVector<ActiveImage> m_activeImages;
+ GraphicsContext *m_ctx;
};
-typedef QSharedPointer<LoadTextureDataJob> LoadTextureDataJobPtr;
-
} // namespace Render
-
} // namespace Qt3DRender
QT_END_NAMESPACE
-#endif // QT3DRENDER_RENDER_LOADTEXTUREDATAJOB_H
+#endif // QT3DRENDER_RENDER_IMAGESUBMISSIONCONTEXT_P_H
diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
index 73393d78b..47779dded 100644
--- a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
@@ -212,6 +212,12 @@ void applyStateHelper<MSAAEnabled>(const MSAAEnabled *state, SubmissionContext *
gc->setMSAAEnabled(std::get<0>(state->values()));
}
+template<>
+void applyStateHelper<DepthRange>(const DepthRange *state, SubmissionContext *gc)
+{
+ const auto values = state->values();
+ gc->depthRange(std::get<0>(values), std::get<1>(values));
+}
template<>
void applyStateHelper<DepthTest>(const DepthTest *state, SubmissionContext *gc)
@@ -219,6 +225,11 @@ void applyStateHelper<DepthTest>(const DepthTest *state, SubmissionContext *gc)
gc->depthTest(std::get<0>(state->values()));
}
+template<>
+void applyStateHelper<RasterMode>(const RasterMode *state, SubmissionContext *gc)
+{
+ gc->rasterMode(std::get<0>(state->values()), std::get<1>(state->values()));
+}
template<>
void applyStateHelper<NoDepthMask>(const NoDepthMask *state, SubmissionContext *gc)
@@ -226,7 +237,6 @@ void applyStateHelper<NoDepthMask>(const NoDepthMask *state, SubmissionContext *
gc->depthMask(std::get<0>(state->values()));
}
-
template<>
void applyStateHelper<CullFace>(const CullFace *state, SubmissionContext *gc)
{
@@ -379,6 +389,7 @@ void SubmissionContext::initialize()
{
GraphicsContext::initialize();
m_textureContext.initialize(this);
+ m_imageContext.initialize(this);
}
void SubmissionContext::resolveRenderTargetFormat()
@@ -469,6 +480,7 @@ void SubmissionContext::endDrawing(bool swapBuffers)
if (m_ownCurrent)
m_gl->doneCurrent();
m_textureContext.endDrawing();
+ m_imageContext.endDrawing();
}
void SubmissionContext::activateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments, GLuint defaultFboId)
@@ -526,9 +538,9 @@ GLuint SubmissionContext::updateRenderTarget(Qt3DCore::QNodeId renderTargetNodeI
// ### TODO QTBUG-64757 this check is insufficient since the
// texture may have changed to another one with the same size. That
// case is not handled atm.
- needsResize |= (rTex != nullptr && rTex->size() != s);
- if (isActiveRenderTarget) {
- if (attachment.m_point == QRenderTargetOutput::Color0)
+ if (rTex) {
+ needsResize |= rTex->size() != s;
+ if (isActiveRenderTarget && attachment.m_point == QRenderTargetOutput::Color0)
m_renderTargetFormat = rTex->properties().format;
}
}
@@ -675,8 +687,8 @@ QImage SubmissionContext::readFramebuffer(const QRect &rect)
GLint samples = 0;
m_gl->functions()->glGetIntegerv(GL_SAMPLES, &samples);
if (samples > 0 && !m_glHelper->supportsFeature(GraphicsHelperInterface::BlitFramebuffer)) {
- qWarning () << Q_FUNC_INFO << "Unable to capture multisampled framebuffer; "
- "Required feature BlitFramebuffer is missing.";
+ qCWarning(Backend) << Q_FUNC_INFO << "Unable to capture multisampled framebuffer; "
+ "Required feature BlitFramebuffer is missing.";
return img;
}
@@ -699,7 +711,7 @@ QImage SubmissionContext::readFramebuffer(const QRect &rect)
if (status != GL_FRAMEBUFFER_COMPLETE) {
gl->glDeleteRenderbuffers(1, &rb);
gl->glDeleteFramebuffers(1, &fbo);
- qWarning () << Q_FUNC_INFO << "Copy-framebuffer not complete: " << status;
+ qCWarning(Backend) << Q_FUNC_INFO << "Copy-framebuffer not complete: " << status;
return img;
}
@@ -785,7 +797,7 @@ bool SubmissionContext::activateShader(ProgramDNA shaderDNA)
m_activeShaderDNA = shaderDNA;
} else {
m_glHelper->useProgram(0);
- qWarning() << "No shader program found for DNA";
+ qCWarning(Backend) << "No shader program found for DNA";
m_activeShaderDNA = 0;
return false;
}
@@ -843,7 +855,7 @@ void SubmissionContext::activateDrawBuffers(const AttachmentPack &attachments)
}
}
} else {
- qWarning() << "FBO incomplete";
+ qCWarning(Backend) << "FBO incomplete";
}
}
@@ -854,6 +866,7 @@ void SubmissionContext::setActiveMaterial(Material *rmat)
return;
m_textureContext.deactivateTexturesWithScope(TextureSubmissionContext::TextureScopeMaterial);
+ m_imageContext.deactivateImages();
m_material = rmat;
}
@@ -911,6 +924,16 @@ void SubmissionContext::applyState(const StateVariant &stateVariant)
break;
}
+ case DepthRangeMask: {
+ applyStateHelper<DepthRange>(static_cast<const DepthRange *>(stateVariant.constState()), this);
+ break;
+ }
+
+ case RasterModeMask: {
+ applyStateHelper<RasterMode>(static_cast<const RasterMode *>(stateVariant.constState()), this);
+ break;
+ }
+
case FrontFaceStateMask: {
applyStateHelper<FrontFace>(static_cast<const FrontFace *>(stateVariant.constState()), this);
break;
@@ -993,6 +1016,9 @@ void SubmissionContext::resetMasked(qint64 maskOfStatesToReset)
if (maskOfStatesToReset & StencilTestStateMask)
funcs->glDisable(GL_STENCIL_TEST);
+ if (maskOfStatesToReset & DepthRangeMask)
+ depthRange(0.0f, 1.0f);
+
if (maskOfStatesToReset & DepthTestStateMask)
funcs->glDisable(GL_DEPTH_TEST);
@@ -1034,6 +1060,11 @@ void SubmissionContext::resetMasked(qint64 maskOfStatesToReset)
if (maskOfStatesToReset & LineWidthMask)
funcs->glLineWidth(1.0f);
+
+#ifndef QT_OPENGL_ES_2
+ if (maskOfStatesToReset & RasterModeMask)
+ m_glHelper->rasterMode(GL_FRONT_AND_BACK, GL_FILL);
+#endif
}
void SubmissionContext::applyStateSet(RenderStateSet *ss)
@@ -1132,13 +1163,15 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
// Update the uniforms with the correct texture unit id's
PackUniformHash &uniformValues = parameterPack.uniforms();
+ // Fill Texture Uniform Value with proper texture units
+ // so that they can be applied as regular uniforms in a second step
for (int i = 0; i < parameterPack.textures().size(); ++i) {
- const ShaderParameterPack::NamedTexture &namedTex = parameterPack.textures().at(i);
+ const ShaderParameterPack::NamedResource &namedTex = parameterPack.textures().at(i);
// Given a Texture QNodeId, we retrieve the associated shared GLTexture
if (uniformValues.contains(namedTex.glslNameId)) {
- GLTexture *t = manager->glTextureManager()->lookupResource(namedTex.texId);
+ GLTexture *t = manager->glTextureManager()->lookupResource(namedTex.nodeId);
if (t != nullptr) {
- UniformValue &texUniform = uniformValues[namedTex.glslNameId];
+ UniformValue &texUniform = uniformValues.value(namedTex.glslNameId);
if (texUniform.valueType() == UniformValue::TextureValue) {
const int texUnit = m_textureContext.activateTexture(TextureSubmissionContext::TextureScopeMaterial, m_gl, t);
texUniform.data<int>()[namedTex.uniformArrayIndex] = texUnit;
@@ -1146,6 +1179,34 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
if (namedTex.glslNameId != irradianceId &&
namedTex.glslNameId != specularId) {
// Only return false if we are not dealing with env light textures
+ qCWarning(Backend) << "Unable to find suitable Texture Unit";
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Fill Image Uniform Value with proper image units
+ // so that they can be applied as regular uniforms in a second step
+ for (int i = 0; i < parameterPack.images().size(); ++i) {
+ const ShaderParameterPack::NamedResource &namedTex = parameterPack.images().at(i);
+ // Given a Texture QNodeId, we retrieve the associated shared GLTexture
+ if (uniformValues.contains(namedTex.glslNameId)) {
+ ShaderImage *img = manager->shaderImageManager()->lookupResource(namedTex.nodeId);
+ if (img != nullptr) {
+ GLTexture *t = manager->glTextureManager()->lookupResource(img->textureId());
+ if (t == nullptr) {
+ qCWarning(Backend) << "Shader Image referencing invalid texture";
+ continue;
+ } else {
+ UniformValue &imgUniform = uniformValues.value(namedTex.glslNameId);
+ if (imgUniform.valueType() == UniformValue::ShaderImageValue) {
+ const int imgUnit = m_imageContext.activateImage(img, t);
+ imgUniform.data<int>()[namedTex.uniformArrayIndex] = imgUnit;
+ if (imgUnit == -1) {
+ qCWarning(Backend) << "Unable to bind Image to Texture";
return false;
}
}
@@ -1199,10 +1260,12 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
for (const ShaderUniform &uniform : activeUniforms) {
// We can use [] as we are sure the the uniform wouldn't
// be un activeUniforms if there wasn't a matching value
- const UniformValue &v = values[uniform.m_nameId];
+ const UniformValue &v = values.value(uniform.m_nameId);
- // skip invalid textures
- if (v.valueType() == UniformValue::TextureValue && *v.constData<int>() == -1)
+ // skip invalid textures/images
+ if ((v.valueType() == UniformValue::TextureValue ||
+ v.valueType() == UniformValue::ShaderImageValue) &&
+ *v.constData<int>() == -1)
continue;
applyUniform(uniform, v);
diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h b/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h
index 844e62f15..a8700dd3a 100644
--- a/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h
@@ -55,6 +55,7 @@
#include <Qt3DRender/private/graphicscontext_p.h>
#include <Qt3DRender/private/texturesubmissioncontext_p.h>
+#include <Qt3DRender/private/imagesubmissioncontext_p.h>
#include <Qt3DRender/qclearbuffers.h>
#include <Qt3DRender/private/glbuffer_p.h>
#include <Qt3DRender/qattribute.h>
@@ -204,6 +205,7 @@ private:
QByteArray m_uboTempArray;
TextureSubmissionContext m_textureContext;
+ ImageSubmissionContext m_imageContext;
// Attributes
friend class OpenGLVertexArrayObject;
diff --git a/src/render/renderers/opengl/jobs/jobs.pri b/src/render/renderers/opengl/jobs/jobs.pri
index 021cd3242..d80b8bfd9 100644
--- a/src/render/renderers/opengl/jobs/jobs.pri
+++ b/src/render/renderers/opengl/jobs/jobs.pri
@@ -3,13 +3,15 @@ INCLUDEPATH += $$PWD
SOURCES += \
$$PWD/filtercompatibletechniquejob.cpp \
$$PWD/materialparametergathererjob.cpp \
- $$PWD/renderviewbuilderjob.cpp \
+ $$PWD/renderviewcommandbuilderjob.cpp \
+ $$PWD/renderviewcommandupdaterjob.cpp \
$$PWD/renderviewinitializerjob.cpp \
$$PWD/renderviewjobutils.cpp
HEADERS += \
$$PWD/filtercompatibletechniquejob_p.h \
$$PWD/materialparametergathererjob_p.h \
- $$PWD/renderviewbuilderjob_p.h \
+ $$PWD/renderviewcommandbuilderjob_p.h \
+ $$PWD/renderviewcommandupdaterjob_p.h \
$$PWD/renderviewinitializerjob_p.h \
$$PWD/renderviewjobutils_p.h
diff --git a/src/render/jobs/updateentityhierarchyjob.cpp b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp
index 7c18514bb..c6bc20423 100644
--- a/src/render/jobs/updateentityhierarchyjob.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp
@@ -37,11 +37,9 @@
**
****************************************************************************/
-#include "updateentityhierarchyjob_p.h"
-#include <Qt3DRender/private/managers_p.h>
-#include <Qt3DRender/private/nodemanagers_p.h>
-#include <Qt3DRender/private/entity_p.h>
+#include "renderviewcommandbuilderjob_p.h"
#include <Qt3DRender/private/job_common_p.h>
+#include <Qt3DRender/private/renderview_p.h>
QT_BEGIN_NAMESPACE
@@ -49,27 +47,25 @@ namespace Qt3DRender {
namespace Render {
-UpdateEntityHierarchyJob::UpdateEntityHierarchyJob()
- : m_manager(nullptr)
+namespace {
+int renderViewInstanceCounter = 0;
+} // anonymous
+
+RenderViewCommandBuilderJob::RenderViewCommandBuilderJob()
+ : Qt3DCore::QAspectJob()
+ , m_renderView(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::UpdateEntityHierarchy, 0);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderViewCommandBuilder, renderViewInstanceCounter++)
}
-void UpdateEntityHierarchyJob::run()
+void RenderViewCommandBuilderJob::run()
{
- Q_ASSERT(m_manager);
- EntityManager *entityManager = m_manager->renderNodesManager();
-
- const QVector<HEntity> handles = entityManager->activeHandles();
-
- // Clear the parents and children
- for (const HEntity &handle : handles) {
- Entity *entity = entityManager->data(handle);
- entity->clearEntityHierarchy();
- }
- for (const HEntity &handle : handles) {
- Entity *entity = entityManager->data(handle);
- entity->rebuildEntityHierarchy();
+ if (!m_renderView->noDraw()) {
+ const bool isDraw = !m_renderView->isCompute();
+ if (isDraw)
+ m_commandData = m_renderView->buildDrawRenderCommands(m_entities);
+ else
+ m_commandData = m_renderView->buildComputeRenderCommands(m_entities);
}
}
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
new file mode 100644
index 000000000..9f45a8005
--- /dev/null
+++ b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_RENDERVIEWCOMMANDBUILDERJOB_P_H
+#define QT3DRENDER_RENDER_RENDERVIEWCOMMANDBUILDERJOB_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DCore/qaspectjob.h>
+#include <Qt3DRender/private/handle_types_p.h>
+#include <Qt3DRender/private/rendercommand_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+class Q_AUTOTEST_EXPORT RenderViewCommandBuilderJob : public Qt3DCore::QAspectJob
+{
+public:
+ RenderViewCommandBuilderJob();
+
+ inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; }
+ inline void setEntities(const QVector<Entity *> &entities) { m_entities = entities; }
+ inline EntityRenderCommandData &commandData() { return m_commandData; }
+
+ void run() final;
+
+private:
+ RenderView *m_renderView;
+ QVector<Entity *> m_entities;
+ EntityRenderCommandData m_commandData;
+};
+
+typedef QSharedPointer<RenderViewCommandBuilderJob> RenderViewCommandBuilderJobPtr;
+
+} // Render
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_RENDERVIEWCOMMANDBUILDERJOB_P_H
diff --git a/src/render/renderers/opengl/jobs/renderviewbuilderjob.cpp b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
index fa6218d6f..af1d545ed 100644
--- a/src/render/renderers/opengl/jobs/renderviewbuilderjob.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "renderviewbuilderjob_p.h"
+#include "renderviewcommandupdaterjob_p.h"
#include <Qt3DRender/private/job_common_p.h>
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/renderview_p.h>
@@ -52,50 +52,26 @@ namespace {
int renderViewInstanceCounter = 0;
} // anonymous
-RenderViewBuilderJob::RenderViewBuilderJob()
- : Qt3DCore::QAspectJob(),
- m_renderView(nullptr)
+RenderViewCommandUpdaterJob::RenderViewCommandUpdaterJob()
+ : Qt3DCore::QAspectJob()
+ , m_renderView(nullptr)
+ , m_renderer(nullptr)
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderViewBuilder, renderViewInstanceCounter++);
+ SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderCommandUpdater, renderViewInstanceCounter++);
}
-void RenderViewBuilderJob::run()
+void RenderViewCommandUpdaterJob::run()
{
// Build RenderCommand should perform the culling as we have no way to determine
// if a child has a mesh in the view frustum while its parent isn't contained in it.
if (!m_renderView->noDraw()) {
-#if defined(QT3D_RENDER_VIEW_JOB_TIMINGS)
- gatherLightsTime = timer.nsecsElapsed();
- timer.restart();
-#endif
- if (!m_renderView->isCompute())
- m_commands = m_renderView->buildDrawRenderCommands(m_renderables);
- else
- m_commands = m_renderView->buildComputeRenderCommands(m_renderables);
-#if defined(QT3D_RENDER_VIEW_JOB_TIMINGS)
- buildCommandsTime = timer.nsecsElapsed();
- timer.restart();
-#endif
- }
-
-#if defined(QT3D_RENDER_VIEW_JOB_TIMINGS)
- qint64 creationTime = timer.nsecsElapsed();
- timer.restart();
-#endif
-
-#if defined(QT3D_RENDER_VIEW_JOB_TIMINGS)
- qint64 sortTime = timer.nsecsElapsed();
-#endif
-
-#if defined(QT3D_RENDER_VIEW_JOB_TIMINGS)
- qDebug() << m_index
- << "state:" << gatherStateTime / 1.0e6
- << "lights:" << gatherLightsTime / 1.0e6
- << "build commands:" << buildCommandsTime / 1.0e6
- << "sort:" << sortTime / 1.0e6;
-#endif
-
+ // Update Render Commands (Uniform Change, Depth Change)
+ m_renderView->updateRenderCommand(m_renderables);
+ // Copy commands out of cached -> ensures we can submit them for rendering
+ // while cache is rebuilt or modified for next frame
+ m_commands = m_renderables.commands;
+ }
}
} // Render
diff --git a/src/render/renderers/opengl/jobs/renderviewbuilderjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
index c38f788b0..72caef6cf 100644
--- a/src/render/renderers/opengl/jobs/renderviewbuilderjob_p.h
+++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
@@ -1,4 +1,4 @@
-/****************************************************************************
+/****************************************************************************
**
** Copyright (C) 2016 Paul Lemire
** Contact: https://www.qt.io/licensing/
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DRENDER_RENDER_RENDERVIEWBUILDERJOB_P_H
-#define QT3DRENDER_RENDER_RENDERVIEWBUILDERJOB_P_H
+#ifndef QT3DRENDER_RENDER_RENDERVIEWCOMMANDUPDATEJOB_P_H
+#define QT3DRENDER_RENDER_RENDERVIEWCOMMANDUPDATEJOB_P_H
//
// W A R N I N G
@@ -53,6 +53,7 @@
#include <Qt3DCore/qaspectjob.h>
#include <Qt3DRender/private/handle_types_p.h>
+#include <Qt3DRender/private/rendercommand_p.h>
QT_BEGIN_NAMESPACE
@@ -62,30 +63,28 @@ namespace Render {
class RenderView;
class Renderer;
-class RenderCommand;
-class Q_AUTOTEST_EXPORT RenderViewBuilderJob : public Qt3DCore::QAspectJob
+class Q_AUTOTEST_EXPORT RenderViewCommandUpdaterJob : public Qt3DCore::QAspectJob
{
public:
- RenderViewBuilderJob();
+ RenderViewCommandUpdaterJob();
inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; }
inline void setRenderer(Renderer *renderer) Q_DECL_NOTHROW { m_renderer = renderer; }
- inline void setIndex(int index) Q_DECL_NOTHROW { m_index = index; }
- inline void setRenderables(const QVector<Entity *> &renderables) Q_DECL_NOTHROW { m_renderables = renderables; }
- QVector<RenderCommand *> &commands() Q_DECL_NOTHROW { return m_commands; }
+ inline void setRenderables(const EntityRenderCommandData &renderables) Q_DECL_NOTHROW { m_renderables = renderables; }
+
+ QVector<RenderCommand> &commands() Q_DECL_NOTHROW { return m_commands; }
void run() final;
private:
RenderView *m_renderView;
Renderer *m_renderer;
- int m_index;
- QVector<Entity *> m_renderables;
- QVector<RenderCommand *> m_commands;
+ EntityRenderCommandData m_renderables;
+ QVector<RenderCommand> m_commands;
};
-typedef QSharedPointer<RenderViewBuilderJob> RenderViewBuilderJobPtr;
+typedef QSharedPointer<RenderViewCommandUpdaterJob> RenderViewCommandUpdaterJobPtr;
} // Render
@@ -93,4 +92,4 @@ typedef QSharedPointer<RenderViewBuilderJob> RenderViewBuilderJobPtr;
QT_END_NAMESPACE
-#endif // QT3DRENDER_RENDER_RENDERVIEWBUILDERJOB_P_H
+#endif // QT3DRENDER_RENDER_RENDERVIEWCOMMANDUPDATEJOB_P_H
diff --git a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
index d8f27d1cd..0ceb188fd 100644
--- a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
@@ -180,9 +180,9 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN
break;
}
- case FrameGraphNode::SubtreeSelector:
- // Has no meaning here. SubtreeSelector was used
- // in a prior step to build the list of RenderViewJobs
+ case FrameGraphNode::SubtreeEnabler:
+ // Has no meaning here. SubtreeEnabler was used
+ // in a prior step to filter the list of RenderViewJobs
break;
case FrameGraphNode::StateSet: {
@@ -286,6 +286,10 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN
break;
}
+ case FrameGraphNode::NoPicking:
+ // Nothing to do RenderView wise for NoPicking
+ break;
+
default:
// Should never get here
qCWarning(Backend) << "Unhandled FrameGraphNode type";
@@ -483,7 +487,12 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *
}
}
} else { // Array of scalar/vec qmlPropertyName[0]
- QString varName = blockName + QLatin1String(".") + qmlPropertyName + QLatin1String("[0]");
+ QString varName;
+ varName.reserve(blockName.length() + 1 + qmlPropertyName.length() + 3);
+ varName.append(blockName);
+ varName.append(QLatin1String("."));
+ varName.append(qmlPropertyName);
+ varName.append(QLatin1String("[0]"));
if (uniforms.contains(varName)) {
qCDebug(Shaders) << "UBO array member " << varName << " set for update";
activeUniformNamesToValue.insert(StringToInt::lookupId(varName), value);
@@ -501,34 +510,39 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *
activeUniformNamesToValue.insert(varId, value);
}
} else { // Scalar / Vec
- QString varName = blockName + QLatin1Char('.') + qmlPropertyName;
+ QString varName;
+ varName.reserve(blockName.length() + 1 + qmlPropertyName.length());
+ varName.append(blockName);
+ varName.append(QLatin1String("."));
+ varName.append(qmlPropertyName);
if (uniforms.contains(varName)) {
qCDebug(Shaders) << "UBO scalar member " << varName << " set for update";
// If the property needs to be transformed, we transform it here as
// the shaderdata cannot hold transformed properties for multiple
// thread contexts at once
- if (currentShaderData->propertyTransformType(qmlPropertyName) != ShaderData::NoTransform)
- activeUniformNamesToValue.insert(StringToInt::lookupId(varName),
- currentShaderData->getTransformedProperty(qmlPropertyName, viewMatrix));
- else
- activeUniformNamesToValue.insert(StringToInt::lookupId(varName), value);
+ activeUniformNamesToValue.insert(StringToInt::lookupId(varName),
+ currentShaderData->getTransformedProperty(qmlPropertyName, viewMatrix));
}
}
}
void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName)
{
- const QHash<QString, QVariant> &properties = rShaderData->properties();
- QHash<QString, QVariant>::const_iterator it = properties.begin();
- const QHash<QString, QVariant>::const_iterator end = properties.end();
+ const QHash<QString, ShaderData::PropertyValue> &properties = rShaderData->properties();
+ auto it = properties.begin();
+ const auto end = properties.end();
while (it != end) {
- const auto prefix = qmlPropertyName.isEmpty() ? QLatin1String("") : QLatin1String(".");
- buildActiveUniformNameValueMapHelper(rShaderData,
- blockName + prefix + qmlPropertyName,
- it.key(),
- it.value());
+ QString fullBlockName;
+ fullBlockName.reserve(blockName.length() + 1 + qmlPropertyName.length());
+ fullBlockName.append(blockName);
+ if (!qmlPropertyName.isEmpty()) {
+ fullBlockName.append(QLatin1String("."));
+ fullBlockName.append(qmlPropertyName);
+ }
+ buildActiveUniformNameValueMapHelper(rShaderData, fullBlockName,
+ it.key(), it.value().value);
++it;
}
}
diff --git a/src/render/renderers/opengl/opengl.pri b/src/render/renderers/opengl/opengl.pri
index 22a32d30f..908c23c80 100644
--- a/src/render/renderers/opengl/opengl.pri
+++ b/src/render/renderers/opengl/opengl.pri
@@ -6,9 +6,6 @@ include (textures/textures.pri)
include (graphicshelpers/graphicshelpers.pri)
include (renderstates/renderstates.pri)
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES += QT_NO_FOREACH
-
gcov {
QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
QMAKE_LFLAGS += -fprofile-arcs -ftest-coverage
diff --git a/src/render/renderers/opengl/renderer/commandthread.cpp b/src/render/renderers/opengl/renderer/commandthread.cpp
deleted file mode 100644
index 70ab964d6..000000000
--- a/src/render/renderers/opengl/renderer/commandthread.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "commandthread_p.h"
-#include <Qt3DRender/private/glcommands_p.h>
-#include <Qt3DRender/private/offscreensurfacehelper_p.h>
-#include <Qt3DRender/private/graphicscontext_p.h>
-#include <Qt3DRender/private/shadercache_p.h>
-#include <QOpenGLContext>
-#include <QOffscreenSurface>
-#include <QDebug>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DRender {
-
-namespace Render {
-
-CommandThread::CommandThread(Renderer *renderer)
- : QThread()
- , m_renderer(renderer)
- , m_waitForStartSemaphore(0)
- , m_initializedSemaphore(0)
- , m_commandRequestedSemaphore(0)
- , m_commandExecutionSemaphore(0)
- , m_mainContext(nullptr)
- , m_shaderCache(nullptr)
- , m_offsreenSurfaceHelper(nullptr)
- , m_currentCommand(nullptr)
- , m_running(0)
-{
-}
-
-CommandThread::~CommandThread()
-{
- Q_ASSERT(!isRunning());
-}
-
-void CommandThread::setShaderCache(ShaderCache *shaderCache)
-{
- m_shaderCache = shaderCache;
-}
-
-// Called by RenderThread or MainThread (Scene3d)
-void CommandThread::initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper)
-{
- // Start the thread
- start();
-
- // Wait for thread to be started
- m_waitForStartSemaphore.acquire();
-
- m_mainContext = mainContext;
- m_offsreenSurfaceHelper = offsreenSurfaceHelper;
- Q_ASSERT(m_mainContext && offsreenSurfaceHelper);
-
- // Initialize shared context and resources for the thread. This must be
- // done here since some platforms do not allow context sharing to be set up
- // with contexts created on different threads. (Windows with WGL, in
- // particular; resource sharing works fine later on, what matters is the
- // thread the wglShareLists call is made on)
- m_localContext.reset(new QOpenGLContext());
- m_localContext->setFormat(m_mainContext->format());
- m_localContext->setScreen(m_mainContext->screen());
- m_localContext->setShareContext(m_mainContext);
- if (!m_localContext->create())
- qWarning("CommandThread: Failed to create local context");
- m_localContext->moveToThread(this);
-
- m_running.fetchAndStoreOrdered(1);
-
- // Allow thread to proceed
- m_initializedSemaphore.release();
-}
-
-// Called by RenderThread or MainThread (Scene3D)
-void CommandThread::shutdown()
-{
- m_running.fetchAndStoreOrdered(0);
-
- // Unblock thread
- m_commandRequestedSemaphore.release(1);
-
- // Wait for thread to exit
- wait();
-
- // Reset semaphores (in case we ever want to restart)
- m_waitForStartSemaphore.acquire(m_waitForStartSemaphore.available());
- m_initializedSemaphore.acquire(m_initializedSemaphore.available());
- m_commandRequestedSemaphore.acquire(m_commandRequestedSemaphore.available());
- m_commandExecutionSemaphore.acquire(m_commandExecutionSemaphore.available());
- m_localContext.reset();
-}
-
-// Any thread can call this, this is a blocking command
-void CommandThread::executeCommand(GLCommand *command)
-{
- if (!isRunning())
- return;
-
- // We lock to prevent any other call to executeCommand to be executed
- // before we have received the result of our command
- m_blockingCallerMutex.lock();
-
- // Store command to be executed
- m_currentCommand = command;
-
- // Allow thread to proceed and execute command
- m_commandRequestedSemaphore.release();
-
- // Wait for thread to be done
- m_commandExecutionSemaphore.acquire();
-
- // Reset command
- m_currentCommand = nullptr;
-
- // Unlock blocking semaphore so that other calls to executeCommand
- // can proceed
- m_blockingCallerMutex.unlock();
-}
-
-void CommandThread::run()
-{
- // Allow initialize to proceed
- m_waitForStartSemaphore.release();
-
- // Wait for initialize to be completed
- m_initializedSemaphore.acquire();
-
- Q_ASSERT(m_mainContext && m_shaderCache);
-
- // Initialize GraphicsContext
- m_graphicsContext.reset(new GraphicsContext());
- m_graphicsContext->setShaderCache(m_shaderCache);
- m_graphicsContext->setOpenGLContext(m_localContext.data());
-
- bool initialized = false;
- while (true) {
-
- // Wait for command
- m_commandRequestedSemaphore.acquire();
-
- // Are we still running?
- if (!m_running.load()) {
- m_graphicsContext->doneCurrent();
- // to prevent executeCommand being locked
- m_commandExecutionSemaphore.release();
- break;
- }
-
- if (Q_UNLIKELY(!initialized)) {
- QOffscreenSurface *offscreenSurface = m_offsreenSurfaceHelper->offscreenSurface();
- Q_ASSERT(offscreenSurface);
- m_graphicsContext->makeCurrent(offscreenSurface);
- initialized = true;
- }
-
- m_currentCommand->execute(m_renderer, m_graphicsContext.data());
-
- // Allow caller to proceed as we are done with the command
- m_commandExecutionSemaphore.release();
- }
-}
-
-} // Render
-
-} // Qt3DRender
-
-QT_END_NAMESPACE
diff --git a/src/render/renderers/opengl/renderer/rendercommand.cpp b/src/render/renderers/opengl/renderer/rendercommand.cpp
index e60b17668..072127391 100644
--- a/src/render/renderers/opengl/renderer/rendercommand.cpp
+++ b/src/render/renderers/opengl/renderer/rendercommand.cpp
@@ -48,6 +48,7 @@ RenderCommand::RenderCommand()
: m_stateSet(nullptr)
, m_depth(0.0f)
, m_changeCost(0)
+ , m_shaderDna(0)
, m_type(RenderCommand::Draw)
, m_primitiveCount(0)
, m_primitiveType(QGeometryRenderer::Triangles)
@@ -70,6 +71,20 @@ RenderCommand::RenderCommand()
m_workGroups[2] = 0;
}
+bool operator==(const RenderCommand &a, const RenderCommand &b) noexcept
+{
+ return (a.m_vao == b.m_vao && a.m_shader == b.m_shader && a.m_material == b.m_material &&
+ a.m_stateSet == b.m_stateSet && a.m_geometry == b.m_geometry && a.m_geometryRenderer == b.m_geometryRenderer &&
+ a.m_indirectDrawBuffer == b.m_indirectDrawBuffer && a.m_activeAttributes == b.m_activeAttributes &&
+ a.m_depth == b.m_depth && a.m_changeCost == b.m_changeCost && a.m_shaderDna == b.m_shaderDna &&
+ a.m_workGroups[0] == b.m_workGroups[0] && a.m_workGroups[1] == b.m_workGroups[1] && a.m_workGroups[2] == b.m_workGroups[2] &&
+ a.m_primitiveCount == b.m_primitiveCount && a.m_primitiveType == b.m_primitiveType && a.m_restartIndexValue == b.m_restartIndexValue &&
+ a.m_firstInstance == b.m_firstInstance && a.m_firstVertex == b.m_firstVertex && a.m_verticesPerPatch == b.m_verticesPerPatch &&
+ a.m_instanceCount == b.m_instanceCount && a.m_indexOffset == b.m_indexOffset && a.m_indexAttributeByteOffset == b.m_indexAttributeByteOffset &&
+ a.m_drawIndexed == b.m_drawIndexed && a.m_drawIndirect == b.m_drawIndirect && a.m_primitiveRestartEnabled == b.m_primitiveRestartEnabled &&
+ a.m_isValid == b.m_isValid && a.m_computeCommand == b.m_computeCommand);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/renderer/rendercommand_p.h b/src/render/renderers/opengl/renderer/rendercommand_p.h
index 67e02d35b..0180d6996 100644
--- a/src/render/renderers/opengl/renderer/rendercommand_p.h
+++ b/src/render/renderers/opengl/renderer/rendercommand_p.h
@@ -55,6 +55,7 @@
#include <qglobal.h>
#include <Qt3DRender/private/shaderparameterpack_p.h>
#include <Qt3DRender/private/handle_types_p.h>
+#include <Qt3DRender/private/renderviewjobutils_p.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
@@ -69,6 +70,7 @@ namespace Qt3DRender {
namespace Render {
class RenderStateSet;
+using RenderStateSetPtr = QSharedPointer<RenderStateSet>;
class Q_AUTOTEST_EXPORT RenderCommand
{
@@ -80,16 +82,17 @@ public:
HMaterial m_material; // Purely used to ease sorting (minimize stage changes, binding changes ....)
ShaderParameterPack m_parameterPack; // Might need to be reworked so as to be able to destroy the
// Texture while submission is happening.
- RenderStateSet *m_stateSet;
+ RenderStateSetPtr m_stateSet;
HGeometry m_geometry;
HGeometryRenderer m_geometryRenderer;
HBuffer m_indirectDrawBuffer; // Reference to indirect draw buffer (valid only m_drawIndirect == true)
+ HComputeCommand m_computeCommand;
// A QAttribute pack might be interesting
// This is a temporary fix in the meantime, to remove the hacked methods in Technique
- QVector<int> m_attributes;
+ QVector<int> m_activeAttributes;
float m_depth;
int m_changeCost;
@@ -103,7 +106,7 @@ public:
CommandType m_type;
int m_workGroups[3];
- // Values filled for draw calls
+ // Values filled for draw calls by Renderer (in prepare Submission)
GLsizei m_primitiveCount;
QGeometryRenderer::PrimitiveType m_primitiveType;
int m_restartIndexValue;
@@ -121,6 +124,65 @@ public:
bool m_isValid;
};
+Q_AUTOTEST_EXPORT bool operator==(const RenderCommand &a, const RenderCommand &b) noexcept;
+
+inline bool operator!=(const RenderCommand &lhs, const RenderCommand &rhs) noexcept
+{ return !operator==(lhs, rhs); }
+
+struct EntityRenderCommandData
+{
+ QVector<Entity *> entities;
+ QVector<RenderCommand> commands;
+ QVector<RenderPassParameterData> passesData;
+
+ void reserve(int size)
+ {
+ entities.reserve(size);
+ commands.reserve(size);
+ passesData.reserve(size);
+ }
+
+ inline int size() const { return entities.size(); }
+
+ inline void push_back(Entity *e, const RenderCommand &c, const RenderPassParameterData &p)
+ {
+ entities.push_back(e);
+ commands.push_back(c);
+ passesData.push_back(p);
+ }
+
+ inline void push_back(Entity *e, RenderCommand &&c, RenderPassParameterData &&p)
+ {
+ entities.push_back(e);
+ commands.push_back(std::move(c));
+ passesData.push_back(std::move(p));
+ }
+
+ EntityRenderCommandData &operator+=(const EntityRenderCommandData &t)
+ {
+ entities += t.entities;
+ commands += t.commands;
+ passesData += t.passesData;
+ return *this;
+ }
+
+ EntityRenderCommandData &operator+=(EntityRenderCommandData &&t)
+ {
+ entities += std::move(t.entities);
+ commands += std::move(t.commands);
+ passesData += std::move(t.passesData);
+ return *this;
+ }
+
+ EntityRenderCommandData mid(int idx, int len) const
+ {
+ return { entities.mid(idx, len), commands.mid(idx, len), passesData.mid(idx, len) };
+ }
+
+
+};
+
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index 0a79df501..a530c26b0 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -89,14 +89,16 @@
#include <Qt3DRender/private/buffercapture_p.h>
#include <Qt3DRender/private/offscreensurfacehelper_p.h>
#include <Qt3DRender/private/renderviewbuilder_p.h>
-#include <Qt3DRender/private/commandthread_p.h>
-#include <Qt3DRender/private/glcommands_p.h>
#include <Qt3DRender/private/setfence_p.h>
+#include <Qt3DRender/private/subtreeenabler_p.h>
+#include <Qt3DRender/private/qshaderprogrambuilder_p.h>
+#include <Qt3DRender/private/qshaderprogram_p.h>
+#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
#include <Qt3DCore/private/qabstractaspectjobmanager_p.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
#if QT_CONFIG(qt3d_profile_jobs)
#include <Qt3DCore/private/aspectcommanddebugger_p.h>
@@ -137,6 +139,82 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
+
+namespace {
+
+class SyncLightsGatherer
+{
+public:
+ explicit SyncLightsGatherer(LightGathererPtr gatherJob,
+ RendererCache *cache)
+ : m_gatherJob(gatherJob)
+ , m_cache(cache)
+ {
+ }
+
+ void operator()()
+ {
+ QMutexLocker lock(m_cache->mutex());
+ m_cache->gatheredLights = m_gatherJob->lights();
+ m_cache->environmentLight = m_gatherJob->takeEnvironmentLight();
+ }
+
+private:
+ LightGathererPtr m_gatherJob;
+ RendererCache *m_cache;
+};
+
+class SyncRenderableEntities
+{
+public:
+ explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob,
+ RendererCache *cache)
+ : m_gatherJob(gatherJob)
+ , m_cache(cache)
+ {
+ }
+
+ void operator()()
+ {
+ QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
+ std::sort(selectedEntities.begin(), selectedEntities.end());
+
+ QMutexLocker lock(m_cache->mutex());
+ m_cache->renderableEntities = selectedEntities;
+ }
+
+private:
+ RenderableEntityFilterPtr m_gatherJob;
+ RendererCache *m_cache;
+};
+
+class SyncComputableEntities
+{
+public:
+ explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob,
+ RendererCache *cache)
+ : m_gatherJob(gatherJob)
+ , m_cache(cache)
+ {
+ }
+
+ void operator()()
+ {
+ QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
+ std::sort(selectedEntities.begin(), selectedEntities.end());
+
+ QMutexLocker lock(m_cache->mutex());
+ m_cache->computeEntities = selectedEntities;
+ }
+
+private:
+ ComputableEntityFilterPtr m_gatherJob;
+ RendererCache *m_cache;
+};
+
+} // anonymous
+
+
/*!
\internal
@@ -165,7 +243,6 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_submissionContext(nullptr)
, m_renderQueue(new RenderQueue())
, m_renderThread(type == QRenderAspect::Threaded ? new RenderThread(this) : nullptr)
- , m_commandThread(new CommandThread(this))
, m_vsyncFrameAdvanceService(new VSyncFrameAdvanceService(m_renderThread != nullptr))
, m_waitForInitializationToBeCompleted(0)
, m_hasBeenInitializedMutex()
@@ -193,16 +270,32 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create())
, m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create())
, m_updateEntityLayersJob(Render::UpdateEntityLayersJobPtr::create())
- , m_updateEntityHierarchyJob(Render::UpdateEntityHierarchyJobPtr::create())
- , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
- , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
- , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
- , m_sendTextureChangesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendTextureChangesToFrontend(); }, JobTypes::SendTextureChangesToFrontend))
- , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
- , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering))
- , m_syncTextureLoadingJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncTextureLoading))
+ , m_lightGathererJob(Render::LightGathererPtr::create())
+ , m_renderableEntityFilterJob(Render::RenderableEntityFilterPtr::create())
+ , m_computableEntityFilterJob(Render::ComputableEntityFilterPtr::create())
+ , m_bufferGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
+ , m_vaoGathererJob(SynchronizerJobPtr::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
+ , m_textureGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
+ , m_sendTextureChangesToFrontendJob(SynchronizerPostFramePtr::create([] {},
+ [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); },
+ JobTypes::SendTextureChangesToFrontend))
+ , m_sendSetFenceHandlesToFrontendJob(SynchronizerJobPtr::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
+ , m_sendDisablesToFrontendJob(SynchronizerPostFramePtr::create([] {},
+ [this] (Qt3DCore::QAspectManager *m) { sendDisablesToFrontend(m); },
+ JobTypes::SendDisablesToFrontend))
+ , m_introspectShaderJob(SynchronizerPostFramePtr::create([this] { reloadDirtyShaders(); },
+ [this] (Qt3DCore::QAspectManager *m) { sendShaderChangesToFrontend(m); },
+ JobTypes::DirtyShaderGathering))
+ , m_syncLoadingJobs(SynchronizerJobPtr::create([] {}, JobTypes::SyncLoadingJobs))
+ , m_cacheRenderableEntitiesJob(SynchronizerJobPtr::create(SyncRenderableEntities(m_renderableEntityFilterJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
+ , m_cacheComputableEntitiesJob(SynchronizerJobPtr::create(SyncComputableEntities(m_computableEntityFilterJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
+ , m_cacheLightsJob(SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
, m_ownedContext(false)
, m_offscreenHelper(nullptr)
+ , m_shouldSwapBuffers(true)
#if QT_CONFIG(qt3d_profile_jobs)
, m_commandExecuter(new Qt3DRender::Debug::CommandExecuter(this))
#endif
@@ -213,9 +306,6 @@ Renderer::Renderer(QRenderAspect::RenderType type)
if (m_renderThread)
m_renderThread->waitForStart();
- m_worldTransformJob->addDependency(m_updateEntityHierarchyJob);
- m_updateEntityLayersJob->addDependency(m_updateEntityHierarchyJob);
-
// Create jobs to update transforms and bounding volumes
// We can only update bounding volumes once all world transforms are known
m_updateWorldBoundingVolumeJob->addDependency(m_worldTransformJob);
@@ -226,12 +316,8 @@ Renderer::Renderer(QRenderAspect::RenderType type)
m_rayCastingJob->addDependency(m_expandBoundingVolumeJob);
// m_calculateBoundingVolumeJob's dependency on m_updateTreeEnabledJob is set in renderBinJobs
- // Dirty texture gathering depends on m_syncTextureLoadingJob
- // m_syncTextureLoadingJob will depend on the texture loading jobs
- m_textureGathererJob->addDependency(m_syncTextureLoadingJob);
-
// Ensures all skeletons are loaded before we try to update them
- m_updateSkinningPaletteJob->addDependency(m_syncTextureLoadingJob);
+ m_updateSkinningPaletteJob->addDependency(m_syncLoadingJobs);
// All world stuff depends on the RenderEntity's localBoundingVolume
m_updateLevelOfDetailJob->addDependency(m_updateMeshTriangleListJob);
@@ -240,6 +326,10 @@ Renderer::Renderer(QRenderAspect::RenderType type)
m_introspectShaderJob->addDependency(m_filterCompatibleTechniqueJob);
+ m_cacheLightsJob->addDependency(m_lightGathererJob);
+ m_cacheRenderableEntitiesJob->addDependency(m_renderableEntityFilterJob);
+ m_cacheComputableEntitiesJob->addDependency(m_computableEntityFilterJob);
+
m_filterCompatibleTechniqueJob->setRenderer(this);
m_defaultRenderStateSet = new RenderStateSet;
@@ -308,7 +398,10 @@ void Renderer::setNodeManagers(NodeManagers *managers)
m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager());
m_updateEntityLayersJob->setManager(m_nodesManager);
m_updateTreeEnabledJob->setManagers(m_nodesManager);
- m_updateEntityHierarchyJob->setManager(m_nodesManager);
+ m_sendBufferCaptureJob->setManagers(m_nodesManager);
+ m_lightGathererJob->setManager(m_nodesManager->renderNodesManager());
+ m_renderableEntityFilterJob->setManager(m_nodesManager->renderNodesManager());
+ m_computableEntityFilterJob->setManager(m_nodesManager->renderNodesManager());
}
void Renderer::setServices(QServiceLocator *services)
@@ -338,18 +431,11 @@ QOpenGLContext *Renderer::shareContext() const
: nullptr);
}
-// Executed in the command thread
+// Executed in the reloadDirtyShader job
void Renderer::loadShader(Shader *shader, HShader shaderHandle)
{
-#ifdef SHADER_LOADING_IN_COMMAND_THREAD
- Q_UNUSED(shaderHandle);
- Profiling::GLTimeRecorder recorder(Profiling::ShaderUpload);
- LoadShaderCommand cmd(shader);
- m_commandThread->executeCommand(&cmd);
-#else
Q_UNUSED(shader);
m_dirtyShaders.push_back(shaderHandle);
-#endif
}
void Renderer::setOpenGLContext(QOpenGLContext *context)
@@ -424,7 +510,6 @@ void Renderer::initialize()
// Set shader cache on submission context and command thread
m_submissionContext->setShaderCache(m_shaderCache);
- m_commandThread->setShaderCache(m_shaderCache);
// Note: we don't have a surface at this point
// The context will be made current later on (at render time)
@@ -437,19 +522,15 @@ void Renderer::initialize()
// (MS Windows), an offscreen surface is just a hidden QWindow.
m_format = ctx->format();
QMetaObject::invokeMethod(m_offscreenHelper, "createOffscreenSurface");
-
- // Initialize command thread (uses the offscreen surface to make its own ctx current)
- m_commandThread->initialize(ctx, m_offscreenHelper);
- // Note: the offscreen surface is also used at shutdown time to release resources
- // of the submission gl context (when the window is already gone).
- // By that time (in releaseGraphicResources), the commandThread has been destroyed
- // and the offscreenSurface can be reused
}
// Awake setScenegraphRoot in case it was waiting
m_waitForInitializationToBeCompleted.release(1);
// Allow the aspect manager to proceed
m_vsyncFrameAdvanceService->proceedToNextFrame();
+
+ // Force initial refresh
+ markDirty(AllDirty, nullptr);
}
/*!
@@ -466,7 +547,7 @@ void Renderer::shutdown()
QMutexLocker lock(&m_hasBeenInitializedMutex);
qCDebug(Backend) << Q_FUNC_INFO << "Requesting renderer shutdown";
- m_running.store(0);
+ m_running.storeRelaxed(0);
// We delete any renderqueue that we may not have had time to render
// before the surface was destroyed
@@ -475,8 +556,6 @@ void Renderer::shutdown()
m_renderQueue->reset();
lockRenderQueue.unlock();
- m_commandThread->shutdown();
-
if (!m_renderThread) {
releaseGraphicsResources();
} else {
@@ -524,9 +603,11 @@ void Renderer::releaseGraphicsResources()
if (context->thread() == QThread::currentThread() && context->makeCurrent(offscreenSurface)) {
// Clean up the graphics context and any resources
- const QVector<GLTexture*> activeTextures = m_nodesManager->glTextureManager()->activeResources();
- for (GLTexture *tex : activeTextures)
- tex->destroyGLTexture();
+ const QVector<HGLTexture> activeTexturesHandles = m_nodesManager->glTextureManager()->activeHandles();
+ for (const HGLTexture &textureHandle : activeTexturesHandles) {
+ GLTexture *tex = m_nodesManager->glTextureManager()->data(textureHandle);
+ tex->destroy();
+ }
// Do the same thing with buffers
const QVector<HGLBuffer> activeBuffers = m_nodesManager->glBufferManager()->activeHandles();
@@ -576,10 +657,9 @@ Render::FrameGraphNode *Renderer::frameGraphRoot() const
// 2) setSceneRoot waits to acquire initialization
// 3) submitRenderView -> check for surface
// -> make surface current + create proper glHelper if needed
-void Renderer::setSceneRoot(QBackendNodeFactory *factory, Entity *sgRoot)
+void Renderer::setSceneRoot(Entity *sgRoot)
{
Q_ASSERT(sgRoot);
- Q_UNUSED(factory);
// If initialization hasn't been completed we must wait
m_waitForInitializationToBeCompleted.acquire();
@@ -637,41 +717,30 @@ void Renderer::render()
// One scene description
// One framegraph description
- while (m_running.load() > 0) {
+ while (m_running.loadRelaxed() > 0) {
doRender();
// TO DO: Restore windows exposed detection
// Probably needs to happens some place else though
}
}
-void Renderer::doRender(bool scene3dBlocking)
+// Either called by render if Qt3D is in charge of the RenderThread
+// or by QRenderAspectPrivate::renderSynchronous (for Scene3D)
+void Renderer::doRender(bool swapBuffers)
{
Renderer::ViewSubmissionResultData submissionData;
bool hasCleanedQueueAndProceeded = false;
bool preprocessingComplete = false;
bool beganDrawing = false;
+
+ // Blocking until RenderQueue is full
const bool canSubmit = isReadyToSubmit();
+ m_shouldSwapBuffers = swapBuffers;
// Lock the mutex to protect access to the renderQueue while we look for its state
QMutexLocker locker(m_renderQueue->mutex());
- bool queueIsComplete = m_renderQueue->isFrameQueueComplete();
- bool queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0;
-
- // Scene3D Blocking Mode
- if (scene3dBlocking && !queueIsComplete && !queueIsEmpty) {
- int i = 0;
- // We wait at most 10ms to avoid a case we could never recover from
- while (!queueIsComplete && !queueIsEmpty && i++ < 10) {
- qCDebug(Backend) << Q_FUNC_INFO << "Waiting for ready queue (try:" << i << "/ 10)";
- locker.unlock();
- // Give worker threads a chance to complete the queue
- QThread::msleep(1);
- locker.relock();
- queueIsComplete = m_renderQueue->isFrameQueueComplete();
- // This could become true if we've tried to shutdown
- queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0;
- }
- }
+ const bool queueIsComplete = m_renderQueue->isFrameQueueComplete();
+ const bool queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0;
// When using synchronous rendering (QtQuick)
// We are not sure that the frame queue is actually complete
@@ -768,16 +837,12 @@ void Renderer::doRender(bool scene3dBlocking)
#endif
}
- // Only reset renderQueue and proceed to next frame if the submission
- // succeeded or if we are using a render thread and that is wasn't performed
- // already
-
// If hasCleanedQueueAndProceeded isn't true this implies that something went wrong
// with the rendering and/or the renderqueue is incomplete from some reason
- // (in the case of scene3d the render jobs may be taking too long ....)
// or alternatively it could be complete but empty (RenderQueue of size 0)
- if (!hasCleanedQueueAndProceeded &&
- (m_renderThread || queueIsComplete || queueIsEmpty)) {
+
+
+ if (!hasCleanedQueueAndProceeded) {
// RenderQueue was full but something bad happened when
// trying to render it and therefore proceedToNextFrame was not called
// Note: in this case the renderQueue mutex is still locked
@@ -800,7 +865,10 @@ void Renderer::doRender(bool scene3dBlocking)
if (beganDrawing) {
SurfaceLocker surfaceLock(submissionData.surface);
// Finish up with last surface used in the list of RenderViews
- m_submissionContext->endDrawing(submissionData.lastBoundFBOId == m_submissionContext->defaultFBO() && surfaceLock.isSurfaceValid());
+ const bool swapBuffers = submissionData.lastBoundFBOId == m_submissionContext->defaultFBO()
+ && surfaceLock.isSurfaceValid()
+ && m_shouldSwapBuffers;
+ m_submissionContext->endDrawing(swapBuffers);
}
}
@@ -819,7 +887,7 @@ void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder
const bool isQueueComplete = m_renderQueue->queueRenderView(renderView, submitOrder);
locker.unlock(); // We're done protecting the queue at this point
if (isQueueComplete) {
- if (m_renderThread && m_running.load())
+ if (m_renderThread && m_running.loadRelaxed())
Q_ASSERT(m_submitRenderViewsSemaphore.available() == 0);
m_submitRenderViewsSemaphore.release(1);
}
@@ -828,7 +896,7 @@ void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder
bool Renderer::canRender() const
{
// Make sure that we've not been told to terminate
- if (m_renderThread && !m_running.load()) {
+ if (m_renderThread && !m_running.loadRelaxed()) {
qCDebug(Rendering) << "RenderThread termination requested whilst waiting";
return false;
}
@@ -842,21 +910,19 @@ bool Renderer::canRender() const
bool Renderer::isReadyToSubmit()
{
- // If we are using a render thread, make sure that
- // we've been told to render before rendering
- if (m_renderThread) { // Prevent ouf of order execution
- m_submitRenderViewsSemaphore.acquire(1);
+ // Make sure that we've been told to render before rendering
+ // Prevent ouf of order execution
+ m_submitRenderViewsSemaphore.acquire(1);
- // Check if shutdown has been requested
- if (m_running.load() == 0)
- return false;
+ // Check if shutdown has been requested
+ if (m_running.loadRelaxed() == 0)
+ return false;
- // When using Thread rendering, the semaphore should only
- // be released when the frame queue is complete and there's
- // something to render
- // The case of shutdown should have been handled just before
- Q_ASSERT(m_renderQueue->isFrameQueueComplete());
- }
+ // The semaphore should only
+ // be released when the frame queue is complete and there's
+ // something to render
+ // The case of shutdown should have been handled just before
+ Q_ASSERT(m_renderQueue->isFrameQueueComplete());
return true;
}
@@ -893,13 +959,13 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
QHash<HVao, bool> updatedTable;
for (RenderView *rv: renderViews) {
- const QVector<RenderCommand *> commands = rv->commands();
- for (RenderCommand *command : commands) {
+ QVector<RenderCommand> &commands = rv->commands();
+ for (RenderCommand &command : commands) {
// Update/Create VAO
- if (command->m_type == RenderCommand::Draw) {
- Geometry *rGeometry = m_nodesManager->data<Geometry, GeometryManager>(command->m_geometry);
- GeometryRenderer *rGeometryRenderer = m_nodesManager->data<GeometryRenderer, GeometryRendererManager>(command->m_geometryRenderer);
- Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command->m_shader);
+ if (command.m_type == RenderCommand::Draw) {
+ Geometry *rGeometry = m_nodesManager->data<Geometry, GeometryManager>(command.m_geometry);
+ GeometryRenderer *rGeometryRenderer = m_nodesManager->data<GeometryRenderer, GeometryRendererManager>(command.m_geometryRenderer);
+ Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command.m_shader);
// We should never have inserted a command for which these are null
// in the first place
@@ -912,15 +978,15 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
// Create VAO or return already created instance associated with command shader/geometry
// (VAO is emulated if not supported)
- createOrUpdateVAO(command, &vaoHandle, &vao);
- command->m_vao = vaoHandle;
+ createOrUpdateVAO(&command, &vaoHandle, &vao);
+ command.m_vao = vaoHandle;
// Avoids redoing the same thing for the same VAO
if (!updatedTable.contains(vaoHandle)) {
updatedTable.insert(vaoHandle, true);
// Do we have any attributes that are dirty ?
- const bool requiresPartialVAOUpdate = requiresVAOAttributeUpdate(rGeometry, command);
+ const bool requiresPartialVAOUpdate = requiresVAOAttributeUpdate(rGeometry, &command);
// If true, we need to reupload all attributes to set the VAO
// Otherwise only dirty attributes will be updates
@@ -931,7 +997,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
if (rGeometry->isDirty())
m_dirtyGeometry.push_back(rGeometry);
- if (!command->m_attributes.isEmpty() && (requiresFullVAOUpdate || requiresPartialVAOUpdate)) {
+ if (!command.m_activeAttributes.isEmpty() && (requiresFullVAOUpdate || requiresPartialVAOUpdate)) {
Profiling::GLTimeRecorder recorder(Profiling::VAOUpload);
// Activate shader
m_submissionContext->activateShader(shader->dna());
@@ -939,7 +1005,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
vao->bind();
// Update or set Attributes and Buffers for the given rGeometry and Command
// Note: this fills m_dirtyAttributes as well
- if (updateVAOWithAttributes(rGeometry, command, shader, requiresFullVAOUpdate))
+ if (updateVAOWithAttributes(rGeometry, &command, shader, requiresFullVAOUpdate))
vao->setSpecified(true);
}
}
@@ -951,12 +1017,11 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
rGeometryRenderer->unsetDirty();
// Prepare the ShaderParameterPack based on the active uniforms of the shader
- shader->prepareUniforms(command->m_parameterPack);
+ shader->prepareUniforms(command.m_parameterPack);
- // TO DO: The step below could be performed by the RenderCommand builder job
{ // Scoped to show extent
- command->m_isValid = !command->m_attributes.empty();
- if (!command->m_isValid)
+ command.m_isValid = !command.m_activeAttributes.empty();
+ if (!command.m_isValid)
continue;
// Update the draw command with what's going to be needed for the drawing
@@ -976,7 +1041,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
indirectAttribute = attribute;
break;
case QAttribute::VertexAttribute: {
- if (command->m_attributes.contains(attribute->nameId()))
+ if (command.m_activeAttributes.contains(attribute->nameId()))
estimatedCount = qMax(attribute->count(), estimatedCount);
break;
}
@@ -986,20 +1051,20 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
}
}
- command->m_drawIndexed = (indexAttribute != nullptr);
- command->m_drawIndirect = (indirectAttribute != nullptr);
+ command.m_drawIndexed = (indexAttribute != nullptr);
+ command.m_drawIndirect = (indirectAttribute != nullptr);
// Update the draw command with all the information required for the drawing
- if (command->m_drawIndexed) {
- command->m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType());
- command->m_indexAttributeByteOffset = indexAttribute->byteOffset() + rGeometryRenderer->indexBufferByteOffset();
+ if (command.m_drawIndexed) {
+ command.m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType());
+ command.m_indexAttributeByteOffset = indexAttribute->byteOffset() + rGeometryRenderer->indexBufferByteOffset();
}
// Note: we only care about the primitiveCount when using direct draw calls
// For indirect draw calls it is assumed the buffer was properly set already
- if (command->m_drawIndirect) {
- command->m_indirectAttributeByteOffset = indirectAttribute->byteOffset();
- command->m_indirectDrawBuffer = m_nodesManager->bufferManager()->lookupHandle(indirectAttribute->bufferId());
+ if (command.m_drawIndirect) {
+ command.m_indirectAttributeByteOffset = indirectAttribute->byteOffset();
+ command.m_indirectDrawBuffer = m_nodesManager->bufferManager()->lookupHandle(indirectAttribute->bufferId());
} else {
// Use the count specified by the GeometryRender
// If not specify use the indexAttribute count if present
@@ -1012,22 +1077,22 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView
}
}
- command->m_primitiveCount = primitiveCount;
- command->m_primitiveType = rGeometryRenderer->primitiveType();
- command->m_primitiveRestartEnabled = rGeometryRenderer->primitiveRestartEnabled();
- command->m_restartIndexValue = rGeometryRenderer->restartIndexValue();
- command->m_firstInstance = rGeometryRenderer->firstInstance();
- command->m_instanceCount = rGeometryRenderer->instanceCount();
- command->m_firstVertex = rGeometryRenderer->firstVertex();
- command->m_indexOffset = rGeometryRenderer->indexOffset();
- command->m_verticesPerPatch = rGeometryRenderer->verticesPerPatch();
+ command.m_primitiveCount = primitiveCount;
+ command.m_primitiveType = rGeometryRenderer->primitiveType();
+ command.m_primitiveRestartEnabled = rGeometryRenderer->primitiveRestartEnabled();
+ command.m_restartIndexValue = rGeometryRenderer->restartIndexValue();
+ command.m_firstInstance = rGeometryRenderer->firstInstance();
+ command.m_instanceCount = rGeometryRenderer->instanceCount();
+ command.m_firstVertex = rGeometryRenderer->firstVertex();
+ command.m_indexOffset = rGeometryRenderer->indexOffset();
+ command.m_verticesPerPatch = rGeometryRenderer->verticesPerPatch();
} // scope
- } else if (command->m_type == RenderCommand::Compute) {
- Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command->m_shader);
+ } else if (command.m_type == RenderCommand::Compute) {
+ Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command.m_shader);
Q_ASSERT(shader);
// Prepare the ShaderParameterPack based on the active uniforms of the shader
- shader->prepareUniforms(command->m_parameterPack);
+ shader->prepareUniforms(command.m_parameterPack);
}
}
}
@@ -1076,6 +1141,7 @@ void Renderer::lookForDirtyBuffers()
}
}
+// Called in prepareSubmission
void Renderer::lookForDownloadableBuffers()
{
m_downloadableBuffers.clear();
@@ -1083,7 +1149,7 @@ void Renderer::lookForDownloadableBuffers()
for (const HBuffer &handle : activeBufferHandles) {
Buffer *buffer = m_nodesManager->bufferManager()->data(handle);
if (buffer->access() & QBuffer::Read)
- m_downloadableBuffers.push_back(handle);
+ m_downloadableBuffers.push_back(buffer->peerId());
}
}
@@ -1157,45 +1223,22 @@ void Renderer::reloadDirtyShaders()
if (shaderBuilder) {
shaderBuilder->setGraphicsApi(*technique->graphicsApiFilter());
- for (int i = 0; i <= ShaderBuilder::Compute; i++) {
- const auto builderType = static_cast<ShaderBuilder::ShaderType>(i);
- if (!shaderBuilder->shaderGraph(builderType).isValid())
+ for (int i = 0; i <= QShaderProgram::Compute; i++) {
+ const auto shaderType = static_cast<QShaderProgram::ShaderType>(i);
+ if (!shaderBuilder->shaderGraph(shaderType).isValid())
continue;
- if (shaderBuilder->isShaderCodeDirty(builderType)) {
- shaderBuilder->generateCode(builderType);
+ if (shaderBuilder->isShaderCodeDirty(shaderType)) {
+ shaderBuilder->generateCode(shaderType);
+ m_shaderBuilderUpdates.append(shaderBuilder->takePendingUpdates());
}
- QShaderProgram::ShaderType shaderType = QShaderProgram::Vertex;
- switch (builderType) {
- case ShaderBuilder::Vertex:
- shaderType = QShaderProgram::Vertex;
- break;
- case ShaderBuilder::TessellationControl:
- shaderType = QShaderProgram::TessellationControl;
- break;
- case ShaderBuilder::TessellationEvaluation:
- shaderType = QShaderProgram::TessellationEvaluation;
- break;
- case ShaderBuilder::Geometry:
- shaderType = QShaderProgram::Geometry;
- break;
- case ShaderBuilder::Fragment:
- shaderType = QShaderProgram::Fragment;
- break;
- case ShaderBuilder::Compute:
- shaderType = QShaderProgram::Compute;
- break;
- }
-
- const auto code = shaderBuilder->shaderCode(builderType);
+ const auto code = shaderBuilder->shaderCode(shaderType);
shader->setShaderCode(shaderType, code);
}
}
- if (Q_UNLIKELY(shader->hasPendingNotifications()))
- shader->submitPendingNotifications();
- // If the shader hasn't be loaded, load it
+ // If the shader hasn't been loaded, load it
if (shader != nullptr && !shader->isLoaded())
loadShader(shader, shaderHandle);
}
@@ -1203,24 +1246,66 @@ void Renderer::reloadDirtyShaders()
}
}
-// Executed in a job
-void Renderer::sendTextureChangesToFrontend()
+// Executed in job postFrame
+void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager)
+{
+ Q_ASSERT(isRunning());
+
+ // Sync Shader
+ const QVector<HShader> activeShaders = m_nodesManager->shaderManager()->activeHandles();
+ for (const HShader &handle :activeShaders) {
+ Shader *s = m_nodesManager->shaderManager()->data(handle);
+ if (s->requiresFrontendSync()) {
+ QShaderProgram *frontend = static_cast<decltype(frontend)>(manager->lookupNode(s->peerId()));
+ QShaderProgramPrivate *dFrontend = static_cast<decltype(dFrontend)>(QNodePrivate::get(frontend));
+ s->unsetRequiresFrontendSync();
+ dFrontend->setStatus(s->status());
+ dFrontend->setLog(s->log());
+ }
+ }
+
+ // Sync ShaderBuilder
+ const QVector<ShaderBuilderUpdate> shaderBuilderUpdates = std::move(m_shaderBuilderUpdates);
+ for (const ShaderBuilderUpdate &update : shaderBuilderUpdates) {
+ QShaderProgramBuilder *builder = static_cast<decltype(builder)>(manager->lookupNode(update.builderId));
+ QShaderProgramBuilderPrivate *dBuilder = static_cast<decltype(dBuilder)>(QNodePrivate::get(builder));
+ dBuilder->setShaderCode(update.shaderCode, update.shaderType);
+ }
+}
+
+// Executed in a job (as postFrame)
+void Renderer::sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager)
{
const QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> updateTextureProperties = std::move(m_updatedTextureProperties);
for (const auto &pair : updateTextureProperties) {
- // Prepare change notification
-
const Qt3DCore::QNodeIdVector targetIds = pair.second;
for (const Qt3DCore::QNodeId targetId: targetIds) {
+
// Lookup texture
Texture *t = m_nodesManager->textureManager()->lookupResource(targetId);
+ // If backend texture is Dirty, some property has changed and the properties we are
+ // about to send are already outdate
+ if (t == nullptr || t->dirtyFlags() != Texture::NotDirty)
+ continue;
- // Texture might have been deleted between previous and current frame
- if (t == nullptr)
+ QAbstractTexture *texture = static_cast<QAbstractTexture *>(manager->lookupNode(targetId));
+ if (!texture)
continue;
+ const TextureProperties &properties = pair.first.properties;
+
+ const bool blocked = texture->blockNotifications(true);
+ texture->setWidth(properties.width);
+ texture->setHeight(properties.height);
+ texture->setDepth(properties.depth);
+ texture->setLayers(properties.layers);
+ texture->setFormat(properties.format);
+ texture->blockNotifications(blocked);
+
+ QAbstractTexturePrivate *dTexture = static_cast<QAbstractTexturePrivate *>(QNodePrivate::get(texture));
- // Send change and update backend
- t->updatePropertiesAndNotify(pair.first);
+ dTexture->setStatus(properties.status);
+ dTexture->setHandleType(pair.first.handleType);
+ dTexture->setHandle(pair.first.handle);
}
}
}
@@ -1241,6 +1326,28 @@ void Renderer::sendSetFenceHandlesToFrontend()
}
}
+// Executed in a job postFrame
+void Renderer::sendDisablesToFrontend(Qt3DCore::QAspectManager *manager)
+{
+ // SubtreeEnabled
+ const auto updatedDisables = std::move(m_updatedDisableSubtreeEnablers);
+ for (const auto &nodeId : updatedDisables) {
+ QSubtreeEnabler *frontend = static_cast<decltype(frontend)>(manager->lookupNode(nodeId));
+ frontend->setEnabled(false);
+ }
+
+ // Compute Commands
+ const QVector<HComputeCommand> activeCommands = m_nodesManager->computeJobManager()->activeHandles();
+ for (const HComputeCommand &handle :activeCommands) {
+ ComputeCommand *c = m_nodesManager->computeJobManager()->data(handle);
+ if (c->hasReachedFrameCount()) {
+ QComputeCommand *frontend = static_cast<decltype(frontend)>(manager->lookupNode(c->peerId()));
+ frontend->setEnabled(false);
+ c->resetHasReachedFrameCount();
+ }
+ }
+}
+
// Render Thread (or QtQuick RenderThread when using Scene3D)
// Scene3D: When using Scene3D rendering, we can't assume that when
// updateGLResources is called, the resource handles points to still existing
@@ -1320,7 +1427,8 @@ void Renderer::updateGLResources()
if (texture == nullptr)
continue;
- // Create or Update GLTexture
+ // Create or Update GLTexture (the GLTexture instance is created if required
+ // and all things that can take place without a GL context are done here)
updateTexture(texture);
}
// We want to upload textures data at this point as the SubmissionThread and
@@ -1328,15 +1436,18 @@ void Renderer::updateGLResources()
// GLTexture
if (m_submissionContext != nullptr) {
GLTextureManager *glTextureManager = m_nodesManager->glTextureManager();
- const QVector<GLTexture *> glTextures = glTextureManager->activeResources();
+ const QVector<HGLTexture> glTextureHandles = glTextureManager->activeHandles();
// Upload texture data
- for (GLTexture *glTexture : glTextures) {
+ for (const HGLTexture &glTextureHandle : glTextureHandles) {
+ GLTexture *glTexture = glTextureManager->data(glTextureHandle);
+
+ // We create/update the actual GL texture using the GL context at this point
const GLTexture::TextureUpdateInfo info = glTexture->createOrUpdateGLTexture();
// GLTexture creation provides us width/height/format ... information
// for textures which had not initially specified these information (TargetAutomatic...)
// Gather these information and store them to be distributed by a change next frame
- const QNodeIdVector referenceTextureIds = glTextureManager->referencedTextureIds(glTexture);
+ const QNodeIdVector referenceTextureIds = { glTextureManager->texNodeIdForGLTexture.value(glTexture) };
// Store properties and referenceTextureIds
if (info.wasUpdated) {
Texture::TextureUpdateInfo updateInfo;
@@ -1347,14 +1458,13 @@ void Renderer::updateGLResources()
}
}
}
+
+ // Record ids of texture to cleanup while we are still blocking the aspect thread
+ m_textureIdsToCleanup += m_nodesManager->textureManager()->takeTexturesIdsToCleanup();
}
- // When Textures are cleaned up, their id is saved so that they can be
- // cleaned up in the render thread Note: we perform this step in second so
- // that the previous updateTexture call has a chance to find a shared
- // texture and avoid possible destroying recreating a new texture
- const QVector<Qt3DCore::QNodeId> cleanedUpTextureIds = m_nodesManager->textureManager()->takeTexturesIdsToCleanup();
- for (const Qt3DCore::QNodeId textureCleanedUpId: cleanedUpTextureIds)
- cleanupTexture(textureCleanedUpId);
+
+ // Record list of buffer that might need uploading
+ lookForDownloadableBuffers();
}
// Render Thread
@@ -1362,92 +1472,60 @@ void Renderer::updateTexture(Texture *texture)
{
// Check that the current texture images are still in place, if not, do not update
const bool isValid = texture->isValid(m_nodesManager->textureImageManager());
- if (!isValid)
+ if (!isValid) {
+ qWarning() << Q_FUNC_INFO << "QTexture referencing invalid QTextureImages";
return;
-
- // For implementing unique, non-shared, non-cached textures.
- // for now, every texture is shared by default except if:
- // - texture is reference by a render attachment
- // - texture is referencing a shared texture id
- bool isUnique = texture->sharedTextureId() > 0;
-
- if (!isUnique) {
- // TO DO: Update the vector once per frame (or in a job)
- const QVector<HAttachment> activeRenderTargetOutputs = m_nodesManager->attachmentManager()->activeHandles();
- // A texture is unique if it's being reference by a render target output
- for (const HAttachment &attachmentHandle : activeRenderTargetOutputs) {
- RenderTargetOutput *attachment = m_nodesManager->attachmentManager()->data(attachmentHandle);
- if (attachment->textureUuid() == texture->peerId()) {
- isUnique = true;
- break;
- }
- }
}
+ // All textures are unique, if you instanciate twice the exact same texture
+ // this will create 2 identical GLTextures, no sharing will take place
+
// Try to find the associated GLTexture for the backend Texture
GLTextureManager *glTextureManager = m_nodesManager->glTextureManager();
GLTexture *glTexture = glTextureManager->lookupResource(texture->peerId());
- auto createOrUpdateGLTexture = [=] () {
- if (isUnique)
- glTextureManager->createUnique(texture);
- else
- glTextureManager->getOrCreateShared(texture);
- texture->unsetDirty();
- };
-
// No GLTexture associated yet -> create it
if (glTexture == nullptr) {
- createOrUpdateGLTexture();
- return;
- }
-
- // if this texture is a shared texture, we might need to look for a new TextureImpl
- // and abandon the old one
- if (glTextureManager->isShared(glTexture)) {
- glTextureManager->abandon(glTexture, texture->peerId());
- // Note: if isUnique is true, a once shared texture will become unique
- createOrUpdateGLTexture();
- return;
- }
-
- // this texture node is the only one referring to the GLTexture.
- // we could thus directly modify the texture. Instead, for non-unique textures,
- // we first see if there is already a matching texture present.
- if (!isUnique) {
- GLTexture *newSharedTex = glTextureManager->findMatchingShared(texture);
- if (newSharedTex && newSharedTex != glTexture) {
- glTextureManager->abandon(glTexture, texture->peerId());
- glTextureManager->adoptShared(newSharedTex, texture);
- texture->unsetDirty();
- return;
- }
+ glTexture = glTextureManager->getOrCreateResource(texture->peerId());
+ glTextureManager->texNodeIdForGLTexture.insert(glTexture, texture->peerId());
}
- // we hold a reference to a unique or exclusive access to a shared texture
- // we can thus modify the texture directly.
+ // Update GLTexture to match Texture instance
const Texture::DirtyFlags dirtyFlags = texture->dirtyFlags();
- if (dirtyFlags.testFlag(Texture::DirtySharedTextureId) &&
- !glTextureManager->setSharedTextureId(glTexture, texture->sharedTextureId()))
- qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setSharedTextureId failed, should be non-shared";
+ if (dirtyFlags.testFlag(Texture::DirtySharedTextureId))
+ glTexture->setSharedTextureId(texture->sharedTextureId());
+
+ if (dirtyFlags.testFlag(Texture::DirtyProperties))
+ glTexture->setProperties(texture->properties());
- if (dirtyFlags.testFlag(Texture::DirtyProperties) &&
- !glTextureManager->setProperties(glTexture, texture->properties()))
- qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setProperties failed, should be non-shared";
+ if (dirtyFlags.testFlag(Texture::DirtyParameters))
+ glTexture->setParameters(texture->parameters());
- if (dirtyFlags.testFlag(Texture::DirtyParameters) &&
- !glTextureManager->setParameters(glTexture, texture->parameters()))
- qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setParameters failed, should be non-shared";
+ // Will make the texture requestUpload
+ if (dirtyFlags.testFlag(Texture::DirtyImageGenerators)) {
+ const QNodeIdVector textureImageIds = texture->textureImageIds();
+ QVector<GLTexture::Image> images;
+ images.reserve(textureImageIds.size());
+ // TODO: Move this into GLTexture directly
+ for (const QNodeId textureImageId : textureImageIds) {
+ const TextureImage *img = m_nodesManager->textureImageManager()->lookupResource(textureImageId);
+ if (img == nullptr) {
+ qWarning() << Q_FUNC_INFO << "invalid TextureImage handle";
+ } else {
+ GLTexture::Image glImg {img->dataGenerator(), img->layer(), img->mipLevel(), img->face()};
+ images.push_back(glImg);
+ }
+ }
+ glTexture->setImages(images);
+ }
// Will make the texture requestUpload
- if (dirtyFlags.testFlag(Texture::DirtyImageGenerators) &&
- !glTextureManager->setImages(glTexture, texture->textureImageIds()))
- qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setGenerators failed, should be non-shared";
+ if (dirtyFlags.testFlag(Texture::DirtyDataGenerator))
+ glTexture->setGenerator(texture->dataGenerator());
// Will make the texture requestUpload
- if (dirtyFlags.testFlag(Texture::DirtyDataGenerator) &&
- !glTextureManager->setGenerator(glTexture, texture->dataGenerator()))
- qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setGenerator failed, should be non-shared";
+ if (dirtyFlags.testFlag(Texture::DirtyPendingDataUpdates))
+ glTexture->addTextureDataUpdates(texture->takePendingTextureDataUpdates());
// Unset the dirty flag on the texture
texture->unsetDirty();
@@ -1459,19 +1537,28 @@ void Renderer::cleanupTexture(Qt3DCore::QNodeId cleanedUpTextureId)
GLTextureManager *glTextureManager = m_nodesManager->glTextureManager();
GLTexture *glTexture = glTextureManager->lookupResource(cleanedUpTextureId);
- if (glTexture != nullptr)
- glTextureManager->abandon(glTexture, cleanedUpTextureId);
+ // Destroying the GLTexture implicitely also destroy the GL resources
+ if (glTexture != nullptr) {
+ glTextureManager->releaseResource(cleanedUpTextureId);
+ glTextureManager->texNodeIdForGLTexture.remove(glTexture);
+ }
}
// Called by SubmitRenderView
void Renderer::downloadGLBuffers()
{
- lookForDownloadableBuffers();
- const QVector<HBuffer> downloadableHandles = std::move(m_downloadableBuffers);
- for (const HBuffer &handle : downloadableHandles) {
- Buffer *buffer = m_nodesManager->bufferManager()->data(handle);
- QByteArray content = m_submissionContext->downloadBufferContent(buffer);
- m_sendBufferCaptureJob->addRequest(QPair<Buffer*, QByteArray>(buffer, content));
+ const QVector<Qt3DCore::QNodeId> downloadableHandles = std::move(m_downloadableBuffers);
+ for (const Qt3DCore::QNodeId &bufferId : downloadableHandles) {
+ BufferManager *bufferManager = m_nodesManager->bufferManager();
+ BufferManager::ReadLocker locker(const_cast<const BufferManager *>(bufferManager));
+ Buffer *buffer = bufferManager->lookupResource(bufferId);
+ // Buffer could have been destroyed at this point
+ if (!buffer)
+ continue;
+ // locker is protecting us from the buffer being destroy while we're looking
+ // up its content
+ const QByteArray content = m_submissionContext->downloadBufferContent(buffer);
+ m_sendBufferCaptureJob->addRequest(QPair<Qt3DCore::QNodeId, QByteArray>(bufferId, content));
}
}
@@ -1485,7 +1572,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
const int renderViewsCount = renderViews.size();
quint64 frameElapsed = queueElapsed;
- m_lastFrameCorrect.store(1); // everything fine until now.....
+ m_lastFrameCorrect.storeRelaxed(1); // everything fine until now.....
qCDebug(Memory) << Q_FUNC_INFO << "rendering frame ";
@@ -1518,7 +1605,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
// to use when surface is null. Or if we should instead expose an
// offscreensurface to Qt3D.
if (!surface || !surfaceLock.isSurfaceValid()) {
- m_lastFrameCorrect.store(0);
+ m_lastFrameCorrect.storeRelaxed(0);
continue;
}
@@ -1526,7 +1613,9 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
const bool surfaceHasChanged = surface != previousSurface;
if (surfaceHasChanged && previousSurface) {
- const bool swapBuffers = (lastBoundFBOId == m_submissionContext->defaultFBO()) && PlatformSurfaceFilter::isSurfaceValid(previousSurface);
+ const bool swapBuffers = lastBoundFBOId == m_submissionContext->defaultFBO()
+ && surfaceLock.isSurfaceValid()
+ && m_shouldSwapBuffers;
// We only call swap buffer if we are sure the previous surface is still valid
m_submissionContext->endDrawing(swapBuffers);
}
@@ -1536,7 +1625,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
// next RenderView. We won't get the full frame but we may get something
if (!m_submissionContext->beginDrawing(surface)) {
qWarning() << "Failed to make OpenGL context current on surface";
- m_lastFrameCorrect.store(0);
+ m_lastFrameCorrect.storeRelaxed(0);
continue;
}
@@ -1637,7 +1726,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
// Execute the render commands
if (!executeCommandsSubmission(renderView))
- m_lastFrameCorrect.store(0); // something went wrong; make sure to render the next frame!
+ m_lastFrameCorrect.storeRelaxed(0); // something went wrong; make sure to render the next frame!
// executeCommandsSubmission takes care of restoring the stateset to the value
// of gc->currentContext() at the moment it was called (either
@@ -1737,9 +1826,10 @@ bool Renderer::shouldRender()
// Only render if something changed during the last frame, or the last frame
// was not rendered successfully (or render-on-demand is disabled)
return (m_settings->renderPolicy() == QRenderSettings::Always
+ || m_renderThread == nullptr // <==> we use Scene3D
|| m_dirtyBits.marked != 0
|| m_dirtyBits.remaining != 0
- || !m_lastFrameCorrect.load());
+ || !m_lastFrameCorrect.loadRelaxed());
}
void Renderer::skipNextFrame()
@@ -1785,7 +1875,6 @@ QVector<QAspectJobPtr> Renderer::preRenderingJobs()
QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
{
QVector<QAspectJobPtr> renderBinJobs;
-
// Create the jobs to build the frame
const QVector<QAspectJobPtr> bufferJobs = createRenderBufferJobs();
@@ -1806,17 +1895,14 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
// Add jobs
const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty;
- const bool entityHierarchyNeedsToBeRebuilt = dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty;
- if (entitiesEnabledDirty || entityHierarchyNeedsToBeRebuilt) {
+ if (entitiesEnabledDirty) {
renderBinJobs.push_back(m_updateTreeEnabledJob);
// This dependency is added here because we clear all dependencies
// at the start of this function.
m_calculateBoundingVolumeJob->addDependency(m_updateTreeEnabledJob);
- m_calculateBoundingVolumeJob->addDependency(m_updateEntityHierarchyJob);
}
- if (dirtyBitsForFrame & AbstractRenderer::TransformDirty ||
- dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty) {
+ if (dirtyBitsForFrame & AbstractRenderer::TransformDirty) {
renderBinJobs.push_back(m_worldTransformJob);
renderBinJobs.push_back(m_updateWorldBoundingVolumeJob);
renderBinJobs.push_back(m_updateShaderDataTransformJob);
@@ -1829,16 +1915,17 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
}
if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty ||
- dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty ||
dirtyBitsForFrame & AbstractRenderer::TransformDirty) {
renderBinJobs.push_back(m_expandBoundingVolumeJob);
}
+ // TO DO: Conditionally add if skeletons dirty
+ renderBinJobs.push_back(m_syncLoadingJobs);
m_updateSkinningPaletteJob->setDirtyJoints(m_nodesManager->jointManager()->dirtyJoints());
renderBinJobs.push_back(m_updateSkinningPaletteJob);
renderBinJobs.push_back(m_updateLevelOfDetailJob);
renderBinJobs.push_back(m_cleanupJob);
-
+ renderBinJobs.push_back(m_sendDisablesToFrontendJob);
renderBinJobs.append(bufferJobs);
// Jobs to prepare GL Resource upload
@@ -1847,31 +1934,42 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
if (dirtyBitsForFrame & AbstractRenderer::BuffersDirty)
renderBinJobs.push_back(m_bufferGathererJob);
- if (dirtyBitsForFrame & AbstractRenderer::TexturesDirty) {
- renderBinJobs.push_back(m_syncTextureLoadingJob);
+ if (dirtyBitsForFrame & AbstractRenderer::TexturesDirty)
renderBinJobs.push_back(m_textureGathererJob);
- }
// Layer cache is dependent on layers, layer filters (hence FG structure
// changes) and the enabled flag on entities
const bool frameGraphDirty = dirtyBitsForFrame & AbstractRenderer::FrameGraphDirty;
- const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty || entityHierarchyNeedsToBeRebuilt;
+ const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty;
const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty || frameGraphDirty;
+ const bool shadersDirty = dirtyBitsForFrame & AbstractRenderer::ShadersDirty;
const bool materialDirty = dirtyBitsForFrame & AbstractRenderer::MaterialDirty;
- const bool materialCacheNeedsToBeRebuilt = materialDirty || frameGraphDirty;
const bool lightsDirty = dirtyBitsForFrame & AbstractRenderer::LightsDirty;
const bool computeableDirty = dirtyBitsForFrame & AbstractRenderer::ComputeDirty;
const bool renderableDirty = dirtyBitsForFrame & AbstractRenderer::GeometryDirty;
-
- // Rebuild Entity Hierarchy if dirty
- if (entityHierarchyNeedsToBeRebuilt)
- renderBinJobs.push_back(m_updateEntityHierarchyJob);
+ const bool materialCacheNeedsToBeRebuilt = shadersDirty || materialDirty || frameGraphDirty;
+ const bool renderCommandsDirty = materialCacheNeedsToBeRebuilt || renderableDirty || computeableDirty;
// Rebuild Entity Layers list if layers are dirty
if (layersDirty)
renderBinJobs.push_back(m_updateEntityLayersJob);
+ if (renderableDirty) {
+ renderBinJobs.push_back(m_renderableEntityFilterJob);
+ renderBinJobs.push_back(m_cacheRenderableEntitiesJob);
+ }
+
+ if (computeableDirty) {
+ renderBinJobs.push_back(m_computableEntityFilterJob);
+ renderBinJobs.push_back(m_cacheComputableEntitiesJob);
+ }
+
+ if (lightsDirty) {
+ renderBinJobs.push_back(m_lightGathererJob);
+ renderBinJobs.push_back(m_cacheLightsJob);
+ }
+
QMutexLocker lock(m_renderQueue->mutex());
if (m_renderQueue->wasReset()) { // Have we rendered yet? (Scene3D case)
// Traverse the current framegraph. For each leaf node create a
@@ -1879,24 +1977,31 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
// populate the RenderView with a set of RenderCommands that get
// their details from the RenderNodes that are visible to the
// Camera selected by the framegraph configuration
- FrameGraphVisitor visitor(m_nodesManager->frameGraphManager());
- const QVector<FrameGraphNode *> fgLeaves = visitor.traverse(frameGraphRoot());
-
- // Remove leaf nodes that no longer exist from cache
- const QList<FrameGraphNode *> keys = m_cache.leafNodeCache.keys();
- for (FrameGraphNode *leafNode : keys) {
- if (!fgLeaves.contains(leafNode))
- m_cache.leafNodeCache.remove(leafNode);
+ if (frameGraphDirty) {
+ FrameGraphVisitor visitor(m_nodesManager->frameGraphManager());
+ m_frameGraphLeaves = visitor.traverse(frameGraphRoot());
+ // Remove leaf nodes that no longer exist from cache
+ const QList<FrameGraphNode *> keys = m_cache.leafNodeCache.keys();
+ for (FrameGraphNode *leafNode : keys) {
+ if (!m_frameGraphLeaves.contains(leafNode))
+ m_cache.leafNodeCache.remove(leafNode);
+ }
+
+ // Handle single shot subtree enablers
+ const auto subtreeEnablers = visitor.takeEnablersToDisable();
+ for (auto *node : subtreeEnablers)
+ m_updatedDisableSubtreeEnablers.push_back(node->peerId());
}
- const int fgBranchCount = fgLeaves.size();
+ const int fgBranchCount = m_frameGraphLeaves.size();
for (int i = 0; i < fgBranchCount; ++i) {
- RenderViewBuilder builder(fgLeaves.at(i), i, this);
- builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt);
- builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt);
- builder.setRenderableCacheNeedsToBeRebuilt(renderableDirty);
- builder.setComputableCacheNeedsToBeRebuilt(computeableDirty);
- builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty);
+ FrameGraphNode *leaf = m_frameGraphLeaves.at(i);
+ RenderViewBuilder builder(leaf, i, this);
+ // If we have a new RV (wasn't in the cache before, then it contains no cached data)
+ const bool isNewRV = !m_cache.leafNodeCache.contains(leaf);
+ builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt || isNewRV);
+ builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt || isNewRV);
+ builder.setRenderCommandCacheNeedsToBeRebuilt(renderCommandsDirty || isNewRV);
builder.prepareJobs();
renderBinJobs.append(builder.buildJobHierachy());
@@ -1953,9 +2058,9 @@ QAspectJobPtr Renderer::rayCastingJob()
return m_rayCastingJob;
}
-QAspectJobPtr Renderer::syncTextureLoadingJob()
+QAspectJobPtr Renderer::syncLoadingJobs()
{
- return m_syncTextureLoadingJob;
+ return m_syncLoadingJobs;
}
QAspectJobPtr Renderer::expandBoundingVolumeJob()
@@ -2099,7 +2204,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
bool allCommandsIssued = true;
// Render drawing commands
- const QVector<RenderCommand *> commands = rv->commands();
+ QVector<RenderCommand> commands = rv->commands();
// Use the graphicscontext to submit the commands to the underlying
// graphics API (OpenGL)
@@ -2108,18 +2213,18 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
RenderStateSet *globalState = m_submissionContext->currentStateSet();
OpenGLVertexArrayObject *vao = nullptr;
- for (RenderCommand *command : qAsConst(commands)) {
+ for (RenderCommand &command : commands) {
- if (command->m_type == RenderCommand::Compute) { // Compute Call
- performCompute(rv, command);
+ if (command.m_type == RenderCommand::Compute) { // Compute Call
+ performCompute(rv, &command);
} else { // Draw Command
// Check if we have a valid command that can be drawn
- if (!command->m_isValid) {
+ if (!command.m_isValid) {
allCommandsIssued = false;
continue;
}
- vao = m_nodesManager->vaoManager()->data(command->m_vao);
+ vao = m_nodesManager->vaoManager()->data(command.m_vao);
// something may have went wrong when initializing the VAO
if (!vao->isSpecified()) {
@@ -2130,7 +2235,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
{
Profiling::GLTimeRecorder recorder(Profiling::ShaderUpdate);
//// We activate the shader here
- if (!m_submissionContext->activateShader(command->m_shaderDna)) {
+ if (!m_submissionContext->activateShader(command.m_shaderDna)) {
allCommandsIssued = false;
continue;
}
@@ -2145,7 +2250,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
{
Profiling::GLTimeRecorder recorder(Profiling::UniformUpdate);
//// Update program uniforms
- if (!m_submissionContext->setParameters(command->m_parameterPack)) {
+ if (!m_submissionContext->setParameters(command.m_parameterPack)) {
allCommandsIssued = false;
// If we have failed to set uniform (e.g unable to bind a texture)
// we won't perform the draw call which could show invalid content
@@ -2156,7 +2261,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
//// OpenGL State
// TO DO: Make states not dependendent on their backend node for this step
// Set state
- RenderStateSet *localState = command->m_stateSet;
+ RenderStateSet *localState = command.m_stateSet.data();
{
@@ -2164,8 +2269,8 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
// Merge the RenderCommand state with the globalState of the RenderView
// Or restore the globalState if no stateSet for the RenderCommand
if (localState != nullptr) {
- command->m_stateSet->merge(globalState);
- m_submissionContext->setCurrentStateSet(command->m_stateSet);
+ command.m_stateSet->merge(globalState);
+ m_submissionContext->setCurrentStateSet(localState);
} else {
m_submissionContext->setCurrentStateSet(globalState);
}
@@ -2175,7 +2280,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
// at that point
//// Draw Calls
- performDraw(command);
+ performDraw(&command);
}
} // end of RenderCommands loop
@@ -2191,7 +2296,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
}
bool Renderer::updateVAOWithAttributes(Geometry *geometry,
- RenderCommand *command,
+ const RenderCommand *command,
Shader *shader,
bool forceUpdate)
{
@@ -2218,7 +2323,7 @@ bool Renderer::updateVAOWithAttributes(Geometry *geometry,
if ((attributeWasDirty = attribute->isDirty()) == true || forceUpdate)
m_submissionContext->specifyIndices(buffer);
// Vertex Attribute
- } else if (command->m_attributes.contains(attribute->nameId())) {
+ } else if (command->m_activeAttributes.contains(attribute->nameId())) {
if ((attributeWasDirty = attribute->isDirty()) == true || forceUpdate) {
// Find the location for the attribute
const QVector<ShaderAttribute> shaderAttributes = shader->attributes();
@@ -2251,7 +2356,7 @@ bool Renderer::updateVAOWithAttributes(Geometry *geometry,
}
bool Renderer::requiresVAOAttributeUpdate(Geometry *geometry,
- RenderCommand *command) const
+ const RenderCommand *command) const
{
const auto attributeIds = geometry->attributes();
@@ -2263,7 +2368,7 @@ bool Renderer::requiresVAOAttributeUpdate(Geometry *geometry,
continue;
if ((attribute->attributeType() == QAttribute::IndexAttribute && attribute->isDirty()) ||
- (command->m_attributes.contains(attribute->nameId()) && attribute->isDirty()))
+ (command->m_activeAttributes.contains(attribute->nameId()) && attribute->isDirty()))
return true;
}
return false;
@@ -2277,12 +2382,11 @@ void Renderer::cleanGraphicsResources()
for (Qt3DCore::QNodeId bufferId : buffersToRelease)
m_submissionContext->releaseBuffer(bufferId);
- // Delete abandoned textures
- const QVector<GLTexture*> abandonedTextures = m_nodesManager->glTextureManager()->takeAbandonedTextures();
- for (GLTexture *tex : abandonedTextures) {
- tex->destroyGLTexture();
- delete tex;
- }
+ // When Textures are cleaned up, their id is saved so that they can be
+ // cleaned up in the render thread
+ const QVector<Qt3DCore::QNodeId> cleanedUpTextureIds = std::move(m_textureIdsToCleanup);
+ for (const Qt3DCore::QNodeId textureCleanedUpId: cleanedUpTextureIds)
+ cleanupTexture(textureCleanedUpId);
// Delete abandoned VAOs
m_abandonedVaosMutex.lock();
diff --git a/src/render/renderers/opengl/renderer/renderer.pri b/src/render/renderers/opengl/renderer/renderer.pri
index 34f6064bd..849bac702 100644
--- a/src/render/renderers/opengl/renderer/renderer.pri
+++ b/src/render/renderers/opengl/renderer/renderer.pri
@@ -1,8 +1,6 @@
INCLUDEPATH += $$PWD
SOURCES += \
- $$PWD/commandthread.cpp \
- $$PWD/glcommands.cpp \
$$PWD/openglvertexarrayobject.cpp \
$$PWD/rendercommand.cpp \
$$PWD/renderer.cpp \
@@ -12,8 +10,6 @@ SOURCES += \
$$PWD/shaderparameterpack.cpp
HEADERS += \
- $$PWD/commandthread_p.h \
- $$PWD/glcommands_p.h \
$$PWD/openglvertexarrayobject_p.h \
$$PWD/renderercache_p.h \
$$PWD/rendercommand_p.h \
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index 9376e9eda..b2889bb0e 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -78,10 +78,11 @@
#include <Qt3DRender/private/filtercompatibletechniquejob_p.h>
#include <Qt3DRender/private/updateskinningpalettejob_p.h>
#include <Qt3DRender/private/updateentitylayersjob_p.h>
-#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
#include <Qt3DRender/private/renderercache_p.h>
#include <Qt3DRender/private/texture_p.h>
#include <Qt3DRender/private/glfence_p.h>
+#include <Qt3DRender/private/shaderbuilder_p.h>
+#include <Qt3DRender/private/lightgatherer_p.h>
#include <QHash>
#include <QMatrix4x4>
@@ -146,7 +147,6 @@ class RenderView;
class Effect;
class RenderPass;
class RenderThread;
-class CommandThread;
class RenderStateSet;
class VSyncFrameAdvanceService;
class PickEventFilter;
@@ -157,7 +157,14 @@ class UpdateLevelOfDetailJob;
typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
-using IntrospectShadersJobPtr = GenericLambdaJobPtr<std::function<void()>>;
+using SynchronizerPostFramePtr = GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>>;
+
+template<typename T, typename ... Ts>
+class FilterEntityByComponentJob;
+template<typename T, typename ... Ts>
+using FilterEntityByComponentJobPtr = QSharedPointer<FilterEntityByComponentJob<T, Ts...>>;
+using ComputableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::ComputeCommand, Render::Material>;
+using RenderableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::GeometryRenderer, Render::Material>;
class Q_3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
{
@@ -183,12 +190,12 @@ public:
void releaseGraphicsResources() override;
void render() override;
- void doRender(bool scene3dBlocking = false) override;
+ void doRender(bool swapBuffers = true) override;
void cleanGraphicsResources() override;
- bool isRunning() const override { return m_running.load(); }
+ bool isRunning() const override { return m_running.loadRelaxed(); }
- void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Entity *sgRoot) override;
+ void setSceneRoot(Entity *sgRoot) override;
Entity *sceneRoot() const override { return m_renderSceneRoot; }
FrameGraphNode *frameGraphRoot() const override;
@@ -207,7 +214,7 @@ public:
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override;
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override;
Qt3DCore::QAspectJobPtr rayCastingJob() override;
- Qt3DCore::QAspectJobPtr syncTextureLoadingJob() override;
+ Qt3DCore::QAspectJobPtr syncLoadingJobs() override;
Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override;
QVector<Qt3DCore::QAspectJobPtr> createRenderBufferJobs() const;
@@ -221,13 +228,19 @@ public:
inline UpdateLevelOfDetailJobPtr updateLevelOfDetailJob() const { return m_updateLevelOfDetailJob; }
inline UpdateMeshTriangleListJobPtr updateMeshTriangleListJob() const { return m_updateMeshTriangleListJob; }
inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; }
- inline SynchronizerJobPtr textureLoadSyncJob() const { return m_syncTextureLoadingJob; }
+ inline SynchronizerJobPtr syncLoadingJobs() const { return m_syncLoadingJobs; }
inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; }
- inline IntrospectShadersJobPtr introspectShadersJob() const { return m_introspectShaderJob; }
+ inline SynchronizerPostFramePtr introspectShadersJob() const { return m_introspectShaderJob; }
inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; }
inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; }
inline Qt3DCore::QAspectJobPtr sendTextureChangesToFrontendJob() const { return m_sendTextureChangesToFrontendJob; }
inline UpdateEntityLayersJobPtr updateEntityLayersJob() const { return m_updateEntityLayersJob; }
+ inline LightGathererPtr lightGathererJob() const { return m_lightGathererJob; }
+ inline RenderableEntityFilterPtr renderableEntityFilterJob() const { return m_renderableEntityFilterJob; }
+ inline ComputableEntityFilterPtr computableEntityFilterJob() const { return m_computableEntityFilterJob; }
+ inline SynchronizerJobPtr cacheLightJob() const { return m_cacheLightsJob; }
+ inline SynchronizerJobPtr cacheRenderableEntitiesJob() const { return m_cacheRenderableEntitiesJob; }
+ inline SynchronizerJobPtr cacheComputableEntitiesJob() const { return m_cacheComputableEntitiesJob; }
Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override;
@@ -255,12 +268,12 @@ public:
void prepareCommandsSubmission(const QVector<RenderView *> &renderViews);
bool executeCommandsSubmission(const RenderView *rv);
bool updateVAOWithAttributes(Geometry *geometry,
- RenderCommand *command,
+ const RenderCommand *command,
Shader *shader,
bool forceUpdate);
bool requiresVAOAttributeUpdate(Geometry *geometry,
- RenderCommand *command) const;
+ const RenderCommand *command) const;
void setOpenGLContext(QOpenGLContext *context) override;
const GraphicsApiFilterData *contextInfo() const;
@@ -324,7 +337,6 @@ private:
RenderQueue *m_renderQueue;
QScopedPointer<RenderThread> m_renderThread;
- QScopedPointer<CommandThread> m_commandThread;
QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService;
QSemaphore m_submitRenderViewsSemaphore;
@@ -371,7 +383,9 @@ private:
UpdateMeshTriangleListJobPtr m_updateMeshTriangleListJob;
FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob;
UpdateEntityLayersJobPtr m_updateEntityLayersJob;
- UpdateEntityHierarchyJobPtr m_updateEntityHierarchyJob;
+ LightGathererPtr m_lightGathererJob;
+ RenderableEntityFilterPtr m_renderableEntityFilterJob;
+ ComputableEntityFilterPtr m_computableEntityFilterJob;
QVector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests;
@@ -381,32 +395,40 @@ private:
HVao *previousVAOHandle,
OpenGLVertexArrayObject **vao);
- GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob;
- GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob;
- GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob;
- GenericLambdaJobPtr<std::function<void ()>> m_sendTextureChangesToFrontendJob;
- GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob;
- IntrospectShadersJobPtr m_introspectShaderJob;
-
- SynchronizerJobPtr m_syncTextureLoadingJob;
+ SynchronizerJobPtr m_bufferGathererJob;
+ SynchronizerJobPtr m_vaoGathererJob;
+ SynchronizerJobPtr m_textureGathererJob;
+ SynchronizerPostFramePtr m_sendTextureChangesToFrontendJob;
+ SynchronizerJobPtr m_sendSetFenceHandlesToFrontendJob;
+ SynchronizerPostFramePtr m_sendDisablesToFrontendJob;
+ SynchronizerPostFramePtr m_introspectShaderJob;
+ SynchronizerJobPtr m_syncLoadingJobs;
+ SynchronizerJobPtr m_cacheRenderableEntitiesJob;
+ SynchronizerJobPtr m_cacheComputableEntitiesJob;
+ SynchronizerJobPtr m_cacheLightsJob;
void lookForAbandonedVaos();
void lookForDirtyBuffers();
void lookForDownloadableBuffers();
void lookForDirtyTextures();
void reloadDirtyShaders();
- void sendTextureChangesToFrontend();
+ void sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager);
+ void sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager);
void sendSetFenceHandlesToFrontend();
+ void sendDisablesToFrontend(Qt3DCore::QAspectManager *manager);
QMutex m_abandonedVaosMutex;
QVector<HVao> m_abandonedVaos;
QVector<HBuffer> m_dirtyBuffers;
- QVector<HBuffer> m_downloadableBuffers;
+ QVector<Qt3DCore::QNodeId> m_downloadableBuffers;
QVector<HShader> m_dirtyShaders;
QVector<HTexture> m_dirtyTextures;
QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties;
QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences;
+ QVector<Qt3DCore::QNodeId> m_updatedDisableSubtreeEnablers;
+ Qt3DCore::QNodeIdVector m_textureIdsToCleanup;
+ QVector<ShaderBuilderUpdate> m_shaderBuilderUpdates;
bool m_ownedContext;
@@ -424,6 +446,9 @@ private:
QMetaObject::Connection m_contextConnection;
RendererCache m_cache;
+ bool m_shouldSwapBuffers;
+
+ QVector<FrameGraphNode *> m_frameGraphLeaves;
QScreen *m_screen = nullptr;
};
diff --git a/src/render/renderers/opengl/renderer/renderercache_p.h b/src/render/renderers/opengl/renderer/renderercache_p.h
index 0e9c5d3cd..02fe4ff41 100644
--- a/src/render/renderers/opengl/renderer/renderercache_p.h
+++ b/src/render/renderers/opengl/renderer/renderercache_p.h
@@ -56,6 +56,7 @@
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/renderviewjobutils_p.h>
#include <Qt3DRender/private/lightsource_p.h>
+#include <Qt3DRender/private/rendercommand_p.h>
QT_BEGIN_NAMESPACE
@@ -69,12 +70,16 @@ struct RendererCache
{
QVector<Entity *> filterEntitiesByLayer;
MaterialParameterGathererData materialParameterGatherer;
- QVector<LightSource> gatheredLights;
- QVector<Entity *> renderableEntities;
- QVector<Entity *> computeEntities;
- EnvironmentLight* environmentLight;
+ EntityRenderCommandData renderCommandData;
};
+ // Shared amongst all RV cache
+ QVector<Entity *> renderableEntities;
+ QVector<Entity *> computeEntities;
+ QVector<LightSource> gatheredLights;
+ EnvironmentLight* environmentLight;
+
+ // Per RV cache
QHash<FrameGraphNode *, LeafNodeData> leafNodeCache;
QMutex *mutex() { return &m_mutex; }
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp
index dd394b5f7..0ac4f876f 100644
--- a/src/render/renderers/opengl/renderer/renderview.cpp
+++ b/src/render/renderers/opengl/renderer/renderview.cpp
@@ -238,11 +238,14 @@ RenderView::RenderView()
: m_isDownloadBuffersEnable(false)
, m_hasBlitFramebufferInfo(false)
, m_renderer(nullptr)
+ , m_manager(nullptr)
, m_devicePixelRatio(1.)
- , m_viewport(QRectF(0.0f, 0.0f, 1.0f, 1.0f))
+ , m_viewport(QRectF(0., 0., 1., 1.))
, m_gamma(2.2f)
, m_surface(nullptr)
, m_clearBuffer(QClearBuffers::None)
+ , m_clearDepthValue(1.f)
+ , m_clearStencilValue(0)
, m_stateSet(nullptr)
, m_noDraw(false)
, m_compute(false)
@@ -279,11 +282,6 @@ RenderView::RenderView()
RenderView::~RenderView()
{
- delete m_stateSet;
- for (RenderCommand *command : qAsConst(m_commands)) {
- delete command->m_stateSet;
- delete command;
- }
}
namespace {
@@ -291,7 +289,7 @@ namespace {
template<int SortType>
struct AdjacentSubRangeFinder
{
- static bool adjacentSubRange(RenderCommand *, RenderCommand *)
+ static bool adjacentSubRange(const RenderCommand &, const RenderCommand &)
{
Q_UNREACHABLE();
return false;
@@ -301,41 +299,62 @@ struct AdjacentSubRangeFinder
template<>
struct AdjacentSubRangeFinder<QSortPolicy::StateChangeCost>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_changeCost == b->m_changeCost;
+ return a.m_changeCost == b.m_changeCost;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::BackToFront>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_depth == b->m_depth;
+ return a.m_depth == b.m_depth;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::Material>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_shaderDna == b->m_shaderDna;
+ return a.m_shaderDna == b.m_shaderDna;
}
};
template<>
struct AdjacentSubRangeFinder<QSortPolicy::FrontToBack>
{
- static bool adjacentSubRange(RenderCommand *a, RenderCommand *b)
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
+ {
+ return a.m_depth == b.m_depth;
+ }
+};
+
+template<>
+struct AdjacentSubRangeFinder<QSortPolicy::Texture>
+{
+ static bool adjacentSubRange(const RenderCommand &a, const RenderCommand &b)
{
- return a->m_depth == b->m_depth;
+ // Two renderCommands are adjacent if one contains all the other command's textures
+ QVector<ShaderParameterPack::NamedResource> texturesA = a.m_parameterPack.textures();
+ QVector<ShaderParameterPack::NamedResource> texturesB = b.m_parameterPack.textures();
+
+ if (texturesB.size() > texturesA.size())
+ qSwap(texturesA, texturesB);
+
+ // textureB.size() is always <= textureA.size()
+ for (const ShaderParameterPack::NamedResource &texB : qAsConst(texturesB)) {
+ if (!texturesA.contains(texB))
+ return false;
+ }
+ return true;
}
};
template<typename Predicate>
-int advanceUntilNonAdjacent(const QVector<RenderCommand *> &commands,
+int advanceUntilNonAdjacent(const QVector<RenderCommand> &commands,
const int beg, const int end, Predicate pred)
{
int i = beg + 1;
@@ -348,7 +367,7 @@ int advanceUntilNonAdjacent(const QVector<RenderCommand *> &commands,
}
-using CommandIt = QVector<RenderCommand *>::iterator;
+using CommandIt = QVector<RenderCommand>::iterator;
template<int SortType>
struct SubRangeSorter
@@ -366,8 +385,8 @@ struct SubRangeSorter<QSortPolicy::StateChangeCost>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_changeCost > b->m_changeCost;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_changeCost > b.m_changeCost;
});
}
};
@@ -377,8 +396,8 @@ struct SubRangeSorter<QSortPolicy::BackToFront>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_depth > b->m_depth;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_depth > b.m_depth;
});
}
};
@@ -389,8 +408,8 @@ struct SubRangeSorter<QSortPolicy::Material>
static void sortSubRange(CommandIt begin, const CommandIt end)
{
// First we sort by shaderDNA
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_shaderDna > b->m_shaderDna;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_shaderDna > b.m_shaderDna;
});
}
};
@@ -400,13 +419,39 @@ struct SubRangeSorter<QSortPolicy::FrontToBack>
{
static void sortSubRange(CommandIt begin, const CommandIt end)
{
- std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) {
- return a->m_depth < b->m_depth;
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ return a.m_depth < b.m_depth;
+ });
+ }
+};
+
+template<>
+struct SubRangeSorter<QSortPolicy::Texture>
+{
+ static void sortSubRange(CommandIt begin, const CommandIt end)
+ {
+ std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) {
+ QVector<ShaderParameterPack::NamedResource> texturesA = a.m_parameterPack.textures();
+ QVector<ShaderParameterPack::NamedResource> texturesB = b.m_parameterPack.textures();
+
+ const int originalTextureASize = texturesA.size();
+
+ if (texturesB.size() > texturesA.size())
+ qSwap(texturesA, texturesB);
+
+ int identicalTextureCount = 0;
+
+ for (const ShaderParameterPack::NamedResource &texB : qAsConst(texturesB)) {
+ if (texturesA.contains(texB))
+ ++identicalTextureCount;
+ }
+
+ return identicalTextureCount < originalTextureASize;
});
}
};
-int findSubRange(const QVector<RenderCommand *> &commands,
+int findSubRange(const QVector<RenderCommand> &commands,
const int begin, const int end,
const QSortPolicy::SortType sortType)
{
@@ -419,20 +464,22 @@ int findSubRange(const QVector<RenderCommand *> &commands,
return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange);
case QSortPolicy::FrontToBack:
return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::FrontToBack>::adjacentSubRange);
+ case QSortPolicy::Texture:
+ return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Texture>::adjacentSubRange);
default:
Q_UNREACHABLE();
return end;
}
}
-void sortByMaterial(QVector<RenderCommand *> &commands, int begin, const int end)
+void sortByMaterial(QVector<RenderCommand> &commands, int begin, const int end)
{
// We try to arrange elements so that their rendering cost is minimized for a given shader
int rangeEnd = advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange);
while (begin != end) {
if (begin + 1 < rangeEnd) {
- std::stable_sort(commands.begin() + begin + 1, commands.begin() + rangeEnd, [] (RenderCommand *a, RenderCommand *b){
- return a->m_material.handle() < b->m_material.handle();
+ std::stable_sort(commands.begin() + begin + 1, commands.begin() + rangeEnd, [] (const RenderCommand &a, const RenderCommand &b){
+ return a.m_material.handle() < b.m_material.handle();
});
}
begin = rangeEnd;
@@ -440,7 +487,7 @@ void sortByMaterial(QVector<RenderCommand *> &commands, int begin, const int end
}
}
-void sortCommandRange(QVector<RenderCommand *> &commands, int begin, const int end, const int level,
+void sortCommandRange(QVector<RenderCommand> &commands, int begin, const int end, const int level,
const QVector<Qt3DRender::QSortPolicy::SortType> &sortingTypes)
{
if (level >= sortingTypes.size())
@@ -462,6 +509,9 @@ void sortCommandRange(QVector<RenderCommand *> &commands, int begin, const int e
case QSortPolicy::FrontToBack:
SubRangeSorter<QSortPolicy::FrontToBack>::sortSubRange(commands.begin() + begin, commands.begin() + end);
break;
+ case QSortPolicy::Texture:
+ SubRangeSorter<QSortPolicy::Texture>::sortSubRange(commands.begin() + begin, commands.begin() + end);
+ break;
default:
Q_UNREACHABLE();
}
@@ -487,24 +537,23 @@ void RenderView::sort()
// Minimize uniform changes
int i = 0;
- while (i < m_commands.size()) {
+ const int commandSize = m_commands.size();
+ while (i < commandSize) {
int j = i;
// Advance while commands share the same shader
- while (i < m_commands.size() && m_commands[j]->m_shaderDna == m_commands[i]->m_shaderDna)
+ while (i < commandSize && m_commands[j].m_shaderDna == m_commands[i].m_shaderDna)
++i;
if (i - j > 0) { // Several commands have the same shader, so we minimize uniform changes
- PackUniformHash cachedUniforms = m_commands[j++]->m_parameterPack.uniforms();
+ PackUniformHash cachedUniforms = m_commands[j++].m_parameterPack.uniforms();
while (j < i) {
// We need the reference here as we are modifying the original container
// not the copy
- PackUniformHash &uniforms = m_commands.at(j)->m_parameterPack.m_uniforms;
- PackUniformHash::iterator it = uniforms.begin();
- const PackUniformHash::iterator end = uniforms.end();
+ PackUniformHash &uniforms = m_commands[j].m_parameterPack.m_uniforms;
- while (it != end) {
+ for (int u = 0; u < uniforms.keys.size();) {
// We are comparing the values:
// - raw uniform values
// - the texture Node id if the uniform represents a texture
@@ -512,12 +561,17 @@ void RenderView::sort()
// sharing the same material (shader) are rendered, we can't have the case
// where two uniforms, referencing the same texture eventually have 2 different
// texture unit values
- const UniformValue refValue = cachedUniforms.value(it.key());
- if (it.value() == refValue) {
- it = uniforms.erase(it);
+ const int uniformNameId = uniforms.keys.at(u);
+ const UniformValue &refValue = cachedUniforms.value(uniformNameId);
+ const UniformValue &newValue = uniforms.values.at(u);
+ if (newValue == refValue) {
+ uniforms.erase(u);
} else {
- cachedUniforms.insert(it.key(), it.value());
- ++it;
+ // Record updated value so that subsequent comparison
+ // for the next command will be made againts latest
+ // uniform value
+ cachedUniforms.insert(uniformNameId, newValue);
+ ++u;
}
}
++j;
@@ -567,17 +621,10 @@ void RenderView::addClearBuffers(const ClearBuffers *cb) {
}
// If we are there, we know that entity had a GeometryRenderer + Material
-QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const
+EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const
{
- // Note: since many threads can be building render commands
- // we need to ensure that the UniformBlockValueBuilder they are using
- // is only accessed from the same thread
- UniformBlockValueBuilder *builder = new UniformBlockValueBuilder();
- builder->shaderDataManager = m_manager->shaderDataManager();
- builder->textureManager = m_manager->textureManager();
- m_localData.setLocalData(builder);
+ EntityRenderCommandData commands;
- QVector<RenderCommand *> commands;
commands.reserve(entities.size());
for (Entity *entity : entities) {
@@ -592,184 +639,153 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit
const Qt3DCore::QNodeId materialComponentId = entity->componentUuid<Material>();
const HMaterial materialHandle = entity->componentHandle<Material>();
const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId);
- HGeometry geometryHandle = m_manager->lookupHandle<Geometry, GeometryManager, HGeometry>(geometryRenderer->geometryId());
- Geometry *geometry = m_manager->data<Geometry, GeometryManager>(geometryHandle);
// 1 RenderCommand per RenderPass pass on an Entity with a Mesh
for (const RenderPassParameterData &passData : renderPassData) {
// Add the RenderPass Parameters
- RenderCommand *command = new RenderCommand();
+ RenderCommand command = {};
+ command.m_geometryRenderer = geometryRendererHandle;
+ command.m_geometry = m_manager->geometryManager()->lookupHandle(geometryRenderer->geometryId());
- // Project the camera-to-object-center vector onto the camera
- // view vector. This gives a depth value suitable as the key
- // for BackToFront sorting.
- command->m_depth = Vector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir);
-
- command->m_geometry = geometryHandle;
- command->m_geometryRenderer = geometryRendererHandle;
- command->m_material = materialHandle;
+ command.m_material = materialHandle;
// For RenderPass based states we use the globally set RenderState
// if no renderstates are defined as part of the pass. That means:
// RenderPass { renderStates: [] } will use the states defined by
// StateSet in the FrameGraph
RenderPass *pass = passData.pass;
if (pass->hasRenderStates()) {
- command->m_stateSet = new RenderStateSet();
- addStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager());
+ command.m_stateSet = RenderStateSetPtr::create();
+ addStatesToRenderStateSet(command.m_stateSet.data(), pass->renderStates(), m_manager->renderStateManager());
if (m_stateSet != nullptr)
- command->m_stateSet->merge(m_stateSet);
- command->m_changeCost = m_renderer->defaultRenderState()->changeCost(command->m_stateSet);
- }
-
- // Pick which lights to take in to account.
- // For now decide based on the distance by taking the MAX_LIGHTS closest lights.
- // Replace with more sophisticated mechanisms later.
- // Copy vector so that we can sort it concurrently and we only want to sort the one for the current command
- QVector<LightSource> lightSources = m_lightSources;
- if (lightSources.size() > 1) {
- const Vector3D entityCenter = entity->worldBoundingVolume()->center();
- std::sort(lightSources.begin(), lightSources.end(),
- [&] (const LightSource &a, const LightSource &b) {
- const float distA = entityCenter.distanceToPoint(a.entity->worldBoundingVolume()->center());
- const float distB = entityCenter.distanceToPoint(b.entity->worldBoundingVolume()->center());
- return distA < distB;
- });
+ command.m_stateSet->merge(m_stateSet);
+ command.m_changeCost = m_renderer->defaultRenderState()->changeCost(command.m_stateSet.data());
}
+ command.m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(pass->shaderProgram());
- ParameterInfoList globalParameters = passData.parameterInfo;
- // setShaderAndUniforms can initialize a localData
- // make sure this is cleared before we leave this function
- setShaderAndUniforms(command,
- pass,
- globalParameters,
- entity,
- lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS)),
- m_environmentLight);
-
- // Store all necessary information for actual drawing if command is valid
- command->m_isValid = !command->m_attributes.empty();
- if (command->m_isValid) {
- // Update the draw command with what's going to be needed for the drawing
- uint primitiveCount = geometryRenderer->vertexCount();
- uint estimatedCount = 0;
- Attribute *indexAttribute = nullptr;
-
- const QVector<Qt3DCore::QNodeId> attributeIds = geometry->attributes();
- for (Qt3DCore::QNodeId attributeId : attributeIds) {
- Attribute *attribute = m_manager->attributeManager()->lookupResource(attributeId);
- if (attribute->attributeType() == QAttribute::IndexAttribute)
- indexAttribute = attribute;
- else if (command->m_attributes.contains(attribute->nameId()))
- estimatedCount = qMax(attribute->count(), estimatedCount);
- }
-
- // Update the draw command with all the information required for the drawing
- command->m_drawIndexed = (indexAttribute != nullptr);
- if (command->m_drawIndexed) {
- command->m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType());
- command->m_indexAttributeByteOffset = indexAttribute->byteOffset();
- }
-
- // Use the count specified by the GeometryRender
- // If not specified use the indexAttribute count if present
- // Otherwise tries to use the count from the attribute with the highest count
- if (primitiveCount == 0) {
- if (indexAttribute)
- primitiveCount = indexAttribute->count();
- else
- primitiveCount = estimatedCount;
- }
-
- command->m_primitiveCount = primitiveCount;
- command->m_primitiveType = geometryRenderer->primitiveType();
- command->m_primitiveRestartEnabled = geometryRenderer->primitiveRestartEnabled();
- command->m_restartIndexValue = geometryRenderer->restartIndexValue();
- command->m_firstInstance = geometryRenderer->firstInstance();
- command->m_instanceCount = geometryRenderer->instanceCount();
- command->m_firstVertex = geometryRenderer->firstVertex();
- command->m_indexOffset = geometryRenderer->indexOffset();
- command->m_verticesPerPatch = geometryRenderer->verticesPerPatch();
- }
-
- commands.append(command);
+ commands.push_back(entity,
+ std::move(command),
+ std::move(passData));
}
}
}
- // We reset the local data once we are done with it
- m_localData.setLocalData(nullptr);
-
return commands;
}
-QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const
+EntityRenderCommandData RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const
{
- // Note: since many threads can be building render commands
- // we need to ensure that the UniformBlockValueBuilder they are using
- // is only accessed from the same thread
- UniformBlockValueBuilder *builder = new UniformBlockValueBuilder();
- builder->shaderDataManager = m_manager->shaderDataManager();
- builder->textureManager = m_manager->textureManager();
- m_localData.setLocalData(builder);
-
// If the RenderView contains only a ComputeDispatch then it cares about
// A ComputeDispatch is also implicitely a NoDraw operation
// enabled flag
// layer component
// material/effect/technique/parameters/filters/
- QVector<RenderCommand *> commands;
+ EntityRenderCommandData commands;
+
commands.reserve(entities.size());
+
for (Entity *entity : entities) {
ComputeCommand *computeJob = nullptr;
- if ((computeJob = entity->renderComponent<ComputeCommand>()) != nullptr
+ HComputeCommand computeCommandHandle = entity->componentHandle<ComputeCommand>();
+ if ((computeJob = nodeManagers()->computeJobManager()->data(computeCommandHandle)) != nullptr
&& computeJob->isEnabled()) {
- // Note: if frameCount has reached 0 in the previous frame, isEnabled
- // would be false
- if (computeJob->runType() == QComputeCommand::Manual)
- computeJob->updateFrameCount();
-
const Qt3DCore::QNodeId materialComponentId = entity->componentUuid<Material>();
const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId);
// 1 RenderCommand per RenderPass pass on an Entity with a Mesh
for (const RenderPassParameterData &passData : renderPassData) {
// Add the RenderPass Parameters
- RenderCommand *command = new RenderCommand();
+ RenderCommand command = {};
RenderPass *pass = passData.pass;
if (pass->hasRenderStates()) {
- command->m_stateSet = new RenderStateSet();
- addStatesToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager());
+ command.m_stateSet = RenderStateSetPtr::create();
+ addStatesToRenderStateSet(command.m_stateSet.data(), pass->renderStates(), m_manager->renderStateManager());
// Merge per pass stateset with global stateset
// so that the local stateset only overrides
if (m_stateSet != nullptr)
- command->m_stateSet->merge(m_stateSet);
- command->m_changeCost = m_renderer->defaultRenderState()->changeCost(command->m_stateSet);
+ command.m_stateSet->merge(m_stateSet);
+ command.m_changeCost = m_renderer->defaultRenderState()->changeCost(command.m_stateSet.data());
}
+ command.m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(pass->shaderProgram());
+ command.m_computeCommand = computeCommandHandle;
+ command.m_type = RenderCommand::Compute;
+ command.m_workGroups[0] = std::max(m_workGroups[0], computeJob->x());
+ command.m_workGroups[1] = std::max(m_workGroups[1], computeJob->y());
+ command.m_workGroups[2] = std::max(m_workGroups[2], computeJob->z());
+
+ commands.push_back(entity,
+ std::move(command),
+ std::move(passData));
+ }
+ }
+ }
+
+ return commands;
+}
+
+void RenderView::updateRenderCommand(EntityRenderCommandData &renderCommandData)
+{
+ // Note: since many threads can be building render commands
+ // we need to ensure that the UniformBlockValueBuilder they are using
+ // is only accessed from the same thread
+ UniformBlockValueBuilder *builder = new UniformBlockValueBuilder();
+ builder->shaderDataManager = m_manager->shaderDataManager();
+ builder->textureManager = m_manager->textureManager();
+ m_localData.setLocalData(builder);
- command->m_type = RenderCommand::Compute;
- command->m_workGroups[0] = std::max(m_workGroups[0], computeJob->x());
- command->m_workGroups[1] = std::max(m_workGroups[1], computeJob->y());
- command->m_workGroups[2] = std::max(m_workGroups[2], computeJob->z());
-
- ParameterInfoList globalParameters = passData.parameterInfo;
- setShaderAndUniforms(command,
- pass,
- globalParameters,
- entity,
- QVector<LightSource>(),
- nullptr);
- commands.append(command);
+ for (int i = 0, m = renderCommandData.size(); i < m; ++i) {
+ Entity *entity = renderCommandData.entities.at(i);
+ const RenderPassParameterData passData = renderCommandData.passesData.at(i);
+ RenderCommand &command = renderCommandData.commands[i];
+
+ // Pick which lights to take in to account.
+ // For now decide based on the distance by taking the MAX_LIGHTS closest lights.
+ // Replace with more sophisticated mechanisms later.
+ // Copy vector so that we can sort it concurrently and we only want to sort the one for the current command
+ QVector<LightSource> lightSources;
+ EnvironmentLight *environmentLight = nullptr;
+
+ if (command.m_type == RenderCommand::Draw) {
+ // Project the camera-to-object-center vector onto the camera
+ // view vector. This gives a depth value suitable as the key
+ // for BackToFront sorting.
+ command.m_depth = Vector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir);
+
+ environmentLight = m_environmentLight;
+ lightSources = m_lightSources;
+
+ if (lightSources.size() > 1) {
+ const Vector3D entityCenter = entity->worldBoundingVolume()->center();
+ std::sort(lightSources.begin(), lightSources.end(),
+ [&] (const LightSource &a, const LightSource &b) {
+ const float distA = entityCenter.distanceToPoint(a.entity->worldBoundingVolume()->center());
+ const float distB = entityCenter.distanceToPoint(b.entity->worldBoundingVolume()->center());
+ return distA < distB;
+ });
}
+ lightSources = lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS));
+ } else { // Compute
+ // Note: if frameCount has reached 0 in the previous frame, isEnabled
+ // would be false
+ ComputeCommand *computeJob = m_manager->computeJobManager()->data(command.m_computeCommand);
+ if (computeJob->runType() == QComputeCommand::Manual)
+ computeJob->updateFrameCount();
}
+
+ ParameterInfoList globalParameters = passData.parameterInfo;
+ // setShaderAndUniforms can initialize a localData
+ // make sure this is cleared before we leave this function
+ setShaderAndUniforms(&command,
+ globalParameters,
+ entity,
+ lightSources,
+ environmentLight);
}
// We reset the local data once we are done with it
m_localData.setLocalData(nullptr);
-
- return commands;
}
void RenderView::updateMatrices()
@@ -796,23 +812,35 @@ void RenderView::updateMatrices()
void RenderView::setUniformValue(ShaderParameterPack &uniformPack, int nameId, const UniformValue &value) const
{
// At this point a uniform value can only be a scalar type
- // or a Qt3DCore::QNodeId corresponding to a Texture
+ // or a Qt3DCore::QNodeId corresponding to a Texture or Image
// ShaderData/Buffers would be handled as UBO/SSBO and would therefore
// not be in the default uniform block
if (value.valueType() == UniformValue::NodeId) {
const Qt3DCore::QNodeId *nodeIds = value.constData<Qt3DCore::QNodeId>();
const int uniformArraySize = value.byteSize() / sizeof(Qt3DCore::QNodeId);
+ UniformValue::ValueType resourceType = UniformValue::TextureValue;
+
for (int i = 0; i < uniformArraySize; ++i) {
- const Qt3DCore::QNodeId texId = nodeIds[i];
- const Texture *tex = m_manager->textureManager()->lookupResource(texId);
- if (tex != nullptr)
- uniformPack.setTexture(nameId, i, texId);
+ const Qt3DCore::QNodeId resourceId = nodeIds[i];
+
+ const Texture *tex = m_manager->textureManager()->lookupResource(resourceId);
+ if (tex != nullptr) {
+ uniformPack.setTexture(nameId, i, resourceId);
+ } else {
+ const ShaderImage *img = m_manager->shaderImageManager()->lookupResource(resourceId);
+ if (img != nullptr) {
+ resourceType = UniformValue::ShaderImageValue;
+ uniformPack.setImage(nameId, i, resourceId);
+ }
+ }
}
- UniformValue textureValue(uniformArraySize * sizeof(int), UniformValue::TextureValue);
- std::fill(textureValue.data<int>(), textureValue.data<int>() + uniformArraySize, -1);
- uniformPack.setUniform(nameId, textureValue);
+ // This uniform will be overridden in SubmissionContext::setParameters
+ // and -1 values will be replaced by valid Texture or Image units
+ UniformValue uniformValue(uniformArraySize * sizeof(int), resourceType);
+ std::fill(uniformValue.data<int>(), uniformValue.data<int>() + uniformArraySize, -1);
+ uniformPack.setUniform(nameId, uniformValue);
} else {
uniformPack.setUniform(nameId, value);
}
@@ -845,56 +873,6 @@ void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack,
uniformPack.setUniformBuffer(std::move(uniformBlockUBO));
// Buffer update to GL buffer will be done at render time
}
-
-
- //ShaderData *shaderData = nullptr;
- // if ((shaderData = m_manager->shaderDataManager()->lookupResource(value.value<Qt3DCore::QNodeId>())) != nullptr) {
- // UBO are indexed by <ShaderId, ShaderDataId> so that a same QShaderData can be used among different shaders
- // while still making sure that if they have a different layout everything will still work
- // If two shaders define the same block with the exact same layout, in that case the UBO could be shared
- // but how do we know that ? We'll need to compare ShaderUniformBlocks
-
- // Note: we assume that if a buffer is shared across multiple shaders
- // then it implies that they share the same layout
-
- // Temporarly disabled
-
- // BufferShaderKey uboKey(shaderData->peerId(),
- // shader->peerId());
-
- // BlockToUBO uniformBlockUBO;
- // uniformBlockUBO.m_blockIndex = block.m_index;
- // uniformBlockUBO.m_shaderDataID = shaderData->peerId();
- // bool uboNeedsUpdate = false;
-
- // // build UBO at uboId if not created before
- // if (!m_manager->glBufferManager()->contains(uboKey)) {
- // m_manager->glBufferManager()->getOrCreateResource(uboKey);
- // uboNeedsUpdate = true;
- // }
-
- // // If shaderData has been updated (property has changed or one of the nested properties has changed)
- // // foreach property defined in the QShaderData, we try to fill the value of the corresponding active uniform(s)
- // // for all the updated properties (all the properties if the UBO was just created)
- // if (shaderData->updateViewTransform(*m_data->m_viewMatrix) || uboNeedsUpdate) {
- // // Clear previous values remaining in the hash
- // m_data->m_uniformBlockBuilder.activeUniformNamesToValue.clear();
- // // Update only update properties if uboNeedsUpdate is true, otherwise update the whole block
- // m_data->m_uniformBlockBuilder.updatedPropertiesOnly = uboNeedsUpdate;
- // // Retrieve names and description of each active uniforms in the uniform block
- // m_data->m_uniformBlockBuilder.uniforms = shader->activeUniformsForUniformBlock(block.m_index);
- // // Builds the name-value map for the block
- // m_data->m_uniformBlockBuilder.buildActiveUniformNameValueMapStructHelper(shaderData, block.m_name);
- // if (!uboNeedsUpdate)
- // shaderData->markDirty();
- // // copy the name-value map into the BlockToUBO
- // uniformBlockUBO.m_updatedProperties = m_data->m_uniformBlockBuilder.activeUniformNamesToValue;
- // uboNeedsUpdate = true;
- // }
-
- // uniformBlockUBO.m_needsUpdate = uboNeedsUpdate;
- // uniformPack.setUniformBuffer(std::move(uniformBlockUBO));
- // }
}
}
@@ -942,7 +920,6 @@ void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &unif
}
void RenderView::setShaderAndUniforms(RenderCommand *command,
- RenderPass *rPass,
ParameterInfoList &parameters,
Entity *entity,
const QVector<LightSource> &activeLightSources,
@@ -958,164 +935,159 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
// For each ParameterBinder in the RenderPass -> create a QUniformPack
// Once that works, improve that to try and minimize QUniformPack updates
- if (rPass != nullptr) {
- // Index Shader by Shader UUID
- command->m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(rPass->shaderProgram());
- Shader *shader = m_manager->data<Shader, ShaderManager>(command->m_shader);
- if (shader != nullptr && shader->isLoaded()) {
- command->m_shaderDna = shader->dna();
-
- // Builds the QUniformPack, sets shader standard uniforms and store attributes name / glname bindings
- // If a parameter is defined and not found in the bindings it is assumed to be a binding of Uniform type with the glsl name
- // equals to the parameter name
- const QVector<int> uniformNamesIds = shader->uniformsNamesIds();
- const QVector<int> uniformBlockNamesIds = shader->uniformBlockNamesIds();
- const QVector<int> shaderStorageBlockNamesIds = shader->storageBlockNamesIds();
- const QVector<int> attributeNamesIds = shader->attributeNamesIds();
-
- // Set fragData Name and index
- // Later on we might want to relink the shader if attachments have changed
- // But for now we set them once and for all
+ // Index Shader by Shader UUID
+ Shader *shader = m_manager->data<Shader, ShaderManager>(command->m_shader);
+ if (shader != nullptr && shader->isLoaded()) {
+ command->m_shaderDna = shader->dna();
+
+ // Builds the QUniformPack, sets shader standard uniforms and store attributes name / glname bindings
+ // If a parameter is defined and not found in the bindings it is assumed to be a binding of Uniform type with the glsl name
+ // equals to the parameter name
+ const QVector<int> uniformNamesIds = shader->uniformsNamesIds();
+ const QVector<int> uniformBlockNamesIds = shader->uniformBlockNamesIds();
+ const QVector<int> shaderStorageBlockNamesIds = shader->storageBlockNamesIds();
+ const QVector<int> attributeNamesIds = shader->attributeNamesIds();
+
+ // Set fragData Name and index
+ // Later on we might want to relink the shader if attachments have changed
+ // But for now we set them once and for all
+ if (!m_renderTarget.isNull() && !shader->isLoaded()) {
QHash<QString, int> fragOutputs;
- if (!m_renderTarget.isNull() && !shader->isLoaded()) {
- const auto atts = m_attachmentPack.attachments();
- for (const Attachment &att : atts) {
- if (att.m_point <= QRenderTargetOutput::Color15)
- fragOutputs.insert(att.m_name, att.m_point);
- }
+ const auto atts = m_attachmentPack.attachments();
+ for (const Attachment &att : atts) {
+ if (att.m_point <= QRenderTargetOutput::Color15)
+ fragOutputs.insert(att.m_name, att.m_point);
}
+ // Set frag outputs in the shaders if hash not empty
+ if (!fragOutputs.isEmpty())
+ shader->setFragOutputs(fragOutputs);
+ }
- if (!uniformNamesIds.isEmpty() || !attributeNamesIds.isEmpty() ||
- !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) {
+ if (!uniformNamesIds.isEmpty() || !attributeNamesIds.isEmpty() ||
+ !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) {
- // Set default standard uniforms without bindings
- const Matrix4x4 worldTransform = *(entity->worldTransform());
- for (const int uniformNameId : uniformNamesIds) {
- if (ms_standardUniformSetters.contains(uniformNameId))
- setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform);
- }
+ // Set default standard uniforms without bindings
+ const Matrix4x4 worldTransform = *(entity->worldTransform());
- // Set default attributes
- for (const int attributeNameId : attributeNamesIds)
- command->m_attributes.push_back(attributeNameId);
-
- // Parameters remaining could be
- // -> uniform scalar / vector
- // -> uniform struct / arrays
- // -> uniform block / array (4.3)
- // -> ssbo block / array (4.3)
-
- ParameterInfoList::const_iterator it = parameters.cbegin();
- const ParameterInfoList::const_iterator parametersEnd = parameters.cend();
-
- while (it != parametersEnd) {
- Parameter *param = m_manager->data<Parameter, ParameterManager>(it->handle);
- const UniformValue &uniformValue = param->uniformValue();
- if (uniformNamesIds.contains(it->nameId)) { // Parameter is a regular uniform
- setUniformValue(command->m_parameterPack, it->nameId, uniformValue);
- } else if (uniformBlockNamesIds.indexOf(it->nameId) != -1) { // Parameter is a uniform block
- setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlockForBlockNameId(it->nameId), uniformValue);
- } else if (shaderStorageBlockNamesIds.indexOf(it->nameId) != -1) { // Parameters is a SSBO
- setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlockForBlockNameId(it->nameId), uniformValue);
- } else { // Parameter is a struct
- ShaderData *shaderData = nullptr;
- if (uniformValue.valueType() == UniformValue::NodeId &&
- (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData<Qt3DCore::QNodeId>())) != nullptr) {
- // Try to check if we have a struct or array matching a QShaderData parameter
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(it->nameId));
- }
- // Otherwise: param unused by current shader
+ for (const int uniformNameId : uniformNamesIds) {
+ if (ms_standardUniformSetters.contains(uniformNameId))
+ setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform);
+ }
+
+ // Set default attributes
+ command->m_activeAttributes = attributeNamesIds;
+
+ // Parameters remaining could be
+ // -> uniform scalar / vector
+ // -> uniform struct / arrays
+ // -> uniform block / array (4.3)
+ // -> ssbo block / array (4.3)
+
+ ParameterInfoList::const_iterator it = parameters.cbegin();
+ const ParameterInfoList::const_iterator parametersEnd = parameters.cend();
+
+ while (it != parametersEnd) {
+ Parameter *param = m_manager->data<Parameter, ParameterManager>(it->handle);
+ const UniformValue &uniformValue = param->uniformValue();
+ if (uniformNamesIds.contains(it->nameId)) { // Parameter is a regular uniform
+ setUniformValue(command->m_parameterPack, it->nameId, uniformValue);
+ } else if (uniformBlockNamesIds.indexOf(it->nameId) != -1) { // Parameter is a uniform block
+ setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlockForBlockNameId(it->nameId), uniformValue);
+ } else if (shaderStorageBlockNamesIds.indexOf(it->nameId) != -1) { // Parameters is a SSBO
+ setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlockForBlockNameId(it->nameId), uniformValue);
+ } else { // Parameter is a struct
+ ShaderData *shaderData = nullptr;
+ if (uniformValue.valueType() == UniformValue::NodeId &&
+ (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData<Qt3DCore::QNodeId>())) != nullptr) {
+ // Try to check if we have a struct or array matching a QShaderData parameter
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(it->nameId));
}
- ++it;
+ // Otherwise: param unused by current shader
}
+ ++it;
+ }
- // Lights
+ // Lights
+
+ int lightIdx = 0;
+ for (const LightSource &lightSource : activeLightSources) {
+ if (lightIdx == MAX_LIGHTS)
+ break;
+ Entity *lightEntity = lightSource.entity;
+ const Matrix4x4 lightWorldTransform = *(lightEntity->worldTransform());
+ const Vector3D worldPos = lightWorldTransform * Vector3D(0.0f, 0.0f, 0.0f);
+ for (Light *light : lightSource.lights) {
+ if (!light->isEnabled())
+ continue;
+
+ ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(light->shaderData());
+ if (!shaderData)
+ continue;
- int lightIdx = 0;
- for (const LightSource &lightSource : activeLightSources) {
if (lightIdx == MAX_LIGHTS)
break;
- Entity *lightEntity = lightSource.entity;
- const Matrix4x4 lightWorldTransform = *(lightEntity->worldTransform());
- const Vector3D worldPos = lightWorldTransform * Vector3D(0.0f, 0.0f, 0.0f);
- for (Light *light : lightSource.lights) {
- if (!light->isEnabled())
- continue;
-
- ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(light->shaderData());
- if (!shaderData)
- continue;
-
- if (lightIdx == MAX_LIGHTS)
- break;
-
- // Note: implicit conversion of values to UniformValue
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[lightIdx], worldPos);
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[lightIdx], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f);
-
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos);
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[lightIdx], 0.5f);
-
- // There is no risk in doing that even if multithreaded
- // since we are sure that a shaderData is unique for a given light
- // and won't ever be referenced as a Component either
- Matrix4x4 *worldTransform = lightEntity->worldTransform();
- if (worldTransform)
- shaderData->updateWorldTransform(*worldTransform);
-
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_NAMES[lightIdx]);
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_UNROLL_NAMES[lightIdx]);
- ++lightIdx;
- }
- }
- if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID))
- setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax((environmentLight ? 0 : 1), lightIdx)));
-
- // If no active light sources and no environment light, add a default light
- if (activeLightSources.isEmpty() && !environmentLight) {
// Note: implicit conversion of values to UniformValue
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f);
-
- setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
- setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight));
- setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
- setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f);
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[lightIdx], worldPos);
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[lightIdx], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f);
+
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos);
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[lightIdx], 0.5f);
+
+
+ // There is no risk in doing that even if multithreaded
+ // since we are sure that a shaderData is unique for a given light
+ // and won't ever be referenced as a Component either
+ Matrix4x4 *worldTransform = lightEntity->worldTransform();
+ if (worldTransform)
+ shaderData->updateWorldTransform(*worldTransform);
+
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_NAMES[lightIdx]);
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_UNROLL_NAMES[lightIdx]);
+ ++lightIdx;
}
+ }
- // Environment Light
- int envLightCount = 0;
- if (environmentLight && environmentLight->isEnabled()) {
- ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData());
- if (shaderData) {
- setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight"));
- envLightCount = 1;
- }
- } else {
- // with some drivers, samplers (like the envbox sampler) need to be bound even though
- // they may not be actually used, otherwise draw calls can fail
- static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight.irradiance"));
- static const int specularId = StringToInt::lookupId(QLatin1String("envLight.specular"));
- setUniformValue(command->m_parameterPack, irradianceId, m_renderer->submissionContext()->maxTextureUnitsCount());
- setUniformValue(command->m_parameterPack, specularId, m_renderer->submissionContext()->maxTextureUnitsCount());
+ if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID))
+ setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax((environmentLight ? 0 : 1), lightIdx)));
+
+ // If no active light sources and no environment light, add a default light
+ if (activeLightSources.isEmpty() && !environmentLight) {
+ // Note: implicit conversion of values to UniformValue
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f);
+
+ setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight));
+ setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f));
+ setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f);
+ }
+
+ // Environment Light
+ int envLightCount = 0;
+ if (environmentLight && environmentLight->isEnabled()) {
+ ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData());
+ if (shaderData) {
+ setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight"));
+ envLightCount = 1;
}
- setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount);
+ } else {
+ // with some drivers, samplers (like the envbox sampler) need to be bound even though
+ // they may not be actually used, otherwise draw calls can fail
+ static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight.irradiance"));
+ static const int specularId = StringToInt::lookupId(QLatin1String("envLight.specular"));
+ setUniformValue(command->m_parameterPack, irradianceId, m_renderer->submissionContext()->maxTextureUnitsCount());
+ setUniformValue(command->m_parameterPack, specularId, m_renderer->submissionContext()->maxTextureUnitsCount());
}
- // Set frag outputs in the shaders if hash not empty
- if (!fragOutputs.isEmpty())
- shader->setFragOutputs(fragOutputs);
+ setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount);
}
}
- else {
- qCWarning(Render::Backend) << Q_FUNC_INFO << "Using default effect as none was provided";
- }
}
bool RenderView::hasBlitFramebufferInfo() const
diff --git a/src/render/renderers/opengl/renderer/renderview_p.h b/src/render/renderers/opengl/renderer/renderview_p.h
index 7ebcdb6bd..1221e7a59 100644
--- a/src/render/renderers/opengl/renderer/renderview_p.h
+++ b/src/render/renderers/opengl/renderer/renderview_p.h
@@ -227,10 +227,16 @@ public:
RenderPassList passesAndParameters(ParameterInfoList *parameter, Entity *node, bool useDefaultMaterials = true);
- QVector<RenderCommand *> buildDrawRenderCommands(const QVector<Entity *> &entities) const;
- QVector<RenderCommand *> buildComputeRenderCommands(const QVector<Entity *> &entities) const;
- void setCommands(QVector<RenderCommand *> &commands) Q_DECL_NOTHROW { m_commands = commands; }
- QVector<RenderCommand *> commands() const Q_DECL_NOTHROW { return m_commands; }
+ EntityRenderCommandData buildDrawRenderCommands(const QVector<Entity *> &entities) const;
+ EntityRenderCommandData buildComputeRenderCommands(const QVector<Entity *> &entities) const;
+
+
+ void updateRenderCommand(EntityRenderCommandData &renderCommandData);
+
+
+ void setCommands(const QVector<RenderCommand> &commands) Q_DECL_NOTHROW { m_commands = commands; }
+ QVector<RenderCommand> &commands() { return m_commands; }
+ QVector<RenderCommand> commands() const { return m_commands; }
void setAttachmentPack(const AttachmentPack &pack) { m_attachmentPack = pack; }
const AttachmentPack &attachmentPack() const { return m_attachmentPack; }
@@ -291,7 +297,6 @@ public:
private:
void setShaderAndUniforms(RenderCommand *command,
- RenderPass *pass,
ParameterInfoList &parameters,
Entity *entity,
const QVector<LightSource> &activeLightSources,
@@ -331,10 +336,7 @@ private:
QVector<Qt3DCore::QNodeId> m_insertFenceIds;
QVector<QWaitFenceData> m_waitFences;
- // We do not use pointers to RenderNodes or Drawable's here so that the
- // render aspect is free to change the drawables on the next frame whilst
- // the render thread is submitting these commands.
- QVector<RenderCommand *> m_commands;
+ QVector<RenderCommand> m_commands;
mutable QVector<LightSource> m_lightSources;
EnvironmentLight *m_environmentLight;
diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
index 83fab301a..96fa55c47 100644
--- a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
+++ b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
@@ -54,14 +54,61 @@ const int RenderViewBuilder::m_optimalParallelJobCount = std::max(std::min(4, QT
namespace {
-class SyncRenderViewCommandBuilders
+class SyncPreCommandBuilding
{
public:
- explicit SyncRenderViewCommandBuilders(const RenderViewInitializerJobPtr &renderViewJob,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs,
- Renderer *renderer)
+ explicit SyncPreCommandBuilding(RenderViewInitializerJobPtr renderViewInitializerJob,
+ const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs,
+ Renderer *renderer,
+ FrameGraphNode *leafNode)
+ : m_renderViewInitializer(renderViewInitializerJob)
+ , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
+ , m_renderer(renderer)
+ , m_leafNode(leafNode)
+ {
+ }
+
+ void operator()()
+ {
+ // Split commands to build among jobs
+ QMutexLocker lock(m_renderer->cache()->mutex());
+ // Rebuild RenderCommands for all entities in RV (ignoring filtering)
+ RendererCache *cache = m_renderer->cache();
+ const RendererCache::LeafNodeData &dataCacheForLeaf = cache->leafNodeCache[m_leafNode];
+ RenderView *rv = m_renderViewInitializer->renderView();
+ const auto entities = !rv->isCompute() ? cache->renderableEntities : cache->computeEntities;
+
+ rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer);
+
+ lock.unlock();
+
+ // Split among the number of command builders
+ int i = 0;
+ const int m = RenderViewBuilder::optimalJobCount() - 1;
+ const int packetSize = entities.size() / RenderViewBuilder::optimalJobCount();
+ while (i < m) {
+ const RenderViewCommandBuilderJobPtr renderViewCommandBuilder = m_renderViewCommandBuilderJobs.at(i);
+ renderViewCommandBuilder->setEntities(entities.mid(i * packetSize, packetSize));
+ ++i;
+ }
+ m_renderViewCommandBuilderJobs.at(i)->setEntities(entities.mid(i * packetSize, packetSize + entities.size() % (m + 1)));
+ }
+
+private:
+ RenderViewInitializerJobPtr m_renderViewInitializer;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
+ Renderer *m_renderer;
+ FrameGraphNode *m_leafNode;
+};
+
+class SyncRenderViewPostCommandUpdate
+{
+public:
+ explicit SyncRenderViewPostCommandUpdate(const RenderViewInitializerJobPtr &renderViewJob,
+ const QVector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdateJobs,
+ Renderer *renderer)
: m_renderViewJob(renderViewJob)
- , m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderViewCommandUpdaterJobs(renderViewCommandUpdateJobs)
, m_renderer(renderer)
{}
@@ -71,17 +118,19 @@ public:
RenderView *rv = m_renderViewJob->renderView();
int totalCommandCount = 0;
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandUpdaterJobs))
totalCommandCount += renderViewCommandBuilder->commands().size();
- QVector<RenderCommand *> commands;
+ QVector<RenderCommand> commands;
commands.reserve(totalCommandCount);
// Reduction
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandUpdaterJobs))
commands += std::move(renderViewCommandBuilder->commands());
+
rv->setCommands(commands);
+ // TO DO: Find way to store commands once or at least only when required
// Sort the commands
rv->sort();
@@ -91,15 +140,15 @@ public:
private:
RenderViewInitializerJobPtr m_renderViewJob;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
Renderer *m_renderer;
};
-class SyncFrustumCulling
+class SyncPreFrustumCulling
{
public:
- explicit SyncFrustumCulling(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCulling)
+ explicit SyncPreFrustumCulling(const RenderViewInitializerJobPtr &renderViewJob,
+ const FrustumCullingJobPtr &frustumCulling)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCulling)
{}
@@ -120,21 +169,23 @@ private:
FrustumCullingJobPtr m_frustumCullingJob;
};
-class SyncRenderViewInitialization
+class SyncRenderViewPostInitialization
{
public:
- explicit SyncRenderViewInitialization(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCullingJob,
- const FilterLayerEntityJobPtr &filterEntityByLayerJob,
- const FilterProximityDistanceJobPtr &filterProximityJob,
- const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs)
+ explicit SyncRenderViewPostInitialization(const RenderViewInitializerJobPtr &renderViewJob,
+ const FrustumCullingJobPtr &frustumCullingJob,
+ const FilterLayerEntityJobPtr &filterEntityByLayerJob,
+ const FilterProximityDistanceJobPtr &filterProximityJob,
+ const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
+ const QVector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdaterJobs,
+ const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCullingJob)
, m_filterEntityByLayerJob(filterEntityByLayerJob)
, m_filterProximityJob(filterProximityJob)
, m_materialGathererJobs(materialGathererJobs)
- , m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderViewCommandUpdaterJobs(renderViewCommandUpdaterJobs)
+ , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
{}
void operator()()
@@ -154,8 +205,10 @@ public:
materialGatherer->setTechniqueFilter(const_cast<TechniqueFilter *>(rv->techniqueFilter()));
}
- // Command builders
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs))
+ // Command builders and updates
+ for (const auto &renderViewCommandUpdater : qAsConst(m_renderViewCommandUpdaterJobs))
+ renderViewCommandUpdater->setRenderView(rv);
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
renderViewCommandBuilder->setRenderView(rv);
// Set whether frustum culling is enabled or not
@@ -168,26 +221,31 @@ private:
FilterLayerEntityJobPtr m_filterEntityByLayerJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
};
-class SyncRenderCommandBuilding
+class SyncRenderViewPreCommandUpdate
{
public:
- explicit SyncRenderCommandBuilding(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCullingJob,
- const FilterProximityDistanceJobPtr &filterProximityJob,
- const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs,
- Renderer *renderer,
- FrameGraphNode *leafNode)
+ explicit SyncRenderViewPreCommandUpdate(const RenderViewInitializerJobPtr &renderViewJob,
+ const FrustumCullingJobPtr &frustumCullingJob,
+ const FilterProximityDistanceJobPtr &filterProximityJob,
+ const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
+ const QVector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdaterJobs,
+ const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs,
+ Renderer *renderer,
+ FrameGraphNode *leafNode,
+ bool fullCommandRebuild)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCullingJob)
, m_filterProximityJob(filterProximityJob)
, m_materialGathererJobs(materialGathererJobs)
- , m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderViewCommandUpdaterJobs(renderViewCommandUpdaterJobs)
+ , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
, m_renderer(renderer)
, m_leafNode(leafNode)
+ , m_fullRebuild(fullCommandRebuild)
{}
void operator()()
@@ -197,21 +255,44 @@ public:
RenderView *rv = m_renderViewJob->renderView();
if (!rv->noDraw()) {
- QVector<Entity *> renderableEntities;
- const bool isDraw = !rv->isCompute();
- QMutexLocker lock(m_renderer->cache()->mutex());
- const auto& cacheData = m_renderer->cache()->leafNodeCache.value(m_leafNode);
+ ///////// CACHE LOCKED ////////////
+ // Retrieve Data from Cache
+ RendererCache *cache = m_renderer->cache();
+ QMutexLocker lock(cache->mutex());
+ Q_ASSERT(cache->leafNodeCache.contains(m_leafNode));
- if (isDraw)
- renderableEntities = cacheData.renderableEntities;
- else
- renderableEntities = cacheData.computeEntities;
+ const bool isDraw = !rv->isCompute();
+ const RendererCache::LeafNodeData &dataCacheForLeaf = cache->leafNodeCache[m_leafNode];
+
+ // Rebuild RenderCommands if required
+ // This should happen fairly infrequently (FrameGraph Change, Geometry/Material change)
+ // and allow to skip that step most of the time
+ if (m_fullRebuild) {
+ EntityRenderCommandData commandData;
+ // Reduction
+ {
+ int totalCommandCount = 0;
+ for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
+ totalCommandCount += renderViewCommandBuilder->commandData().size();
+ commandData.reserve(totalCommandCount);
+ for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
+ commandData += std::move(renderViewCommandBuilder->commandData());
+ }
+
+ // Store new cache
+ RendererCache::LeafNodeData &writableCacheForLeaf = cache->leafNodeCache[m_leafNode];
+ writableCacheForLeaf.renderCommandData = std::move(commandData);
+ }
+ const EntityRenderCommandData commandData = dataCacheForLeaf.renderCommandData;
- const QVector<Entity *> filteredEntities = cacheData.filterEntitiesByLayer;
- QVector<LightSource> lightSources = cacheData.gatheredLights;
- rv->setEnvironmentLight(cacheData.environmentLight);
+ const QVector<Entity *> filteredEntities = dataCacheForLeaf.filterEntitiesByLayer;
+ QVector<Entity *> renderableEntities = isDraw ? cache->renderableEntities : cache->computeEntities;
+ QVector<LightSource> lightSources = cache->gatheredLights;
+ rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer);
+ rv->setEnvironmentLight(cache->environmentLight);
lock.unlock();
+ ///////// END OF CACHE LOCKED ////////////
// Filter out entities that weren't selected by the layer filters
// Remove all entities from the compute and renderable vectors that aren't in the filtered layer vector
@@ -229,23 +310,49 @@ public:
if (rv->frustumCulling())
renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, m_frustumCullingJob->visibleEntities());
// Filter out entities which didn't satisfy proximity filtering
- renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, m_filterProximityJob->filteredEntities());
+ if (!rv->proximityFilterIds().empty())
+ renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, m_filterProximityJob->filteredEntities());
+ }
+
+ // Filter out Render commands for which the Entity wasn't selected because
+ // of frustum, proximity or layer filtering
+ EntityRenderCommandData filteredCommandData;
+ filteredCommandData.reserve(renderableEntities.size());
+ // Because dataCacheForLeaf.renderableEntities or computeEntities are sorted
+ // What we get out of EntityRenderCommandData is also sorted by Entity
+ auto eIt = std::cbegin(renderableEntities);
+ const auto eEnd = std::cend(renderableEntities);
+ int cIt = 0;
+ const int cEnd = commandData.size();
+
+ while (eIt != eEnd) {
+ const Entity *targetEntity = *eIt;
+ // Advance until we have commands whose Entity has a lower address
+ // than the selected filtered entity
+ while (cIt != cEnd && commandData.entities.at(cIt) < targetEntity)
+ ++cIt;
+
+ // Push pointers to command data for all commands that match the
+ // entity
+ while (cIt != cEnd && commandData.entities.at(cIt) == targetEntity) {
+ filteredCommandData.push_back(commandData.entities.at(cIt),
+ commandData.commands.at(cIt),
+ commandData.passesData.at(cIt));
+ ++cIt;
+ }
+ ++eIt;
}
// Split among the number of command builders
int i = 0;
const int m = RenderViewBuilder::optimalJobCount() - 1;
- const int packetSize = renderableEntities.size() / RenderViewBuilder::optimalJobCount();
+ const int packetSize = filteredCommandData.size() / RenderViewBuilder::optimalJobCount();
while (i < m) {
- const RenderViewBuilderJobPtr renderViewCommandBuilder = m_renderViewBuilderJobs.at(i);
- renderViewCommandBuilder->setRenderables(renderableEntities.mid(i * packetSize, packetSize));
+ const RenderViewCommandUpdaterJobPtr renderViewCommandBuilder = m_renderViewCommandUpdaterJobs.at(i);
+ renderViewCommandBuilder->setRenderables(filteredCommandData.mid(i * packetSize, packetSize));
++i;
}
- m_renderViewBuilderJobs.at(i)->setRenderables(renderableEntities.mid(i * packetSize, packetSize + renderableEntities.size() % (m + 1)));
- {
- QMutexLocker rendererCacheLock(m_renderer->cache()->mutex());
- rv->setMaterialParameterTable(m_renderer->cache()->leafNodeCache.value(m_leafNode).materialParameterGatherer);
- }
+ m_renderViewCommandUpdaterJobs.at(i)->setRenderables(filteredCommandData.mid(i * packetSize, packetSize + filteredCommandData.size() % (m + 1)));
}
}
@@ -254,9 +361,11 @@ private:
FrustumCullingJobPtr m_frustumCullingJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
Renderer *m_renderer;
FrameGraphNode *m_leafNode;
+ bool m_fullRebuild;
};
class SetClearDrawBufferIndex
@@ -335,84 +444,6 @@ private:
FrameGraphNode *m_leafNode;
};
-class SyncLightsGatherer
-{
-public:
- explicit SyncLightsGatherer(LightGathererPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_gatherJob(gatherJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.gatheredLights = m_gatherJob->lights();
- dataCacheForLeaf.environmentLight = m_gatherJob->takeEnvironmentLight();
- }
-
-private:
- LightGathererPtr m_gatherJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
-class SyncRenderableEntities
-{
-public:
- explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_gatherJob(gatherJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.renderableEntities = m_gatherJob->filteredEntities();
- std::sort(dataCacheForLeaf.renderableEntities.begin(), dataCacheForLeaf.renderableEntities.end());
- }
-
-private:
- RenderableEntityFilterPtr m_gatherJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
-class SyncComputableEntities
-{
-public:
- explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_gatherJob(gatherJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.computeEntities = m_gatherJob->filteredEntities();
- std::sort(dataCacheForLeaf.computeEntities.begin(), dataCacheForLeaf.computeEntities.end());
- }
-
-private:
- ComputableEntityFilterPtr m_gatherJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
} // anonymous
RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int renderViewIndex, Renderer *renderer)
@@ -421,13 +452,11 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende
, m_renderer(renderer)
, m_layerCacheNeedsToBeRebuilt(false)
, m_materialGathererCacheNeedsToBeRebuilt(false)
- , m_lightsCacheNeedsToBeRebuilt(false)
- , m_renderableCacheNeedsToBeRebuilt(false)
- , m_computableCacheNeedsToBeRebuilt(false)
+ , m_renderCommandCacheNeedsToBeRebuilt(false)
, m_renderViewJob(RenderViewInitializerJobPtr::create())
, m_filterEntityByLayerJob()
, m_frustumCullingJob(new Render::FrustumCullingJob())
- , m_syncFrustumCullingJob(SynchronizerJobPtr::create(SyncFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling))
+ , m_syncPreFrustumCullingJob(SynchronizerJobPtr::create(SyncPreFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling))
, m_setClearDrawBufferIndexJob(SynchronizerJobPtr::create(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex))
, m_syncFilterEntityByLayerJob()
, m_filterProximityJob(Render::FilterProximityDistanceJobPtr::create())
@@ -444,54 +473,49 @@ FilterLayerEntityJobPtr RenderViewBuilder::filterEntityByLayerJob() const
return m_filterEntityByLayerJob;
}
-LightGathererPtr RenderViewBuilder::lightGathererJob() const
-{
- return m_lightGathererJob;
-}
-
-RenderableEntityFilterPtr RenderViewBuilder::renderableEntityFilterJob() const
+FrustumCullingJobPtr RenderViewBuilder::frustumCullingJob() const
{
- return m_renderableEntityFilterJob;
+ return m_frustumCullingJob;
}
-ComputableEntityFilterPtr RenderViewBuilder::computableEntityFilterJob() const
+QVector<RenderViewCommandUpdaterJobPtr> RenderViewBuilder::renderViewCommandUpdaterJobs() const
{
- return m_computableEntityFilterJob;
+ return m_renderViewCommandUpdaterJobs;
}
-FrustumCullingJobPtr RenderViewBuilder::frustumCullingJob() const
+QVector<RenderViewCommandBuilderJobPtr> RenderViewBuilder::renderViewCommandBuilderJobs() const
{
- return m_frustumCullingJob;
+ return m_renderViewCommandBuilderJobs;
}
-QVector<RenderViewBuilderJobPtr> RenderViewBuilder::renderViewBuilderJobs() const
+QVector<MaterialParameterGathererJobPtr> RenderViewBuilder::materialGathererJobs() const
{
- return m_renderViewBuilderJobs;
+ return m_materialGathererJobs;
}
-QVector<MaterialParameterGathererJobPtr> RenderViewBuilder::materialGathererJobs() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPostInitializationJob() const
{
- return m_materialGathererJobs;
+ return m_syncRenderViewPostInitializationJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncRenderViewInitializationJob() const
+SynchronizerJobPtr RenderViewBuilder::syncPreFrustumCullingJob() const
{
- return m_syncRenderViewInitializationJob;
+ return m_syncPreFrustumCullingJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncFrustumCullingJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPreCommandBuildingJob() const
{
- return m_syncFrustumCullingJob;
+ return m_syncRenderViewPreCommandBuildingJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncRenderCommandBuildingJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPreCommandUpdateJob() const
{
- return m_syncRenderCommandBuildingJob;
+ return m_syncRenderViewPreCommandUpdateJob;
}
-SynchronizerJobPtr RenderViewBuilder::syncRenderViewCommandBuildersJob() const
+SynchronizerJobPtr RenderViewBuilder::syncRenderViewPostCommandUpdateJob() const
{
- return m_syncRenderViewCommandBuildersJob;
+ return m_syncRenderViewPostCommandUpdateJob;
}
SynchronizerJobPtr RenderViewBuilder::setClearDrawBufferIndexJob() const
@@ -517,37 +541,21 @@ FilterProximityDistanceJobPtr RenderViewBuilder::filterProximityJob() const
void RenderViewBuilder::prepareJobs()
{
// Init what we can here
- EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager();
m_filterProximityJob->setManager(m_renderer->nodeManagers());
m_frustumCullingJob->setRoot(m_renderer->sceneRoot());
- if (m_lightsCacheNeedsToBeRebuilt) {
- m_lightGathererJob = Render::LightGathererPtr::create();
- m_lightGathererJob->setManager(entityManager);
-
- m_cacheLightsJob = SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
- m_cacheLightsJob->addDependency(m_lightGathererJob);
- }
-
- if (m_renderableCacheNeedsToBeRebuilt) {
- m_renderableEntityFilterJob = RenderableEntityFilterPtr::create();
- m_renderableEntityFilterJob->setManager(entityManager);
+ if (m_renderCommandCacheNeedsToBeRebuilt) {
- m_cacheRenderableEntitiesJob = SynchronizerJobPtr::create(
- SyncRenderableEntities(m_renderableEntityFilterJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
- m_cacheRenderableEntitiesJob->addDependency(m_renderableEntityFilterJob);
- }
-
- if (m_computableCacheNeedsToBeRebuilt) {
- m_computableEntityFilterJob = ComputableEntityFilterPtr::create();
- m_computableEntityFilterJob->setManager(entityManager);
-
- m_cacheComputableEntitiesJob = SynchronizerJobPtr::create(
- SyncComputableEntities(m_computableEntityFilterJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
- m_cacheComputableEntitiesJob->addDependency(m_computableEntityFilterJob);
+ m_renderViewCommandBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
+ for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
+ auto renderViewCommandBuilder = Render::RenderViewCommandBuilderJobPtr::create();
+ m_renderViewCommandBuilderJobs.push_back(renderViewCommandBuilder);
+ }
+ m_syncRenderViewPreCommandBuildingJob = SynchronizerJobPtr::create(SyncPreCommandBuilding(m_renderViewJob,
+ m_renderViewCommandBuilderJobs,
+ m_renderer,
+ m_leafNode),
+ JobTypes::SyncRenderViewPreCommandBuilding);
}
m_renderViewJob->setRenderer(m_renderer);
@@ -556,12 +564,11 @@ void RenderViewBuilder::prepareJobs()
// RenderCommand building is the most consuming task -> split it
// Estimate the number of jobs to create based on the number of entities
- m_renderViewBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
+ m_renderViewCommandUpdaterJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
- auto renderViewCommandBuilder = Render::RenderViewBuilderJobPtr::create();
- renderViewCommandBuilder->setIndex(m_renderViewIndex);
- renderViewCommandBuilder->setRenderer(m_renderer);
- m_renderViewBuilderJobs.push_back(renderViewCommandBuilder);
+ auto renderViewCommandUpdater = Render::RenderViewCommandUpdaterJobPtr::create();
+ renderViewCommandUpdater->setRenderer(m_renderer);
+ m_renderViewCommandUpdaterJobs.push_back(renderViewCommandUpdater);
}
if (m_materialGathererCacheNeedsToBeRebuilt) {
@@ -582,7 +589,7 @@ void RenderViewBuilder::prepareJobs()
m_syncMaterialGathererJob = SynchronizerJobPtr::create(SyncMaterialParameterGatherer(m_materialGathererJobs,
m_renderer,
m_leafNode),
- JobTypes::SyncMaterialGatherer);
+ JobTypes::SyncMaterialGatherer);
}
if (m_layerCacheNeedsToBeRebuilt) {
@@ -594,34 +601,37 @@ void RenderViewBuilder::prepareJobs()
JobTypes::SyncFilterEntityByLayer);
}
- m_syncRenderCommandBuildingJob = SynchronizerJobPtr::create(SyncRenderCommandBuilding(m_renderViewJob,
- m_frustumCullingJob,
- m_filterProximityJob,
- m_materialGathererJobs,
- m_renderViewBuilderJobs,
- m_renderer,
- m_leafNode),
- JobTypes::SyncRenderViewCommandBuilding);
-
- m_syncRenderViewCommandBuildersJob = SynchronizerJobPtr::create(SyncRenderViewCommandBuilders(m_renderViewJob,
- m_renderViewBuilderJobs,
- m_renderer),
- JobTypes::SyncRenderViewCommandBuilder);
-
- m_syncRenderViewInitializationJob = SynchronizerJobPtr::create(SyncRenderViewInitialization(m_renderViewJob,
- m_frustumCullingJob,
- m_filterEntityByLayerJob,
- m_filterProximityJob,
- m_materialGathererJobs,
- m_renderViewBuilderJobs),
- JobTypes::SyncRenderViewInitialization);
+ m_syncRenderViewPreCommandUpdateJob = SynchronizerJobPtr::create(SyncRenderViewPreCommandUpdate(m_renderViewJob,
+ m_frustumCullingJob,
+ m_filterProximityJob,
+ m_materialGathererJobs,
+ m_renderViewCommandUpdaterJobs,
+ m_renderViewCommandBuilderJobs,
+ m_renderer,
+ m_leafNode,
+ m_renderCommandCacheNeedsToBeRebuilt),
+ JobTypes::SyncRenderViewPreCommandUpdate);
+
+ m_syncRenderViewPostCommandUpdateJob = SynchronizerJobPtr::create(SyncRenderViewPostCommandUpdate(m_renderViewJob,
+ m_renderViewCommandUpdaterJobs,
+ m_renderer),
+ JobTypes::SyncRenderViewPostCommandUpdate);
+
+ m_syncRenderViewPostInitializationJob = SynchronizerJobPtr::create(SyncRenderViewPostInitialization(m_renderViewJob,
+ m_frustumCullingJob,
+ m_filterEntityByLayerJob,
+ m_filterProximityJob,
+ m_materialGathererJobs,
+ m_renderViewCommandUpdaterJobs,
+ m_renderViewCommandBuilderJobs),
+ JobTypes::SyncRenderViewInitialization);
}
QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
{
QVector<Qt3DCore::QAspectJobPtr> jobs;
- jobs.reserve(m_materialGathererJobs.size() + m_renderViewBuilderJobs.size() + 11);
+ jobs.reserve(m_materialGathererJobs.size() + m_renderViewCommandUpdaterJobs.size() + 11);
// Set dependencies
@@ -629,97 +639,97 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
// TODO: Maybe only update skinning palettes for non-culled entities
m_renderViewJob->addDependency(m_renderer->updateSkinningPaletteJob());
- m_syncFrustumCullingJob->addDependency(m_renderer->updateWorldTransformJob());
- m_syncFrustumCullingJob->addDependency(m_renderer->updateShaderDataTransformJob());
- m_syncFrustumCullingJob->addDependency(m_syncRenderViewInitializationJob);
+ m_syncPreFrustumCullingJob->addDependency(m_renderer->updateWorldTransformJob());
+ m_syncPreFrustumCullingJob->addDependency(m_renderer->updateShaderDataTransformJob());
+ m_syncPreFrustumCullingJob->addDependency(m_syncRenderViewPostInitializationJob);
m_frustumCullingJob->addDependency(m_renderer->expandBoundingVolumeJob());
- m_frustumCullingJob->addDependency(m_syncFrustumCullingJob);
+ m_frustumCullingJob->addDependency(m_syncPreFrustumCullingJob);
- m_setClearDrawBufferIndexJob->addDependency(m_syncRenderViewInitializationJob);
+ m_setClearDrawBufferIndexJob->addDependency(m_syncRenderViewPostInitializationJob);
- m_syncRenderViewInitializationJob->addDependency(m_renderViewJob);
+ m_syncRenderViewPostInitializationJob->addDependency(m_renderViewJob);
m_filterProximityJob->addDependency(m_renderer->expandBoundingVolumeJob());
- m_filterProximityJob->addDependency(m_syncRenderViewInitializationJob);
+ m_filterProximityJob->addDependency(m_syncRenderViewPostInitializationJob);
- m_syncRenderCommandBuildingJob->addDependency(m_syncRenderViewInitializationJob);
- m_syncRenderCommandBuildingJob->addDependency(m_filterProximityJob);
- m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncRenderViewPostInitializationJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_filterProximityJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_frustumCullingJob);
// Ensure the RenderThread won't be able to process dirtyResources
// before they have been completely gathered
- m_syncRenderCommandBuildingJob->addDependency(m_renderer->introspectShadersJob());
- m_syncRenderCommandBuildingJob->addDependency(m_renderer->bufferGathererJob());
- m_syncRenderCommandBuildingJob->addDependency(m_renderer->textureGathererJob());
-
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) {
- renderViewCommandBuilder->addDependency(m_syncRenderCommandBuildingJob);
- m_syncRenderViewCommandBuildersJob->addDependency(renderViewCommandBuilder);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->introspectShadersJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->bufferGathererJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->textureGathererJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->cacheLightJob());
+
+ for (const auto &renderViewCommandUpdater : qAsConst(m_renderViewCommandUpdaterJobs)) {
+ renderViewCommandUpdater->addDependency(m_syncRenderViewPreCommandUpdateJob);
+ m_syncRenderViewPostCommandUpdateJob->addDependency(renderViewCommandUpdater);
}
- m_renderer->frameCleanupJob()->addDependency(m_syncRenderViewCommandBuildersJob);
+ m_renderer->frameCleanupJob()->addDependency(m_syncRenderViewPostCommandUpdateJob);
m_renderer->frameCleanupJob()->addDependency(m_setClearDrawBufferIndexJob);
// Add jobs
jobs.push_back(m_renderViewJob); // Step 1
- if (m_lightsCacheNeedsToBeRebuilt) {
- jobs.push_back(m_lightGathererJob); // Step 1
- jobs.push_back(m_cacheLightsJob);
- m_syncRenderCommandBuildingJob->addDependency(m_cacheLightsJob);
- }
+ jobs.push_back(m_syncRenderViewPostInitializationJob); // Step 2
- if (m_renderableCacheNeedsToBeRebuilt) {
- jobs.push_back(m_renderableEntityFilterJob); // Step 1
- jobs.push_back(m_cacheRenderableEntitiesJob);
- m_syncRenderCommandBuildingJob->addDependency(m_cacheRenderableEntitiesJob);
- }
+ if (m_renderCommandCacheNeedsToBeRebuilt) { // Step 3
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->cacheComputableEntitiesJob());
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->cacheRenderableEntitiesJob());
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncRenderViewPostInitializationJob);
- if (m_computableCacheNeedsToBeRebuilt) {
- // Note: do it only if OpenGL 4.3+ available
- jobs.push_back(m_computableEntityFilterJob); // Step 1
- jobs.push_back(m_cacheComputableEntitiesJob);
- m_syncRenderCommandBuildingJob->addDependency(m_cacheComputableEntitiesJob);
- }
+ if (m_materialGathererCacheNeedsToBeRebuilt)
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncMaterialGathererJob);
- jobs.push_back(m_syncRenderViewInitializationJob); // Step 2
+ jobs.push_back(m_syncRenderViewPreCommandBuildingJob);
+
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs)) {
+ renderViewCommandBuilder->addDependency(m_syncRenderViewPreCommandBuildingJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(renderViewCommandBuilder);
+ jobs.push_back(renderViewCommandBuilder);
+ }
+ }
if (m_layerCacheNeedsToBeRebuilt) {
m_filterEntityByLayerJob->addDependency(m_renderer->updateEntityLayersJob());
- m_filterEntityByLayerJob->addDependency(m_syncRenderViewInitializationJob);
+ m_filterEntityByLayerJob->addDependency(m_syncRenderViewPostInitializationJob);
m_filterEntityByLayerJob->addDependency(m_renderer->updateTreeEnabledJob());
m_syncFilterEntityByLayerJob->addDependency(m_filterEntityByLayerJob);
- m_syncRenderCommandBuildingJob->addDependency(m_syncFilterEntityByLayerJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncFilterEntityByLayerJob);
jobs.push_back(m_filterEntityByLayerJob); // Step 3
jobs.push_back(m_syncFilterEntityByLayerJob); // Step 4
}
- jobs.push_back(m_syncFrustumCullingJob); // Step 3
+ jobs.push_back(m_syncPreFrustumCullingJob); // Step 3
jobs.push_back(m_filterProximityJob); // Step 3
jobs.push_back(m_setClearDrawBufferIndexJob); // Step 3
if (m_materialGathererCacheNeedsToBeRebuilt) {
for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) {
- materialGatherer->addDependency(m_syncRenderViewInitializationJob);
+ materialGatherer->addDependency(m_syncRenderViewPostInitializationJob);
materialGatherer->addDependency(m_renderer->introspectShadersJob());
materialGatherer->addDependency(m_renderer->filterCompatibleTechniqueJob());
jobs.push_back(materialGatherer); // Step3
m_syncMaterialGathererJob->addDependency(materialGatherer);
}
- m_syncRenderCommandBuildingJob->addDependency(m_syncMaterialGathererJob);
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncMaterialGathererJob);
jobs.push_back(m_syncMaterialGathererJob); // Step 3
}
jobs.push_back(m_frustumCullingJob); // Step 4
- jobs.push_back(m_syncRenderCommandBuildingJob); // Step 5
+ jobs.push_back(m_syncRenderViewPreCommandUpdateJob); // Step 5
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 6
+ // Build RenderCommands or Update RenderCommand Uniforms
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewCommandUpdaterJobs)) // Step 6
jobs.push_back(renderViewCommandBuilder);
- jobs.push_back(m_syncRenderViewCommandBuildersJob); // Step 7
+ jobs.push_back(m_syncRenderViewPostCommandUpdateJob); // Step 7
return jobs;
}
@@ -754,34 +764,14 @@ bool RenderViewBuilder::materialGathererCacheNeedsToBeRebuilt() const
return m_materialGathererCacheNeedsToBeRebuilt;
}
-void RenderViewBuilder::setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
-{
- m_renderableCacheNeedsToBeRebuilt = needsToBeRebuilt;
-}
-
-bool RenderViewBuilder::renderableCacheNeedsToBeRebuilt() const
-{
- return m_renderableCacheNeedsToBeRebuilt;
-}
-
-void RenderViewBuilder::setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
-{
- m_computableCacheNeedsToBeRebuilt = needsToBeRebuilt;
-}
-
-bool RenderViewBuilder::computableCacheNeedsToBeRebuilt() const
-{
- return m_computableCacheNeedsToBeRebuilt;
-}
-
-void RenderViewBuilder::setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
+void RenderViewBuilder::setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
{
- m_lightsCacheNeedsToBeRebuilt = needsToBeRebuilt;
+ m_renderCommandCacheNeedsToBeRebuilt = needsToBeRebuilt;
}
-bool RenderViewBuilder::lightGathererCacheNeedsToBeRebuilt() const
+bool RenderViewBuilder::renderCommandCacheNeedsToBeRebuilt() const
{
- return m_lightsCacheNeedsToBeRebuilt;
+ return m_renderCommandCacheNeedsToBeRebuilt;
}
int RenderViewBuilder::optimalJobCount()
diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
index e223a5f1e..a2ab80e7e 100644
--- a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
+++ b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
@@ -53,15 +53,14 @@
#include <functional>
#include <Qt3DCore/qaspectjob.h>
-#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
#include <Qt3DRender/private/filterlayerentityjob_p.h>
#include <Qt3DRender/private/genericlambdajob_p.h>
#include <Qt3DRender/private/materialparametergathererjob_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
-#include <Qt3DRender/private/renderviewbuilderjob_p.h>
+#include <Qt3DRender/private/renderviewcommandbuilderjob_p.h>
+#include <Qt3DRender/private/renderviewcommandupdaterjob_p.h>
#include <Qt3DRender/private/renderview_p.h>
#include <Qt3DRender/private/frustumcullingjob_p.h>
-#include <Qt3DRender/private/lightgatherer_p.h>
#include <Qt3DRender/private/filterproximitydistancejob_p.h>
QT_BEGIN_NAMESPACE
@@ -73,8 +72,6 @@ namespace Render {
class Renderer;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
-using ComputableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::ComputeCommand, Render::Material>;
-using RenderableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::GeometryRenderer, Render::Material>;
class Q_AUTOTEST_EXPORT RenderViewBuilder
{
@@ -83,16 +80,15 @@ public:
RenderViewInitializerJobPtr renderViewJob() const;
FilterLayerEntityJobPtr filterEntityByLayerJob() const;
- LightGathererPtr lightGathererJob() const;
- RenderableEntityFilterPtr renderableEntityFilterJob() const;
- ComputableEntityFilterPtr computableEntityFilterJob() const;
FrustumCullingJobPtr frustumCullingJob() const;
- QVector<RenderViewBuilderJobPtr> renderViewBuilderJobs() const;
+ QVector<RenderViewCommandBuilderJobPtr> renderViewCommandBuilderJobs() const;
+ QVector<RenderViewCommandUpdaterJobPtr> renderViewCommandUpdaterJobs() const;
QVector<MaterialParameterGathererJobPtr> materialGathererJobs() const;
- SynchronizerJobPtr syncRenderViewInitializationJob() const;
- SynchronizerJobPtr syncFrustumCullingJob() const;
- SynchronizerJobPtr syncRenderCommandBuildingJob() const;
- SynchronizerJobPtr syncRenderViewCommandBuildersJob() const;
+ SynchronizerJobPtr syncRenderViewPostInitializationJob() const;
+ SynchronizerJobPtr syncPreFrustumCullingJob() const;
+ SynchronizerJobPtr syncRenderViewPreCommandBuildingJob() const;
+ SynchronizerJobPtr syncRenderViewPreCommandUpdateJob() const;
+ SynchronizerJobPtr syncRenderViewPostCommandUpdateJob() const;
SynchronizerJobPtr setClearDrawBufferIndexJob() const;
SynchronizerJobPtr syncFilterEntityByLayerJob() const;
FilterProximityDistanceJobPtr filterProximityJob() const;
@@ -108,15 +104,8 @@ public:
bool layerCacheNeedsToBeRebuilt() const;
void setMaterialGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
bool materialGathererCacheNeedsToBeRebuilt() const;
-
- void setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
- bool renderableCacheNeedsToBeRebuilt() const;
-
- void setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
- bool computableCacheNeedsToBeRebuilt() const;
-
- void setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
- bool lightGathererCacheNeedsToBeRebuilt() const;
+ void setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
+ bool renderCommandCacheNeedsToBeRebuilt() const;
static int optimalJobCount();
static QVector<Entity *> entitiesInSubset(const QVector<Entity *> &entities, const QVector<Entity *> &subset);
@@ -127,32 +116,25 @@ private:
Renderer *m_renderer;
bool m_layerCacheNeedsToBeRebuilt;
bool m_materialGathererCacheNeedsToBeRebuilt;
- bool m_lightsCacheNeedsToBeRebuilt;
- bool m_renderableCacheNeedsToBeRebuilt;
- bool m_computableCacheNeedsToBeRebuilt;
+ bool m_renderCommandCacheNeedsToBeRebuilt;
RenderViewInitializerJobPtr m_renderViewJob;
FilterLayerEntityJobPtr m_filterEntityByLayerJob;
- LightGathererPtr m_lightGathererJob;
- RenderableEntityFilterPtr m_renderableEntityFilterJob;
- ComputableEntityFilterPtr m_computableEntityFilterJob;
FrustumCullingJobPtr m_frustumCullingJob;
- QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
+ QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- SynchronizerJobPtr m_syncRenderViewInitializationJob;
- SynchronizerJobPtr m_syncFrustumCullingJob;
- SynchronizerJobPtr m_syncRenderCommandBuildingJob;
- SynchronizerJobPtr m_syncRenderViewCommandBuildersJob;
+ SynchronizerJobPtr m_syncRenderViewPostInitializationJob;
+ SynchronizerJobPtr m_syncPreFrustumCullingJob;
+ SynchronizerJobPtr m_syncRenderViewPreCommandBuildingJob;
+ SynchronizerJobPtr m_syncRenderViewPreCommandUpdateJob;
+ SynchronizerJobPtr m_syncRenderViewPostCommandUpdateJob;
SynchronizerJobPtr m_setClearDrawBufferIndexJob;
SynchronizerJobPtr m_syncFilterEntityByLayerJob;
SynchronizerJobPtr m_syncMaterialGathererJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
- SynchronizerJobPtr m_cacheRenderableEntitiesJob;
- SynchronizerJobPtr m_cacheComputableEntitiesJob;
- SynchronizerJobPtr m_cacheLightsJob;
-
static const int m_optimalParallelJobCount;
};
diff --git a/src/render/renderers/opengl/renderer/shaderparameterpack.cpp b/src/render/renderers/opengl/renderer/shaderparameterpack.cpp
index f78e45a5e..1cfb59343 100644
--- a/src/render/renderers/opengl/renderer/shaderparameterpack.cpp
+++ b/src/render/renderers/opengl/renderer/shaderparameterpack.cpp
@@ -57,7 +57,6 @@ namespace Render {
ShaderParameterPack::~ShaderParameterPack()
{
- m_uniforms.clear();
}
void ShaderParameterPack::setUniform(const int glslNameId, const UniformValue &val)
@@ -71,11 +70,24 @@ void ShaderParameterPack::setTexture(const int glslNameId, int uniformArrayIndex
if (m_textures[t].glslNameId != glslNameId || m_textures[t].uniformArrayIndex != uniformArrayIndex)
continue;
- m_textures[t].texId = texId;
+ m_textures[t].nodeId = texId;
return;
}
- m_textures.append(NamedTexture(glslNameId, texId, uniformArrayIndex));
+ m_textures.append(NamedResource(glslNameId, texId, uniformArrayIndex, NamedResource::Texture));
+}
+
+void ShaderParameterPack::setImage(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId id)
+{
+ for (int i=0, m = m_images.size(); i < m; ++i) {
+ if (m_images[i].glslNameId != glslNameId || m_images[i].uniformArrayIndex != uniformArrayIndex)
+ continue;
+
+ m_images[i].nodeId = id;
+ return;
+ }
+
+ m_images.append(NamedResource(glslNameId, id, uniformArrayIndex, NamedResource::Image));
}
// Contains Uniform Block Index and QNodeId of the ShaderData (UBO)
diff --git a/src/render/renderers/opengl/renderer/shaderparameterpack_p.h b/src/render/renderers/opengl/renderer/shaderparameterpack_p.h
index fe9ab3995..cb599124c 100644
--- a/src/render/renderers/opengl/renderer/shaderparameterpack_p.h
+++ b/src/render/renderers/opengl/renderer/shaderparameterpack_p.h
@@ -89,7 +89,56 @@ struct BlockToSSBO {
QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, BlockToSSBO, Q_PRIMITIVE_TYPE)
-typedef QHash<int, UniformValue> PackUniformHash;
+struct PackUniformHash
+{
+ QVector<int> keys;
+ QVector<UniformValue> values;
+
+ PackUniformHash()
+ {
+ keys.reserve(10);
+ values.reserve(10);
+ }
+
+ void insert(int key, const UniformValue &value)
+ {
+ const int idx = keys.indexOf(key);
+ if (idx != -1) {
+ values[idx] = value;
+ } else {
+ keys.push_back(key);
+ values.push_back(value);
+ }
+ }
+
+ UniformValue value(int key) const
+ {
+ const int idx = keys.indexOf(key);
+ if (idx != -1)
+ return values.at(idx);
+ return UniformValue();
+ }
+
+ UniformValue& value(int key)
+ {
+ const int idx = keys.indexOf(key);
+ if (idx != -1)
+ return values[idx];
+ insert(key, UniformValue());
+ return value(key);
+ }
+
+ void erase(int idx)
+ {
+ keys.removeAt(idx);
+ values.removeAt(idx);
+ }
+
+ bool contains(int key) const
+ {
+ return keys.contains(key);
+ }
+};
class Q_AUTOTEST_EXPORT ShaderParameterPack
{
@@ -98,6 +147,8 @@ public:
void setUniform(const int glslNameId, const UniformValue &val);
void setTexture(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId id);
+ void setImage(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId id);
+
void setUniformBuffer(BlockToUBO blockToUBO);
void setShaderStorageBuffer(BlockToSSBO blockToSSBO);
void setSubmissionUniform(const ShaderUniform &uniform);
@@ -106,35 +157,59 @@ public:
inline const PackUniformHash &uniforms() const { return m_uniforms; }
UniformValue uniform(const int glslNameId) const { return m_uniforms.value(glslNameId); }
- struct NamedTexture
+
+ struct NamedResource
{
- NamedTexture() {}
- NamedTexture(const int glslNameId, Qt3DCore::QNodeId texId, int uniformArrayIndex)
+ enum Type {
+ Texture = 0,
+ Image
+ };
+
+ NamedResource() {}
+ NamedResource(const int glslNameId, Qt3DCore::QNodeId texId,
+ int uniformArrayIndex, Type type)
: glslNameId(glslNameId)
- , texId(texId)
+ , nodeId(texId)
, uniformArrayIndex(uniformArrayIndex)
+ , type(type)
{ }
int glslNameId;
- Qt3DCore::QNodeId texId;
+ Qt3DCore::QNodeId nodeId;
int uniformArrayIndex;
+ Type type;
+
+ bool operator==(const NamedResource &other) const
+ {
+ return glslNameId == other.glslNameId &&
+ nodeId == other.nodeId &&
+ uniformArrayIndex == other.uniformArrayIndex &&
+ type == other.type;
+ }
+
+ bool operator!=(const NamedResource &other) const
+ {
+ return !(*this == other);
+ }
};
- inline QVector<NamedTexture> textures() const { return m_textures; }
+ inline QVector<NamedResource> textures() const { return m_textures; }
+ inline QVector<NamedResource> images() const { return m_images; }
inline QVector<BlockToUBO> uniformBuffers() const { return m_uniformBuffers; }
inline QVector<BlockToSSBO> shaderStorageBuffers() const { return m_shaderStorageBuffers; }
inline QVector<ShaderUniform> submissionUniforms() const { return m_submissionUniforms; }
private:
PackUniformHash m_uniforms;
- QVector<NamedTexture> m_textures;
+ QVector<NamedResource> m_textures;
+ QVector<NamedResource> m_images;
QVector<BlockToUBO> m_uniformBuffers;
QVector<BlockToSSBO> m_shaderStorageBuffers;
QVector<ShaderUniform> m_submissionUniforms;
friend class RenderView;
};
-QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, ShaderParameterPack::NamedTexture, Q_PRIMITIVE_TYPE)
+QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, ShaderParameterPack::NamedResource, Q_PRIMITIVE_TYPE)
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/textures/gltexture.cpp b/src/render/renderers/opengl/textures/gltexture.cpp
index 4fd8a8a86..20e6007a0 100644
--- a/src/render/renderers/opengl/textures/gltexture.cpp
+++ b/src/render/renderers/opengl/textures/gltexture.cpp
@@ -41,6 +41,8 @@
#include "gltexture_p.h"
#include <private/qdebug_p.h>
+#include <private/qopengltexture_p.h>
+#include <private/qopengltexturehelper_p.h>
#include <QDebug>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
@@ -49,13 +51,9 @@
#include <Qt3DRender/qtexturedata.h>
#include <Qt3DRender/qtextureimagedata.h>
#include <Qt3DRender/private/managers_p.h>
-#include <Qt3DRender/private/texturedatamanager_p.h>
#include <Qt3DRender/private/qabstracttexture_p.h>
#include <Qt3DRender/private/renderbuffer_p.h>
#include <Qt3DRender/private/qtextureimagedata_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#if !defined(QT_OPENGL_ES_2)
#include <QOpenGLFunctions_3_1>
@@ -69,59 +67,110 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
-GLTexture::GLTexture(TextureDataManager *texDataMgr,
- TextureImageDataManager *texImgDataMgr,
- const QTextureGeneratorPtr &texGen,
- bool unique)
- : m_unique(unique)
+namespace {
+
+// This uploadGLData where the data is a fullsize subimage
+// as QOpenGLTexture doesn't allow partial subimage uploads
+void uploadGLData(QOpenGLTexture *glTex,
+ int level, int layer, QOpenGLTexture::CubeMapFace face,
+ const QByteArray &bytes, const QTextureImageDataPtr &data)
+{
+ if (data->isCompressed()) {
+ glTex->setCompressedData(level, layer, face, bytes.size(), bytes.constData());
+ } else {
+ QOpenGLPixelTransferOptions uploadOptions;
+ uploadOptions.setAlignment(1);
+ glTex->setData(level, layer, face, data->pixelFormat(), data->pixelType(), bytes.constData(), &uploadOptions);
+ }
+}
+
+// For partial sub image uploads
+void uploadGLData(QOpenGLTexture *glTex,
+ int mipLevel, int layer, QOpenGLTexture::CubeMapFace cubeFace,
+ int xOffset, int yOffset, int zOffset,
+ const QByteArray &bytes, const QTextureImageDataPtr &data)
+{
+ if (data->isCompressed()) {
+ qWarning() << Q_FUNC_INFO << "Uploading non full sized Compressed Data not supported yet";
+ } else {
+ QOpenGLPixelTransferOptions uploadOptions;
+ uploadOptions.setAlignment(1);
+ glTex->setData(xOffset, yOffset, zOffset,
+ data->width(), data->height(), data->depth(),
+ mipLevel, layer, cubeFace, data->layers(),
+ data->pixelFormat(), data->pixelType(),
+ bytes.constData(), &uploadOptions);
+ }
+}
+
+} // anonymous
+
+
+GLTexture::GLTexture()
+ : m_dirtyFlags(None)
, m_gl(nullptr)
, m_renderBuffer(nullptr)
- , m_textureDataManager(texDataMgr)
- , m_textureImageDataManager(texImgDataMgr)
- , m_dataFunctor(texGen)
+ , m_dataFunctor()
, m_pendingDataFunctor(nullptr)
, m_sharedTextureId(-1)
, m_externalRendering(false)
+ , m_wasTextureRecreated(false)
{
- // make sure texture generator is executed
- // this is needed when Texture have the TargetAutomatic
- // to ensure they are loaded before trying to instantiate the QOpenGLTexture
- if (!texGen.isNull())
- m_textureDataManager->requestData(texGen, this);
}
GLTexture::~GLTexture()
{
- destroyGLTexture();
}
-void GLTexture::destroyResources()
-{
- if (m_dataFunctor)
- m_textureDataManager->releaseData(m_dataFunctor, this);
-}
-
-void GLTexture::destroyGLTexture()
+// Must be called from RenderThread with active GL context
+void GLTexture::destroy()
{
delete m_gl;
m_gl = nullptr;
delete m_renderBuffer;
m_renderBuffer = nullptr;
- m_dirtyFlags.store(0);
+ m_dirtyFlags = None;
+ m_sharedTextureId = -1;
+ m_externalRendering = false;
+ m_wasTextureRecreated = false;
+ m_dataFunctor.reset();
+ m_pendingDataFunctor = nullptr;
- destroyResources();
+ m_properties = {};
+ m_parameters = {};
+ m_textureData.reset();
+ m_images.clear();
+ m_imageData.clear();
+ m_pendingTextureDataUpdates.clear();
}
bool GLTexture::loadTextureDataFromGenerator()
{
- m_textureData = m_textureDataManager->getData(m_dataFunctor);
+ m_textureData = m_dataFunctor->operator()();
// if there is a texture generator, most properties will be defined by it
if (m_textureData) {
- if (m_properties.target != QAbstractTexture::TargetAutomatic)
- qWarning() << "[Qt3DRender::GLTexture] When a texture provides a generator, it's target is expected to be TargetAutomatic";
+ const QAbstractTexture::Target target = m_textureData->target();
+
+ // If both target and functor return Automatic we are still
+ // probably loading the texture, return false
+ if (m_properties.target == QAbstractTexture::TargetAutomatic &&
+ target == QAbstractTexture::TargetAutomatic) {
+ m_textureData.reset();
+ return false;
+ }
- m_actualTarget = m_textureData->target();
+ if (m_properties.target != QAbstractTexture::TargetAutomatic &&
+ target != QAbstractTexture::TargetAutomatic &&
+ m_properties.target != target) {
+ qWarning() << Q_FUNC_INFO << "Generator and Properties not requesting the same texture target";
+ m_textureData.reset();
+ return false;
+ }
+
+ // We take target type from generator if it wasn't explicitly set by the user
+ if (m_properties.target == QAbstractTexture::TargetAutomatic)
+ m_properties.target = target;
m_properties.width = m_textureData->width();
m_properties.height = m_textureData->height();
m_properties.depth = m_textureData->depth();
@@ -143,7 +192,7 @@ void GLTexture::loadTextureDataFromImages()
{
int maxMipLevel = 0;
for (const Image &img : qAsConst(m_images)) {
- const QTextureImageDataPtr imgData = m_textureImageDataManager->getData(img.generator);
+ const QTextureImageDataPtr imgData = img.generator->operator()();
// imgData may be null in the following cases:
// - Texture is created with TextureImages which have yet to be
// loaded (skybox where you don't yet know the path, source set by
@@ -179,26 +228,23 @@ void GLTexture::loadTextureDataFromImages()
}
}
+// Called from RenderThread
GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture()
{
- QMutexLocker locker(&m_textureMutex);
- bool needUpload = false;
TextureUpdateInfo textureInfo;
-
- m_properties.status = QAbstractTexture::Error;
+ m_wasTextureRecreated = false;
const bool hasSharedTextureId = m_sharedTextureId > 0;
-
// Only load texture data if we are not using a sharedTextureId
+ // Check if dataFunctor or images have changed
if (!hasSharedTextureId) {
- // on the first invocation in the render thread, make sure to
- // evaluate the texture data generator output
- // (this might change some property values)
- if (m_dataFunctor && !m_textureData) {
+ // If dataFunctor exists and we have no data and it hasn´t run yet
+ if (m_dataFunctor && !m_textureData && m_dataFunctor.get() != m_pendingDataFunctor ) {
const bool successfullyLoadedTextureData = loadTextureDataFromGenerator();
+ // If successful, m_textureData has content
if (successfullyLoadedTextureData) {
setDirtyFlag(Properties, true);
- needUpload = true;
+ setDirtyFlag(TextureData, true);
} else {
if (m_pendingDataFunctor != m_dataFunctor.get()) {
qWarning() << "[Qt3DRender::GLTexture] No QTextureData generated from Texture Generator yet. Texture will be invalid for this frame";
@@ -209,56 +255,77 @@ GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture()
}
}
- // additional texture images may be defined through image data generators
- if (testDirtyFlag(TextureData)) {
+ // If images have changed, clear previous images data
+ // and regenerate m_imageData for the images
+ if (testDirtyFlag(TextureImageData)) {
m_imageData.clear();
loadTextureDataFromImages();
- needUpload = true;
+ // Mark for upload if we actually have something to upload
+ if (!m_imageData.empty()) {
+ setDirtyFlag(TextureData, true);
+ }
+ // Reset image flag
+ setDirtyFlag(TextureImageData, false);
}
- // don't try to create the texture if the format was not set
- if (m_properties.format == QAbstractTexture::Automatic) {
+ // Don't try to create the texture if the target or format was still not set
+ // Format should either be set by user or if Automatic
+ // by either the dataGenerator of the texture or the first Image
+ // Target should explicitly be set by the user or the dataGenerator
+ if (m_properties.target == QAbstractTexture::TargetAutomatic ||
+ m_properties.format == QAbstractTexture::Automatic ||
+ m_properties.format == QAbstractTexture::NoFormat) {
textureInfo.properties.status = QAbstractTexture::Error;
return textureInfo;
}
}
- // if the properties changed, we need to re-allocate the texture
+ // If the properties changed or texture has become a shared texture from a
+ // 3rd party engine, we need to destroy and maybe re-allocate the texture
if (testDirtyFlag(Properties) || testDirtyFlag(SharedTextureId)) {
delete m_gl;
m_gl = nullptr;
textureInfo.wasUpdated = true;
- // If we are destroyed because of some property change but still our content data
- // make sure we are marked for upload
- if (m_textureData || !m_imageData.empty())
- needUpload = true;
+ // If we are destroyed because of some property change but still have (some) of
+ // our content data make sure we are marked for upload
+ // TO DO: We should actually check if the textureData is still correct
+ // in regard to the size, target and format of the texture though.
+ if (!testDirtyFlag(SharedTextureId) &&
+ (m_textureData || !m_imageData.empty() || !m_pendingTextureDataUpdates.empty()))
+ setDirtyFlag(TextureData, true);
}
m_properties.status = QAbstractTexture::Ready;
- if (hasSharedTextureId && testDirtyFlag(SharedTextureId)) {
+ if (testDirtyFlag(SharedTextureId) || hasSharedTextureId) {
// Update m_properties by doing introspection on the texture
- introspectPropertiesFromSharedTextureId();
+ if (hasSharedTextureId)
+ introspectPropertiesFromSharedTextureId();
+ setDirtyFlag(SharedTextureId, false);
} else {
// We only build a QOpenGLTexture if we have no shared textureId set
if (!m_gl) {
m_gl = buildGLTexture();
if (!m_gl) {
+ qWarning() << "[Qt3DRender::GLTexture] failed to create texture";
textureInfo.properties.status = QAbstractTexture::Error;
return textureInfo;
}
m_gl->allocateStorage();
if (!m_gl->isStorageAllocated()) {
+ qWarning() << "[Qt3DRender::GLTexture] failed to allocate texture";
textureInfo.properties.status = QAbstractTexture::Error;
return textureInfo;
}
+ m_wasTextureRecreated = true;
}
textureInfo.texture = m_gl;
// need to (re-)upload texture data?
- if (needUpload) {
+ const bool needsUpload = testDirtyFlag(TextureData);
+ if (needsUpload) {
uploadGLTextureData();
setDirtyFlag(TextureData, false);
}
@@ -266,26 +333,20 @@ GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture()
// need to set texture parameters?
if (testDirtyFlag(Properties) || testDirtyFlag(Parameters)) {
updateGLTextureParameters();
+ setDirtyFlag(Properties, false);
+ setDirtyFlag(Parameters, false);
}
}
textureInfo.properties = m_properties;
- // un-set properties and parameters. The TextureData flag might have been set by another thread
- // in the meantime, so don't clear that.
- setDirtyFlag(Properties, false);
- setDirtyFlag(Parameters, false);
- setDirtyFlag(SharedTextureId, false);
-
return textureInfo;
}
RenderBuffer *GLTexture::getOrCreateRenderBuffer()
{
- QMutexLocker locker(&m_textureMutex);
-
if (m_dataFunctor && !m_textureData) {
- m_textureData = m_textureDataManager->getData(m_dataFunctor);
+ m_textureData = m_dataFunctor->operator()();
if (m_textureData) {
if (m_properties.target != QAbstractTexture::TargetAutomatic)
qWarning() << "[Qt3DRender::GLTexture] [renderbuffer] When a texture provides a generator, it's target is expected to be TargetAutomatic";
@@ -318,9 +379,15 @@ RenderBuffer *GLTexture::getOrCreateRenderBuffer()
return m_renderBuffer;
}
+// This must be called from the RenderThread
+// So GLTexture release from the manager can only be done from that thread
+void GLTexture::cleanup()
+{
+ destroy();
+}
+
void GLTexture::setParameters(const TextureParameters &params)
{
- QMutexLocker locker(&m_textureMutex);
if (m_parameters != params) {
m_parameters = params;
setDirtyFlag(Parameters);
@@ -329,10 +396,8 @@ void GLTexture::setParameters(const TextureParameters &params)
void GLTexture::setProperties(const TextureProperties &props)
{
- QMutexLocker locker(&m_textureMutex);
if (m_properties != props) {
m_properties = props;
- m_actualTarget = props.target;
setDirtyFlag(Properties);
}
}
@@ -353,25 +418,16 @@ void GLTexture::setImages(const QVector<Image> &images)
if (!same) {
m_images = images;
- requestUpload();
+ requestImageUpload();
}
}
void GLTexture::setGenerator(const QTextureGeneratorPtr &generator)
{
- // Note: we do not compare if the generator is different
- // as in some cases we may want to reset the same generator to force a reload
- // e.g when using remote urls for textures
- if (m_dataFunctor)
- m_textureDataManager->releaseData(m_dataFunctor, this);
-
m_textureData.reset();
m_dataFunctor = generator;
-
- if (m_dataFunctor) {
- m_textureDataManager->requestData(m_dataFunctor, this);
- requestUpload();
- }
+ m_pendingDataFunctor = nullptr;
+ requestUpload();
}
void GLTexture::setSharedTextureId(int textureId)
@@ -382,6 +438,12 @@ void GLTexture::setSharedTextureId(int textureId)
}
}
+void GLTexture::addTextureDataUpdates(const QVector<QTextureDataUpdate> &updates)
+{
+ m_pendingTextureDataUpdates += updates;
+ requestUpload();
+}
+
// Return nullptr if
// - context cannot be obtained
// - texture hasn't yet been loaded
@@ -393,28 +455,29 @@ QOpenGLTexture *GLTexture::buildGLTexture()
return nullptr;
}
- if (m_actualTarget == QAbstractTexture::TargetAutomatic) {
+ const QAbstractTexture::Target actualTarget = m_properties.target;
+ if (actualTarget == QAbstractTexture::TargetAutomatic) {
// If the target is automatic at this point, it means that the texture
// hasn't been loaded yet (case of remote urls) and that loading failed
// and that target format couldn't be deduced
return nullptr;
}
- QOpenGLTexture* glTex = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(m_actualTarget));
+ QOpenGLTexture* glTex = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(actualTarget));
// m_format may not be ES2 compatible. Now it's time to convert it, if necessary.
QAbstractTexture::TextureFormat format = m_properties.format;
if (ctx->isOpenGLES() && ctx->format().majorVersion() < 3) {
switch (m_properties.format) {
- case QOpenGLTexture::RGBA8_UNorm:
- case QOpenGLTexture::RGBAFormat:
+ case QAbstractTexture::RGBA8_UNorm:
+ case QAbstractTexture::RGBAFormat:
format = QAbstractTexture::RGBAFormat;
break;
- case QOpenGLTexture::RGB8_UNorm:
- case QOpenGLTexture::RGBFormat:
+ case QAbstractTexture::RGB8_UNorm:
+ case QAbstractTexture::RGBFormat:
format = QAbstractTexture::RGBFormat;
break;
- case QOpenGLTexture::DepthFormat:
+ case QAbstractTexture::DepthFormat:
format = QAbstractTexture::DepthFormat;
break;
default:
@@ -436,19 +499,19 @@ QOpenGLTexture *GLTexture::buildGLTexture()
}
glTex->setFormat(m_properties.format == QAbstractTexture::Automatic ?
- QOpenGLTexture::NoFormat :
- static_cast<QOpenGLTexture::TextureFormat>(format));
+ QOpenGLTexture::NoFormat :
+ static_cast<QOpenGLTexture::TextureFormat>(format));
glTex->setSize(m_properties.width, m_properties.height, m_properties.depth);
// Set layers count if texture array
- if (m_actualTarget == QAbstractTexture::Target1DArray ||
- m_actualTarget == QAbstractTexture::Target2DArray ||
- m_actualTarget == QAbstractTexture::Target2DMultisampleArray ||
- m_actualTarget == QAbstractTexture::TargetCubeMapArray) {
+ if (actualTarget == QAbstractTexture::Target1DArray ||
+ actualTarget == QAbstractTexture::Target2DArray ||
+ actualTarget == QAbstractTexture::Target2DMultisampleArray ||
+ actualTarget == QAbstractTexture::TargetCubeMapArray) {
glTex->setLayers(m_properties.layers);
}
- if (m_actualTarget == QAbstractTexture::Target2DMultisample ||
- m_actualTarget == QAbstractTexture::Target2DMultisampleArray) {
+ if (actualTarget == QAbstractTexture::Target2DMultisample ||
+ actualTarget == QAbstractTexture::Target2DMultisampleArray) {
// Set samples count if multisampled texture
// (multisampled textures don't have mipmaps)
glTex->setSamples(m_properties.samples);
@@ -471,19 +534,6 @@ QOpenGLTexture *GLTexture::buildGLTexture()
return glTex;
}
-static void uploadGLData(QOpenGLTexture *glTex,
- int level, int layer, QOpenGLTexture::CubeMapFace face,
- const QByteArray &bytes, const QTextureImageDataPtr &data)
-{
- if (data->isCompressed()) {
- glTex->setCompressedData(level, layer, face, bytes.size(), bytes.constData());
- } else {
- QOpenGLPixelTransferOptions uploadOptions;
- uploadOptions.setAlignment(1);
- glTex->setData(level, layer, face, data->pixelFormat(), data->pixelType(), bytes.constData(), &uploadOptions);
- }
-}
-
void GLTexture::uploadGLTextureData()
{
// Upload all QTexImageData set by the QTextureGenerator
@@ -518,23 +568,69 @@ void GLTexture::uploadGLTextureData()
static_cast<QOpenGLTexture::CubeMapFace>(m_images[i].face),
bytes, imgData);
}
+ // Free up image data once content has been uploaded
+ // Note: if data functor stores the data, this won't really free anything though
+ m_imageData.clear();
+
+ // Update data from TextureUpdates
+ const QVector<QTextureDataUpdate> textureDataUpdates = std::move(m_pendingTextureDataUpdates);
+ for (const QTextureDataUpdate &update : textureDataUpdates) {
+ const QTextureImageDataPtr imgData = update.data();
+
+ if (!imgData) {
+ qWarning() << Q_FUNC_INFO << "QTextureDataUpdate no QTextureImageData set";
+ continue;
+ }
+
+ const int xOffset = update.x();
+ const int yOffset = update.y();
+ const int zOffset = update.z();
+ const int xExtent = xOffset + imgData->width();
+ const int yExtent = yOffset + imgData->height();
+ const int zExtent = zOffset + imgData->depth();
+
+ // Check update is compatible with our texture
+ if (xOffset >= m_gl->width() ||
+ yOffset >= m_gl->height() ||
+ zOffset >= m_gl->depth() ||
+ xExtent > m_gl->width() ||
+ yExtent > m_gl->height() ||
+ zExtent > m_gl->depth() ||
+ update.mipLevel() >= m_gl->mipLevels() ||
+ update.layer() >= m_gl->layers()) {
+ qWarning() << Q_FUNC_INFO << "QTextureDataUpdate incompatible with texture";
+ continue;
+ }
+
+ const QByteArray bytes = (QTextureImageDataPrivate::get(imgData.get())->m_data);
+ // Here the bytes in the QTextureImageData contain data for a single
+ // layer, face or mip level, unlike the QTextureGenerator case where
+ // they are in a single blob. Hence QTextureImageData::data() is not suitable.
+
+ uploadGLData(m_gl,
+ update.mipLevel(), update.layer(),
+ static_cast<QOpenGLTexture::CubeMapFace>(update.face()),
+ xOffset, yOffset, zOffset,
+ bytes, imgData);
+ }
}
void GLTexture::updateGLTextureParameters()
{
- const bool isMultisampledTexture = (m_actualTarget == QAbstractTexture::Target2DMultisample ||
- m_actualTarget == QAbstractTexture::Target2DMultisampleArray);
+ const QAbstractTexture::Target actualTarget = m_properties.target;
+ const bool isMultisampledTexture = (actualTarget == QAbstractTexture::Target2DMultisample ||
+ actualTarget == QAbstractTexture::Target2DMultisampleArray);
// Multisampled textures can only be accessed by texelFetch in shaders
// and don't support wrap modes and mig/mag filtes
if (isMultisampledTexture)
return;
m_gl->setWrapMode(QOpenGLTexture::DirectionS, static_cast<QOpenGLTexture::WrapMode>(m_parameters.wrapModeX));
- if (m_actualTarget != QAbstractTexture::Target1D &&
- m_actualTarget != QAbstractTexture::Target1DArray &&
- m_actualTarget != QAbstractTexture::TargetBuffer)
+ if (actualTarget != QAbstractTexture::Target1D &&
+ actualTarget != QAbstractTexture::Target1DArray &&
+ actualTarget != QAbstractTexture::TargetBuffer)
m_gl->setWrapMode(QOpenGLTexture::DirectionT, static_cast<QOpenGLTexture::WrapMode>(m_parameters.wrapModeY));
- if (m_actualTarget == QAbstractTexture::Target3D)
+ if (actualTarget == QAbstractTexture::Target3D)
m_gl->setWrapMode(QOpenGLTexture::DirectionR, static_cast<QOpenGLTexture::WrapMode>(m_parameters.wrapModeZ));
m_gl->setMinMagFilters(static_cast<QOpenGLTexture::Filter>(m_parameters.minificationFilter),
static_cast<QOpenGLTexture::Filter>(m_parameters.magnificationFilter));
@@ -581,8 +677,8 @@ void GLTexture::introspectPropertiesFromSharedTextureId()
const QPair<int, int> ctxGLVersion = ctx->format().version();
if (ctxGLVersion.first > 4 || (ctxGLVersion.first == 4 && ctxGLVersion.second >= 5)) {
// Only for GL 4.5+
- QOpenGLFunctions_4_5_Core *gl5 = ctx->versionFunctions<QOpenGLFunctions_4_5_Core>();
#ifdef GL_TEXTURE_TARGET
+ QOpenGLFunctions_4_5_Core *gl5 = ctx->versionFunctions<QOpenGLFunctions_4_5_Core>();
if (gl5 != nullptr)
gl5->glGetTextureParameteriv(m_sharedTextureId, GL_TEXTURE_TARGET, reinterpret_cast<int *>(&m_properties.target));
#endif
diff --git a/src/render/renderers/opengl/textures/gltexture_p.h b/src/render/renderers/opengl/textures/gltexture_p.h
index 66f66926c..ca851712d 100644
--- a/src/render/renderers/opengl/textures/gltexture_p.h
+++ b/src/render/renderers/opengl/textures/gltexture_p.h
@@ -96,13 +96,18 @@ class RenderBuffer;
class Q_AUTOTEST_EXPORT GLTexture
{
public:
- GLTexture(TextureDataManager *texDataMgr,
- TextureImageDataManager *texImgDataMgr,
- const QTextureGeneratorPtr &texGen,
- bool unique);
-
+ GLTexture();
~GLTexture();
+ enum DirtyFlag {
+ None = 0,
+ TextureData = (1 << 0), // texture data needs uploading to GPU
+ Properties = (1 << 1), // texture needs to be (re-)created
+ Parameters = (1 << 2), // texture parameters need to be (re-)set
+ SharedTextureId = (1 << 3), // texture id from shared context
+ TextureImageData = (1 << 4) // texture image data needs uploading
+ };
+
/**
* Helper class to hold the defining properties of TextureImages
*/
@@ -120,8 +125,6 @@ public:
inline bool operator!=(const Image &o) const { return !(*this == o); }
};
- inline bool isUnique() const { return m_unique; }
-
inline TextureProperties properties() const { return m_properties; }
inline TextureParameters parameters() const { return m_parameters; }
inline QTextureGeneratorPtr textureGenerator() const { return m_dataFunctor; }
@@ -157,23 +160,21 @@ public:
*/
RenderBuffer *getOrCreateRenderBuffer();
- /**
- * @brief Make sure to call this before calling the dtor
- */
- void destroyGLTexture();
- // Called by TextureDataManager when it has new texture data from
- // a generator that needs to be uploaded.
- void requestUpload()
- {
- setDirtyFlag(TextureData, true);
- }
+ void destroy();
- bool isDirty()
+ void cleanup();
+
+ bool isDirty() const
{
- return m_dirtyFlags.load() != 0;
+ return m_dirtyFlags != None;
}
+ bool hasTextureData() const { return !m_textureData.isNull(); }
+ bool hasImagesData() const { return !m_imageData.isEmpty(); }
+
+ QFlags<DirtyFlag> dirtyFlags() const { return m_dirtyFlags; }
+
QMutex *externalRenderingLock()
{
return &m_externalRenderingMutex;
@@ -189,44 +190,41 @@ public:
return m_externalRendering;
}
-protected:
- template<class APITexture, class APITextureImage>
- friend class APITextureManager;
+ // Purely for unit testing purposes
+ bool wasTextureRecreated() const
+ {
+ return m_wasTextureRecreated;
+ }
- /*
- * These methods are to be accessed from the GLTextureManager.
- * The renderer and the texture backend nodes can only modify Textures
- * through the GLTextureManager.
- *
- * The methods should only be called for unique textures, or textures
- * that are not shared between multiple nodes.
- */
void setParameters(const TextureParameters &params);
void setProperties(const TextureProperties &props);
void setImages(const QVector<Image> &images);
void setGenerator(const QTextureGeneratorPtr &generator);
void setSharedTextureId(int textureId);
+ void addTextureDataUpdates(const QVector<QTextureDataUpdate> &updates);
+
+ QVector<QTextureDataUpdate> textureDataUpdates() const { return m_pendingTextureDataUpdates; }
+ QTextureGeneratorPtr dataGenerator() const { return m_dataFunctor; }
private:
+ void requestImageUpload()
+ {
+ m_dirtyFlags |= TextureImageData;
+ }
- enum DirtyFlag {
- TextureData = 0x01, // one or more image generators have been executed, data needs uploading to GPU
- Properties = 0x02, // texture needs to be (re-)created
- Parameters = 0x04, // texture parameters need to be (re-)set
- SharedTextureId = 0x08 // texture id from shared context
- };
+ void requestUpload()
+ {
+ m_dirtyFlags |= TextureData;
+ }
bool testDirtyFlag(DirtyFlag flag)
{
- return m_dirtyFlags.load() & flag;
+ return m_dirtyFlags.testFlag(flag);
}
void setDirtyFlag(DirtyFlag flag, bool value = true)
{
- if (value)
- m_dirtyFlags |= flag;
- else
- m_dirtyFlags &= ~static_cast<int>(flag);
+ m_dirtyFlags.setFlag(flag, value);
}
QOpenGLTexture *buildGLTexture();
@@ -237,18 +235,12 @@ private:
void introspectPropertiesFromSharedTextureId();
void destroyResources();
- bool m_unique;
- QAtomicInt m_dirtyFlags;
- QMutex m_textureMutex;
+ QFlags<DirtyFlag> m_dirtyFlags;
QMutex m_externalRenderingMutex;
QOpenGLTexture *m_gl;
RenderBuffer *m_renderBuffer;
- TextureDataManager *m_textureDataManager;
- TextureImageDataManager *m_textureImageDataManager;
-
// target which is actually used for GL texture
- QAbstractTexture::Target m_actualTarget;
TextureProperties m_properties;
TextureParameters m_parameters;
@@ -259,9 +251,11 @@ private:
// cache actual image data generated by the functors
QTextureDataPtr m_textureData;
QVector<QTextureImageDataPtr> m_imageData;
+ QVector<QTextureDataUpdate> m_pendingTextureDataUpdates;
int m_sharedTextureId;
bool m_externalRendering;
+ bool m_wasTextureRecreated;
};
} // namespace Render
diff --git a/src/render/renderers/opengl/textures/gltexturemanager_p.h b/src/render/renderers/opengl/textures/gltexturemanager_p.h
index 1c8b49911..335af136c 100644
--- a/src/render/renderers/opengl/textures/gltexturemanager_p.h
+++ b/src/render/renderers/opengl/textures/gltexturemanager_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DRender/private/apitexturemanager_p.h>
+#include <Qt3DCore/private/qresourcemanager_p.h>
#include <Qt3DRender/private/gltexture_p.h>
QT_BEGIN_NAMESPACE
@@ -59,21 +59,20 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
namespace Render {
-class Q_AUTOTEST_EXPORT GLTextureManager : public APITextureManager<GLTexture, GLTexture::Image>
+class Q_AUTOTEST_EXPORT GLTextureManager : public Qt3DCore::QResourceManager<
+ GLTexture,
+ Qt3DCore::QNodeId,
+ Qt3DCore::NonLockingPolicy>
{
public:
- explicit GLTextureManager(TextureImageManager *textureImageManager,
- TextureDataManager *textureDataManager,
- TextureImageDataManager *textureImageDataManager)
- : APITextureManager<GLTexture, GLTexture::Image>(textureImageManager,
- textureDataManager,
- textureImageDataManager)
- {}
+ QHash<GLTexture *, Qt3DCore::QNodeId> texNodeIdForGLTexture;
};
} // namespace Render
} // namespace Qt3DRender
+Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::GLTexture, Q_REQUIRES_CLEANUP)
+
QT_END_NAMESPACE
#endif // QT3DRENDER_RENDER_GLTEXTUREMANAGER_H
diff --git a/src/render/renderstates/genericstate_p.h b/src/render/renderstates/genericstate_p.h
index b07487d65..e3ece36f5 100644
--- a/src/render/renderstates/genericstate_p.h
+++ b/src/render/renderstates/genericstate_p.h
@@ -80,7 +80,7 @@ public:
virtual StateMask mask() const = 0;
virtual bool equalTo(const RenderStateImpl &renderState) const = 0;
- virtual void updateProperty(const char *name, const QVariant &value);
+ virtual void updateProperties(const QRenderState *);
};
template <class StateSetImpl, StateMask stateMask, typename ... T>
diff --git a/src/render/renderstates/qdepthrange.cpp b/src/render/renderstates/qdepthrange.cpp
new file mode 100644
index 000000000..ec5bbce9f
--- /dev/null
+++ b/src/render/renderstates/qdepthrange.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdepthrange.h"
+#include "qdepthrange_p.h"
+#include <Qt3DRender/private/qrenderstatecreatedchange_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+/*!
+ \class Qt3DRender::QDepthRange
+ \inmodule Qt3DRender
+ \since 5.14
+ \ingroup renderstates
+ \brief Enables remapping depth values written into the depth buffer.
+
+ By default, OpenGL writes scene depth information into the depth buffer in
+ the range [0.0, 1.0] with 0.0 corresponding to the near clip plane and 1.0 to
+ the far clip plane. QDepthRange allows mapping these values into a different
+ range so parts of the scene are always rendered in front of or behind other
+ parts. Valid values for near and far are between 0 and 1.
+ */
+
+/*!
+ \qmltype DepthRange
+ \instantiates Qt3DRender::QDepthRange
+ \inherits RenderState
+ \inqmlmodule Qt3D.Render
+ \ingroup renderstates
+ \since 5.14
+ \brief Enables remapping depth values written into the depth buffer.
+
+ By default, OpenGL writes scene depth information into the depth buffer in
+ the range [0.0, 1.0] corresponding to the near and far clip planes.
+ QDepthRange allows mapping these values into a different range. For example
+ setting the range [0.0, 0.5] will map the rendered scene into the depth
+ buffer such that objects at the near clip plane have depth value of 0.0 and
+ objects at the far clip plane have a depth value of 0.5. This allows
+ rendering parts of the scene always in front of or behind other parts.
+*/
+
+/*!
+ \qmlproperty real QDepthRange::nearValue
+ The depth buffer value corresponding to the near clip plane. Valid values for are
+ between 0 and 1.
+*/
+
+/*!
+ \qmlproperty real QDepthRange::farValue
+ The depth buffer value corresponding to the far clip plane. Valid values for are
+ between 0 and 1.
+*/
+
+/*!
+ \property QDepthRange::nearValue
+ The depth buffer value corresponding to the near clip plane. Valid values for are
+ between 0 and 1.
+*/
+
+/*!
+ \property QDepthRange::farValue
+ The depth buffer value corresponding to the far clip plane. Valid values for are
+ between 0 and 1.
+*/
+
+QDepthRange::QDepthRange(QNode *parent)
+ : QRenderState(*new QDepthRangePrivate(), parent)
+{
+}
+
+/*! \internal */
+QDepthRange::~QDepthRange()
+{
+}
+
+double QDepthRange::nearValue() const
+{
+ Q_D(const QDepthRange);
+ return d->m_nearValue;
+}
+
+double QDepthRange::farValue() const
+{
+ Q_D(const QDepthRange);
+ return d->m_farValue;
+}
+
+void QDepthRange::setNearValue(double value)
+{
+ Q_D(QDepthRange);
+ if (value != d->m_nearValue) {
+ d->m_nearValue = value;
+ Q_EMIT nearValueChanged(value);
+ }
+}
+
+void QDepthRange::setFarValue(double value)
+{
+ Q_D(QDepthRange);
+ if (value != d->m_farValue) {
+ d->m_farValue = value;
+ Q_EMIT farValueChanged(value);
+ }
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QDepthRange::createNodeCreationChange() const
+{
+ auto creationChange = QRenderStateCreatedChangePtr<QDepthRangeData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QDepthRange);
+ data.nearValue = d->m_nearValue;
+ data.farValue = d->m_farValue;
+ return creationChange;
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/renderstates/qdepthrange.h b/src/render/renderstates/qdepthrange.h
new file mode 100644
index 000000000..9352f5e3a
--- /dev/null
+++ b/src/render/renderstates/qdepthrange.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QDEPTHRANGE_H
+#define QT3DRENDER_QDEPTHRANGE_H
+
+#include <Qt3DRender/qrenderstate.h>
+#include <QtGui/qvector3d.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QDepthRangePrivate;
+
+class Q_3DRENDERSHARED_EXPORT QDepthRange : public QRenderState
+{
+ Q_OBJECT
+ Q_PROPERTY(double nearValue READ nearValue WRITE setNearValue NOTIFY nearValueChanged)
+ Q_PROPERTY(double farValue READ farValue WRITE setFarValue NOTIFY farValueChanged)
+public:
+ explicit QDepthRange(Qt3DCore::QNode *parent = nullptr);
+ ~QDepthRange();
+
+ double nearValue() const;
+ double farValue() const;
+
+public Q_SLOTS:
+ void setNearValue(double value);
+ void setFarValue(double value);
+
+Q_SIGNALS:
+ void nearValueChanged(double nearValue);
+ void farValueChanged(double farValue);
+
+private:
+ Q_DECLARE_PRIVATE(QDepthRange)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QDEPTHRANGE_H
diff --git a/src/render/jobs/updateentityhierarchyjob_p.h b/src/render/renderstates/qdepthrange_p.h
index fd2b13631..43eeeb4c7 100644
--- a/src/render/jobs/updateentityhierarchyjob_p.h
+++ b/src/render/renderstates/qdepthrange_p.h
@@ -37,9 +37,8 @@
**
****************************************************************************/
-
-#ifndef QT3DRENDER_RENDER_UPDATEENTITYHIERARCHYJOB_P_H
-#define QT3DRENDER_RENDER_UPDATEENTITYHIERARCHYJOB_P_H
+#ifndef QT3DRENDER_QDEPTHRANGE_P_H
+#define QT3DRENDER_QDEPTHRANGE_P_H
//
// W A R N I N G
@@ -52,40 +51,35 @@
// We mean it.
//
+#include <Qt3DRender/private/qrenderstate_p.h>
+#include <Qt3DRender/qalphatest.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
-#include <Qt3DCore/qaspectjob.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-namespace Render {
-
-class Entity;
-class NodeManagers;
-
-class Q_3DRENDERSHARED_PRIVATE_EXPORT UpdateEntityHierarchyJob: public Qt3DCore::QAspectJob
+class Q_3DRENDERSHARED_PRIVATE_EXPORT QDepthRangePrivate : public QRenderStatePrivate
{
public:
- UpdateEntityHierarchyJob();
-
- inline void setManager(NodeManagers *manager) { m_manager = manager; }
- inline NodeManagers *manager() const { return m_manager; }
-
- // QAspectJob interface
- void run() final;
-
-private:
- NodeManagers *m_manager;
+ QDepthRangePrivate()
+ : QRenderStatePrivate(Render::DepthRangeMask)
+ , m_nearValue(0.0f)
+ , m_farValue(1.0f)
+ {}
+
+ double m_nearValue;
+ double m_farValue;
};
+struct QDepthRangeData
+{
+ double nearValue;
+ double farValue;
+};
-using UpdateEntityHierarchyJobPtr = QSharedPointer<UpdateEntityHierarchyJob>;
-
-} // Render
-
-} // Qt3DRender
+} // namespace Qt3DRender
QT_END_NAMESPACE
-#endif // QT3DRENDER_RENDER_UPDATEENTITYHIERARCHYJOB_P_H
+#endif // QT3DRENDER_QDEPTHRANGE_P_H
diff --git a/src/render/renderstates/qdithering.cpp b/src/render/renderstates/qdithering.cpp
index ae77ced97..a449be508 100644
--- a/src/render/renderstates/qdithering.cpp
+++ b/src/render/renderstates/qdithering.cpp
@@ -41,7 +41,6 @@
#include "qdithering.h"
#include "qrenderstate_p.h"
#include <private/qnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/renderstates/qmultisampleantialiasing.cpp b/src/render/renderstates/qmultisampleantialiasing.cpp
index bb5136846..249dcd4bd 100644
--- a/src/render/renderstates/qmultisampleantialiasing.cpp
+++ b/src/render/renderstates/qmultisampleantialiasing.cpp
@@ -40,7 +40,6 @@
#include "qmultisampleantialiasing.h"
#include "qrenderstate_p.h"
#include <private/qnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/renderstates/qnodepthmask.cpp b/src/render/renderstates/qnodepthmask.cpp
index 7be7f24f4..241751a26 100644
--- a/src/render/renderstates/qnodepthmask.cpp
+++ b/src/render/renderstates/qnodepthmask.cpp
@@ -41,7 +41,6 @@
#include "qnodepthmask.h"
#include "qrenderstate_p.h"
#include <private/qnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/renderstates/qrastermode.cpp b/src/render/renderstates/qrastermode.cpp
new file mode 100644
index 000000000..648872a84
--- /dev/null
+++ b/src/render/renderstates/qrastermode.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrastermode.h"
+#include "qrastermode_p.h"
+#include <Qt3DRender/private/qrenderstatecreatedchange_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+/*!
+ \class Qt3DRender::QRasterMode
+ \brief The QRasterMode render state allows to control the type of
+ rasterization to be performed.
+ \since 5.14
+ \inmodule Qt3DRender
+ \ingroup renderstates
+
+ The QRasterMode class is used to control the rasterization step of the
+ primitives at render time. This can be used to choose whether we only
+ want to show points, edges or fill a primitive.
+
+ \note This is not supported when rendering on OpenGL ES 2.0 platforms.
+
+ \sa QAlphaTest, QStencilTest
+ */
+
+/*!
+ \qmltype RasterMode
+ \brief The RasterMode render state allows to control the type of
+ rasterization to be performed.
+ \since 5.14
+ \inqmlmodule Qt3D.Render
+ \inherits RenderState
+ \instantiates Qt3DRender::QRasterMode
+ \ingroup renderstates
+
+ The QRasterMode class is used to control the rasterization step of the
+ primitives at render time. This can be used to choose whether we only
+ want to show points, edges or fill a primitive.
+
+ \note This is not supported when rendering on OpenGL ES 2.0 platforms.
+
+ \sa AlphaTest, StencilTest
+ */
+
+/*!
+ \enum Qt3DRender::QRasterMode::RasterMode
+
+ Enumeration for raster mode values
+ \value Points Vertices at the start of an edge are drawn as points.
+ \value Lines Edges of a polygon are draw as line segments.
+ \value Fill Fills the interior of the primitive.
+*/
+
+/*!
+ \enum Qt3DRender::QRasterMode::FaceMode
+
+ Enumeration for face mode values
+ \value Front Applies to front faces only
+ \value Back Applies to back faces only
+ \value FrontAndBack Applies to front and back faces
+*/
+
+/*!
+ \property QRasterMode::rasterMode
+
+ Holds the raster mode to be used.
+*/
+
+/*!
+ \property QRasterMode::faceMode
+
+ Holds the face mode to be used. Controls on which face the raster mode is
+ to be applied.
+*/
+
+/*!
+ \qmlproperty enumeration RasterMode::rasterMode
+
+ Holds the raster mode to be used.
+
+ \list
+ \li Points Vertices at the start of an edge are drawn as points.
+ \li Lines Edges of a polygon are draw as line segments.
+ \li Fill Fills the interior of the primitive.
+ \endlist
+*/
+
+/*!
+ \qmlproperty enumeration RasterMode::faceMode
+
+ Holds the face mode to be used. Controls on which face the raster mode is
+ to be applied.
+
+ \list
+ \li Front Applies to front faces only
+ \li Back Applies to back faces only
+ \li FrontAndBack Applies to front and back faces
+ \endlist
+*/
+
+
+
+QRasterMode::QRasterMode(QNode *parent)
+ : QRenderState(*new QRasterModePrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QRasterMode::~QRasterMode()
+ = default;
+
+QRasterMode::RasterMode QRasterMode::rasterMode() const
+{
+ Q_D(const QRasterMode);
+ return d->m_rasterMode;
+}
+
+QRasterMode::FaceMode QRasterMode::faceMode() const
+{
+ Q_D(const QRasterMode);
+ return d->m_faceMode;
+}
+
+void QRasterMode::setRasterMode(QRasterMode::RasterMode rasterMode)
+{
+ Q_D(QRasterMode);
+ if (d->m_rasterMode != rasterMode) {
+ d->m_rasterMode = rasterMode;
+ emit rasterModeChanged(rasterMode);
+ }
+}
+
+void QRasterMode::setFaceMode(QRasterMode::FaceMode faceMode)
+{
+ Q_D(QRasterMode);
+ if (d->m_faceMode != faceMode) {
+ d->m_faceMode = faceMode;
+ emit faceModeChanged(faceMode);
+ }
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QRasterMode::createNodeCreationChange() const
+{
+ auto creationChange = QRenderStateCreatedChangePtr<QRasterModeData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QRasterMode);
+ data.rasterMode = d->m_rasterMode;
+ data.faceMode = d->m_faceMode;
+ return creationChange;
+}
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/jobs/loadtexturedatajob.cpp b/src/render/renderstates/qrastermode.h
index 55232d74f..d460fa10c 100644
--- a/src/render/jobs/loadtexturedatajob.cpp
+++ b/src/render/renderstates/qrastermode.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,49 +37,60 @@
**
****************************************************************************/
-#include "loadtexturedatajob_p.h"
-#include <Qt3DRender/private/nodemanagers_p.h>
-#include <Qt3DRender/private/texturedatamanager_p.h>
-#include <Qt3DRender/qtextureimagedata.h>
-#include <Qt3DRender/private/job_common_p.h>
-#include <Qt3DRender/private/qtextureimagedata_p.h>
+#ifndef QT3DRENDER_QRASTERMODE_H
+#define QT3DRENDER_QRASTERMODE_H
+
+#include <Qt3DRender/qrenderstate.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-namespace Render {
-LoadTextureDataJob::LoadTextureDataJob(const QTextureGeneratorPtr &texGen)
- : m_texGen(texGen)
- , m_imgDataGen(nullptr)
-{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadTextureData, 0);
-}
+class QRasterModePrivate;
-LoadTextureDataJob::LoadTextureDataJob(const QTextureImageDataGeneratorPtr &imgDataGen)
- : m_texGen(nullptr)
- , m_imgDataGen(imgDataGen)
+class Q_3DRENDERSHARED_EXPORT QRasterMode : public QRenderState
{
- SET_JOB_RUN_STAT_TYPE(this, JobTypes::LoadTextureData, 0);
-}
+ Q_OBJECT
+ Q_PROPERTY(RasterMode rasterMode READ rasterMode WRITE setRasterMode NOTIFY rasterModeChanged)
+ Q_PROPERTY(FaceMode faceMode READ faceMode WRITE setFaceMode NOTIFY faceModeChanged)
+public:
-LoadTextureDataJob::~LoadTextureDataJob()
-{
-}
+ enum RasterMode {
+ Points = 0x1B00,
+ Lines = 0x1B01,
+ Fill = 0x1B02,
+ };
+ Q_ENUM(RasterMode) // LCOV_EXCL_LINE
+
+ enum FaceMode
+ {
+ Front = 0x0404,
+ Back = 0x0405,
+ FrontAndBack = 0x0408
+ };
+ Q_ENUM(FaceMode) // LCOV_EXCL_LINE
+
+ explicit QRasterMode(Qt3DCore::QNode *parent = nullptr);
+ ~QRasterMode();
+
+ RasterMode rasterMode() const;
+ FaceMode faceMode() const;
+
+public Q_SLOTS:
+ void setRasterMode(RasterMode rasterMode);
+ void setFaceMode(FaceMode faceMode);
+
+Q_SIGNALS:
+ void rasterModeChanged(RasterMode rasterMode);
+ void faceModeChanged(FaceMode faceMode);
+
+private:
+ Q_DECLARE_PRIVATE(QRasterMode)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override;
+};
-void LoadTextureDataJob::run()
-{
- if (m_texGen) {
- QTextureDataPtr texData = (*m_texGen)();
- m_manager->textureDataManager()->assignData(m_texGen, texData);
- }
- if (m_imgDataGen) {
- QTextureImageDataPtr imgData = (*m_imgDataGen)();
- m_manager->textureImageDataManager()->assignData(m_imgDataGen, imgData);
- }
-}
-
-} // namespace Render
} // namespace Qt3DRender
QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QRASTERMODE_H
diff --git a/src/render/renderstates/qrastermode_p.h b/src/render/renderstates/qrastermode_p.h
new file mode 100644
index 000000000..2e8e790de
--- /dev/null
+++ b/src/render/renderstates/qrastermode_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QRASTERMODE_P_H
+#define QT3DRENDER_QRASTERMODE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qrenderstate_p.h>
+#include <Qt3DRender/qrastermode.h>
+#include <Qt3DRender/private/qt3drender_global_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class Q_3DRENDERSHARED_PRIVATE_EXPORT QRasterModePrivate : public QRenderStatePrivate
+{
+public :
+ QRasterModePrivate()
+ : QRenderStatePrivate(Render::RasterModeMask)
+ , m_rasterMode(QRasterMode::Fill)
+ , m_faceMode(QRasterMode::FrontAndBack)
+ {
+ }
+
+ Q_DECLARE_PUBLIC(QRasterMode)
+ QRasterMode::RasterMode m_rasterMode;
+ QRasterMode::FaceMode m_faceMode;
+};
+
+struct QRasterModeData
+{
+ QRasterMode::FaceMode faceMode;
+ QRasterMode::RasterMode rasterMode;
+};
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_QRASTERMODE_P_H
diff --git a/src/render/renderstates/qseamlesscubemap.cpp b/src/render/renderstates/qseamlesscubemap.cpp
index 860b36450..8458aded8 100644
--- a/src/render/renderstates/qseamlesscubemap.cpp
+++ b/src/render/renderstates/qseamlesscubemap.cpp
@@ -40,7 +40,6 @@
#include "qseamlesscubemap.h"
#include "qrenderstate_p.h"
#include <private/qnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/src/render/renderstates/qstenciloperation.cpp b/src/render/renderstates/qstenciloperation.cpp
index af7e014f5..34f95c03d 100644
--- a/src/render/renderstates/qstenciloperation.cpp
+++ b/src/render/renderstates/qstenciloperation.cpp
@@ -40,7 +40,6 @@
#include "qstenciloperation.h"
#include "qstenciloperation_p.h"
#include "qstenciloperationarguments.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/qrenderstatecreatedchange_p.h>
QT_BEGIN_NAMESPACE
@@ -106,7 +105,7 @@ QStencilOperation::QStencilOperation(QNode *parent)
{
Q_D(QStencilOperation);
- const auto resend = [d]() { d->resendArguments(); };
+ const auto resend = [d]() { d->update(); };
(void) connect(d->m_front, &QStencilOperationArguments::allTestsPassOperationChanged, resend);
(void) connect(d->m_front, &QStencilOperationArguments::depthTestFailureOperationChanged, resend);
@@ -125,17 +124,6 @@ QStencilOperation::~QStencilOperation()
}
/*! \internal */
-void QStencilOperationPrivate::resendArguments()
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id);
- QStencilOperationData data;
- fillData(data);
- e->setPropertyName("arguments");
- e->setValue(QVariant::fromValue(data));
- notifyObservers(e);
-}
-
-/*! \internal */
void QStencilOperationPrivate::fillData(QStencilOperationData &data) const
{
data.front.face = m_front->faceMode();
diff --git a/src/render/renderstates/qstenciloperation_p.h b/src/render/renderstates/qstenciloperation_p.h
index a1c0cda4a..d38abf0d7 100644
--- a/src/render/renderstates/qstenciloperation_p.h
+++ b/src/render/renderstates/qstenciloperation_p.h
@@ -76,7 +76,6 @@ public:
QStencilOperationArguments *m_front;
QStencilOperationArguments *m_back;
- void resendArguments();
void fillData(QStencilOperationData &data) const;
};
diff --git a/src/render/renderstates/qstenciltest.cpp b/src/render/renderstates/qstenciltest.cpp
index a364c3b88..7284af140 100644
--- a/src/render/renderstates/qstenciltest.cpp
+++ b/src/render/renderstates/qstenciltest.cpp
@@ -41,7 +41,6 @@
#include "qstenciltest.h"
#include "qstenciltest_p.h"
#include "qstenciltestarguments.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/private/qrenderstatecreatedchange_p.h>
QT_BEGIN_NAMESPACE
@@ -109,7 +108,7 @@ QStencilTest::QStencilTest(QNode *parent)
{
Q_D(QStencilTest);
- const auto resend = [d]() { d->resendArguments(); };
+ const auto resend = [d]() { d->update(); };
(void) connect(d->m_front, &QStencilTestArguments::comparisonMaskChanged, resend);
(void) connect(d->m_front, &QStencilTestArguments::faceModeChanged, resend);
@@ -128,17 +127,6 @@ QStencilTest::~QStencilTest()
}
/*! \internal */
-void QStencilTestPrivate::resendArguments()
-{
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id);
- QStencilTestData data;
- fillData(data);
- e->setPropertyName("arguments");
- e->setValue(QVariant::fromValue(data));
- notifyObservers(e);
-}
-
-/*! \internal */
void QStencilTestPrivate::fillData(QStencilTestData &data) const
{
data.front.face = m_front->faceMode();
diff --git a/src/render/renderstates/qstenciltest_p.h b/src/render/renderstates/qstenciltest_p.h
index 328e34878..9ddfc6e33 100644
--- a/src/render/renderstates/qstenciltest_p.h
+++ b/src/render/renderstates/qstenciltest_p.h
@@ -78,7 +78,6 @@ public:
QStencilTestArguments *m_front;
QStencilTestArguments *m_back;
- void resendArguments();
void fillData(QStencilTestData &data) const;
};
diff --git a/src/render/renderstates/renderstatenode.cpp b/src/render/renderstates/renderstatenode.cpp
index 52d5e20ce..3040c5aaa 100644
--- a/src/render/renderstates/renderstatenode.cpp
+++ b/src/render/renderstates/renderstatenode.cpp
@@ -37,7 +37,6 @@
#include "renderstatenode_p.h"
#include <Qt3DRender/qrenderstate.h>
#include <Qt3DRender/private/qrenderstatecreatedchange_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qalphacoverage.h>
#include <Qt3DRender/qalphatest.h>
@@ -51,8 +50,12 @@
#include <Qt3DRender/qcullface.h>
#include <Qt3DRender/private/qcullface_p.h>
#include <Qt3DRender/qnodepthmask.h>
+#include <Qt3DRender/qdepthrange.h>
+#include <Qt3DRender/private/qdepthrange_p.h>
#include <Qt3DRender/qdepthtest.h>
#include <Qt3DRender/private/qdepthtest_p.h>
+#include <Qt3DRender/qrastermode.h>
+#include <Qt3DRender/private/qrastermode_p.h>
#include <Qt3DRender/qdithering.h>
#include <Qt3DRender/qfrontface.h>
#include <Qt3DRender/private/qfrontface_p.h>
@@ -86,106 +89,105 @@ namespace Render {
namespace {
-StateVariant createStateImplementation(const Qt3DRender::QRenderStateCreatedChangeBasePtr renderStateChange)
+StateVariant createStateImplementation(const QRenderState *node)
{
- switch (renderStateChange->renderStateType()) {
+ const QRenderStatePrivate *d = static_cast<const QRenderStatePrivate *>(Qt3DCore::QNodePrivate::get(node));
+ switch (d->m_type) {
case AlphaCoverageStateMask: {
return StateVariant::createState<AlphaCoverage>();
}
case AlphaTestMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QAlphaTestData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<AlphaFunc>(data.alphaFunction, data.referenceValue);
+ const QAlphaTest *alphaTest = static_cast<const QAlphaTest *>(node);
+ return StateVariant::createState<AlphaFunc>(alphaTest->alphaFunction(), alphaTest->referenceValue());
}
case BlendStateMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QBlendEquationData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<BlendEquation>(data.blendFunction);
+ const QBlendEquation *blendEquation = static_cast<const QBlendEquation *>(node);
+ return StateVariant::createState<BlendEquation>(blendEquation->blendFunction());
}
case BlendEquationArgumentsMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QBlendEquationArgumentsData>>(renderStateChange);
- const auto &data = typedChange->data;
+ const QBlendEquationArguments *blendArgs = static_cast<const QBlendEquationArguments *>(node);
return StateVariant::createState<BlendEquationArguments>(
- data.sourceRgb, data.destinationRgb,
- data.sourceAlpha, data.destinationAlpha,
- renderStateChange->isNodeEnabled(),
- data.bufferIndex);
+ blendArgs->sourceRgb(), blendArgs->destinationRgb(),
+ blendArgs->sourceAlpha(), blendArgs->destinationAlpha(),
+ blendArgs->isEnabled(),
+ blendArgs->bufferIndex());
}
case MSAAEnabledStateMask: {
- return StateVariant::createState<MSAAEnabled>(renderStateChange->isNodeEnabled());
+ return StateVariant::createState<MSAAEnabled>(node->isEnabled());
}
case CullFaceStateMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QCullFaceData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<CullFace>(data.mode);
+ const QCullFace *cullFace = static_cast<const QCullFace *>(node);
+ return StateVariant::createState<CullFace>(cullFace->mode());
+ }
+
+ case DepthRangeMask: {
+ const QDepthRange *depthRange = static_cast<const QDepthRange *>(node);
+ return StateVariant::createState<DepthRange>(depthRange->nearValue(), depthRange->farValue());
}
case DepthWriteStateMask: {
- return StateVariant::createState<NoDepthMask>(false);
+ return StateVariant::createState<NoDepthMask>(!node->isEnabled());
}
case DepthTestStateMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QDepthTestData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<DepthTest>(data.depthFunction);
+ const QDepthTest *depthTest = static_cast<const QDepthTest *>(node);
+ return StateVariant::createState<DepthTest>(depthTest->depthFunction());
+ }
+
+ case RasterModeMask: {
+ const QRasterMode *rasterMode = static_cast<const QRasterMode *>(node);
+ return StateVariant::createState<RasterMode>(rasterMode->faceMode(), rasterMode->rasterMode());
}
case FrontFaceStateMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QFrontFaceData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<FrontFace>(data.direction);
+ const QFrontFace *frontFace = static_cast<const QFrontFace *>(node);
+ return StateVariant::createState<FrontFace>(frontFace->direction());
}
case ScissorStateMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QScissorTestData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<ScissorTest>(data.left, data.bottom,
- data.width, data.height);
+ const QScissorTest *scissorTest = static_cast<const QScissorTest *>(node);
+ return StateVariant::createState<ScissorTest>(scissorTest->left(), scissorTest->bottom(),
+ scissorTest->width(), scissorTest->height());
}
case StencilTestStateMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QStencilTestData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<StencilTest>(data.front.stencilFunction,
- data.front.referenceValue,
- data.front.comparisonMask,
- data.back.stencilFunction,
- data.back.referenceValue,
- data.back.comparisonMask);
+ const QStencilTest *stencilTest = static_cast<const QStencilTest *>(node);
+ return StateVariant::createState<StencilTest>(stencilTest->front()->stencilFunction(),
+ stencilTest->front()->referenceValue(),
+ stencilTest->front()->comparisonMask(),
+ stencilTest->back()->stencilFunction(),
+ stencilTest->back()->referenceValue(),
+ stencilTest->back()->comparisonMask());
}
case PointSizeMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QPointSizeData>>(renderStateChange);
- const auto &data = typedChange->data;
- const bool isProgrammable = (data.sizeMode == QPointSize::Programmable);
- return StateVariant::createState<PointSize>(isProgrammable, data.value);
+ const QPointSize *pointSize = static_cast<const QPointSize *>(node);
+ const bool isProgrammable = (pointSize->sizeMode() == QPointSize::Programmable);
+ return StateVariant::createState<PointSize>(isProgrammable, pointSize->value());
}
case PolygonOffsetStateMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QPolygonOffsetData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<PolygonOffset>(data.scaleFactor, data.depthSteps);
+ const QPolygonOffset *offset = static_cast<const QPolygonOffset *>(node);
+ return StateVariant::createState<PolygonOffset>(offset->scaleFactor(), offset->depthSteps());
}
case ColorStateMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QColorMaskData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<ColorMask>(data.redMasked, data.greenMasked,
- data.blueMasked, data.alphaMasked);
+ const QColorMask *colorMask = static_cast<const QColorMask *>(node);
+ return StateVariant::createState<ColorMask>(colorMask->isRedMasked(), colorMask->isGreenMasked(),
+ colorMask->isBlueMasked(), colorMask->isAlphaMasked());
}
case ClipPlaneMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QClipPlaneData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<ClipPlane>(data.planeIndex,
- data.normal,
- data.distance);
+ const QClipPlane *clipPlane = static_cast<const QClipPlane *>(node);
+ return StateVariant::createState<ClipPlane>(clipPlane->planeIndex(),
+ clipPlane->normal(),
+ clipPlane->distance());
}
case SeamlessCubemapMask: {
@@ -193,21 +195,19 @@ StateVariant createStateImplementation(const Qt3DRender::QRenderStateCreatedChan
}
case StencilOpMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QStencilOperationData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<StencilOp>(data.front.stencilTestFailureOperation,
- data.front.depthTestFailureOperation,
- data.front.allTestsPassOperation,
- data.back.stencilTestFailureOperation,
- data.back.depthTestFailureOperation,
- data.back.allTestsPassOperation);
+ const QStencilOperation *stencilOp = static_cast<const QStencilOperation *>(node);
+ return StateVariant::createState<StencilOp>(stencilOp->front()->stencilTestFailureOperation(),
+ stencilOp->front()->depthTestFailureOperation(),
+ stencilOp->front()->allTestsPassOperation(),
+ stencilOp->back()->stencilTestFailureOperation(),
+ stencilOp->back()->depthTestFailureOperation(),
+ stencilOp->back()->allTestsPassOperation());
}
case StencilWriteStateMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QStencilMaskData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<StencilMask>(data.frontOutputMask,
- data.backOutputMask);
+ const QStencilMask *stencilMask = static_cast<const QStencilMask *>(node);
+ return StateVariant::createState<StencilMask>(stencilMask->frontOutputMask(),
+ stencilMask->backOutputMask());
}
case DitheringStateMask: {
@@ -215,9 +215,8 @@ StateVariant createStateImplementation(const Qt3DRender::QRenderStateCreatedChan
}
case LineWidthMask: {
- const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QLineWidthData>>(renderStateChange);
- const auto &data = typedChange->data;
- return StateVariant::createState<LineWidth>(data.value, data.smooth);
+ const QLineWidth *lineWidth = static_cast<const QLineWidth *>(node);
+ return StateVariant::createState<LineWidth>(lineWidth->value(), lineWidth->smooth());
}
default:
@@ -242,21 +241,19 @@ void RenderStateNode::cleanup()
{
}
-void RenderStateNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chang3)
+void RenderStateNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime)
{
- cleanup();
- const auto renderStateChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChangeBase>(chang3);
- m_impl = createStateImplementation(renderStateChange);
-}
+ const QRenderState *node = qobject_cast<const QRenderState *>(frontEnd);
+ if (!node)
+ return;
-void RenderStateNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- if (e->type() == Qt3DCore::PropertyUpdated) {
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e);
- m_impl.state()->updateProperty(propertyChange->propertyName(), propertyChange->value());
- markDirty(AbstractRenderer::AllDirty);
- }
- BackendNode::sceneChangeEvent(e);
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+
+ if (firstTime)
+ m_impl = createStateImplementation(node);
+
+ m_impl.state()->updateProperties(node);
+ markDirty(AbstractRenderer::AllDirty);
}
} // namespace Render
diff --git a/src/render/renderstates/renderstatenode_p.h b/src/render/renderstates/renderstatenode_p.h
index 277b8a7c8..e0258112f 100644
--- a/src/render/renderstates/renderstatenode_p.h
+++ b/src/render/renderstates/renderstatenode_p.h
@@ -63,8 +63,7 @@ public:
RenderStateNode();
virtual ~RenderStateNode();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
-
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
StateMask type() const { return m_impl.type; }
StateVariant impl() const { return m_impl; }
@@ -72,7 +71,6 @@ protected:
void cleanup();
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
StateVariant m_impl;
};
diff --git a/src/render/renderstates/renderstates.cpp b/src/render/renderstates/renderstates.cpp
index d6be80b1c..5e238c010 100644
--- a/src/render/renderstates/renderstates.cpp
+++ b/src/render/renderstates/renderstates.cpp
@@ -40,7 +40,6 @@
#include "renderstates_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qrenderstate.h>
#include <Qt3DRender/qcullface.h>
#include <Qt3DRender/qpointsize.h>
@@ -48,140 +47,181 @@
#include <Qt3DRender/private/graphicscontext_p.h>
#include <Qt3DRender/private/qstenciloperation_p.h>
#include <Qt3DRender/private/qstenciltest_p.h>
+#include <Qt3DRender/qblendequationarguments.h>
+#include <Qt3DRender/qblendequation.h>
+#include <Qt3DRender/qalphatest.h>
+#include <Qt3DRender/qdepthrange.h>
+#include <Qt3DRender/qdepthtest.h>
+#include <Qt3DRender/qrastermode.h>
+#include <Qt3DRender/qfrontface.h>
+#include <Qt3DRender/qscissortest.h>
+#include <Qt3DRender/qpolygonoffset.h>
+#include <Qt3DRender/qcolormask.h>
+#include <Qt3DRender/qclipplane.h>
+#include <Qt3DRender/qstencilmask.h>
+#include <Qt3DRender/qlinewidth.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
namespace Render {
-void RenderStateImpl::updateProperty(const char *name, const QVariant &value)
+void RenderStateImpl::updateProperties(const QRenderState *)
{
- Q_UNUSED(name);
- Q_UNUSED(value);
}
-void BlendEquationArguments::updateProperty(const char *name, const QVariant &value)
+void BlendEquationArguments::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("sourceRgb")) std::get<0>(m_values) = value.toInt();
- else if (name == QByteArrayLiteral("destinationRgb")) std::get<1>(m_values) = value.toInt();
- else if (name == QByteArrayLiteral("sourceAlpha")) std::get<2>(m_values) = value.toInt();
- else if (name == QByteArrayLiteral("destinationAlpha")) std::get<3>(m_values) = value.toInt();
- else if (name == QByteArrayLiteral("enabled")) std::get<4>(m_values) = value.toBool();
- else if (name == QByteArrayLiteral("bufferIndex")) std::get<5>(m_values) = value.toInt();
+ const QBlendEquationArguments *args = static_cast<const QBlendEquationArguments *>(node);
+
+ std::get<0>(m_values) = args->sourceRgb();
+ std::get<1>(m_values) = args->destinationRgb();
+ std::get<2>(m_values) = args->sourceAlpha();
+ std::get<3>(m_values) = args->destinationAlpha();
+ std::get<4>(m_values) = args->isEnabled();
+ std::get<5>(m_values) = args->bufferIndex();
}
-void BlendEquation::updateProperty(const char *name, const QVariant &value)
+void BlendEquation::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("blendFunction")) std::get<0>(m_values) = value.toInt();
+ const QBlendEquation *equation = static_cast<const QBlendEquation *>(node);
+ std::get<0>(m_values) = equation->blendFunction();
}
-void AlphaFunc::updateProperty(const char *name, const QVariant &value)
+void AlphaFunc::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("alphaFunction"))
- std::get<0>(m_values) = value.toInt();
- if (name == QByteArrayLiteral("referenceValue"))
- std::get<1>(m_values) = value.toFloat();
+ const QAlphaTest *alphaTest = static_cast<const QAlphaTest *>(node);
+ std::get<0>(m_values) = alphaTest->alphaFunction();
+ std::get<1>(m_values) = alphaTest->referenceValue();
}
-void MSAAEnabled::updateProperty(const char *name, const QVariant &value)
+void MSAAEnabled::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("enabled"))
- std::get<0>(m_values) = value.toBool();
+ std::get<0>(m_values) = node->isEnabled();
+}
+
+void DepthRange::updateProperties(const QRenderState *node)
+{
+ const QDepthRange *depthRange = static_cast<const QDepthRange *>(node);
+
+ std::get<0>(m_values) = depthRange->nearValue();
+ std::get<1>(m_values) = depthRange->farValue();
+}
+
+void DepthTest::updateProperties(const QRenderState *node)
+{
+ const QDepthTest *depthTest = static_cast<const QDepthTest *>(node);
+
+ std::get<0>(m_values) = depthTest->depthFunction();
}
-void DepthTest::updateProperty(const char *name, const QVariant &value)
+void RasterMode::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("depthFunction")) std::get<0>(m_values) = value.toInt();
+ const QRasterMode *rasterMode = static_cast<const QRasterMode *>(node);
+
+ std::get<0>(m_values) = rasterMode->faceMode();
+ std::get<1>(m_values) = rasterMode->rasterMode();
}
-void CullFace::updateProperty(const char *name, const QVariant &value)
+void CullFace::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("mode")) std::get<0>(m_values) = value.toInt();
+ const QCullFace *cullFace = static_cast<const QCullFace *>(node);
+
+ std::get<0>(m_values) = cullFace->mode();
}
-void FrontFace::updateProperty(const char *name, const QVariant &value)
+void FrontFace::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("direction")) std::get<0>(m_values) = value.toInt();
+ const QFrontFace *frontFace = static_cast<const QFrontFace *>(node);
+
+ std::get<0>(m_values) = frontFace->direction();
}
-void NoDepthMask::updateProperty(const char *name, const QVariant &value)
+void NoDepthMask::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("mask")) std::get<0>(m_values) = value.toBool();
+ std::get<0>(m_values) = !node->isEnabled();
}
-void ScissorTest::updateProperty(const char *name, const QVariant &value)
+void ScissorTest::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("left")) std::get<0>(m_values) = value.toInt();
- else if (name == QByteArrayLiteral("bottom")) std::get<1>(m_values) = value.toInt();
- else if (name == QByteArrayLiteral("width")) std::get<2>(m_values) = value.toInt();
- else if (name == QByteArrayLiteral("height")) std::get<3>(m_values) = value.toInt();
+ const QScissorTest *scissorTest = static_cast<const QScissorTest *>(node);
+
+ std::get<0>(m_values) = scissorTest->left();
+ std::get<1>(m_values) = scissorTest->bottom();
+ std::get<2>(m_values) = scissorTest->width();
+ std::get<3>(m_values) = scissorTest->height();
}
-void StencilTest::updateProperty(const char *name, const QVariant &value)
+void StencilTest::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("arguments")) {
- const QStencilTestData data = value.value<QStencilTestData>();
- std::get<0>(m_values) = data.front.stencilFunction;
- std::get<1>(m_values) = data.front.referenceValue;
- std::get<2>(m_values) = data.front.comparisonMask;
- std::get<3>(m_values) = data.back.stencilFunction;
- std::get<4>(m_values) = data.back.referenceValue;
- std::get<5>(m_values) = data.back.comparisonMask;
- }
+ const QStencilTest *stencilTest = static_cast<const QStencilTest *>(node);
+ std::get<0>(m_values) = stencilTest->front()->stencilFunction();
+ std::get<1>(m_values) = stencilTest->front()->referenceValue();
+ std::get<2>(m_values) = stencilTest->front()->comparisonMask();
+ std::get<3>(m_values) = stencilTest->back()->stencilFunction();
+ std::get<4>(m_values) = stencilTest->back()->referenceValue();
+ std::get<5>(m_values) = stencilTest->back()->comparisonMask();
}
-void PointSize::updateProperty(const char *name, const QVariant &value)
+void PointSize::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("sizeMode")) std::get<0>(m_values) = (value.toInt() == QPointSize::Programmable);
- else if (name == QByteArrayLiteral("value")) std::get<1>(m_values) = value.toFloat();
+ const QPointSize *pointSize = static_cast<const QPointSize *>(node);
+
+ std::get<0>(m_values) = (pointSize->sizeMode() == QPointSize::Programmable);
+ std::get<1>(m_values) = pointSize->value();
}
-void PolygonOffset::updateProperty(const char *name, const QVariant &value)
+void PolygonOffset::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("scaleFactor")) std::get<0>(m_values) = value.toFloat();
- else if (name == QByteArrayLiteral("depthSteps")) std::get<1>(m_values) = value.toFloat();
+ const QPolygonOffset *offset = static_cast<const QPolygonOffset *>(node);
+
+ std::get<0>(m_values) = offset->scaleFactor();
+ std::get<1>(m_values) = offset->depthSteps();
}
-void ColorMask::updateProperty(const char *name, const QVariant &value)
+void ColorMask::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("redMasked")) std::get<0>(m_values) = value.toBool();
- else if (name == QByteArrayLiteral("greenMasked")) std::get<1>(m_values) = value.toBool();
- else if (name == QByteArrayLiteral("blueMasked")) std::get<2>(m_values) = value.toBool();
- else if (name == QByteArrayLiteral("alphaMasked")) std::get<3>(m_values) = value.toBool();
+ const QColorMask *colorMask = static_cast<const QColorMask *>(node);
+
+ std::get<0>(m_values) = colorMask->isRedMasked();
+ std::get<1>(m_values) = colorMask->isGreenMasked();
+ std::get<2>(m_values) = colorMask->isBlueMasked();
+ std::get<3>(m_values) = colorMask->isAlphaMasked();
}
-void ClipPlane::updateProperty(const char *name, const QVariant &value)
+void ClipPlane::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("planeIndex")) std::get<0>(m_values) = value.toInt();
- else if (name == QByteArrayLiteral("normal")) std::get<1>(m_values) = value.value<QVector3D>();
- else if (name == QByteArrayLiteral("distance")) std::get<2>(m_values) = value.toFloat();
+ const QClipPlane *clipPlane = static_cast<const QClipPlane *>(node);
+
+ std::get<0>(m_values) = clipPlane->planeIndex();
+ std::get<1>(m_values) = clipPlane->normal();
+ std::get<2>(m_values) = clipPlane->distance();
}
-void StencilOp::updateProperty(const char *name, const QVariant &value)
+void StencilOp::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("arguments")) {
- const QStencilOperationData data = value.value<QStencilOperationData>();
- std::get<0>(m_values) = data.front.stencilTestFailureOperation;
- std::get<1>(m_values) = data.front.depthTestFailureOperation;
- std::get<2>(m_values) = data.front.allTestsPassOperation;
- std::get<3>(m_values) = data.back.stencilTestFailureOperation;
- std::get<4>(m_values) = data.back.depthTestFailureOperation;
- std::get<5>(m_values) = data.back.allTestsPassOperation;
- }
+ const QStencilOperation *stencilOp = static_cast<const QStencilOperation *>(node);
+
+ std::get<0>(m_values) = stencilOp->front()->stencilTestFailureOperation();
+ std::get<1>(m_values) = stencilOp->front()->depthTestFailureOperation();
+ std::get<2>(m_values) = stencilOp->front()->allTestsPassOperation();
+ std::get<3>(m_values) = stencilOp->back()->stencilTestFailureOperation();
+ std::get<4>(m_values) = stencilOp->back()->depthTestFailureOperation();
+ std::get<5>(m_values) = stencilOp->back()->allTestsPassOperation();
}
-void StencilMask::updateProperty(const char *name, const QVariant &value)
+void StencilMask::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("frontOutputMask")) std::get<0>(m_values) = value.toInt();
- else if (name == QByteArrayLiteral("backOutputMask")) std::get<1>(m_values) = value.toInt();
+ const QStencilMask *stencilMask = static_cast<const QStencilMask *>(node);
+ std::get<0>(m_values) = stencilMask->frontOutputMask();
+ std::get<1>(m_values) = stencilMask->backOutputMask();
}
-void LineWidth::updateProperty(const char *name, const QVariant &value)
+void LineWidth::updateProperties(const QRenderState *node)
{
- if (name == QByteArrayLiteral("value"))
- std::get<0>(m_values) = value.toFloat();
- else if (name == QByteArrayLiteral("smooth"))
- std::get<1>(m_values) = value.toBool();
+ const QLineWidth *lineWidth = static_cast<const QLineWidth *>(node);
+ std::get<0>(m_values) = lineWidth->value();
+ std::get<1>(m_values) = lineWidth->smooth();
}
} // namespace Render
diff --git a/src/render/renderstates/renderstates.pri b/src/render/renderstates/renderstates.pri
index c6a041bd9..06ba53a41 100644
--- a/src/render/renderstates/renderstates.pri
+++ b/src/render/renderstates/renderstates.pri
@@ -24,6 +24,7 @@ HEADERS += \
$$PWD/renderstates_p.h \
$$PWD/qpointsize.h \
$$PWD/qseamlesscubemap.h \
+ $$PWD/qdepthrange.h \
$$PWD/qdepthtest.h \
$$PWD/qnodepthmask.h \
$$PWD/qlinewidth.h \
@@ -33,6 +34,7 @@ HEADERS += \
$$PWD/qclipplane_p.h \
$$PWD/qcolormask_p.h \
$$PWD/qcullface_p.h \
+ $$PWD/qdepthrange_p.h \
$$PWD/qdepthtest_p.h \
$$PWD/qfrontface_p.h \
$$PWD/qpointsize_p.h \
@@ -47,7 +49,9 @@ HEADERS += \
$$PWD/renderstatenode_p.h \
$$PWD/qmultisampleantialiasing.h \
$$PWD/statemask_p.h \
- $$PWD/statevariant_p.h
+ $$PWD/statevariant_p.h \
+ $$PWD/qrastermode.h \
+ $$PWD/qrastermode_p.h
SOURCES += \
$$PWD/qalphacoverage.cpp \
@@ -57,6 +61,7 @@ SOURCES += \
$$PWD/qclipplane.cpp \
$$PWD/qcolormask.cpp \
$$PWD/qcullface.cpp \
+ $$PWD/qdepthrange.cpp \
$$PWD/qdepthtest.cpp \
$$PWD/qdithering.cpp \
$$PWD/qfrontface.cpp \
@@ -76,4 +81,5 @@ SOURCES += \
$$PWD/qrenderstatecreatedchange.cpp \
$$PWD/renderstatenode.cpp \
$$PWD/statevariant.cpp \
- $$PWD/qmultisampleantialiasing.cpp
+ $$PWD/qmultisampleantialiasing.cpp \
+ $$PWD/qrastermode.cpp
diff --git a/src/render/renderstates/renderstates_p.h b/src/render/renderstates/renderstates_p.h
index eafaeb25f..6c8e9d551 100644
--- a/src/render/renderstates/renderstates_p.h
+++ b/src/render/renderstates/renderstates_p.h
@@ -62,49 +62,61 @@ namespace Render {
class Q_AUTOTEST_EXPORT BlendEquationArguments : public GenericState<BlendEquationArguments, BlendEquationArgumentsMask, GLenum, GLenum, GLenum, GLenum, bool, int>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT BlendEquation : public GenericState<BlendEquation, BlendStateMask, GLenum>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT AlphaFunc : public GenericState<AlphaFunc, AlphaTestMask, GLenum, GLclampf>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT MSAAEnabled : public GenericState<MSAAEnabled, MSAAEnabledStateMask, GLboolean>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
+};
+
+class Q_AUTOTEST_EXPORT DepthRange : public GenericState<DepthRange, DepthRangeMask, double, double>
+{
+public:
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT DepthTest : public GenericState<DepthTest, DepthTestStateMask, GLenum>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
+};
+
+class Q_AUTOTEST_EXPORT RasterMode : public GenericState<RasterMode, RasterModeMask, GLenum, GLenum>
+{
+public:
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT NoDepthMask : public GenericState<NoDepthMask, DepthWriteStateMask, GLboolean>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT CullFace : public GenericState<CullFace, CullFaceStateMask, GLenum>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT FrontFace : public GenericState<FrontFace, FrontFaceStateMask, GLenum>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT Dithering : public GenericState<Dithering, DitheringStateMask>
@@ -114,13 +126,13 @@ class Q_AUTOTEST_EXPORT Dithering : public GenericState<Dithering, DitheringStat
class Q_AUTOTEST_EXPORT ScissorTest : public GenericState<ScissorTest, ScissorStateMask, int, int, int, int>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT StencilTest : public GenericState<StencilTest, StencilTestStateMask, GLenum, int, uint, GLenum, int, uint>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT AlphaCoverage : public GenericState<AlphaCoverage, AlphaCoverageStateMask>
@@ -130,26 +142,26 @@ class Q_AUTOTEST_EXPORT AlphaCoverage : public GenericState<AlphaCoverage, Alpha
class Q_AUTOTEST_EXPORT PointSize : public GenericState<PointSize, PointSizeMask, bool, GLfloat>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT PolygonOffset : public GenericState<PolygonOffset, PolygonOffsetStateMask, GLfloat, GLfloat>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT ColorMask : public GenericState<ColorMask, ColorStateMask, GLboolean, GLboolean, GLboolean, GLboolean>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT ClipPlane : public GenericState<ClipPlane, ClipPlaneMask, int, QVector3D, float>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT SeamlessCubemap : public GenericState<SeamlessCubemap, SeamlessCubemapMask>
@@ -159,19 +171,19 @@ class Q_AUTOTEST_EXPORT SeamlessCubemap : public GenericState<SeamlessCubemap, S
class Q_AUTOTEST_EXPORT StencilOp : public GenericState<StencilOp, StencilOpMask, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT StencilMask : public GenericState<StencilMask, StencilWriteStateMask, uint, uint>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
class Q_AUTOTEST_EXPORT LineWidth : public GenericState<LineWidth, LineWidthMask, GLfloat, bool>
{
public:
- void updateProperty(const char *name, const QVariant &value) override;
+ void updateProperties(const QRenderState *node) override;
};
} // namespace Render
diff --git a/src/render/renderstates/statemask_p.h b/src/render/renderstates/statemask_p.h
index 1f3305747..ca64e30cd 100644
--- a/src/render/renderstates/statemask_p.h
+++ b/src/render/renderstates/statemask_p.h
@@ -81,6 +81,8 @@ enum StateMask
MSAAEnabledStateMask = 1 << 17,
BlendEquationArgumentsMask = 1 << 18,
LineWidthMask = 1 << 19,
+ DepthRangeMask = 1 << 20,
+ RasterModeMask = 1 << 21
};
} // namespace Render
diff --git a/src/render/renderstates/statevariant.cpp b/src/render/renderstates/statevariant.cpp
index 8161cba0b..47b3fd0a7 100644
--- a/src/render/renderstates/statevariant.cpp
+++ b/src/render/renderstates/statevariant.cpp
@@ -51,6 +51,7 @@ RenderStateImpl *StateVariant::state()
case BlendStateMask:
case AlphaTestMask:
case MSAAEnabledStateMask:
+ case DepthRangeMask:
case DepthTestStateMask:
case DepthWriteStateMask:
case CullFaceStateMask:
@@ -67,6 +68,7 @@ RenderStateImpl *StateVariant::state()
case StencilOpMask:
case StencilWriteStateMask:
case LineWidthMask:
+ case RasterModeMask:
return &data.blendEquationArguments;
default:
Q_UNREACHABLE();
@@ -80,6 +82,7 @@ const RenderStateImpl *StateVariant::constState() const
case BlendStateMask:
case AlphaTestMask:
case MSAAEnabledStateMask:
+ case DepthRangeMask:
case DepthTestStateMask:
case DepthWriteStateMask:
case CullFaceStateMask:
@@ -96,6 +99,7 @@ const RenderStateImpl *StateVariant::constState() const
case StencilOpMask:
case StencilWriteStateMask:
case LineWidthMask:
+ case RasterModeMask:
return &data.blendEquationArguments;
default:
Q_UNREACHABLE();
diff --git a/src/render/renderstates/statevariant_p.h b/src/render/renderstates/statevariant_p.h
index ac3c12682..ef6c80744 100644
--- a/src/render/renderstates/statevariant_p.h
+++ b/src/render/renderstates/statevariant_p.h
@@ -67,6 +67,7 @@ struct Q_AUTOTEST_EXPORT StateVariant
BlendEquation blendEquation;
AlphaFunc alphaFunc;
MSAAEnabled msaaEnabled;
+ DepthRange depthRange;
DepthTest depthTest;
NoDepthMask noDepthMask;
CullFace cullFace;
diff --git a/src/render/services/vsyncframeadvanceservice.cpp b/src/render/services/vsyncframeadvanceservice.cpp
index 8749a54ab..d7398e2ce 100644
--- a/src/render/services/vsyncframeadvanceservice.cpp
+++ b/src/render/services/vsyncframeadvanceservice.cpp
@@ -62,7 +62,7 @@ public:
QSemaphore m_semaphore;
QElapsedTimer m_elapsed;
- quint64 m_elapsedTimeSincePreviousFrame;
+ qint64 m_elapsedTimeSincePreviousFrame;
bool m_drivenByRenderThread;
};
@@ -75,23 +75,19 @@ VSyncFrameAdvanceService::~VSyncFrameAdvanceService()
{
}
-// Aspect Thread
+// Main Thread
qint64 VSyncFrameAdvanceService::waitForNextFrame()
{
Q_D(VSyncFrameAdvanceService);
- // When rendering with Scene3D, we always want to acquire the available
- // amount + 1 to handle the cases where for some reason proceedToNextFrame
- // is being called more than once between calls to waitForNextFrame This
- // could be the case when resizing the window
+#ifdef Q_OS_MACOS
+ if (!d->m_semaphore.tryAcquire(std::max(d->m_semaphore.available(), 1), 4))
+ return -1;
+#else
+ d->m_semaphore.acquire(std::max(d->m_semaphore.available(), 1));
+#endif
- // When Qt3D is driving rendering however, this shouldn't happen
- if (d->m_drivenByRenderThread)
- d->m_semaphore.acquire(1);
- else
- d->m_semaphore.acquire(d->m_semaphore.available() + 1);
-
- const quint64 currentTime = d->m_elapsed.nsecsElapsed();
+ const qint64 currentTime = d->m_elapsed.nsecsElapsed();
qCDebug(VSyncAdvanceService) << "Elapsed nsecs since last call " << currentTime - d->m_elapsedTimeSincePreviousFrame;
d->m_elapsedTimeSincePreviousFrame = currentTime;
return currentTime;
diff --git a/src/render/texture/apitexturemanager_p.h b/src/render/texture/apitexturemanager_p.h
deleted file mode 100644
index 79dc9af94..000000000
--- a/src/render/texture/apitexturemanager_p.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QT3DRENDER_RENDER_APITEXTUREMANAGER_P_H
-#define QT3DRENDER_RENDER_APITEXTUREMANAGER_P_H
-
-#include <Qt3DRender/private/managers_p.h>
-#include <Qt3DRender/private/texturedatamanager_p.h>
-#include <Qt3DRender/private/textureimage_p.h>
-#include <Qt3DRender/private/texture_p.h>
-#include <Qt3DRender/qtexturegenerator.h>
-#include <Qt3DRender/qtextureimagedatagenerator.h>
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DRender {
-
-namespace Render {
-
-// Manages instances of APITexture. This includes sharing between multiple
-// Texture nodes, updating APITextures and deleting abandoned instances.
-template <class APITexture, class APITextureImage>
-class APITextureManager
-{
-public:
-
- explicit APITextureManager(TextureImageManager *textureImageManager,
- TextureDataManager *textureDataManager,
- TextureImageDataManager *textureImageDataManager)
- : m_textureImageManager(textureImageManager)
- , m_textureDataManager(textureDataManager)
- , m_textureImageDataManager(textureImageDataManager)
- {
- }
-
- ~APITextureManager()
- {
- qDeleteAll(activeResources());
- m_nodeIdToGLTexture.clear();
- m_sharedTextures.clear();
- m_updatedTextures.clear();
- }
-
- // Used to retrieve all resources that needs to be destroyed on the GPU
- QVector<APITexture *> activeResources() const
- {
- // Active Resources are
- // all shared textures
- // all unique textures
- // all textures that haven't yet been destroyed
- // Note: updatedTextures only referenced textures in one of these 3 vectors
- return m_sharedTextures.keys().toVector() + m_uniqueTextures + m_abandonedTextures;
- }
-
- APITexture *lookupResource(Qt3DCore::QNodeId textureId) const
- {
- return m_nodeIdToGLTexture.value(textureId);
- }
-
- Qt3DCore::QNodeIdVector referencedTextureIds(APITexture *apiTexture) const
- {
- return m_sharedTextures.value(apiTexture);
- }
-
- // Returns a APITexture that matches the given QTexture node. Will make sure
- // that texture data generator jobs are launched, if necessary. The APITexture
- // may be shared between multiple texture backend nodes
- APITexture *getOrCreateShared(const Texture *node)
- {
- Q_ASSERT(node);
-
- APITexture *shared = findMatchingShared(node);
-
- // no matching shared texture was found; create a new one:
- if (shared == nullptr)
- shared = createTexture(node, false);
-
- // store texture node to shared texture relationship
- adoptShared(shared, node);
-
- return shared;
- }
-
- // Store that the shared texture references node
- void adoptShared(APITexture *sharedApiTexture, const Texture *node)
- {
- if (!m_sharedTextures[sharedApiTexture].contains(node->peerId())) {
- m_sharedTextures[sharedApiTexture].push_back(node->peerId());
- m_nodeIdToGLTexture.insert(node->peerId(), sharedApiTexture);
- }
- }
-
- // If there is already a shared texture with the properties of the given
- // texture node, return this instance, else NULL.
- // Note: the reference to the texture node is added if the shared texture
- // wasn't referencing it already
- APITexture *findMatchingShared(const Texture *node)
- {
- Q_ASSERT(node);
-
- // search for existing texture
- const auto end = m_sharedTextures.end();
- for (auto it = m_sharedTextures.begin(); it != end; ++it)
- if (isSameTexture(it.key(), node))
- return it.key();
- return nullptr;
- }
-
- // Returns a APITexture that matches the given QTexture node. Will make sure
- // that texture data generator jobs are launched, if necessary.
- APITexture *createUnique(const Texture *node)
- {
- Q_ASSERT(node);
- APITexture *uniqueTex = createTexture(node, true);
- m_uniqueTextures.push_back(uniqueTex);
- m_nodeIdToGLTexture.insert(node->peerId(), uniqueTex);
- return uniqueTex;
- }
-
- // De-associate the given APITexture from the backend node. If the texture
- // is no longer referenced by any other node, it will be deleted.
- void abandon(APITexture *tex, const Qt3DCore::QNodeId nodeId)
- {
- APITexture *apiTexture = m_nodeIdToGLTexture.take(nodeId);
- Q_ASSERT(tex == apiTexture);
-
- if (Q_UNLIKELY(!apiTexture)) {
- qWarning() << "[Qt3DRender::TextureManager] abandon: could not find Texture";
- return;
- }
-
- if (tex->isUnique()) {
- m_uniqueTextures.removeAll(apiTexture);
- m_abandonedTextures.push_back(apiTexture);
- } else {
- QVector<Qt3DCore::QNodeId> &referencedTextureNodes = m_sharedTextures[apiTexture];
- referencedTextureNodes.removeAll(nodeId);
-
- // If no texture nodes is referencing the shared APITexture, remove it
- if (referencedTextureNodes.empty()) {
- m_abandonedTextures.push_back(apiTexture);
- m_sharedTextures.remove(apiTexture);
- tex->destroyResources();
- }
- }
- }
-
- // Change the properties of the given texture, if it is a non-shared texture
- // Returns true, if it was changed successfully, false otherwise
- bool setProperties(APITexture *tex, const TextureProperties &props)
- {
- Q_ASSERT(tex);
-
- if (isShared(tex))
- return false;
-
- tex->setProperties(props);
- m_updatedTextures.push_back(tex);
-
- return true;
- }
-
- // Change the parameters of the given texture, if it is a non-shared texture
- // Returns true, if it was changed successfully, false otherwise
- bool setParameters(APITexture *tex, const TextureParameters &params)
- {
- Q_ASSERT(tex);
-
- if (isShared(tex))
- return false;
-
- tex->setParameters(params);
- m_updatedTextures.push_back(tex);
-
- return true;
- }
-
- // Change the texture images of the given texture, if it is a non-shared texture
- // Return true, if it was changed successfully, false otherwise
- bool setImages(APITexture *tex, const Qt3DCore::QNodeIdVector &imageIds)
- {
- Q_ASSERT(tex);
-
- if (isShared(tex))
- return false;
-
- // create Image structs
- QVector<APITextureImage> texImgs = texImgsFromNodes(imageIds);
- if (texImgs.size() != imageIds.size())
- return false;
-
- tex->setImages(texImgs);
- m_updatedTextures.push_back(tex);
-
- return true;
- }
-
- // Change the texture data generator for given texture, if it is a non-shared texture
- // Return true, if it was changed successfully, false otherwise
- bool setGenerator(APITexture *tex, const QTextureGeneratorPtr &generator)
- {
- Q_ASSERT(tex);
-
- if (isShared(tex))
- return false;
-
- tex->setGenerator(generator);
- m_updatedTextures.push_back(tex);
-
- return true;
- }
-
- // Change the texture's referenced texture Id from a shared context
- bool setSharedTextureId(APITexture *tex, int textureId)
- {
- Q_ASSERT(tex);
-
- if (isShared(tex))
- return false;
-
- tex->setSharedTextureId(textureId);
- m_updatedTextures.push_back(tex);
- return true;
- }
-
- // Retrieves abandoned textures. This should be regularly called from the OpenGL thread
- // to make sure needed GL resources are de-allocated.
- QVector<APITexture*> takeAbandonedTextures()
- {
- return std::move(m_abandonedTextures);
- }
-
- // Retrieves textures that have been modified
- QVector<APITexture*> takeUpdatedTextures()
- {
- return std::move(m_updatedTextures);
- }
-
- // Returns whether the given APITexture is shared between multiple TextureNodes
- bool isShared(APITexture *impl)
- {
- Q_ASSERT(impl);
-
- if (impl->isUnique())
- return false;
-
- auto it = m_sharedTextures.constFind(impl);
- if (it == m_sharedTextures.cend())
- return false;
-
- return it.value().size() > 1;
- }
-
-private:
-
- // Check if the given APITexture matches the TextureNode
- bool isSameTexture(const APITexture *tex, const Texture *texNode)
- {
- // make sure there either are no texture generators, or the two are the same
- if (tex->textureGenerator().isNull() != texNode->dataGenerator().isNull())
- return false;
- if (!tex->textureGenerator().isNull() && !(*tex->textureGenerator() == *texNode->dataGenerator()))
- return false;
-
- // make sure the image generators are the same
- const QVector<APITextureImage> texImgGens = tex->images();
- const Qt3DCore::QNodeIdVector texImgs = texNode->textureImageIds();
- if (texImgGens.size() != texImgs.size())
- return false;
- for (int i = 0; i < texImgGens.size(); ++i) {
- const TextureImage *img = m_textureImageManager->lookupResource(texImgs[i]);
- Q_ASSERT(img != nullptr);
- if (!(*img->dataGenerator() == *texImgGens[i].generator)
- || img->layer() != texImgGens[i].layer
- || img->face() != texImgGens[i].face
- || img->mipLevel() != texImgGens[i].mipLevel)
- return false;
- }
-
- // if the texture has a texture generator, this generator will mostly determine
- // the properties of the texture.
- if (!tex->textureGenerator().isNull())
- return (tex->properties().generateMipMaps == texNode->properties().generateMipMaps
- && tex->parameters() == texNode->parameters());
-
- // if it doesn't have a texture generator, but texture image generators,
- // few more properties will influence the texture type
- if (!texImgGens.empty())
- return (tex->properties().target == texNode->properties().target
- && tex->properties().format == texNode->properties().format
- && tex->properties().generateMipMaps == texNode->properties().generateMipMaps
- && tex->parameters() == texNode->parameters());
-
- // texture without images
- return tex->properties() == texNode->properties()
- && tex->parameters() == texNode->parameters();
- }
-
- // Create APITexture from given TextureNode. Also make sure the generators
- // will be executed by jobs soon.
- APITexture *createTexture(const Texture *node, bool unique)
- {
- // create Image structs
- const QVector<APITextureImage> texImgs = texImgsFromNodes(node->textureImageIds());
- if (texImgs.empty() && !node->textureImageIds().empty())
- return nullptr;
-
- // no matching shared texture was found, create a new one
- APITexture *newTex = new APITexture(m_textureDataManager, m_textureImageDataManager, node->dataGenerator(), unique);
- newTex->setProperties(node->properties());
- newTex->setParameters(node->parameters());
- newTex->setImages(texImgs);
- newTex->setSharedTextureId(node->sharedTextureId());
-
- m_updatedTextures.push_back(newTex);
-
- return newTex;
- }
-
- QVector<APITextureImage> texImgsFromNodes(const Qt3DCore::QNodeIdVector &imageIds) const
- {
- QVector<APITextureImage> ret;
- ret.resize(imageIds.size());
-
- for (int i = 0; i < imageIds.size(); ++i) {
- const TextureImage *img = m_textureImageManager->lookupResource(imageIds[i]);
- if (!img) {
- qWarning() << "[Qt3DRender::TextureManager] invalid TextureImage handle";
- return QVector<APITextureImage>();
- }
-
- ret[i].generator = img->dataGenerator();
- ret[i].face = img->face();
- ret[i].layer = img->layer();
- ret[i].mipLevel = img->mipLevel();
- }
-
- return ret;
- }
-
- TextureImageManager *m_textureImageManager;
- TextureDataManager *m_textureDataManager;
- TextureImageDataManager *m_textureImageDataManager;
-
- /* each non-unique texture is associated with a number of Texture nodes referencing it */
- QHash<APITexture*, QVector<Qt3DCore::QNodeId>> m_sharedTextures;
-
- // Texture id -> APITexture (both shared and unique ones)
- QHash<Qt3DCore::QNodeId, APITexture *> m_nodeIdToGLTexture;
-
- QVector<APITexture*> m_uniqueTextures;
- QVector<APITexture*> m_abandonedTextures;
- QVector<APITexture*> m_updatedTextures;
-};
-
-
-} // Render
-
-} // Qt3DRender
-
-QT_END_NAMESPACE
-
-
-#endif // QT3DRENDER_RENDER_APITEXTUREMANAGER_P_H
diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp
index 3d7d751a1..258ab44dc 100644
--- a/src/render/texture/qabstracttexture.cpp
+++ b/src/render/texture/qabstracttexture.cpp
@@ -81,10 +81,40 @@ void QAbstractTexturePrivate::setDataFunctor(const QTextureGeneratorPtr &generat
{
if (generator != m_dataFunctor) {
m_dataFunctor = generator;
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id);
- change->setPropertyName("generator");
- change->setValue(QVariant::fromValue(generator));
- notifyObservers(change);
+ update();
+ }
+}
+
+void QAbstractTexturePrivate::setStatus(QAbstractTexture::Status status)
+{
+ Q_Q(QAbstractTexture);
+ if (m_status != status) {
+ m_status = status;
+ const bool blocked = q->blockNotifications(true);
+ q->statusChanged(status);
+ q->blockNotifications(blocked);
+ }
+}
+
+void QAbstractTexturePrivate::setHandle(const QVariant &handle)
+{
+ Q_Q(QAbstractTexture);
+ if (m_handle != handle) {
+ m_handle = handle;
+ const bool blocked = q->blockNotifications(true);
+ emit q->handleChanged(handle);
+ q->blockNotifications(blocked);
+ }
+}
+
+void QAbstractTexturePrivate::setHandleType(QAbstractTexture::HandleType type)
+{
+ Q_Q(QAbstractTexture);
+ if (m_handleType != type) {
+ m_handleType = type;
+ const bool blocked = q->blockNotifications(true);
+ emit q->handleTypeChanged(type);
+ q->blockNotifications(blocked);
}
}
@@ -94,12 +124,18 @@ void QAbstractTexturePrivate::setDataFunctor(const QTextureGeneratorPtr &generat
\since 5.5
\brief A base class to be used to provide textures.
- The QAbstractTexture class shouldn't be used directly but rather
- through one of its subclasses. Each subclass implements a given texture
- target (2D, 2DArray, 3D, CubeMap ...) Each subclass provides a set of
- functors for each layer, cube map face and mipmap level. In turn the
- backend uses those functor to properly fill a corresponding OpenGL texture
- with data.
+ The QAbstractTexture class shouldn't be used directly but rather through
+ one of its subclasses. Each subclass implements a given texture target (2D,
+ 2DArray, 3D, CubeMap ...) Each subclass provides a set of functors for each
+ layer, cube map face and mipmap level. In turn the backend uses those
+ functor to properly fill a corresponding OpenGL texture with data. It is
+ expected the functor does as minimal processing as possible so as not
+ to slow down textures generation and upload. If the content of a texture is
+ the result of a slow procedural generation process, it is recommended not
+ to implement this directly in a functor.
+
+ All textures are unique. If you instantiate twice the same texture this
+ will create 2 identical textures on the GPU, no sharing will take place.
*/
/*!
@@ -261,6 +297,8 @@ void QAbstractTexturePrivate::setDataFunctor(const QTextureGeneratorPtr &generat
\value RGBA4
GL_RGBA4
\value RGB10A2
+ GL_RGB10_A2
+ \value RGB10A2U
GL_RGB10_A2UI
\value D16
GL_DEPTH_COMPONENT16
@@ -624,7 +662,9 @@ void QAbstractTexture::setStatus(Status status)
Q_D(QAbstractTexture);
if (status != d->m_status) {
d->m_status = status;
+ const bool blocked = blockNotifications(true);
emit statusChanged(status);
+ blockNotifications(blocked);
}
}
@@ -740,11 +780,7 @@ void QAbstractTexture::addTextureImage(QAbstractTextureImage *textureImage)
if (!textureImage->parent())
textureImage->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeAddedChangePtr::create(id(), textureImage);
- change->setPropertyName("textureImage");
- d->notifyObservers(change);
- }
+ d->updateNode(textureImage, "textureImage", PropertyValueAdded);
}
}
@@ -755,11 +791,7 @@ void QAbstractTexture::removeTextureImage(QAbstractTextureImage *textureImage)
{
Q_ASSERT(textureImage);
Q_D(QAbstractTexture);
- if (d->m_changeArbiter != nullptr) {
- const auto change = QPropertyNodeRemovedChangePtr::create(id(), textureImage);
- change->setPropertyName("textureImage");
- d->notifyObservers(change);
- }
+ d->updateNode(textureImage, "textureImage", PropertyValueRemoved);
d->m_textureImages.removeOne(textureImage);
// Remove bookkeeping connection
d->unregisterDestructionHelper(textureImage);
@@ -895,24 +927,15 @@ void QAbstractTexture::setWrapMode(const QTextureWrapMode &wrapMode)
Q_D(QAbstractTexture);
if (d->m_wrapMode.x() != wrapMode.x()) {
d->m_wrapMode.setX(wrapMode.x());
- auto e = QPropertyUpdatedChangePtr::create(d->m_id);
- e->setPropertyName("wrapModeX");
- e->setValue(static_cast<int>(d->m_wrapMode.x()));
- d->notifyObservers(e);
+ d->update();
}
if (d->m_wrapMode.y() != wrapMode.y()) {
d->m_wrapMode.setY(wrapMode.y());
- auto e = QPropertyUpdatedChangePtr::create(d->m_id);
- e->setPropertyName("wrapModeY");
- e->setValue(static_cast<int>(d->m_wrapMode.y()));
- d->notifyObservers(e);
+ d->update();
}
if (d->m_wrapMode.z() != wrapMode.z()) {
d->m_wrapMode.setZ(wrapMode.z());
- auto e = QPropertyUpdatedChangePtr::create(d->m_id);
- e->setPropertyName("wrapModeZ");
- e->setValue(static_cast<int>(d->m_wrapMode.z()));
- d->notifyObservers(e);
+ d->update();
}
}
@@ -954,7 +977,7 @@ float QAbstractTexture::maximumAnisotropy() const
}
/*!
- \property Qt3DRender::QAbstractTexture::ComparisonFunction
+ \property Qt3DRender::QAbstractTexture::comparisonFunction
Holds the comparison function of the texture provider.
*/
@@ -985,7 +1008,7 @@ QAbstractTexture::ComparisonFunction QAbstractTexture::comparisonFunction() cons
}
/*!
- \property Qt3DRender::QAbstractTexture::ComparisonMode
+ \property Qt3DRender::QAbstractTexture::comparisonMode
Holds the comparison mode of the texture provider.
*/
@@ -1032,9 +1055,12 @@ QTextureGeneratorPtr QAbstractTexture::dataGenerator() const
*/
/*!
- * \qmlproperty handleType
+ * \qmlproperty enumeration AbstractTexture::handleType
*
* Holds the current texture handle type.
+ *
+ * \value AbstractTexture.NoHandle
+ * \value AbstractTexture.OpenGLTextureId
*/
/*!
@@ -1047,7 +1073,6 @@ QAbstractTexture::HandleType QAbstractTexture::handleType() const
return d->m_handleType;
}
-
/*!
* \property Qt3DRender::QAbstractTexture::handle
*
@@ -1056,7 +1081,7 @@ QAbstractTexture::HandleType QAbstractTexture::handleType() const
*/
/*!
- * \qmlproperty handle
+ * \qmlproperty var AbstractTexture::handle
*
* Holds the current texture handle, if Qt 3D is using the OpenGL renderer,
* handle is a texture id integer.
@@ -1074,6 +1099,19 @@ QVariant QAbstractTexture::handle() const
return d->m_handle;
}
+/*!
+ * Updates a sub region of the texture, defined by \a update, without having
+ * to change the data generator or rely on adding or removing texture images.
+ * \since 5.14
+ */
+void QAbstractTexture::updateData(const QTextureDataUpdate &update)
+{
+ Q_D(QAbstractTexture);
+
+ d->m_pendingDataUpdates.push_back(update);
+ d->update();
+}
+
Qt3DCore::QNodeCreatedChangeBasePtr QAbstractTexture::createNodeCreationChange() const
{
auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAbstractTextureData>::create(this);
@@ -1098,6 +1136,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QAbstractTexture::createNodeCreationChange()
data.samples = d->m_samples;
data.dataFunctor = d->m_dataFunctor;
data.sharedTextureId = d->m_sharedTextureId;
+ data.initialDataUpdates = d->m_pendingDataUpdates;
return creationChange;
}
diff --git a/src/render/texture/qabstracttexture.h b/src/render/texture/qabstracttexture.h
index 6097e4449..b3d5efb34 100644
--- a/src/render/texture/qabstracttexture.h
+++ b/src/render/texture/qabstracttexture.h
@@ -52,7 +52,7 @@ class QAbstractTexturePrivate;
class QTextureWrapMode;
class QAbstractTextureImage;
class QTextureGenerator;
-
+class QTextureDataUpdate;
typedef QSharedPointer<QTextureGenerator> QTextureGeneratorPtr;
class Q_3DRENDERSHARED_EXPORT QAbstractTexture : public Qt3DCore::QNode
@@ -178,7 +178,8 @@ public:
R5G6B5 = 0x8D62, // GL_RGB565
RGB5A1 = 0x8057, // GL_RGB5_A1
RGBA4 = 0x8056, // GL_RGBA4
- RGB10A2 = 0x906F, // GL_RGB10_A2UI
+ RGB10A2 = 0x8059, // GL_RGB10_A2
+ RGB10A2U = 0x906F, // GL_RGB10_A2UI
// Depth formats
D16 = 0x81A5, // GL_DEPTH_COMPONENT16
@@ -309,6 +310,9 @@ public:
HandleType handleType() const;
QVariant handle() const;
+ Q_INVOKABLE void updateData(const QTextureDataUpdate &update);
+
+
public Q_SLOTS:
void setFormat(TextureFormat format);
void setGenerateMipMaps(bool gen);
@@ -346,6 +350,7 @@ protected:
explicit QAbstractTexture(QAbstractTexturePrivate &dd, Qt3DCore::QNode *parent = nullptr);
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override;
+ // TO DO Qt6, should be on private class
void setStatus(Status status);
void setHandle(const QVariant &handle);
void setHandleType(HandleType type);
diff --git a/src/render/texture/qabstracttexture_p.h b/src/render/texture/qabstracttexture_p.h
index f4bdecacc..5b2945f73 100644
--- a/src/render/texture/qabstracttexture_p.h
+++ b/src/render/texture/qabstracttexture_p.h
@@ -56,6 +56,7 @@
#include <Qt3DRender/qabstracttexture.h>
#include <Qt3DRender/qtexturewrapmode.h>
#include <Qt3DRender/qtexturegenerator.h>
+#include <Qt3DRender/qtexturedataupdate.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
QT_BEGIN_NAMESPACE
@@ -95,6 +96,12 @@ public :
QTextureGeneratorPtr dataFunctor() const;
void setDataFunctor(const QTextureGeneratorPtr &generator);
+ void setStatus(QAbstractTexture::Status status);
+ void setHandle(const QVariant &handle);
+ void setHandleType(QAbstractTexture::HandleType type);
+
+ QVector<QTextureDataUpdate> m_pendingDataUpdates;
+
private:
QTextureGeneratorPtr m_dataFunctor;
};
@@ -120,6 +127,7 @@ struct QAbstractTextureData
int samples;
int sharedTextureId;
QTextureGeneratorPtr dataFunctor;
+ QVector<QTextureDataUpdate> initialDataUpdates;
};
} // QT3D
diff --git a/src/render/texture/qabstracttextureimage.cpp b/src/render/texture/qabstracttextureimage.cpp
index a95e1fffd..6f68221fd 100644
--- a/src/render/texture/qabstracttextureimage.cpp
+++ b/src/render/texture/qabstracttextureimage.cpp
@@ -39,7 +39,6 @@
#include "qabstracttextureimage.h"
#include "qabstracttextureimage_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qtextureimagedatagenerator.h>
QT_BEGIN_NAMESPACE
@@ -94,6 +93,12 @@ QAbstractTextureImagePrivate::~QAbstractTextureImagePrivate()
{
}
+QTextureImageDataGeneratorPtr QAbstractTextureImagePrivate::dataGenerator() const
+{
+ Q_Q(const QAbstractTextureImage);
+ return q->dataGenerator();
+}
+
/*!
\qmltype AbstractTextureImage
\instantiates Qt3DRender::QAbstractTextureImage
@@ -126,8 +131,8 @@ QAbstractTextureImagePrivate::~QAbstractTextureImagePrivate()
/*!
\fn Qt3DRender::QTextureImageDataGeneratorPtr Qt3DRender::QAbstractTextureImage::dataGenerator() const
- Implement this method to return the \l QTextureImageDataGeneratorPtr, which will
- provide the data for the texture image.
+ Implement this method to return the QTextureImageDataGeneratorPtr instance,
+ which will provide the data for the texture image.
*/
/*!
@@ -255,12 +260,7 @@ void QAbstractTextureImage::setFace(QAbstractTexture::CubeMapFace face)
void QAbstractTextureImage::notifyDataGeneratorChanged()
{
Q_D(QAbstractTextureImage);
- if (d->m_changeArbiter != nullptr) {
- auto change = QPropertyUpdatedChangePtr::create(d->m_id);
- change->setPropertyName("dataGenerator");
- change->setValue(QVariant::fromValue(dataGenerator()));
- d->notifyObservers(change);
- }
+ d->update();
}
/*! \internal */
diff --git a/src/render/texture/qabstracttextureimage_p.h b/src/render/texture/qabstracttextureimage_p.h
index a5299acd7..f93d0e3ca 100644
--- a/src/render/texture/qabstracttextureimage_p.h
+++ b/src/render/texture/qabstracttextureimage_p.h
@@ -54,6 +54,7 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DRender/private/qt3drender_global_p.h>
#include <Qt3DRender/qabstracttexture.h>
+#include <Qt3DRender/qtextureimagedatagenerator.h>
QT_BEGIN_NAMESPACE
@@ -72,6 +73,7 @@ public:
int m_mipLevel;
int m_layer;
QAbstractTexture::CubeMapFace m_face;
+ QTextureImageDataGeneratorPtr dataGenerator() const;
};
struct QAbstractTextureImageData
diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp
index 78a995b5d..84a228428 100644
--- a/src/render/texture/qtexture.cpp
+++ b/src/render/texture/qtexture.cpp
@@ -40,6 +40,7 @@
#include "qtextureimage.h"
#include "qabstracttextureimage.h"
#include "qtextureimage_p.h"
+#include "qtextureimagedata_p.h"
#include "qtexturedata.h"
#include "qtexture.h"
#include "qtexture_p.h"
@@ -56,7 +57,6 @@
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/texture_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>
-#include <Qt3DRender/private/texturedatamanager_p.h>
#include <Qt3DRender/private/gltexturemanager_p.h>
QT_BEGIN_NAMESPACE
@@ -452,7 +452,8 @@ enum ImageFormat {
GenericImageFormat = 0,
DDS,
PKM,
- HDR
+ HDR,
+ KTX
};
ImageFormat imageFormatFromSuffix(const QString &suffix)
@@ -463,9 +464,144 @@ ImageFormat imageFormatFromSuffix(const QString &suffix)
return DDS;
if (suffix == QStringLiteral("hdr"))
return HDR;
+ if (suffix == QStringLiteral("ktx"))
+ return KTX;
return GenericImageFormat;
}
+// NOTE: the ktx loading code is a near-duplication of the code in qt3d-runtime, and changes
+// should be kept up to date in both locations.
+quint32 blockSizeForTextureFormat(QOpenGLTexture::TextureFormat format)
+{
+ switch (format) {
+ case QOpenGLTexture::RGB8_ETC1:
+ case QOpenGLTexture::RGB8_ETC2:
+ case QOpenGLTexture::SRGB8_ETC2:
+ case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::R11_EAC_UNorm:
+ case QOpenGLTexture::R11_EAC_SNorm:
+ case QOpenGLTexture::RGB_DXT1:
+ return 8;
+
+ default:
+ return 16;
+ }
+}
+
+QTextureImageDataPtr setKtxFile(QIODevice *source)
+{
+ static const int KTX_IDENTIFIER_LENGTH = 12;
+ static const char ktxIdentifier[KTX_IDENTIFIER_LENGTH] = { '\xAB', 'K', 'T', 'X', ' ', '1', '1', '\xBB', '\r', '\n', '\x1A', '\n' };
+ static const quint32 platformEndianIdentifier = 0x04030201;
+ static const quint32 inversePlatformEndianIdentifier = 0x01020304;
+
+ struct KTXHeader {
+ quint8 identifier[KTX_IDENTIFIER_LENGTH];
+ quint32 endianness;
+ quint32 glType;
+ quint32 glTypeSize;
+ quint32 glFormat;
+ quint32 glInternalFormat;
+ quint32 glBaseInternalFormat;
+ quint32 pixelWidth;
+ quint32 pixelHeight;
+ quint32 pixelDepth;
+ quint32 numberOfArrayElements;
+ quint32 numberOfFaces;
+ quint32 numberOfMipmapLevels;
+ quint32 bytesOfKeyValueData;
+ };
+
+ KTXHeader header;
+ QTextureImageDataPtr imageData;
+ if (source->read(reinterpret_cast<char *>(&header), sizeof(header)) != sizeof(header)
+ || qstrncmp(reinterpret_cast<char *>(header.identifier), ktxIdentifier, KTX_IDENTIFIER_LENGTH) != 0
+ || (header.endianness != platformEndianIdentifier && header.endianness != inversePlatformEndianIdentifier))
+ {
+ return imageData;
+ }
+
+ const bool isInverseEndian = (header.endianness == inversePlatformEndianIdentifier);
+ auto decode = [isInverseEndian](quint32 val) {
+ return isInverseEndian ? qbswap<quint32>(val) : val;
+ };
+
+ const bool isCompressed = decode(header.glType) == 0 && decode(header.glFormat) == 0 && decode(header.glTypeSize) == 1;
+ if (!isCompressed) {
+ qWarning("Uncompressed ktx texture data is not supported");
+ return imageData;
+ }
+
+ if (decode(header.numberOfArrayElements) != 0) {
+ qWarning("Array ktx textures not supported");
+ return imageData;
+ }
+
+ if (decode(header.pixelDepth) != 0) {
+ qWarning("Only 2D and cube ktx textures are supported");
+ return imageData;
+ }
+
+ const int bytesToSkip = decode(header.bytesOfKeyValueData);
+ if (source->read(bytesToSkip).count() != bytesToSkip) {
+ qWarning("Unexpected end of ktx data");
+ return imageData;
+ }
+
+ const int level0Width = decode(header.pixelWidth);
+ const int level0Height = decode(header.pixelHeight);
+ const int faceCount = decode(header.numberOfFaces);
+ const int mipMapLevels = decode(header.numberOfMipmapLevels);
+ const QOpenGLTexture::TextureFormat format = QOpenGLTexture::TextureFormat(decode(header.glInternalFormat));
+ const int blockSize = blockSizeForTextureFormat(format);
+
+ // now for each mipmap level we have (arrays and 3d textures not supported here)
+ // uint32 imageSize
+ // for each array element
+ // for each face
+ // for each z slice
+ // compressed data
+ // padding so that each face data starts at an offset that is a multiple of 4
+ // padding so that each imageSize starts at an offset that is a multiple of 4
+
+ // assumes no depth or uncompressed textures (per above)
+ auto computeMipMapLevelSize = [&] (int level) {
+ const int w = qMax(level0Width >> level, 1);
+ const int h = qMax(level0Height >> level, 1);
+ return ((w + 3) / 4) * ((h + 3) / 4) * blockSize;
+ };
+
+ int dataSize = 0;
+ for (auto i = 0; i < mipMapLevels; ++i)
+ dataSize += computeMipMapLevelSize(i) * faceCount + 4; // assumes a single layer (per above)
+
+ const QByteArray rawData = source->read(dataSize);
+ if (rawData.size() < dataSize) {
+ qWarning() << "Unexpected end of data in" << source;
+ return imageData;
+ }
+
+ if (!source->atEnd())
+ qWarning() << "Unrecognized data in" << source;
+
+ imageData = QTextureImageDataPtr::create();
+ imageData->setTarget(faceCount == 6 ? QOpenGLTexture::TargetCubeMap : QOpenGLTexture::Target2D);
+ imageData->setFormat(format);
+ imageData->setWidth(level0Width);
+ imageData->setHeight(level0Height);
+ imageData->setLayers(1);
+ imageData->setDepth(1);
+ imageData->setFaces(faceCount);
+ imageData->setMipLevels(mipMapLevels);
+ imageData->setPixelFormat(QOpenGLTexture::NoSourceFormat);
+ imageData->setPixelType(QOpenGLTexture::NoPixelType);
+ imageData->setData(rawData, blockSize, true);
+ QTextureImageDataPrivate::get(imageData.data())->m_isKtx = true; // see note in QTextureImageDataPrivate
+
+ return imageData;
+}
+
QTextureImageDataPtr setPkmFile(QIODevice *source)
{
QTextureImageDataPtr imageData;
@@ -890,6 +1026,10 @@ QTextureImageDataPtr TextureLoadingHelper::loadTextureData(QIODevice *data, cons
case HDR:
textureData = setHdrFile(data);
break;
+ case KTX: {
+ textureData = setKtxFile(data);
+ break;
+ }
default: {
QImage img;
if (img.load(data, suffix.toLatin1())) {
@@ -925,7 +1065,8 @@ QTextureDataPtr QTextureFromSourceGenerator::operator ()()
auto downloadService = Qt3DCore::QDownloadHelperService::getService(m_engine);
Qt3DCore::QDownloadRequestPtr request(new TextureDownloadRequest(sharedFromThis(),
m_url,
- m_engine));
+ m_engine,
+ m_texture));
downloadService->submitRequest(request);
}
return generatedData;
@@ -974,15 +1115,17 @@ QTextureDataPtr QTextureFromSourceGenerator::operator ()()
TextureDownloadRequest::TextureDownloadRequest(const QTextureFromSourceGeneratorPtr &functor,
const QUrl &source,
- Qt3DCore::QAspectEngine *engine)
+ Qt3DCore::QAspectEngine *engine,
+ Qt3DCore::QNodeId texNodeId)
: Qt3DCore::QDownloadRequest(source)
, m_functor(functor)
, m_engine(engine)
+ , m_texNodeId(texNodeId)
{
}
-// Executed in aspect thread
+// Executed in main thread
void TextureDownloadRequest::onCompleted()
{
if (cancelled() || !succeeded())
@@ -992,46 +1135,18 @@ void TextureDownloadRequest::onCompleted()
if (!d_aspect)
return;
- // Find all textures which share the same functor
- // Note: this should be refactored to not pull in API specific managers
- // but texture sharing forces us to do that currently
- Render::TextureDataManager *textureDataManager = d_aspect->m_nodeManagers->textureDataManager();
- const QVector<Render::GLTexture *> referencedGLTextures = textureDataManager->referencesForGenerator(m_functor);
-
- // We should have at most 1 GLTexture referencing this
- // Since all textures having the same source should have the same functor == same GLTexture
- Q_ASSERT(referencedGLTextures.size() <= 1);
-
- Render::GLTexture *glTex = referencedGLTextures.size() > 0 ? referencedGLTextures.first() : nullptr;
- if (glTex == nullptr)
- return;
-
- Render::GLTextureManager *glTextureManager = d_aspect->m_nodeManagers->glTextureManager();
- Qt3DCore::QNodeIdVector referencingTexturesIds = glTextureManager->referencedTextureIds(glTex);
-
-
Render::TextureManager *textureManager = d_aspect->m_nodeManagers->textureManager();
- for (const Qt3DCore::QNodeId texId : referencingTexturesIds) {
- Render::Texture *texture = textureManager->lookupResource(texId);
- if (texture != nullptr) {
- // Each texture has a QTextureFunctor which matches m_functor;
- // Update m_sourceData on each functor as we don't know which one
- // is used as the reference for texture sharing
-
- QTextureFromSourceGeneratorPtr oldGenerator = qSharedPointerCast<QTextureFromSourceGenerator>(texture->dataGenerator());
+ Render::Texture *texture = textureManager->lookupResource(m_texNodeId);
+ if (texture == nullptr)
+ return;
- // We create a new functor
- // Which is a copy of the old one + the downloaded sourceData
- auto newGenerator = QTextureFromSourceGeneratorPtr::create(*oldGenerator);
+ QTextureFromSourceGeneratorPtr oldGenerator = qSharedPointerCast<QTextureFromSourceGenerator>(texture->dataGenerator());
- // Set raw data on functor so that it can really load something
- newGenerator->m_sourceData = m_data;
+ // Set raw data on functor so that it can really load something
+ oldGenerator->m_sourceData = m_data;
- // Set new generator on texture
- // it implictely marks the texture as dirty so that the functor runs again with the downloaded data
- texture->setDataGenerator(newGenerator);
- }
- }
+ // Mark the texture as dirty so that the functor runs again with the downloaded data
+ texture->addDirtyFlag(Render::Texture::DirtyDataGenerator);
}
/*!
@@ -1400,7 +1515,10 @@ QTextureLoader::QTextureLoader(QNode *parent)
// Regenerate the texture functor when properties we support overriding
// from QAbstractTexture get changed.
Q_D(QTextureLoader);
- auto regenerate = [=] () { d->updateGenerator(); };
+ auto regenerate = [=] () {
+ if (!notificationsBlocked()) // check the change doesn't come from the backend
+ d->updateGenerator();
+ };
connect(this, &QAbstractTexture::formatChanged, regenerate);
}
@@ -1440,6 +1558,11 @@ void QTextureLoader::setSource(const QUrl& source)
Q_D(QTextureLoader);
if (source != d->m_source) {
d->m_source = source;
+
+ // Reset target and format
+ d->m_target = TargetAutomatic;
+ setFormat(NoFormat);
+
d->updateGenerator();
const bool blocked = blockNotifications(true);
emit sourceChanged(source);
diff --git a/src/render/texture/qtexture_p.h b/src/render/texture/qtexture_p.h
index 012b719ff..6b06aecd1 100644
--- a/src/render/texture/qtexture_p.h
+++ b/src/render/texture/qtexture_p.h
@@ -84,13 +84,15 @@ class Q_AUTOTEST_EXPORT TextureDownloadRequest : public Qt3DCore::QDownloadReque
public:
TextureDownloadRequest(const QTextureFromSourceGeneratorPtr &functor,
const QUrl &url,
- Qt3DCore::QAspectEngine *engine);
+ Qt3DCore::QAspectEngine *engine,
+ Qt3DCore::QNodeId texNodeId);
void onCompleted() override;
private:
QTextureFromSourceGeneratorPtr m_functor;
Qt3DCore::QAspectEngine *m_engine;
+ Qt3DCore::QNodeId m_texNodeId;
};
class Q_AUTOTEST_EXPORT QTextureFromSourceGenerator : public QTextureGenerator,
diff --git a/src/render/texture/qtexturedataupdate.cpp b/src/render/texture/qtexturedataupdate.cpp
new file mode 100644
index 000000000..e3d5220f0
--- /dev/null
+++ b/src/render/texture/qtexturedataupdate.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtexturedataupdate.h"
+#include "qtexturedataupdate_p.h"
+#include <iostream>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender
+{
+
+static bool operator==(const QTextureDataUpdatePrivate &lhs, const QTextureDataUpdatePrivate &rhs) noexcept
+{
+ return lhs.m_x == rhs.m_x &&
+ lhs.m_y == rhs.m_y &&
+ lhs.m_z == rhs.m_z &&
+ lhs.m_layer == rhs.m_layer &&
+ lhs.m_mipLevel == rhs.m_mipLevel &&
+ lhs.m_face == rhs.m_face &&
+ lhs.m_data == rhs.m_data;
+}
+
+/*!
+ \class Qt3DRender::QTextureDataUpdate
+ \inmodule Qt3DRender
+ \brief QTextureDataUpdate holds content and information required to perform
+ partial updates of a texture content.
+
+ The actual data content is contained in a QTextureImageDataPtr member.
+ Additional members allow to specify the x, y, z offset of the content update
+ as well as the eventual layer, mipLevel and face.
+
+ \sa QAbstractTexture
+ \since 5.14
+ */
+
+QTextureDataUpdate::QTextureDataUpdate()
+ : d_ptr(new QTextureDataUpdatePrivate())
+{
+}
+
+QTextureDataUpdate::QTextureDataUpdate(const QTextureDataUpdate &other)
+ = default;
+
+QTextureDataUpdate &QTextureDataUpdate::operator=(const QTextureDataUpdate &other)
+ = default;
+
+QTextureDataUpdate::~QTextureDataUpdate()
+ = default;
+
+bool operator==(const QTextureDataUpdate &lhs, const QTextureDataUpdate &rhs) noexcept
+{
+ return *lhs.d_func() == *rhs.d_func();
+}
+
+int QTextureDataUpdate::x() const
+{
+ Q_D(const QTextureDataUpdate);
+ return d->m_x;
+}
+
+int QTextureDataUpdate::y() const
+{
+ Q_D(const QTextureDataUpdate);
+ return d->m_y;
+}
+
+int QTextureDataUpdate::z() const
+{
+ Q_D(const QTextureDataUpdate);
+ return d->m_z;
+}
+
+int QTextureDataUpdate::layer() const
+{
+ Q_D(const QTextureDataUpdate);
+ return d->m_layer;
+}
+
+int QTextureDataUpdate::mipLevel() const
+{
+ Q_D(const QTextureDataUpdate);
+ return d->m_mipLevel;
+}
+
+QAbstractTexture::CubeMapFace QTextureDataUpdate::face() const
+{
+ Q_D(const QTextureDataUpdate);
+ return d->m_face;
+}
+
+QTextureImageDataPtr QTextureDataUpdate::data() const
+{
+ Q_D(const QTextureDataUpdate);
+ return d->m_data;
+}
+
+void QTextureDataUpdate::setX(int x)
+{
+ d_ptr.detach();
+ Q_D(QTextureDataUpdate);
+ d->m_x = x;
+}
+
+void QTextureDataUpdate::setY(int y)
+{
+ d_ptr.detach();
+ Q_D(QTextureDataUpdate);
+ d->m_y = y;
+}
+
+void QTextureDataUpdate::setZ(int z)
+{
+ d_ptr.detach();
+ Q_D(QTextureDataUpdate);
+ d->m_z = z;
+}
+
+void QTextureDataUpdate::setLayer(int layer)
+{
+ d_ptr.detach();
+ Q_D(QTextureDataUpdate);
+ d->m_layer = layer;
+}
+
+void QTextureDataUpdate::setMipLevel(int mipLevel)
+{
+ d_ptr.detach();
+ Q_D(QTextureDataUpdate);
+ d->m_mipLevel = mipLevel;
+}
+
+void QTextureDataUpdate::setFace(QAbstractTexture::CubeMapFace face)
+{
+ d_ptr.detach();
+ Q_D(QTextureDataUpdate);
+ d->m_face = face;
+}
+
+void QTextureDataUpdate::setData(const QTextureImageDataPtr &data)
+{
+ d_ptr.detach();
+ Q_D(QTextureDataUpdate);
+ d->m_data = data;
+}
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
diff --git a/src/render/texture/qtexturedataupdate.h b/src/render/texture/qtexturedataupdate.h
new file mode 100644
index 000000000..3505d85fa
--- /dev/null
+++ b/src/render/texture/qtexturedataupdate.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_QTEXTUREDATAUPDATE_H
+#define QT3DRENDER_QTEXTUREDATAUPDATE_H
+
+#include <Qt3DRender/qt3drender_global.h>
+#include <Qt3DRender/qabstracttexture.h>
+
+#include <QtCore/qshareddata.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender
+{
+
+class QTextureDataUpdate;
+class QTextureDataUpdatePrivate;
+
+Q_3DRENDERSHARED_EXPORT bool operator==(const QTextureDataUpdate &lhs, const QTextureDataUpdate &rhs) noexcept;
+
+class Q_3DRENDERSHARED_EXPORT QTextureDataUpdate
+{
+public:
+ QTextureDataUpdate();
+ QTextureDataUpdate(const QTextureDataUpdate &other);
+ QTextureDataUpdate &operator=(const QTextureDataUpdate &other);
+ QTextureDataUpdate &operator=(QTextureDataUpdate &&other) noexcept
+ { swap(other); return *this; }
+ ~QTextureDataUpdate();
+
+ void swap(QTextureDataUpdate &other) noexcept { qSwap(d_ptr, other.d_ptr); }
+
+ int x() const;
+ int y() const;
+ int z() const;
+ int layer() const;
+ int mipLevel() const;
+ QAbstractTexture::CubeMapFace face() const;
+ QTextureImageDataPtr data() const;
+
+ void setX(int x);
+ void setY(int y);
+ void setZ(int z);
+ void setLayer(int layer);
+ void setMipLevel(int mipLevel);
+ void setFace(QAbstractTexture::CubeMapFace face);
+ void setData(const QTextureImageDataPtr &data);
+
+private:
+ friend Q_3DRENDERSHARED_EXPORT bool operator==(const QTextureDataUpdate &lhs, const QTextureDataUpdate &rhs) noexcept;
+ Q_DECLARE_PRIVATE(QTextureDataUpdate)
+ QExplicitlySharedDataPointer<QTextureDataUpdatePrivate> d_ptr;
+};
+QT3D_DECLARE_TYPEINFO(Qt3DRender, QTextureDataUpdate, Q_MOVABLE_TYPE)
+
+inline bool operator!=(const QTextureDataUpdate &lhs, const QTextureDataUpdate &rhs) noexcept
+{ return !operator==(lhs, rhs); }
+
+inline void swap(QTextureDataUpdate &lhs, QTextureDataUpdate &rhs) noexcept { return lhs.swap(rhs); }
+
+} // Qt3DRender
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3DRender::QTextureDataUpdate)
+
+
+#endif // QT3DRENDER_QTEXTUREDATAUPDATE_H
diff --git a/src/render/renderers/opengl/renderer/glcommands_p.h b/src/render/texture/qtexturedataupdate_p.h
index 5ed360759..e6be170e9 100644
--- a/src/render/renderers/opengl/renderer/glcommands_p.h
+++ b/src/render/texture/qtexturedataupdate_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QT3DRENDER_RENDER_GLCOMMANDS_P_H
-#define QT3DRENDER_RENDER_GLCOMMANDS_P_H
+#ifndef QT3DRENDER_QTEXTUREDATAUPDATE_P_H
+#define QT3DRENDER_QTEXTUREDATAUPDATE_P_H
//
// W A R N I N G
@@ -51,39 +51,29 @@
// We mean it.
//
-#include <Qt3DRender/qt3drender_global.h>
+#include <Qt3DRender/qtextureimagedata.h>
+#include <Qt3DRender/qabstracttexture.h>
-QT_BEGIN_NAMESPACE
+#include <QtCore/qshareddata.h>
+QT_BEGIN_NAMESPACE
namespace Qt3DRender {
-namespace Render {
-
-class GraphicsContext;
-class Renderer;
-class Shader;
-
-class GLCommand
+class QTextureDataUpdatePrivate : public QSharedData
{
public:
- virtual void execute(Renderer *renderer, GraphicsContext *ctx) = 0;
-};
-
-class Q_AUTOTEST_EXPORT LoadShaderCommand : public GLCommand
-{
-public:
- explicit LoadShaderCommand(Shader *shader);
- Shader *shader() const { return m_shader; }
- void execute(Renderer *renderer, GraphicsContext *ctx) Q_DECL_OVERRIDE;
-
-private:
- Shader *m_shader = nullptr;
+ int m_x = 0;
+ int m_y = 0;
+ int m_z = 0;
+ int m_layer = 0;
+ int m_mipLevel = 0;
+ QAbstractTexture::CubeMapFace m_face = QAbstractTexture::CubeMapPositiveX;
+ QTextureImageDataPtr m_data;
};
-} // Render
} // Qt3DRender
QT_END_NAMESPACE
-#endif // QT3DRENDER_RENDER_GLCOMMANDS_P_H
+#endif // QT3DRENDER_QTEXTUREDATAUPDATE_P_H
diff --git a/src/render/texture/qtexturegenerator.cpp b/src/render/texture/qtexturegenerator.cpp
index 5e350af2d..36b5f6498 100644
--- a/src/render/texture/qtexturegenerator.cpp
+++ b/src/render/texture/qtexturegenerator.cpp
@@ -52,8 +52,7 @@ QTextureGenerator::~QTextureGenerator()
}
/*!
- \class QTextureGenerator
- \inherits QAbstractFunctor
+ \class Qt3DRender::QTextureGenerator
\inmodule Qt3DRender
\brief Provides the image data for a texture.
*/
diff --git a/src/render/texture/qtextureimage.cpp b/src/render/texture/qtextureimage.cpp
index 6bcdaba7d..b4e9ed46f 100644
--- a/src/render/texture/qtextureimage.cpp
+++ b/src/render/texture/qtextureimage.cpp
@@ -289,10 +289,12 @@ QImageTextureDataFunctor::QImageTextureDataFunctor(const QUrl &url, bool mirrore
QTextureImageDataPtr QImageTextureDataFunctor::operator ()()
{
+ if (!m_url.isValid())
+ return QTextureImageDataPtr();
+
// We assume that a texture image is going to contain a single image data
// For compressed dds or ktx textures a warning should be issued if
// there are layers or 3D textures
-
if (!Qt3DCore::QDownloadHelperService::isLocal(m_url))
qWarning() << "QTextureImage only supports local url";
diff --git a/src/render/texture/qtextureimagedata.cpp b/src/render/texture/qtextureimagedata.cpp
index bf43a6e16..28d296feb 100644
--- a/src/render/texture/qtextureimagedata.cpp
+++ b/src/render/texture/qtextureimagedata.cpp
@@ -59,9 +59,25 @@ QTextureImageDataPrivate::QTextureImageDataPrivate()
, m_pixelFormat(QOpenGLTexture::RGBA)
, m_pixelType(QOpenGLTexture::UInt8)
, m_isCompressed(false)
+ , m_isKtx(false)
{
}
+QByteArray QTextureImageDataPrivate::ktxData(int layer, int face, int mipmapLevel) const
+{
+ Q_ASSERT(layer >= 0 && layer < m_layers &&
+ face >= 0 && face < m_faces &&
+ mipmapLevel >= 0 && mipmapLevel < m_mipLevels);
+
+ int offset = 0;
+ for (int i = 0; i < mipmapLevel; i++)
+ offset += (mipmapLevelSize(i) * m_faces * m_layers) + 4;
+ const int selectedMipmapLevelSize = mipmapLevelSize(mipmapLevel);
+ offset += (selectedMipmapLevelSize * m_faces * layer) + (selectedMipmapLevelSize * face) + 4;
+
+ return QByteArray::fromRawData(m_data.constData() + offset, selectedMipmapLevelSize);
+}
+
QByteArray QTextureImageDataPrivate::data(int layer, int face, int mipmapLevel) const
{
if (layer < 0 || layer >= m_layers ||
@@ -71,7 +87,10 @@ QByteArray QTextureImageDataPrivate::data(int layer, int face, int mipmapLevel)
return QByteArray();
}
- int offset = layer * layerSize() + face * faceSize();
+ if (m_isKtx)
+ return ktxData(layer, face, mipmapLevel);
+
+ int offset = layer * ddsLayerSize() + face * ddsFaceSize();
for (int i = 0; i < mipmapLevel; i++)
offset += mipmapLevelSize(i);
@@ -93,12 +112,12 @@ void QTextureImageDataPrivate::setData(const QByteArray &data,
m_blockSize = blockSize;
}
-int QTextureImageDataPrivate::layerSize() const
+int QTextureImageDataPrivate::ddsLayerSize() const
{
- return m_faces * faceSize();
+ return m_faces * ddsFaceSize();
}
-int QTextureImageDataPrivate::faceSize() const
+int QTextureImageDataPrivate::ddsFaceSize() const
{
int size = 0;
diff --git a/src/render/texture/qtextureimagedata_p.h b/src/render/texture/qtextureimagedata_p.h
index 8bb836d5b..d9a0952de 100644
--- a/src/render/texture/qtextureimagedata_p.h
+++ b/src/render/texture/qtextureimagedata_p.h
@@ -82,17 +82,20 @@ public:
QOpenGLTexture::PixelType m_pixelType;
bool m_isCompressed;
+ // ### Qt 6
+ // QTextureImageData was originally written with assumptions around the internal data format
+ // matching dds layout. This is an ugly, but easy, way to add basic ktx support without any
+ // public API changes. Consider https://codereview.qt-project.org/#/c/178474/ for Qt 6.
+ bool m_isKtx;
QByteArray m_data;
static QTextureImageDataPrivate *get(QTextureImageData *imageData);
private:
- int layerSize() const;
- int faceSize() const;
+ int ddsLayerSize() const;
+ int ddsFaceSize() const;
int mipmapLevelSize(int level) const;
-
- bool setPkmFile(const QString &source);
- bool setDdsFile(const QString &source);
+ QByteArray ktxData(int layer, int face, int mipmapLevel) const;
};
} // namespace Qt3DRender
diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp
index 17fd47be3..1414cd337 100644
--- a/src/render/texture/texture.cpp
+++ b/src/render/texture/texture.cpp
@@ -47,7 +47,6 @@
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/private/texture_p.h>
-#include <Qt3DRender/private/qabstracttexture_p.h>
#include <Qt3DRender/private/gltexturemanager_p.h>
#include <Qt3DRender/private/managers_p.h>
@@ -62,6 +61,7 @@ Texture::Texture()
// We need backend -> frontend notifications to update the status of the texture
: BackendNode(ReadWrite)
, m_dirty(DirtyImageGenerators|DirtyProperties|DirtyParameters|DirtyDataGenerator)
+ , m_sharedTextureId(-1)
{
}
@@ -93,20 +93,6 @@ void Texture::unsetDirty()
m_dirty = Texture::NotDirty;
}
-void Texture::addTextureImage(Qt3DCore::QNodeId id)
-{
- if (!m_textureImageIds.contains(id)) {
- m_textureImageIds.push_back(id);
- addDirtyFlag(DirtyImageGenerators);
- }
-}
-
-void Texture::removeTextureImage(Qt3DCore::QNodeId id)
-{
- m_textureImageIds.removeAll(id);
- addDirtyFlag(DirtyImageGenerators);
-}
-
// This is called by Renderer::updateGLResources
// when the texture has been marked for cleanup
void Texture::cleanup()
@@ -115,6 +101,7 @@ void Texture::cleanup()
// texture is being referenced by a shared API specific texture (GLTexture)
m_dataFunctor.reset();
m_textureImageIds.clear();
+ m_pendingTextureDataUpdates.clear();
m_sharedTextureId = -1;
// set default values
@@ -124,94 +111,66 @@ void Texture::cleanup()
m_dirty = NotDirty;
}
-// ChangeArbiter/Aspect Thread
-void Texture::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- DirtyFlags dirty;
-
- switch (e->type()) {
- case PropertyUpdated: {
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
- if (propertyChange->propertyName() == QByteArrayLiteral("width")) {
- m_properties.width = propertyChange->value().toInt();
- dirty = DirtyProperties;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("height")) {
- m_properties.height = propertyChange->value().toInt();
- dirty = DirtyProperties;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("depth")) {
- m_properties.depth = propertyChange->value().toInt();
- dirty = DirtyProperties;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("format")) {
- m_properties.format = static_cast<QAbstractTexture::TextureFormat>(propertyChange->value().toInt());
- dirty = DirtyProperties;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("target")) {
- m_properties.target = static_cast<QAbstractTexture::Target>(propertyChange->value().toInt());
- dirty = DirtyProperties;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("mipmaps")) {
- m_properties.generateMipMaps = propertyChange->value().toBool();
- dirty = DirtyProperties;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("minificationFilter")) {
- m_parameters.minificationFilter = static_cast<QAbstractTexture::Filter>(propertyChange->value().toInt());
- dirty = DirtyParameters;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("magnificationFilter")) {
- m_parameters.magnificationFilter = static_cast<QAbstractTexture::Filter>(propertyChange->value().toInt());
- dirty = DirtyParameters;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeX")) {
- m_parameters.wrapModeX = static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt());
- dirty = DirtyParameters;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeY")) {
- m_parameters.wrapModeY = static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt());
- dirty = DirtyParameters;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("wrapModeZ")) {
- m_parameters.wrapModeZ =static_cast<QTextureWrapMode::WrapMode>(propertyChange->value().toInt());
- dirty = DirtyParameters;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("maximumAnisotropy")) {
- m_parameters.maximumAnisotropy = propertyChange->value().toFloat();
- dirty = DirtyParameters;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("comparisonFunction")) {
- m_parameters.comparisonFunction = propertyChange->value().value<QAbstractTexture::ComparisonFunction>();
- dirty = DirtyParameters;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("comparisonMode")) {
- m_parameters.comparisonMode = propertyChange->value().value<QAbstractTexture::ComparisonMode>();
- dirty = DirtyParameters;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("layers")) {
- m_properties.layers = propertyChange->value().toInt();
- dirty = DirtyProperties;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("samples")) {
- m_properties.samples = propertyChange->value().toInt();
- dirty = DirtyProperties;
- } else if (propertyChange->propertyName() == QByteArrayLiteral("generator")) {
- setDataGenerator(propertyChange->value().value<QTextureGeneratorPtr>());
- } else if (propertyChange->propertyName() == QByteArrayLiteral("textureId")) {
- m_sharedTextureId = propertyChange->value().toInt();
- dirty = DirtySharedTextureId;
- }
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ const QAbstractTexture *node = qobject_cast<const QAbstractTexture *>(frontEnd);
+ if (!node)
+ return;
+
+ TextureProperties p = m_properties;
+ p.width = node->width();
+ p.height = node->height();
+ p.depth = node->depth();
+ p.format = node->format();
+ p.target = node->target();
+ p.generateMipMaps = node->generateMipMaps();
+ p.layers = node->layers();
+ p.samples = node->samples();
+ if (p != m_properties) {
+ m_properties = p;
+ addDirtyFlag(DirtyProperties);
}
- break;
- case PropertyValueAdded: {
- const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("textureImage")) {
- addTextureImage(change->addedNodeId());
- }
+ TextureParameters q = m_parameters;
+ q.magnificationFilter = node->magnificationFilter();
+ q.minificationFilter = node->minificationFilter();
+ q.wrapModeX = const_cast<QAbstractTexture *>(node)->wrapMode()->x();
+ q.wrapModeY = const_cast<QAbstractTexture *>(node)->wrapMode()->y();
+ q.wrapModeZ = const_cast<QAbstractTexture *>(node)->wrapMode()->z();
+ q.maximumAnisotropy = node->maximumAnisotropy();
+ q.comparisonFunction = node->comparisonFunction();
+ q.comparisonMode = node->comparisonMode();
+ if (q != m_parameters) {
+ m_parameters = q;
+ addDirtyFlag(DirtyParameters);
}
- break;
- case PropertyValueRemoved: {
- const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
- if (change->propertyName() == QByteArrayLiteral("textureImage")) {
- removeTextureImage(change->removedNodeId());
- }
+ auto newGenerator = node->dataGenerator();
+ if (newGenerator != m_dataFunctor) {
+ setDataGenerator(newGenerator);
+ QAbstractTexturePrivate *dTexture = static_cast<QAbstractTexturePrivate *>(QNodePrivate::get(const_cast<QNode *>(frontEnd)));
+ dTexture->setStatus(QAbstractTexture::Loading);
}
- break;
- default:
- break;
+ QAbstractTexturePrivate *dnode = dynamic_cast<QAbstractTexturePrivate *>(QAbstractTexturePrivate::get(const_cast<QAbstractTexture *>(node)));
+ if (dnode) {
+ for (const QTextureDataUpdate &pendingUpdate : dnode->m_pendingDataUpdates)
+ addTextureDataUpdate(pendingUpdate);
+ dnode->m_pendingDataUpdates.clear();
+
+ auto ids = Qt3DCore::qIdsForNodes(dnode->m_textureImages);
+ std::sort(std::begin(ids), std::end(ids));
+ if (ids != m_textureImageIds) {
+ m_textureImageIds = ids;
+ addDirtyFlag(DirtyImageGenerators);
+ }
+ if (dnode->m_sharedTextureId != m_sharedTextureId) {
+ m_sharedTextureId = dnode->m_sharedTextureId;
+ addDirtyFlag(DirtySharedTextureId);
+ }
}
-
- addDirtyFlag(dirty);
- BackendNode::sceneChangeEvent(e);
}
// Called by sceneChangeEvent or TextureDownloadRequest (both in AspectThread context)
@@ -221,91 +180,9 @@ void Texture::setDataGenerator(const QTextureGeneratorPtr &generator)
addDirtyFlag(DirtyDataGenerator);
}
-// Called by sendTextureChangesToFrontendJob once GLTexture and sharing
-// has been performed
-void Texture::updatePropertiesAndNotify(const TextureUpdateInfo &updateInfo)
-{
- // If we are Dirty, some property has changed and the properties we have
- // received are potentially already outdated
- if (m_dirty != NotDirty)
- return;
-
- // Note we don't update target has it is constant for frontend nodes
-
- if (updateInfo.properties.width != m_properties.width) {
- m_properties.width = updateInfo.properties.width;
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- change->setPropertyName("width");
- change->setValue(updateInfo.properties.width);
- notifyObservers(change);
- }
-
- if (updateInfo.properties.height != m_properties.height) {
- m_properties.height = updateInfo.properties.height;
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- change->setPropertyName("height");
- change->setValue(updateInfo.properties.height);
- notifyObservers(change);
- }
-
- if (updateInfo.properties.depth != m_properties.depth) {
- m_properties.depth = updateInfo.properties.depth;
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- change->setPropertyName("depth");
- change->setValue(updateInfo.properties.depth);
- notifyObservers(change);
- }
-
- if (updateInfo.properties.layers != m_properties.layers) {
- m_properties.layers = updateInfo.properties.layers;
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- change->setPropertyName("layers");
- change->setValue(updateInfo.properties.layers);
- notifyObservers(change);
- }
-
- if (updateInfo.properties.format != m_properties.format) {
- m_properties.format = updateInfo.properties.format;
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- change->setPropertyName("format");
- change->setValue(updateInfo.properties.format);
- notifyObservers(change);
- }
-
- if (updateInfo.properties.status != m_properties.status) {
- m_properties.status = updateInfo.properties.status;
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- change->setPropertyName("status");
- change->setValue(updateInfo.properties.status);
- notifyObservers(change);
- }
-
- {
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- change->setPropertyName("handleType");
- change->setValue(updateInfo.handleType);
- notifyObservers(change);
- }
-
- {
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId());
- change->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- change->setPropertyName("handle");
- change->setValue(updateInfo.handle);
- notifyObservers(change);
- }
-}
-
bool Texture::isValid(TextureImageManager *manager) const
{
- for (const QNodeId id : m_textureImageIds) {
+ for (const QNodeId &id : m_textureImageIds) {
TextureImage *img = manager->lookupResource(id);
if (img == nullptr)
return false;
@@ -337,14 +214,25 @@ void Texture::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chan
m_dataFunctor = data.dataFunctor;
m_sharedTextureId = data.sharedTextureId;
- for (const QNodeId imgId : data.textureImageIds)
- addTextureImage(imgId);
+ m_textureImageIds = data.textureImageIds;
+ if (m_textureImageIds.size())
+ addDirtyFlag(DirtyImageGenerators);
+
+ const QVector<QTextureDataUpdate> initialDataUpdates = data.initialDataUpdates;
+ for (const QTextureDataUpdate &initialUpdate : initialDataUpdates)
+ addTextureDataUpdate(initialUpdate);
addDirtyFlag(DirtyFlags(DirtyImageGenerators|DirtyProperties|DirtyParameters));
if (m_sharedTextureId > 0)
addDirtyFlag(DirtySharedTextureId);
}
+void Texture::addTextureDataUpdate(const QTextureDataUpdate &update)
+{
+ m_pendingTextureDataUpdates.push_back(update);
+ addDirtyFlag(DirtyPendingDataUpdates);
+}
+
TextureFunctor::TextureFunctor(AbstractRenderer *renderer,
TextureManager *textureNodeManager)
diff --git a/src/render/texture/texture.pri b/src/render/texture/texture.pri
index 0d520a9ec..87c77a2ff 100644
--- a/src/render/texture/texture.pri
+++ b/src/render/texture/texture.pri
@@ -8,7 +8,6 @@ HEADERS += \
$$PWD/qtextureimage_p.h \
$$PWD/qtexturewrapmode.h \
$$PWD/texture_p.h \
- $$PWD/texturedatamanager_p.h \
$$PWD/textureimage_p.h \
$$PWD/qabstracttexture.h \
$$PWD/qabstracttexture_p.h \
@@ -21,7 +20,8 @@ HEADERS += \
$$PWD/qtexture_p.h \
$$PWD/qpaintedtextureimage.h \
$$PWD/qpaintedtextureimage_p.h \
- $$PWD/apitexturemanager_p.h
+ $$PWD/qtexturedataupdate.h \
+ $$PWD/qtexturedataupdate_p.h
SOURCES += \
$$PWD/qabstracttextureimage.cpp \
@@ -34,4 +34,5 @@ SOURCES += \
$$PWD/qtextureimagedata.cpp \
$$PWD/qtexturedata.cpp \
$$PWD/qtexturegenerator.cpp \
- $$PWD/qpaintedtextureimage.cpp
+ $$PWD/qpaintedtextureimage.cpp \
+ $$PWD/qtexturedataupdate.cpp
diff --git a/src/render/texture/texture_p.h b/src/render/texture/texture_p.h
index c60e90181..9e347243e 100644
--- a/src/render/texture/texture_p.h
+++ b/src/render/texture/texture_p.h
@@ -53,6 +53,7 @@
#include <Qt3DRender/private/backendnode_p.h>
#include <Qt3DRender/private/handle_types_p.h>
+#include <Qt3DRender/private/qabstracttexture_p.h>
#include <Qt3DRender/qtexture.h>
#include <Qt3DRender/qtexturedata.h>
#include <Qt3DRender/qtexturegenerator.h>
@@ -83,7 +84,7 @@ struct TextureProperties
int layers = 1;
int mipLevels = 1;
int samples = 1;
- QAbstractTexture::Target target = QAbstractTexture::Target2D;
+ QAbstractTexture::Target target = QAbstractTexture::TargetAutomatic;
QAbstractTexture::TextureFormat format = QAbstractTexture::NoFormat;
bool generateMipMaps = false;
QAbstractTexture::Status status = QAbstractTexture::None;
@@ -97,6 +98,7 @@ struct TextureProperties
inline bool operator!=(const TextureProperties &o) const { return !(*this == o); }
};
+
/**
* Texture parameters that are independent of texture data and that may
* change without the re-uploading the texture
@@ -134,11 +136,12 @@ public:
enum DirtyFlag {
NotDirty = 0,
- DirtyProperties = 0x1,
- DirtyParameters = 0x2,
- DirtyImageGenerators = 0x4,
- DirtyDataGenerator = 0x8,
- DirtySharedTextureId = 0x16
+ DirtyProperties = (1 << 0),
+ DirtyParameters = (1 << 1),
+ DirtyImageGenerators = (1 << 2),
+ DirtyDataGenerator = (1 << 3),
+ DirtySharedTextureId = (1 << 4),
+ DirtyPendingDataUpdates = (1 << 5),
};
Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)
@@ -153,11 +156,12 @@ public:
DirtyFlags dirtyFlags();
void unsetDirty();
- void addTextureImage(Qt3DCore::QNodeId id);
- void removeTextureImage(Qt3DCore::QNodeId id);
void cleanup();
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void addTextureDataUpdate(const QTextureDataUpdate &update);
+ QVector<QTextureDataUpdate> takePendingTextureDataUpdates() { return std::move(m_pendingTextureDataUpdates); }
+
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
inline const TextureProperties& properties() const { return m_properties; }
inline const TextureParameters& parameters() const { return m_parameters; }
@@ -166,7 +170,6 @@ public:
inline int sharedTextureId() const { return m_sharedTextureId; }
void setDataGenerator(const QTextureGeneratorPtr &generator);
- void updatePropertiesAndNotify(const TextureUpdateInfo &updateInfo);
bool isValid(TextureImageManager *manager) const;
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
@@ -180,6 +183,7 @@ private:
Qt3DCore::QNodeIdVector m_textureImageIds;
QMutex m_flagsMutex;
+ QVector<QTextureDataUpdate> m_pendingTextureDataUpdates;
};
class Q_AUTOTEST_EXPORT TextureFunctor : public Qt3DCore::QBackendNodeMapper
@@ -211,5 +215,6 @@ inline QDebug operator<<(QDebug dbg, const Texture &texture)
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Qt3DRender::Render::Texture*) // LCOV_EXCL_LINE
+Q_DECLARE_METATYPE(Qt3DRender::Render::TextureProperties) // LCOV_EXCL_LINE
#endif // QT3DRENDER_RENDER_TEXTURE_H
diff --git a/src/render/texture/texturedatamanager_p.h b/src/render/texture/texturedatamanager_p.h
deleted file mode 100644
index 9319a64e0..000000000
--- a/src/render/texture/texturedatamanager_p.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QT3DRENDER_RENDER_TEXTUREDATAMANAGER_H
-#define QT3DRENDER_RENDER_TEXTUREDATAMANAGER_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QMutex>
-#include <QMutexLocker>
-#include <Qt3DRender/qtexture.h>
-#include <Qt3DRender/qtextureimagedata.h>
-#include <Qt3DRender/qtexturegenerator.h>
-#include <Qt3DRender/qtextureimagedatagenerator.h>
-#include <Qt3DRender/private/gltexture_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DRender {
-namespace Render {
-
-/**
- * The texture data managers associates each texture data generator
- * with the data objects generated by them. That is, either
- *
- * QTextureImageDataGenerator -> QTextureImageData, or
- * QTextureGenerator -> QTextureData
- *
- * This way, texture classes only need to refer to the texture functors used.
- * Aspect jobs will make sure that at the start of each frame, all generators
- * registered with the GeneratorDataManagers have been executed.
- *
- * This guarantees that no texture data generator is executed twice.
- *
- * Each Generator is associated with a number of textures that reference it.
- * If the last texture disassociates from a generator, the QTextureData will
- * be deleted.
- */
-template <class GeneratorPtr, class DataPtr, class ReferencedType>
-class GeneratorDataManager
-{
-public:
- GeneratorDataManager() {}
-
- /*!
- * If no data for the given generator exists, make sure that the
- * generators are executed the next frame. Reference generator by
- * given texture
- *
- * Returns true if the Entry for a given generator had to be created
- */
- bool requestData(const GeneratorPtr &generator, ReferencedType r)
- {
- QMutexLocker lock(&m_mutex);
-
- Entry *entry = findEntry(generator);
- const bool needsToBeCreated = (entry == nullptr);
- if (needsToBeCreated)
- entry = createEntry(generator);
- Q_ASSERT(entry);
- if (!entry->referencingObjects.contains(r))
- entry->referencingObjects.push_back(r);
- return needsToBeCreated;
- }
-
- QVector<ReferencedType> referencesForGenerator(const GeneratorPtr &generator)
- {
- QMutexLocker lock(&m_mutex);
-
- Entry *entry = findEntry(generator);
- if (entry == nullptr)
- return {};
- return entry->referencingObjects;
- }
-
-
- /*!
- * Dereference given generator from texture. If no other textures still reference
- * the generator, the associated data will be deleted
- */
- void releaseData(const GeneratorPtr &generator, ReferencedType r)
- {
- QMutexLocker lock(&m_mutex);
-
- const auto end = m_data.end();
- for (auto it = m_data.begin(); it != end; ++it) {
- Entry &entry = *it;
- if (*entry.generator == *generator) {
- entry.referencingObjects.removeAll(r);
- // delete, if that was the last reference
- if (entry.referencingObjects.empty()) {
- m_data.erase(it);
- return;
- }
- }
- }
- }
-
- /*!
- * Return data associated with given generator, if existent
- */
- DataPtr getData(const GeneratorPtr &generator)
- {
- QMutexLocker lock(&m_mutex);
-
- const Entry *entry = findEntry(generator);
- return entry ? entry->data : DataPtr();
- }
-
- /*!
- * Returns all generators that were not yet executed
- */
- QVector<GeneratorPtr> pendingGenerators()
- {
- QMutexLocker lock(&m_mutex);
-
- QVector<GeneratorPtr> ret;
- for (const Entry &entry : m_data)
- if (!entry.data && !ret.contains(entry.generator))
- ret.push_back(entry.generator);
- return ret;
- }
-
- /*!
- * Assigns a piece of data to the generator that was used to
- * create it.
- */
- void assignData(const GeneratorPtr &generator, const DataPtr &data)
- {
- QMutexLocker lock(&m_mutex);
-
- Entry *entry = findEntry(generator);
- if (!entry) {
- qWarning() << "[TextureDataManager] assignData() called with non-existent generator";
- return;
- }
- entry->data = data;
- }
-
- bool contains(const GeneratorPtr &generator)
- {
- return findEntry(generator) != nullptr;
- }
-
-private:
-
- struct Entry {
- GeneratorPtr generator;
- QVector<ReferencedType> referencingObjects;
- DataPtr data;
- };
-
- /*!
- * Helper function: return entry for given generator if it exists, nullptr
- * otherwise.
- */
- Entry* findEntry(const GeneratorPtr &generator)
- {
- for (int i = 0, sz = m_data.size(); i < sz; ++i)
- if (*m_data[i].generator == *generator)
- return &m_data[i];
- return nullptr;
- }
-
- Entry *createEntry(const GeneratorPtr &generator)
- {
- Entry newEntry;
- newEntry.generator = generator;
-
- m_data.push_back(newEntry);
- return &m_data.back();
- }
-
- QMutex m_mutex;
- QVector<Entry> m_data;
-};
-
-class Q_AUTOTEST_EXPORT TextureDataManager
- : public GeneratorDataManager<QTextureGeneratorPtr, QTextureDataPtr, GLTexture*>
-{
-};
-
-class Q_AUTOTEST_EXPORT TextureImageDataManager
- : public GeneratorDataManager<QTextureImageDataGeneratorPtr, QTextureImageDataPtr, Qt3DCore::QNodeId>
-{
-};
-
-} // namespace Render
-} // namespace Qt3DRender
-
-QT_END_NAMESPACE
-
-#endif // TEXTUREDATAMANAGER_H
diff --git a/src/render/texture/textureimage.cpp b/src/render/texture/textureimage.cpp
index 880562b87..25001b9df 100644
--- a/src/render/texture/textureimage.cpp
+++ b/src/render/texture/textureimage.cpp
@@ -38,11 +38,9 @@
****************************************************************************/
#include "textureimage_p.h"
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DRender/qtextureimage.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/qabstracttextureimage_p.h>
-#include <Qt3DRender/private/texturedatamanager_p.h>
QT_BEGIN_NAMESPACE
@@ -57,7 +55,6 @@ TextureImage::TextureImage()
, m_layer(0)
, m_mipLevel(0)
, m_face(QAbstractTexture::CubeMapPositiveX)
- , m_textureImageDataManager(nullptr)
{
}
@@ -67,56 +64,46 @@ TextureImage::~TextureImage()
void TextureImage::cleanup()
{
- if (m_generator) {
- m_textureImageDataManager->releaseData(m_generator, peerId());
- m_generator.reset();
- }
+ m_generator.reset();
m_dirty = false;
m_layer = 0;
m_mipLevel = 0;
m_face = QAbstractTexture::CubeMapPositiveX;
}
-void TextureImage::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
+void TextureImage::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractTextureImageData>>(change);
- const auto &data = typedChange->data;
- m_mipLevel = data.mipLevel;
- m_layer = data.layer;
- m_face = data.face;
- m_generator = data.generator;
- m_dirty = true;
-
- // Request functor upload
- if (m_generator)
- m_textureImageDataManager->requestData(m_generator, peerId());
-}
+ const QAbstractTextureImage *node = qobject_cast<const QAbstractTextureImage *>(frontEnd);
+ if (!node)
+ return;
-void TextureImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
-{
- QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e);
-
- if (e->type() == PropertyUpdated) {
- if (propertyChange->propertyName() == QByteArrayLiteral("layer")) {
- m_layer = propertyChange->value().toInt();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("mipLevel")) {
- m_mipLevel = propertyChange->value().toInt();
- } else if (propertyChange->propertyName() == QByteArrayLiteral("face")) {
- m_face = static_cast<QAbstractTexture::CubeMapFace>(propertyChange->value().toInt());
- } else if (propertyChange->propertyName() == QByteArrayLiteral("dataGenerator")) {
- // Release ref to generator
- if (m_generator)
- m_textureImageDataManager->releaseData(m_generator, peerId());
- m_generator = propertyChange->value().value<QTextureImageDataGeneratorPtr>();
- // Request functor upload
- if (m_generator)
- m_textureImageDataManager->requestData(m_generator, peerId());
- }
+ const bool oldEnabled = isEnabled();
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ m_dirty |= (oldEnabled != isEnabled());
+
+ if (node->layer() != m_layer) {
+ m_layer = node->layer();
+ m_dirty = true;
+ }
+
+ if (node->mipLevel() != m_mipLevel) {
+ m_mipLevel = node->mipLevel();
+ m_dirty = true;
+ }
+
+ if (node->face() != m_face) {
+ m_face = node->face();
+ m_dirty = true;
+ }
+
+ const QAbstractTextureImagePrivate *d = static_cast<const QAbstractTextureImagePrivate *>(QNodePrivate::get(node));
+ if (d->dataGenerator() != m_generator) {
+ m_generator = d->dataGenerator();
m_dirty = true;
}
- markDirty(AbstractRenderer::AllDirty);
- BackendNode::sceneChangeEvent(e);
+ if (m_dirty)
+ markDirty(AbstractRenderer::AllDirty);
}
void TextureImage::unsetDirty()
@@ -125,18 +112,15 @@ void TextureImage::unsetDirty()
}
TextureImageFunctor::TextureImageFunctor(AbstractRenderer *renderer,
- TextureImageManager *textureImageManager,
- TextureImageDataManager *textureImageDataManager)
+ TextureImageManager *textureImageManager)
: m_renderer(renderer)
, m_textureImageManager(textureImageManager)
- , m_textureImageDataManager(textureImageDataManager)
{
}
Qt3DCore::QBackendNode *TextureImageFunctor::create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const
{
TextureImage *backend = m_textureImageManager->getOrCreateResource(change->subjectId());
- backend->setTextureImageDataManager(m_textureImageDataManager);
backend->setRenderer(m_renderer);
return backend;
}
diff --git a/src/render/texture/textureimage_p.h b/src/render/texture/textureimage_p.h
index 19801ee77..57bbdea75 100644
--- a/src/render/texture/textureimage_p.h
+++ b/src/render/texture/textureimage_p.h
@@ -77,12 +77,7 @@ public:
~TextureImage();
void cleanup();
-
- void setTextureImageDataManager(TextureImageDataManager *dataManager) { m_textureImageDataManager = dataManager; }
-
- TextureImageDataManager *textureImageDataManager() const { return m_textureImageDataManager; }
-
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
inline int layer() const { return m_layer; }
inline int mipLevel() const { return m_mipLevel; }
@@ -92,23 +87,18 @@ public:
void unsetDirty();
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
-
bool m_dirty;
int m_layer;
int m_mipLevel;
QAbstractTexture::CubeMapFace m_face;
QTextureImageDataGeneratorPtr m_generator;
-
- TextureImageDataManager *m_textureImageDataManager;
};
class TextureImageFunctor : public Qt3DCore::QBackendNodeMapper
{
public:
explicit TextureImageFunctor(AbstractRenderer *renderer,
- TextureImageManager *textureImageManager,
- TextureImageDataManager *textureImageDataManager);
+ TextureImageManager *textureImageManager);
Qt3DCore::QBackendNode *create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const final;
Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const final;
@@ -117,7 +107,6 @@ public:
private:
AbstractRenderer *m_renderer;
TextureImageManager *m_textureImageManager;
- TextureImageDataManager *m_textureImageDataManager;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/tests/auto/animation/additiveclipblend/tst_additiveclipblend.cpp b/tests/auto/animation/additiveclipblend/tst_additiveclipblend.cpp
index 462c02518..8e8ce43db 100644
--- a/tests/auto/animation/additiveclipblend/tst_additiveclipblend.cpp
+++ b/tests/auto/animation/additiveclipblend/tst_additiveclipblend.cpp
@@ -32,7 +32,6 @@
#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/private/qadditiveclipblend_p.h>
#include <Qt3DAnimation/private/additiveclipblend_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
using namespace Qt3DAnimation::Animation;
@@ -143,7 +142,7 @@ private Q_SLOTS:
{
// WHEN
AdditiveClipBlend backendAdditiveBlend;
- simulateInitialization(&additiveBlend, &backendAdditiveBlend);
+ simulateInitializationSync(&additiveBlend, &backendAdditiveBlend);
// THEN
QCOMPARE(backendAdditiveBlend.isEnabled(), true);
@@ -156,7 +155,7 @@ private Q_SLOTS:
// WHEN
AdditiveClipBlend backendAdditiveBlend;
additiveBlend.setEnabled(false);
- simulateInitialization(&additiveBlend, &backendAdditiveBlend);
+ simulateInitializationSync(&additiveBlend, &backendAdditiveBlend);
// THEN
QCOMPARE(backendAdditiveBlend.peerId(), additiveBlend.id());
@@ -167,14 +166,14 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DAnimation::QAdditiveClipBlend additiveBlend;
AdditiveClipBlend backendAdditiveBlend;
+ simulateInitializationSync(&additiveBlend, &backendAdditiveBlend);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendAdditiveBlend.sceneChangeEvent(change);
+ additiveBlend.setEnabled(newValue);
+ backendAdditiveBlend.syncFromFrontEnd(&additiveBlend, false);
// THEN
QCOMPARE(backendAdditiveBlend.isEnabled(), newValue);
@@ -182,32 +181,26 @@ private Q_SLOTS:
{
// WHEN
const float newValue = 0.883f;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("additiveFactor");
- change->setValue(QVariant::fromValue(newValue));
- backendAdditiveBlend.sceneChangeEvent(change);
+ additiveBlend.setAdditiveFactor(newValue);
+ backendAdditiveBlend.syncFromFrontEnd(&additiveBlend, false);
// THEN
QCOMPARE(backendAdditiveBlend.additiveFactor(), newValue);
}
{
// WHEN
- const Qt3DAnimation::QAdditiveClipBlend newValue;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("baseClip");
- change->setValue(QVariant::fromValue(newValue.id()));
- backendAdditiveBlend.sceneChangeEvent(change);
+ Qt3DAnimation::QAdditiveClipBlend newValue;
+ additiveBlend.setBaseClip(&newValue);
+ backendAdditiveBlend.syncFromFrontEnd(&additiveBlend, false);
// THEN
QCOMPARE(backendAdditiveBlend.baseClipId(), newValue.id());
}
{
// WHEN
- const Qt3DAnimation::QAdditiveClipBlend newValue;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("additiveClip");
- change->setValue(QVariant::fromValue(newValue.id()));
- backendAdditiveBlend.sceneChangeEvent(change);
+ Qt3DAnimation::QAdditiveClipBlend newValue;
+ additiveBlend.setAdditiveClip(&newValue);
+ backendAdditiveBlend.syncFromFrontEnd(&additiveBlend, false);
// THEN
QCOMPARE(backendAdditiveBlend.additiveClipId(), newValue.id());
diff --git a/tests/auto/animation/animationclip/tst_animationclip.cpp b/tests/auto/animation/animationclip/tst_animationclip.cpp
index 15ee60581..d28a8fc58 100644
--- a/tests/auto/animation/animationclip/tst_animationclip.cpp
+++ b/tests/auto/animation/animationclip/tst_animationclip.cpp
@@ -31,9 +31,7 @@
#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
@@ -55,7 +53,7 @@ private Q_SLOTS:
clip.setSource(QUrl::fromLocalFile("walk.qlip"));
// WHEN
- simulateInitialization(&clip, &backendClip);
+ simulateInitializationSync(&clip, &backendClip);
// THEN
QCOMPARE(backendClip.peerId(), clip.id());
@@ -82,7 +80,7 @@ private Q_SLOTS:
clip.setSource(QUrl::fromLocalFile("walk.qlip"));
// WHEN
- simulateInitialization(&clip, &backendClip);
+ simulateInitializationSync(&clip, &backendClip);
backendClip.setSource(QUrl::fromLocalFile("run.qlip"));
backendClip.cleanup();
@@ -96,95 +94,27 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DAnimation::QAnimationClipLoader clip;
AnimationClip backendClip;
Handler handler;
backendClip.setHandler(&handler);
- backendClip.setDataType(Qt3DAnimation::Animation::AnimationClip::File);
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
+ simulateInitializationSync(&clip, &backendClip);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendClip.sceneChangeEvent(updateChange);
+ clip.setEnabled(false);
+ backendClip.syncFromFrontEnd(&clip, false);
// THEN
- QCOMPARE(backendClip.isEnabled(), true);
+ QCOMPARE(backendClip.isEnabled(), false);
// WHEN
const QUrl newSource = QUrl::fromLocalFile("fallover.qlip");
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("source");
- updateChange->setValue(newSource);
- backendClip.sceneChangeEvent(updateChange);
+ clip.setSource(newSource);
+ backendClip.syncFromFrontEnd(&clip, false);
// THEN
QCOMPARE(backendClip.source(), newSource);
}
-
- void checkDurationPropertyBackendNotification()
- {
- // GIVEN
- TestArbiter arbiter;
- AnimationClip backendClip;
- backendClip.setEnabled(true);
- Qt3DCore::QBackendNodePrivate::get(&backendClip)->setArbiter(&arbiter);
-
- // WHEN
- backendClip.setDuration(64.0f);
-
- // THEN
- QCOMPARE(backendClip.duration(), 64.0f);
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "duration");
- QCOMPARE(change->value().toFloat(), backendClip.duration());
- QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isIntermediate,
- false);
-
- arbiter.events.clear();
-
- // WHEN
- backendClip.setDuration(64.0f);
-
- // THEN
- QCOMPARE(backendClip.duration(), 64.0f);
- QCOMPARE(arbiter.events.count(), 0);
-
- arbiter.events.clear();
- }
-
- void checkStatusPropertyBackendNotification()
- {
- // GIVEN
- TestArbiter arbiter;
- AnimationClip backendClip;
- backendClip.setEnabled(true);
- Qt3DCore::QBackendNodePrivate::get(&backendClip)->setArbiter(&arbiter);
-
- // WHEN
- backendClip.setStatus(Qt3DAnimation::QAnimationClipLoader::Error);
-
- // THEN
- QCOMPARE(backendClip.status(), Qt3DAnimation::QAnimationClipLoader::Error);
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DAnimation::QAnimationClipLoader::Status>(), backendClip.status());
- QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isIntermediate,
- false);
-
- arbiter.events.clear();
-
- // WHEN
- backendClip.setStatus(Qt3DAnimation::QAnimationClipLoader::Error);
-
- // THEN
- QCOMPARE(backendClip.status(), Qt3DAnimation::QAnimationClipLoader::Error);
- QCOMPARE(arbiter.events.count(), 0);
-
- arbiter.events.clear();
- }
};
QTEST_APPLESS_MAIN(tst_AnimationClip)
diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp
index 36f1cbe2f..385398bd1 100644
--- a/tests/auto/animation/animationutils/tst_animationutils.cpp
+++ b/tests/auto/animation/animationutils/tst_animationutils.cpp
@@ -795,16 +795,12 @@ private Q_SLOTS:
QTest::addColumn<Qt3DCore::QNodeId>("animatorId");
QTest::addColumn<QVector<MappingData>>("mappingData");
QTest::addColumn<QVector<float>>("channelResults");
- QTest::addColumn<float>("normalizedTime");
- QTest::addColumn<bool>("finalFrame");
- QTest::addColumn<QVector<Qt3DCore::QPropertyUpdatedChangePtr>>("expectedChanges");
+ QTest::addColumn<AnimationRecord>("expectedChanges");
Qt3DCore::QNodeId animatorId;
QVector<MappingData> mappingData;
QVector<float> channelResults;
- bool finalFrame;
- float normalizedTime;
- QVector<Qt3DCore::QPropertyUpdatedChangePtr> expectedChanges;
+ AnimationRecord expectedChanges;
// Single property, vec3
{
@@ -816,40 +812,22 @@ private Q_SLOTS:
mapping.channelIndices = QVector<int>() << 0 << 1 << 2;
mappingData.push_back(mapping);
channelResults = QVector<float>() << 1.0f << 2.0f << 3.0f;
- finalFrame = false;
- normalizedTime = 1.1f; // Invalid
-
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId);
- change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- change->setPropertyName(mapping.propertyName);
- change->setValue(QVariant::fromValue(QVector3D(1.0f, 2.0f, 3.0f)));
- expectedChanges.push_back(change);
+ expectedChanges.normalizedTime = 1.1f; // Invalid
+ expectedChanges.finalFrame = false;
+ expectedChanges.targetChanges.push_back({mapping.targetId, mapping.propertyName, QVariant::fromValue(QVector3D(1.0f, 2.0f, 3.0f))});
QTest::newRow("vec3 translation, final = false")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
-
- normalizedTime = 1.0f;
- auto normalizedTimeChange = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId);
- normalizedTimeChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- normalizedTimeChange->setPropertyName("normalizedTime");
- normalizedTimeChange->setValue(normalizedTime);
- expectedChanges.push_back(normalizedTimeChange);
-
- finalFrame = true;
- auto animatorChange = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId);
- animatorChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- animatorChange->setPropertyName("running");
- animatorChange->setValue(false);
- expectedChanges.push_back(animatorChange);
+ << animatorId << mappingData << channelResults << expectedChanges;
+
+ expectedChanges.normalizedTime = 1.0f;
+ expectedChanges.finalFrame = true;
QTest::newRow("vec3 translation, final = true, normalizedTime = 1.0f")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
+ << animatorId << mappingData << channelResults << expectedChanges;
mappingData.clear();
channelResults.clear();
- expectedChanges.clear();
+ expectedChanges.targetChanges.clear();
}
// Multiple properties, all vec3
@@ -871,46 +849,24 @@ private Q_SLOTS:
channelResults = QVector<float>() << 1.0f << 2.0f << 3.0f
<< 4.0f << 5.0f << 6.0f;
- finalFrame = false;
- normalizedTime = -0.1f; // Invalid
-
- auto translationChange = Qt3DCore::QPropertyUpdatedChangePtr::create(translationMapping.targetId);
- translationChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- translationChange->setPropertyName(translationMapping.propertyName);
- translationChange->setValue(QVariant::fromValue(QVector3D(1.0f, 2.0f, 3.0f)));
- expectedChanges.push_back(translationChange);
+ expectedChanges.finalFrame = false;
+ expectedChanges.normalizedTime = -0.1f; // Invalid
- auto scaleChange = Qt3DCore::QPropertyUpdatedChangePtr::create(scaleMapping.targetId);
- scaleChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- scaleChange->setPropertyName(scaleMapping.propertyName);
- scaleChange->setValue(QVariant::fromValue(QVector3D(4.0f, 5.0f, 6.0f)));
- expectedChanges.push_back(scaleChange);
+ expectedChanges.targetChanges.push_back({translationMapping.targetId, translationMapping.propertyName, QVariant::fromValue(QVector3D(1.0f, 2.0f, 3.0f))});
+ expectedChanges.targetChanges.push_back({scaleMapping.targetId, scaleMapping.propertyName, QVariant::fromValue(QVector3D(4.0f, 5.0f, 6.0f))});
QTest::newRow("vec3 translation, vec3 scale, final = false")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
-
- normalizedTime = 0.5f;
- auto normalizedTimeChange = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId);
- normalizedTimeChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- normalizedTimeChange->setPropertyName("normalizedTime");
- normalizedTimeChange->setValue(normalizedTime);
- expectedChanges.push_back(normalizedTimeChange);
-
- finalFrame = true;
- auto animatorChange = Qt3DCore::QPropertyUpdatedChangePtr::create(animatorId);
- animatorChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- animatorChange->setPropertyName("running");
- animatorChange->setValue(false);
- expectedChanges.push_back(animatorChange);
+ << animatorId << mappingData << channelResults << expectedChanges;
+
+ expectedChanges.normalizedTime = 0.5f;
+ expectedChanges.finalFrame = true;
QTest::newRow("vec3 translation, vec3 scale, final = true")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
+ << animatorId << mappingData << channelResults << expectedChanges;
mappingData.clear();
channelResults.clear();
- expectedChanges.clear();
+ expectedChanges.targetChanges.clear();
}
// Single property, double
@@ -923,22 +879,16 @@ private Q_SLOTS:
mapping.channelIndices = QVector<int>() << 0;
mappingData.push_back(mapping);
channelResults = QVector<float>() << 3.5f;
- finalFrame = false;
- normalizedTime = -1.0f; // Invalid
-
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId);
- change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- change->setPropertyName(mapping.propertyName);
- change->setValue(QVariant::fromValue(3.5f));
- expectedChanges.push_back(change);
+ expectedChanges.finalFrame = false;
+ expectedChanges.normalizedTime = -1.0f; // Invalid
+ expectedChanges.targetChanges.push_back({mapping.targetId, mapping.propertyName, QVariant::fromValue(3.5f)});
QTest::newRow("double mass")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
+ << animatorId << mappingData << channelResults << expectedChanges;
mappingData.clear();
channelResults.clear();
- expectedChanges.clear();
+ expectedChanges.targetChanges.clear();
}
// Single property, vec2
@@ -951,22 +901,16 @@ private Q_SLOTS:
mapping.channelIndices = QVector<int>() << 0 << 1;
mappingData.push_back(mapping);
channelResults = QVector<float>() << 2.0f << 1.0f;
- finalFrame = false;
- normalizedTime = 1.1f; // Invalid
-
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId);
- change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- change->setPropertyName(mapping.propertyName);
- change->setValue(QVariant::fromValue(QVector2D(2.0f, 1.0f)));
- expectedChanges.push_back(change);
+ expectedChanges.finalFrame = false;
+ expectedChanges.normalizedTime = 1.1f; // Invalid
+ expectedChanges.targetChanges.push_back({mapping.targetId, mapping.propertyName, QVariant::fromValue(QVector2D(2.0f, 1.0f))});
QTest::newRow("vec2 pos")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
+ << animatorId << mappingData << channelResults << expectedChanges;
mappingData.clear();
channelResults.clear();
- expectedChanges.clear();
+ expectedChanges.targetChanges.clear();
}
// Single property, vec4
@@ -979,22 +923,16 @@ private Q_SLOTS:
mapping.channelIndices = QVector<int>() << 0 << 1 << 2 << 3;
mappingData.push_back(mapping);
channelResults = QVector<float>() << 4.0f << 3.0f << 2.0f << 1.0f;
- finalFrame = false;
- normalizedTime = 1.1f; // Invalid
-
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId);
- change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- change->setPropertyName(mapping.propertyName);
- change->setValue(QVariant::fromValue(QVector4D(4.0f, 3.0f, 2.0f, 1.0f)));
- expectedChanges.push_back(change);
+ expectedChanges.finalFrame = false;
+ expectedChanges.normalizedTime = 1.1f; // Invalid
+ expectedChanges.targetChanges.push_back({mapping.targetId, mapping.propertyName, QVariant::fromValue(QVector4D(4.0f, 3.0f, 2.0f, 1.0f))});
QTest::newRow("vec4 foo")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
+ << animatorId << mappingData << channelResults << expectedChanges;
mappingData.clear();
channelResults.clear();
- expectedChanges.clear();
+ expectedChanges.targetChanges.clear();
}
// Single property, quaternion
@@ -1007,22 +945,16 @@ private Q_SLOTS:
mapping.channelIndices = QVector<int>() << 0 << 1 << 2 << 3;
mappingData.push_back(mapping);
channelResults = QVector<float>() << 1.0f << 0.0f << 0.0f << 1.0f;
- finalFrame = false;
- normalizedTime = -0.1f; // Invalid
-
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId);
- change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- change->setPropertyName(mapping.propertyName);
- change->setValue(QVariant::fromValue(QQuaternion(1.0f, 0.0f, 0.0f, 1.0f).normalized()));
- expectedChanges.push_back(change);
+ expectedChanges.finalFrame = false;
+ expectedChanges.normalizedTime = -0.1f; // Invalid
+ expectedChanges.targetChanges.push_back({mapping.targetId, mapping.propertyName, QVariant::fromValue(QQuaternion(1.0f, 0.0f, 0.0f, 1.0f).normalized())});
QTest::newRow("quaternion rotation")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
+ << animatorId << mappingData << channelResults << expectedChanges;
mappingData.clear();
channelResults.clear();
- expectedChanges.clear();
+ expectedChanges.targetChanges.clear();
}
// Single property, QColor
@@ -1035,22 +967,16 @@ private Q_SLOTS:
mapping.channelIndices = QVector<int>() << 0 << 1 << 2;
mappingData.push_back(mapping);
channelResults = QVector<float>() << 0.5f << 0.4f << 0.3f;
- finalFrame = false;
- normalizedTime = 1.1f; // Invalid
-
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId);
- change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- change->setPropertyName(mapping.propertyName);
- change->setValue(QVariant::fromValue(QColor::fromRgbF(0.5f, 0.4f, 0.3f)));
- expectedChanges.push_back(change);
+ expectedChanges.finalFrame = false;
+ expectedChanges.normalizedTime = 1.1f; // Invalid
+ expectedChanges.targetChanges.push_back({mapping.targetId, mapping.propertyName, QVariant::fromValue(QColor::fromRgbF(0.5f, 0.4f, 0.3f))});
QTest::newRow("QColor color")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
+ << animatorId << mappingData << channelResults << expectedChanges;
mappingData.clear();
channelResults.clear();
- expectedChanges.clear();
+ expectedChanges.targetChanges.clear();
}
// Single property, QVariantList
@@ -1063,23 +989,17 @@ private Q_SLOTS:
mapping.channelIndices = QVector<int>() << 0 << 1 << 2 << 3 << 4 << 5 << 6;
mappingData.push_back(mapping);
channelResults = QVector<float>() << 0.5f << 0.4f << 0.3f << 0.0f << 1.0f << 0.6f << 0.9f;
- finalFrame = false;
- normalizedTime = 1.1f; // Invalid
-
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(mapping.targetId);
- change->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll);
- change->setPropertyName(mapping.propertyName);
+ expectedChanges.finalFrame = false;
+ expectedChanges.normalizedTime = 1.1f; // Invalid
QVariantList expectedValue = QVariantList() << 0.5f << 0.4f << 0.3f << 0.0f << 1.0f << 0.6f << 0.9f;
- change->setValue(QVariant::fromValue(expectedValue));
- expectedChanges.push_back(change);
+ expectedChanges.targetChanges.push_back({mapping.targetId, mapping.propertyName, QVariant::fromValue(expectedValue)});
QTest::newRow("QVariantList weights")
- << animatorId << mappingData << channelResults << normalizedTime
- << finalFrame << expectedChanges;
+ << animatorId << mappingData << channelResults << expectedChanges;
mappingData.clear();
channelResults.clear();
- expectedChanges.clear();
+ expectedChanges.targetChanges.clear();
}
}
@@ -1090,25 +1010,21 @@ private Q_SLOTS:
QFETCH(Qt3DCore::QNodeId, animatorId);
QFETCH(QVector<MappingData>, mappingData);
QFETCH(QVector<float>, channelResults);
- QFETCH(float, normalizedTime);
- QFETCH(bool, finalFrame);
- QFETCH(QVector<Qt3DCore::QPropertyUpdatedChangePtr>, expectedChanges);
+ QFETCH(AnimationRecord, expectedChanges);
// WHEN
- QVector<Qt3DCore::QSceneChangePtr> actualChanges
- = preparePropertyChanges(animatorId, mappingData, channelResults, finalFrame, normalizedTime);
+ AnimationRecord actualChanges = prepareAnimationRecord(animatorId, mappingData, channelResults,
+ expectedChanges.finalFrame, expectedChanges.normalizedTime);
// THEN
- QCOMPARE(actualChanges.size(), expectedChanges.size());
- for (int i = 0; i < actualChanges.size(); ++i) {
- auto expectedChange = expectedChanges[i];
- auto actualChange
- = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(actualChanges[i]);
-
- QCOMPARE(actualChange->subjectId(), expectedChange->subjectId());
- QCOMPARE(actualChange->deliveryFlags(), expectedChange->deliveryFlags());
- QCOMPARE(actualChange->propertyName(), expectedChange->propertyName());
- QCOMPARE(actualChange->value(), expectedChange->value());
+ QCOMPARE(actualChanges.targetChanges.size(), expectedChanges.targetChanges.size());
+ for (int i = 0; i < actualChanges.targetChanges.size(); ++i) {
+ const auto &expectedChange = expectedChanges.targetChanges[i];
+ const auto &actualChange = actualChanges.targetChanges[i];
+
+ QCOMPARE(actualChange.targetId, expectedChange.targetId);
+ QCOMPARE(actualChange.propertyName, expectedChange.propertyName);
+ QCOMPARE(actualChange.value, expectedChange.value);
}
}
diff --git a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp
index c0e1581f9..fb741050b 100644
--- a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp
+++ b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp
@@ -29,10 +29,10 @@
#include <QtTest/QTest>
#include <Qt3DAnimation/private/blendedclipanimator_p.h>
#include <Qt3DAnimation/qanimationcliploader.h>
+#include <Qt3DAnimation/qadditiveclipblend.h>
#include <Qt3DAnimation/qblendedclipanimator.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
@@ -43,7 +43,6 @@
#include <Qt3DAnimation/qchannelmapper.h>
#include <Qt3DAnimation/private/qblendedclipanimator_p.h>
#include <Qt3DAnimation/private/blendedclipanimator_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
class tst_BlendedClipAnimator : public Qt3DCore::QBackendNodeTester
@@ -114,7 +113,7 @@ private Q_SLOTS:
Qt3DAnimation::Animation::Handler handler;
backendBlendedClipAnimator.setHandler(&handler);
- simulateInitialization(&blendedClipAnimator, &backendBlendedClipAnimator);
+ simulateInitializationSync(&blendedClipAnimator, &backendBlendedClipAnimator);
// THEN
QCOMPARE(backendBlendedClipAnimator.isEnabled(), true);
@@ -131,7 +130,7 @@ private Q_SLOTS:
backendBlendedClipAnimator.setHandler(&handler);
blendedClipAnimator.setEnabled(false);
- simulateInitialization(&blendedClipAnimator, &backendBlendedClipAnimator);
+ simulateInitializationSync(&blendedClipAnimator, &backendBlendedClipAnimator);
// THEN
QCOMPARE(backendBlendedClipAnimator.peerId(), blendedClipAnimator.id());
@@ -142,61 +141,53 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DAnimation::QBlendedClipAnimator blendedClipAnimator;
Qt3DAnimation::Animation::BlendedClipAnimator backendBlendedClipAnimator;
Qt3DAnimation::Animation::Handler handler;
backendBlendedClipAnimator.setHandler(&handler);
+ simulateInitializationSync(&blendedClipAnimator, &backendBlendedClipAnimator);
{
- // WHEN
- const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendBlendedClipAnimator.sceneChangeEvent(change);
-
- // THEN
+ // WHEN
+ const bool newValue = false;
+ blendedClipAnimator.setEnabled(newValue);
+ backendBlendedClipAnimator.syncFromFrontEnd(&blendedClipAnimator, false);
+
+ // THEN
QCOMPARE(backendBlendedClipAnimator.isEnabled(), newValue);
}
{
- // WHEN
- const Qt3DCore::QNodeId newValue = Qt3DCore::QNodeId::createId();
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("blendTree");
- change->setValue(QVariant::fromValue(newValue));
- backendBlendedClipAnimator.sceneChangeEvent(change);
-
- // THEN
- QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), newValue);
+ // WHEN
+ auto blendTree = new Qt3DAnimation::QAdditiveClipBlend();
+ blendedClipAnimator.setBlendTree(blendTree);
+ backendBlendedClipAnimator.syncFromFrontEnd(&blendedClipAnimator, false);
+
+ // THEN
+ QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), blendTree->id());
}
{
- // WHEN
- const Qt3DCore::QNodeId newValue = Qt3DCore::QNodeId::createId();
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("channelMapper");
- change->setValue(QVariant::fromValue(newValue));
- backendBlendedClipAnimator.sceneChangeEvent(change);
-
- // THEN
- QCOMPARE(backendBlendedClipAnimator.mapperId(), newValue);
+ // WHEN
+ auto channelMapper = new Qt3DAnimation::QChannelMapper();
+ blendedClipAnimator.setChannelMapper(channelMapper);
+ backendBlendedClipAnimator.syncFromFrontEnd(&blendedClipAnimator, false);
+
+ // THEN
+ QCOMPARE(backendBlendedClipAnimator.mapperId(), channelMapper->id());
}
{
- // WHEN
- const bool newValue = true;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("running");
- change->setValue(QVariant::fromValue(newValue));
- backendBlendedClipAnimator.sceneChangeEvent(change);
-
- // THEN
+ // WHEN
+ const bool newValue = true;
+ blendedClipAnimator.setRunning(newValue);
+ backendBlendedClipAnimator.syncFromFrontEnd(&blendedClipAnimator, false);
+
+ // THEN
QCOMPARE(backendBlendedClipAnimator.isRunning(), newValue);
}
{
// WHEN
const int newValue = 883;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("loops");
- change->setValue(QVariant::fromValue(newValue));
- backendBlendedClipAnimator.sceneChangeEvent(change);
+ blendedClipAnimator.setLoopCount(newValue);
+ backendBlendedClipAnimator.syncFromFrontEnd(&blendedClipAnimator, false);
// THEN
QCOMPARE(backendBlendedClipAnimator.loops(), newValue);
diff --git a/tests/auto/animation/channelmapper/tst_channelmapper.cpp b/tests/auto/animation/channelmapper/tst_channelmapper.cpp
index 446e1a0c5..ad9f3c423 100644
--- a/tests/auto/animation/channelmapper/tst_channelmapper.cpp
+++ b/tests/auto/animation/channelmapper/tst_channelmapper.cpp
@@ -37,9 +37,6 @@
#include <Qt3DAnimation/private/qchannelmapper_p.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include "testpostmanarbiter.h"
@@ -60,7 +57,7 @@ private Q_SLOTS:
mapper.addMapping(new Qt3DAnimation::QChannelMapping);
// WHEN
- simulateInitialization(&mapper, &backendMapper);
+ simulateInitializationSync(&mapper, &backendMapper);
// THEN
QCOMPARE(backendMapper.peerId(), mapper.id());
@@ -90,7 +87,7 @@ private Q_SLOTS:
mapper.addMapping(new Qt3DAnimation::QChannelMapping());
// WHEN
- simulateInitialization(&mapper, &backendMapper);
+ simulateInitializationSync(&mapper, &backendMapper);
backendMapper.cleanup();
// THEN
@@ -101,19 +98,18 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DAnimation::QChannelMapper mapper;
Qt3DAnimation::Animation::Handler handler;
Qt3DAnimation::Animation::ChannelMapper backendMapper;
backendMapper.setHandler(&handler);
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
+ simulateInitializationSync(&mapper, &backendMapper);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendMapper.sceneChangeEvent(updateChange);
+ mapper.setEnabled(false);
+ backendMapper.syncFromFrontEnd(&mapper, false);
// THEN
- QCOMPARE(backendMapper.isEnabled(), true);
+ QCOMPARE(backendMapper.isEnabled(), false);
// WHEN
Qt3DAnimation::QChannelMapping mapping;
@@ -121,11 +117,10 @@ private Q_SLOTS:
Qt3DAnimation::Animation::ChannelMapping *backendMapping
= handler.channelMappingManager()->getOrCreateResource(mappingId);
backendMapping->setHandler(&handler);
- simulateInitialization(&mapping, backendMapping);
+ simulateInitializationSync(&mapping, backendMapping);
- auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping);
- nodeAddedChange->setPropertyName("mappings");
- backendMapper.sceneChangeEvent(nodeAddedChange);
+ mapper.addMapping(&mapping);
+ backendMapper.syncFromFrontEnd(&mapper, false);
// THEN
QCOMPARE(backendMapper.mappingIds().size(), 1);
@@ -139,11 +134,10 @@ private Q_SLOTS:
Qt3DAnimation::Animation::ChannelMapping *backendMapping2
= handler.channelMappingManager()->getOrCreateResource(mappingId2);
backendMapping2->setHandler(&handler);
- simulateInitialization(&mapping2, backendMapping2);
+ simulateInitializationSync(&mapping2, backendMapping2);
- nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &mapping2);
- nodeAddedChange->setPropertyName("mappings");
- backendMapper.sceneChangeEvent(nodeAddedChange);
+ mapper.addMapping(&mapping2);
+ backendMapper.syncFromFrontEnd(&mapper, false);
// THEN
QCOMPARE(backendMapper.mappingIds().size(), 2);
@@ -154,9 +148,8 @@ private Q_SLOTS:
QCOMPARE(backendMapper.mappings().last(), backendMapping2);
// WHEN
- const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &mapping);
- nodeRemovedChange->setPropertyName("mappings");
- backendMapper.sceneChangeEvent(nodeRemovedChange);
+ mapper.removeMapping(&mapping);
+ backendMapper.syncFromFrontEnd(&mapper, false);
// THEN
QCOMPARE(backendMapper.mappingIds().size(), 1);
diff --git a/tests/auto/animation/channelmapping/tst_channelmapping.cpp b/tests/auto/animation/channelmapping/tst_channelmapping.cpp
index 35ffcb10a..26a57449d 100644
--- a/tests/auto/animation/channelmapping/tst_channelmapping.cpp
+++ b/tests/auto/animation/channelmapping/tst_channelmapping.cpp
@@ -34,10 +34,10 @@
#include <Qt3DAnimation/qskeletonmapping.h>
#include <Qt3DAnimation/private/qchannelmapping_p.h>
#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/qskeleton.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include "testpostmanarbiter.h"
@@ -72,7 +72,7 @@ private Q_SLOTS:
mapping.setProperty(QLatin1String("foo"));
// WHEN
- simulateInitialization(&mapping, &backendMapping);
+ simulateInitializationSync(&mapping, &backendMapping);
// THEN
QCOMPARE(backendMapping.peerId(), mapping.id());
@@ -93,7 +93,7 @@ private Q_SLOTS:
skeletonMapping.setSkeleton(skeleton);
// WHEN
- simulateInitialization(&skeletonMapping, &backendSkeletonMapping);
+ simulateInitializationSync(&skeletonMapping, &backendSkeletonMapping);
// THEN
QCOMPARE(backendSkeletonMapping.peerId(), skeletonMapping.id());
@@ -128,7 +128,7 @@ private Q_SLOTS:
mapping.setProperty(QLatin1String("foo"));
// WHEN
- simulateInitialization(&mapping, &backendMapping);
+ simulateInitializationSync(&mapping, &backendMapping);
backendMapping.setSkeletonId(Qt3DCore::QNodeId::createId());
backendMapping.cleanup();
@@ -146,77 +146,65 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DAnimation::QChannelMapping mapping;
Qt3DAnimation::Animation::Handler handler;
Qt3DAnimation::Animation::ChannelMapping backendMapping;
backendMapping.setHandler(&handler);
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
+ simulateInitializationSync(&mapping, &backendMapping);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendMapping.sceneChangeEvent(updateChange);
+ mapping.setEnabled(false);
+ backendMapping.syncFromFrontEnd(&mapping, false);
// THEN
- QCOMPARE(backendMapping.isEnabled(), true);
+ QCOMPARE(backendMapping.isEnabled(), false);
// WHEN
- const QString channelName(QLatin1String("Rotation"));
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("channelName");
- updateChange->setValue(channelName);
- backendMapping.sceneChangeEvent(updateChange);
+ const QString channelName(QLatin1String("Translation"));
+ mapping.setChannelName(channelName);
+ backendMapping.syncFromFrontEnd(&mapping, false);
// THEN
QCOMPARE(backendMapping.channelName(), channelName);
// WHEN
- const auto id = Qt3DCore::QNodeId::createId();
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("target");
- updateChange->setValue(QVariant::fromValue(id));
- backendMapping.sceneChangeEvent(updateChange);
-
- // THEN
- QCOMPARE(backendMapping.targetId(), id);
-
- // WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("type");
- updateChange->setValue(QVariant(static_cast<int>(QVariant::Vector3D)));
- backendMapping.sceneChangeEvent(updateChange);
+ const auto target = new Qt3DCore::QTransform();
+ mapping.setTarget(target);
+ mapping.setProperty("translation");
+ backendMapping.syncFromFrontEnd(&mapping, false);
// THEN
+ QCOMPARE(backendMapping.targetId(), target->id());
QCOMPARE(backendMapping.type(), static_cast<int>(QVariant::Vector3D));
+ QCOMPARE(backendMapping.componentCount(), 3);
- // WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("componentCount");
- updateChange->setValue(4);
- backendMapping.sceneChangeEvent(updateChange);
+ const char *testName = "translation";
+ QCOMPARE(qstrcmp(testName, backendMapping.propertyName()), 0);
+ }
- // THEN
- QCOMPARE(backendMapping.componentCount(), 4);
+ void checkSkeletonPropertyUpdate()
+ {
+ // GIVEN
+ Qt3DAnimation::QSkeletonMapping mapping;
+ Qt3DAnimation::Animation::Handler handler;
+ Qt3DAnimation::Animation::ChannelMapping backendMapping;
+ backendMapping.setHandler(&handler);
+ simulateInitializationSync(&mapping, &backendMapping);
// WHEN
- const char *testName = "883";
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("propertyName");
- updateChange->setValue(QVariant::fromValue(reinterpret_cast<void *>(const_cast<char *>(testName))));
- backendMapping.sceneChangeEvent(updateChange);
+ mapping.setEnabled(false);
+ backendMapping.syncFromFrontEnd(&mapping, false);
// THEN
- QCOMPARE(backendMapping.propertyName(), testName);
+ QCOMPARE(backendMapping.isEnabled(), false);
// WHEN
- const auto skeletonId = Qt3DCore::QNodeId::createId();
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("skeleton");
- updateChange->setValue(QVariant::fromValue(skeletonId));
- backendMapping.sceneChangeEvent(updateChange);
+ auto skeleton = new Qt3DCore::QSkeleton;
+ mapping.setSkeleton(skeleton);
+ backendMapping.syncFromFrontEnd(&mapping, false);
// THEN
- QCOMPARE(backendMapping.skeletonId(), skeletonId);
+ QCOMPARE(backendMapping.skeletonId(), skeleton->id());
}
};
diff --git a/tests/auto/animation/clipanimator/tst_clipanimator.cpp b/tests/auto/animation/clipanimator/tst_clipanimator.cpp
index 0272bcfaa..5eccb0432 100644
--- a/tests/auto/animation/clipanimator/tst_clipanimator.cpp
+++ b/tests/auto/animation/clipanimator/tst_clipanimator.cpp
@@ -29,11 +29,11 @@
#include <QtTest/QTest>
#include <Qt3DAnimation/private/clipanimator_p.h>
#include <Qt3DAnimation/qanimationcliploader.h>
+#include <Qt3DAnimation/qchannelmapper.h>
#include <Qt3DAnimation/qclipanimator.h>
#include <Qt3DAnimation/qclock.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
@@ -59,7 +59,7 @@ private Q_SLOTS:
animator.setNormalizedTime(0.5f);
// WHEN
- simulateInitialization(&animator, &backendAnimator);
+ simulateInitializationSync(&animator, &backendAnimator);
// THEN
QCOMPARE(backendAnimator.peerId(), animator.id());
@@ -98,7 +98,7 @@ private Q_SLOTS:
animator.setNormalizedTime(1.0f);
// WHEN
- simulateInitialization(&animator, &backendAnimator);
+ simulateInitializationSync(&animator, &backendAnimator);
backendAnimator.setClipId(Qt3DCore::QNodeId::createId());
backendAnimator.setClockId(Qt3DCore::QNodeId::createId());
backendAnimator.cleanup();
@@ -115,63 +115,60 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DAnimation::QClipAnimator animator;
Qt3DAnimation::Animation::Handler handler;
Qt3DAnimation::Animation::ClipAnimator backendAnimator;
backendAnimator.setHandler(&handler);
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
+ simulateInitializationSync(&animator, &backendAnimator);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendAnimator.sceneChangeEvent(updateChange);
+ animator.setEnabled(false);
+ backendAnimator.syncFromFrontEnd(&animator, false);
// THEN
- QCOMPARE(backendAnimator.isEnabled(), true);
+ QCOMPARE(backendAnimator.isEnabled(), false);
// WHEN
auto newClip = new Qt3DAnimation::QAnimationClipLoader();
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("clip");
- updateChange->setValue(QVariant::fromValue(newClip->id()));
- backendAnimator.sceneChangeEvent(updateChange);
+ animator.setClip(newClip);
+ backendAnimator.syncFromFrontEnd(&animator, false);
// THEN
QCOMPARE(backendAnimator.clipId(), newClip->id());
// WHEN
+ auto newMapper = new Qt3DAnimation::QChannelMapper();
+ animator.setChannelMapper(newMapper);
+ backendAnimator.syncFromFrontEnd(&animator, false);
+
+ // THEN
+ QCOMPARE(backendAnimator.mapperId(), newMapper->id());
+
+ // WHEN
auto clock = new Qt3DAnimation::QClock();
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("clock");
- updateChange->setValue(QVariant::fromValue(clock->id()));
- backendAnimator.sceneChangeEvent(updateChange);
+ animator.setClock(clock);
+ backendAnimator.syncFromFrontEnd(&animator, false);
// THEN
QCOMPARE(backendAnimator.clockId(), clock->id());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("running");
- updateChange->setValue(true);
- backendAnimator.sceneChangeEvent(updateChange);
+ animator.setRunning(true);
+ backendAnimator.syncFromFrontEnd(&animator, false);
// THEN
QCOMPARE(backendAnimator.isRunning(), true);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("loops");
- updateChange->setValue(64);
- backendAnimator.sceneChangeEvent(updateChange);
+ animator.setLoopCount(64);
+ backendAnimator.syncFromFrontEnd(&animator, false);
// THEN
QCOMPARE(backendAnimator.loops(), 64);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("normalizedTime");
- updateChange->setValue(0.5f);
- backendAnimator.sceneChangeEvent(updateChange);
+ animator.setNormalizedTime(0.5f);
+ backendAnimator.syncFromFrontEnd(&animator, false);
// THEN
QVERIFY(qFuzzyCompare(backendAnimator.normalizedLocalTime(), 0.5f));
diff --git a/tests/auto/animation/clipblendnode/tst_clipblendnode.cpp b/tests/auto/animation/clipblendnode/tst_clipblendnode.cpp
index dab6e698d..c8649a692 100644
--- a/tests/auto/animation/clipblendnode/tst_clipblendnode.cpp
+++ b/tests/auto/animation/clipblendnode/tst_clipblendnode.cpp
@@ -33,10 +33,6 @@
#include <Qt3DAnimation/private/qabstractclipblendnode_p.h>
#include <Qt3DAnimation/private/clipblendnode_p.h>
#include <Qt3DAnimation/private/managers_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include "qbackendnodetester.h"
#include <random>
diff --git a/tests/auto/animation/clipblendnodevisitor/tst_clipblendnodevisitor.cpp b/tests/auto/animation/clipblendnodevisitor/tst_clipblendnodevisitor.cpp
index 3f705e713..54de87b1e 100644
--- a/tests/auto/animation/clipblendnodevisitor/tst_clipblendnodevisitor.cpp
+++ b/tests/auto/animation/clipblendnodevisitor/tst_clipblendnodevisitor.cpp
@@ -73,11 +73,11 @@ private Q_SLOTS:
manager.appendNode(childBlendNode12.id(), backendChildBlendNode12);
// WHEN
- simulateInitialization(&rootBlendNode, backendRootBlendNode);
- simulateInitialization(&childBlendNode1, backendChildBlendNode1);
- simulateInitialization(&childBlendNode2, backendChildBlendNode2);
- simulateInitialization(&childBlendNode11, backendChildBlendNode11);
- simulateInitialization(&childBlendNode12, backendChildBlendNode12);
+ simulateInitializationSync(&rootBlendNode, backendRootBlendNode);
+ simulateInitializationSync(&childBlendNode1, backendChildBlendNode1);
+ simulateInitializationSync(&childBlendNode2, backendChildBlendNode2);
+ simulateInitializationSync(&childBlendNode11, backendChildBlendNode11);
+ simulateInitializationSync(&childBlendNode12, backendChildBlendNode12);
// THEN
QCOMPARE(backendRootBlendNode->allDependencyIds().size(), 2);
@@ -121,7 +121,7 @@ private Q_SLOTS:
// We purposely forgot the to do: manager.appendNode(rootBlendNode.id(), backendRootBlendNode);
// WHEN
- simulateInitialization(&rootBlendNode, backendRootBlendNode);
+ simulateInitializationSync(&rootBlendNode, backendRootBlendNode);
// THEN
QCOMPARE(backendRootBlendNode->allDependencyIds().size(), 2);
@@ -159,9 +159,9 @@ private Q_SLOTS:
// WHEN
- simulateInitialization(&rootBlendNode, backendRootBlendNode);
- simulateInitialization(&childBlendNode1, backendChildBlendNode1);
- simulateInitialization(&childBlendNode2, backendChildBlendNode2);
+ simulateInitializationSync(&rootBlendNode, backendRootBlendNode);
+ simulateInitializationSync(&childBlendNode1, backendChildBlendNode1);
+ simulateInitializationSync(&childBlendNode2, backendChildBlendNode2);
// THEN
QCOMPARE(backendRootBlendNode->allDependencyIds().size(), 2);
diff --git a/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp
index 197378094..75d1ab57f 100644
--- a/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp
+++ b/tests/auto/animation/clipblendvalue/tst_clipblendvalue.cpp
@@ -32,7 +32,6 @@
#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/private/qclipblendvalue_p.h>
#include <Qt3DAnimation/private/clipblendvalue_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include <random>
@@ -80,7 +79,7 @@ private Q_SLOTS:
{
// WHEN
ClipBlendValue backendClipBlendValue;
- simulateInitialization(&clipBlendValue, &backendClipBlendValue);
+ simulateInitializationSync(&clipBlendValue, &backendClipBlendValue);
// THEN
QCOMPARE(backendClipBlendValue.isEnabled(), true);
@@ -91,7 +90,7 @@ private Q_SLOTS:
// WHEN
ClipBlendValue backendClipBlendValue;
clipBlendValue.setEnabled(false);
- simulateInitialization(&clipBlendValue, &backendClipBlendValue);
+ simulateInitializationSync(&clipBlendValue, &backendClipBlendValue);
// THEN
QCOMPARE(backendClipBlendValue.peerId(), clipBlendValue.id());
@@ -102,25 +101,23 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DAnimation::QClipBlendValue clipBlendValue;
ClipBlendValue backendClipBlendValue;
+ simulateInitializationSync(&clipBlendValue, &backendClipBlendValue);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendClipBlendValue.sceneChangeEvent(change);
+ clipBlendValue.setEnabled(newValue);
+ backendClipBlendValue.syncFromFrontEnd(&clipBlendValue, false);
// THEN
QCOMPARE(backendClipBlendValue.isEnabled(), newValue);
}
{
// WHEN
- const Qt3DAnimation::QAnimationClipLoader newValue;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("clip");
- change->setValue(QVariant::fromValue(newValue.id()));
- backendClipBlendValue.sceneChangeEvent(change);
+ Qt3DAnimation::QAnimationClipLoader newValue;
+ clipBlendValue.setClip(&newValue);
+ backendClipBlendValue.syncFromFrontEnd(&clipBlendValue, false);
// THEN
QCOMPARE(backendClipBlendValue.clipId(), newValue.id());
diff --git a/tests/auto/animation/clock/tst_clock.cpp b/tests/auto/animation/clock/tst_clock.cpp
index a81adfe7b..03be85613 100644
--- a/tests/auto/animation/clock/tst_clock.cpp
+++ b/tests/auto/animation/clock/tst_clock.cpp
@@ -31,7 +31,6 @@
#include <Qt3DAnimation/private/clock_p.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
@@ -50,7 +49,7 @@ private Q_SLOTS:
clock.setPlaybackRate(10.5);
// WHEN
- simulateInitialization(&clock, &backendClock);
+ simulateInitializationSync(&clock, &backendClock);
// THEN
QCOMPARE(backendClock.playbackRate(), clock.playbackRate());
@@ -69,7 +68,7 @@ private Q_SLOTS:
clock.setPlaybackRate(10.5);
// WHEN
- simulateInitialization(&clock, &backendClock);
+ simulateInitializationSync(&clock, &backendClock);
backendClock.cleanup();
// THEN
@@ -79,15 +78,15 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DAnimation::QClock clock;
Qt3DAnimation::Animation::Clock backendClock;
+ simulateInitializationSync(&clock, &backendClock);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendClock.sceneChangeEvent(change);
+ clock.setEnabled(newValue);
+ backendClock.syncFromFrontEnd(&clock, false);
// THEN
QCOMPARE(backendClock.isEnabled(), newValue);
@@ -95,10 +94,8 @@ private Q_SLOTS:
{
// WHEN
const double newPlaybackRateValue = 2.0;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("playbackRate");
- change->setValue(newPlaybackRateValue);
- backendClock.sceneChangeEvent(change);
+ clock.setPlaybackRate(newPlaybackRateValue);
+ backendClock.syncFromFrontEnd(&clock, false);
// THEN
QCOMPARE(backendClock.playbackRate(), newPlaybackRateValue);
diff --git a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp
index 5d71b7dc6..baebf8e46 100644
--- a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp
+++ b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp
@@ -39,7 +39,6 @@
#include <Qt3DAnimation/private/managers_p.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
diff --git a/tests/auto/animation/lerpclipblend/tst_lerpclipblend.cpp b/tests/auto/animation/lerpclipblend/tst_lerpclipblend.cpp
index e75c4f2f8..29c982253 100644
--- a/tests/auto/animation/lerpclipblend/tst_lerpclipblend.cpp
+++ b/tests/auto/animation/lerpclipblend/tst_lerpclipblend.cpp
@@ -32,7 +32,6 @@
#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/private/qlerpclipblend_p.h>
#include <Qt3DAnimation/private/lerpclipblend_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
using namespace Qt3DAnimation::Animation;
@@ -137,7 +136,7 @@ private Q_SLOTS:
{
// WHEN
LerpClipBlend backendLerpBlend;
- simulateInitialization(&lerpBlend, &backendLerpBlend);
+ simulateInitializationSync(&lerpBlend, &backendLerpBlend);
// THEN
QCOMPARE(backendLerpBlend.isEnabled(), true);
@@ -148,7 +147,7 @@ private Q_SLOTS:
// WHEN
LerpClipBlend backendLerpBlend;
lerpBlend.setEnabled(false);
- simulateInitialization(&lerpBlend, &backendLerpBlend);
+ simulateInitializationSync(&lerpBlend, &backendLerpBlend);
// THEN
QCOMPARE(backendLerpBlend.peerId(), lerpBlend.id());
@@ -159,27 +158,26 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DAnimation::QLerpClipBlend lerpBlend;
LerpClipBlend backendLerpBlend;
+ simulateInitializationSync(&lerpBlend, &backendLerpBlend);
+
{
- // WHEN
- const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendLerpBlend.sceneChangeEvent(change);
-
- // THEN
+ // WHEN
+ const bool newValue = false;
+ lerpBlend.setEnabled(newValue);
+ backendLerpBlend.syncFromFrontEnd(&lerpBlend, false);
+
+ // THEN
QCOMPARE(backendLerpBlend.isEnabled(), newValue);
}
{
- // WHEN
- const float newValue = 0.883f;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("blendFactor");
- change->setValue(QVariant::fromValue(newValue));
- backendLerpBlend.sceneChangeEvent(change);
-
- // THEN
+ // WHEN
+ const float newValue = 0.883f;
+ lerpBlend.setBlendFactor(newValue);
+ backendLerpBlend.syncFromFrontEnd(&lerpBlend, false);
+
+ // THEN
QCOMPARE(backendLerpBlend.blendFactor(), newValue);
}
}
diff --git a/tests/auto/animation/qadditiveclipblend/tst_qadditiveclipblend.cpp b/tests/auto/animation/qadditiveclipblend/tst_qadditiveclipblend.cpp
index c1f01394f..41f6b268a 100644
--- a/tests/auto/animation/qadditiveclipblend/tst_qadditiveclipblend.cpp
+++ b/tests/auto/animation/qadditiveclipblend/tst_qadditiveclipblend.cpp
@@ -33,7 +33,6 @@
#include <Qt3DAnimation/private/qadditiveclipblend_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
@@ -197,25 +196,22 @@ private Q_SLOTS:
{
// WHEN
addBlend.setAdditiveFactor(0.4f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "additiveFactor");
- QCOMPARE(change->value().value<float>(), addBlend.additiveFactor());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &addBlend);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
addBlend.setAdditiveFactor(0.4f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -231,25 +227,22 @@ private Q_SLOTS:
{
// WHEN
addBlend.setBaseClip(baseClip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "baseClip");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), addBlend.baseClip()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &addBlend);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
addBlend.setBaseClip(baseClip);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -264,25 +257,21 @@ private Q_SLOTS:
{
// WHEN
addBlend.setAdditiveClip(additiveClip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "additiveClip");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), addBlend.additiveClip()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &addBlend);
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
addBlend.setAdditiveClip(additiveClip);
- QCoreApplication::processEvents();
- // THEN
+ //
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp b/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp
index 968ad8764..00130add3 100644
--- a/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp
+++ b/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp
@@ -30,7 +30,6 @@
#include <QtTest/QTest>
#include <Qt3DAnimation/qanimationcliploader.h>
#include <Qt3DAnimation/private/qanimationcliploader_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <QObject>
@@ -139,60 +138,25 @@ private Q_SLOTS:
{
// WHEN
clip.setSource(QUrl(QStringLiteral("qrc:/toyplane.qlip")));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "source");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &clip);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
clip.setSource(QStringLiteral("qrc:/toyplane.qlip"));
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
-
- void checkStatusPropertyUpdate()
- {
- // GIVEN
- qRegisterMetaType<Qt3DAnimation::QAnimationClipLoader::Status>("Status");
- TestArbiter arbiter;
- arbiter.setArbiterOnNode(this);
- QSignalSpy spy(this, SIGNAL(statusChanged(Status)));
- const Qt3DAnimation::QAnimationClipLoader::Status newStatus = Qt3DAnimation::QAnimationClipLoader::Error;
-
- // THEN
- QVERIFY(spy.isValid());
-
- // WHEN
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("status");
- valueChange->setValue(QVariant::fromValue(newStatus));
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 1);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(status(), newStatus);
-
- // WHEN
- spy.clear();
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 0);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(status(), newStatus);
- }
};
QTEST_MAIN(tst_QAnimationClipLoader)
diff --git a/tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp b/tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp
index 56be94472..81222292f 100644
--- a/tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp
+++ b/tests/auto/animation/qblendedclipanimator/tst_qblendedclipanimator.cpp
@@ -32,7 +32,6 @@
#include <Qt3DAnimation/private/qblendedclipanimator_p.h>
#include <Qt3DAnimation/qlerpclipblend.h>
#include <Qt3DAnimation/qchannelmapper.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <QObject>
@@ -261,25 +260,22 @@ private Q_SLOTS:
{
// WHEN
blendedClipAnimator.setBlendTree(&blendRoot);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "blendTree");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), blendRoot.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
blendedClipAnimator.setBlendTree(&blendRoot);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -312,25 +308,22 @@ private Q_SLOTS:
{
// WHEN
blendedClipAnimator.setChannelMapper(&channelMapper);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "channelMapper");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), channelMapper.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
blendedClipAnimator.setChannelMapper(&channelMapper);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -362,25 +355,22 @@ private Q_SLOTS:
{
// WHEN
blendedClipAnimator.setRunning(true);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "running");
- QCOMPARE(change->value().value<bool>(), blendedClipAnimator.isRunning());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
blendedClipAnimator.setRunning(true);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -395,25 +385,22 @@ private Q_SLOTS:
{
// WHEN
blendedClipAnimator.setLoopCount(1584);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "loops");
- QCOMPARE(change->value().value<int>(), blendedClipAnimator.loopCount());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
blendedClipAnimator.setLoopCount(1584);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -428,25 +415,22 @@ private Q_SLOTS:
{
// WHEN
blendedClipAnimator.setNormalizedTime(0.5f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "normalizedTime");
- QCOMPARE(change->value().value<float>(), blendedClipAnimator.normalizedTime());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &blendedClipAnimator);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
blendedClipAnimator.setNormalizedTime(0.5f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp
index 78dff8b64..fe1a2eda8 100644
--- a/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp
+++ b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp
@@ -30,7 +30,6 @@
#include <Qt3DAnimation/qcallbackmapping.h>
#include <Qt3DAnimation/private/qcallbackmapping_p.h>
#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
@@ -164,23 +163,18 @@ private Q_SLOTS:
{
// WHEN
mapping.setChannelName(QStringLiteral("Scale"));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "channelName");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toString(), mapping.channelName());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mapping);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
mapping.setChannelName(QStringLiteral("Scale"));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
{
@@ -190,23 +184,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 3);
- auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "type");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toInt(), int(QVariant::Vector3D));
-
- change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "callback");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(reinterpret_cast<DummyCallback *>(change->value().value<void *>()), callback);
-
- change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "callbackFlags");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toInt(), static_cast<int>(Qt3DAnimation::QAnimationCallback::OnThreadPool));
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mapping);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
mapping.setCallback(QVariant::Vector3D, callback, Qt3DAnimation::QAnimationCallback::OnThreadPool);
@@ -214,6 +196,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
};
diff --git a/tests/auto/animation/qchannelmapper/tst_qchannelmapper.cpp b/tests/auto/animation/qchannelmapper/tst_qchannelmapper.cpp
index bbc27fa41..a55a509b2 100644
--- a/tests/auto/animation/qchannelmapper/tst_qchannelmapper.cpp
+++ b/tests/auto/animation/qchannelmapper/tst_qchannelmapper.cpp
@@ -35,10 +35,6 @@
#include <Qt3DAnimation/private/qchannelmapper_p.h>
#include <Qt3DAnimation/qchannelmapping.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
-
#include "testpostmanarbiter.h"
class tst_QChannelmapper : public Qt3DAnimation::QChannelMapper
@@ -102,16 +98,12 @@ private Q_SLOTS:
// WHEN
mapper->setEnabled(false);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr propertyChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(propertyChange->propertyName(), "enabled");
- QCOMPARE(propertyChange->value().toBool(), mapper->isEnabled());
- QCOMPARE(propertyChange->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), mapper.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkMappingBookkeeping()
diff --git a/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp b/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp
index a6e4e5eb8..749bc5ec7 100644
--- a/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp
+++ b/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp
@@ -31,7 +31,6 @@
#include <Qt3DAnimation/private/qabstractchannelmapping_p.h>
#include <Qt3DAnimation/private/qchannelmapping_p.h>
#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
@@ -246,45 +245,35 @@ private Q_SLOTS:
{
// WHEN
mapping.setChannelName(QStringLiteral("Scale"));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "channelName");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toString(), mapping.channelName());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mapping);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
mapping.setChannelName(QStringLiteral("Scale"));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
{
// WHEN
mapping.setTarget(target.data());
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "target");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), mapping.target()->id());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mapping);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
mapping.setTarget(target.data());
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
{
@@ -294,24 +283,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 3);
-
- auto change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "type");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toInt(), static_cast<int>(QVariant::Vector3D));
-
- change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "componentCount");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toInt(), 3);
-
- change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "propertyName");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QVERIFY(qstrcmp(reinterpret_cast<const char *>(change->value().value<void *>()), "scale") == 0);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mapping);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
mapping.setProperty(QStringLiteral("scale"));
@@ -319,6 +295,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -350,6 +327,9 @@ private Q_SLOTS:
QFETCH(int, expectedType);
QFETCH(int, expectedComponentCount);
+ Q_UNUSED(expectedType)
+ Q_UNUSED(expectedComponentCount)
+
TestArbiter arbiter;
Qt3DAnimation::QChannelMapping mapping;
QScopedPointer<Qt3DCore::QEntity> target(new tst_QTargetEntity());
@@ -359,41 +339,18 @@ private Q_SLOTS:
{
// WHEN
target->setProperty(propertyName.constData(), value);
- mapping.setProperty(QString::fromLatin1(propertyName));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 4);
-
- // Automatic notification change when property is updated
- auto change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), propertyName.constData());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value(), value);
-
- change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "type");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toInt(), expectedType);
-
- change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "componentCount");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toInt(), expectedComponentCount);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), target.data());
- change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "propertyName");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QVERIFY(qstrcmp(reinterpret_cast<const char *>(change->value().value<void *>()), propertyName.constData()) == 0);
+ arbiter.dirtyNodes.clear();
- arbiter.events.clear();
-
- // WHEN
+ // THEN
mapping.setProperty(QString::fromLatin1(propertyName));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
}
}
diff --git a/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp b/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp
index 0b28228d9..174cd6bce 100644
--- a/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp
+++ b/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp
@@ -34,7 +34,6 @@
#include <Qt3DAnimation/qclipanimator.h>
#include <Qt3DAnimation/private/qanimationclip_p.h>
#include <Qt3DAnimation/private/qclipanimator_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <QObject>
@@ -248,25 +247,20 @@ private Q_SLOTS:
{
// WHEN
animator.setClip(clip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "clip");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), clip->id());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &animator);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
animator.setClip(clip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
// GIVEN
@@ -274,25 +268,20 @@ private Q_SLOTS:
{
// WHEN
animator.setChannelMapper(mapper);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "channelMapper");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), mapper->id());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &animator);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
animator.setChannelMapper(mapper);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
// GIVEN
@@ -300,49 +289,39 @@ private Q_SLOTS:
{
// WHEN
animator.setClock(clock);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "clock");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), clock->id());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &animator);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
animator.setClock(clock);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
{
// WHEN
animator.setLoopCount(10);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "loops");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toInt(), animator.loopCount());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &animator);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
animator.setLoopCount(10);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/animation/qclipblendvalue/tst_qclipblendvalue.cpp b/tests/auto/animation/qclipblendvalue/tst_qclipblendvalue.cpp
index bdbee9380..b7e4f453b 100644
--- a/tests/auto/animation/qclipblendvalue/tst_qclipblendvalue.cpp
+++ b/tests/auto/animation/qclipblendvalue/tst_qclipblendvalue.cpp
@@ -33,7 +33,6 @@
#include <Qt3DAnimation/private/qclipblendvalue_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
@@ -148,25 +147,20 @@ private Q_SLOTS:
{
// WHEN
clipBlendNode.setClip(clip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "clip");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), clipBlendNode.clip()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &clipBlendNode);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
clipBlendNode.setClip(clip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/animation/qclock/tst_qclock.cpp b/tests/auto/animation/qclock/tst_qclock.cpp
index 34c70da7b..65c485566 100644
--- a/tests/auto/animation/qclock/tst_qclock.cpp
+++ b/tests/auto/animation/qclock/tst_qclock.cpp
@@ -30,7 +30,6 @@
#include <QtTest/QTest>
#include <Qt3DAnimation/qclock.h>
#include <Qt3DAnimation/private/qclock_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <QObject>
@@ -136,26 +135,21 @@ private Q_SLOTS:
{
// WHEN
- clock.setPlaybackRate(10.5);
- QCoreApplication::processEvents();
+ clock.setPlaybackRate(10.5f);
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "playbackRate");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<double>(), clock.playbackRate());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &clock);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
clock.setPlaybackRate(10.5f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
};
diff --git a/tests/auto/animation/qlerpclipblend/tst_qlerpclipblend.cpp b/tests/auto/animation/qlerpclipblend/tst_qlerpclipblend.cpp
index 057f37786..68970838c 100644
--- a/tests/auto/animation/qlerpclipblend/tst_qlerpclipblend.cpp
+++ b/tests/auto/animation/qlerpclipblend/tst_qlerpclipblend.cpp
@@ -33,7 +33,6 @@
#include <Qt3DAnimation/private/qlerpclipblend_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DAnimation/qclipblendnodecreatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
@@ -197,25 +196,20 @@ private Q_SLOTS:
{
// WHEN
lerpBlend.setBlendFactor(0.4f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "blendFactor");
- QCOMPARE(change->value().value<float>(), lerpBlend.blendFactor());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &lerpBlend);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
lerpBlend.setBlendFactor(0.4f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -231,25 +225,20 @@ private Q_SLOTS:
{
// WHEN
lerpBlend.setStartClip(startClip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "startClip");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), lerpBlend.startClip()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &lerpBlend);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
lerpBlend.setStartClip(startClip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -264,25 +253,20 @@ private Q_SLOTS:
{
// WHEN
lerpBlend.setEndClip(endClip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "endClip");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), lerpBlend.endClip()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &lerpBlend);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
lerpBlend.setEndClip(endClip);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp b/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp
index 452292e9e..1eff6a568 100644
--- a/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp
+++ b/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp
@@ -30,7 +30,6 @@
#include <Qt3DAnimation/qskeletonmapping.h>
#include <Qt3DAnimation/private/qskeletonmapping_p.h>
#include <Qt3DCore/qskeleton.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
@@ -149,23 +148,18 @@ private Q_SLOTS:
// WHEN
auto target = new Qt3DCore::QSkeleton();
mapping.setSkeleton(target);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "skeleton");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), mapping.skeleton()->id());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mapping);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
mapping.setSkeleton(target);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
};
diff --git a/tests/auto/animation/skeleton/tst_skeleton.cpp b/tests/auto/animation/skeleton/tst_skeleton.cpp
index 9116be199..d9b209194 100644
--- a/tests/auto/animation/skeleton/tst_skeleton.cpp
+++ b/tests/auto/animation/skeleton/tst_skeleton.cpp
@@ -32,7 +32,6 @@
#include <Qt3DAnimation/private/skeleton_p.h>
#include <Qt3DAnimation/private/handler_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
@@ -63,7 +62,7 @@ private Q_SLOTS:
skeleton.setRootJoint(rootJoint);
// WHEN
- simulateInitialization(&skeleton, &backendSkeleton);
+ simulateInitializationSync(&skeleton, &backendSkeleton);
// THEN - nothing mirrored from frontend
QCOMPARE(backendSkeleton.peerId(), skeleton.id());
@@ -127,37 +126,15 @@ private Q_SLOTS:
Handler handler;
Skeleton backendSkeleton;
backendSkeleton.setHandler(&handler);
- QPropertyUpdatedChangePtr updateChange;
-
- // WHEN
- updateChange = QPropertyUpdatedChangePtr::create(QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendSkeleton.sceneChangeEvent(updateChange);
-
- // THEN
- QCOMPARE(backendSkeleton.isEnabled(), true);
-
- // GIVEN
- const QVector<QString> names = (QVector<QString>()
- << QLatin1String("root")
- << QLatin1String("child1")
- << QLatin1String("child2"));
- const QVector<Sqt> localPoses = (QVector<Sqt>() << Sqt() << Sqt() << Sqt());
+ QSkeleton skeleton;
+ simulateInitializationSync(&skeleton, &backendSkeleton);
// WHEN
- JointNamesAndLocalPoses namesAndPoses;
- namesAndPoses.names = names;
- namesAndPoses.localPoses = localPoses;
-
- updateChange = QPropertyUpdatedChangePtr::create(QNodeId());
- updateChange->setPropertyName("jointNamesAndLocalPoses");
- updateChange->setValue(QVariant::fromValue(namesAndPoses));
- backendSkeleton.sceneChangeEvent(updateChange);
+ skeleton.setEnabled(false);
+ backendSkeleton.syncFromFrontEnd(&skeleton, false);
// THEN
- QCOMPARE(backendSkeleton.jointNames(), names);
- QCOMPARE(backendSkeleton.jointLocalPoses(), localPoses);
+ QCOMPARE(backendSkeleton.isEnabled(), false);
}
void checkJointTransforms_data()
diff --git a/tests/auto/core/common/qbackendnodetester.cpp b/tests/auto/core/common/qbackendnodetester.cpp
index 5d4a10b81..a2685f556 100644
--- a/tests/auto/core/common/qbackendnodetester.cpp
+++ b/tests/auto/core/common/qbackendnodetester.cpp
@@ -36,7 +36,6 @@
#include "qbackendnodetester.h"
#include <Qt3DCore/qbackendnode.h>
-#include <Qt3DCore/qnode.h>
QT_BEGIN_NAMESPACE
diff --git a/tests/auto/core/common/qbackendnodetester.h b/tests/auto/core/common/qbackendnodetester.h
index a9738dff0..a0b89e503 100644
--- a/tests/auto/core/common/qbackendnodetester.h
+++ b/tests/auto/core/common/qbackendnodetester.h
@@ -41,13 +41,13 @@
#include <Qt3DCore/qnodeid.h>
#include <Qt3DCore/qscenechange.h>
#include <Qt3DCore/qnodecreatedchange.h>
+#include <Qt3DCore/qnode.h>
QT_BEGIN_NAMESPACE
namespace Qt3DCore {
class QBackendNode;
-class QNode;
class QBackendNodeTester : public QObject
{
@@ -57,9 +57,21 @@ public:
// Proxies to allow test classes to call private methods on QBackendNode
void setPeerId(QBackendNode *backend, QNodeId id);
- void simulateInitialization(QNode *frontend, QBackendNode *backend);
void sceneChangeEvent(QBackendNode *backend, const Qt3DCore::QSceneChangePtr &e);
Qt3DCore::QNodeCreatedChangeBasePtr creationChange(QNode *frontend) const;
+
+ template<class Backend>
+ void simulateInitializationSync(QNode *frontend, Backend *backend)
+ {
+ Q_ASSERT(frontend);
+ Q_ASSERT(backend);
+
+ backend->setPeerId(frontend->id());
+ backend->setEnabled(frontend->isEnabled());
+ backend->syncFromFrontEnd(frontend, true);
+ }
+
+ void simulateInitialization(QNode *frontend, QBackendNode *backend);
};
} // namespace Qt3DCore
diff --git a/tests/auto/core/common/testpostmanarbiter.cpp b/tests/auto/core/common/testpostmanarbiter.cpp
index 59c59f5ab..5869cbad3 100644
--- a/tests/auto/core/common/testpostmanarbiter.cpp
+++ b/tests/auto/core/common/testpostmanarbiter.cpp
@@ -72,7 +72,7 @@ void TestArbiter::sceneChangeEventWithLock(const Qt3DCore::QSceneChangePtr &e)
void TestArbiter::sceneChangeEventWithLock(const Qt3DCore::QSceneChangeList &e)
{
- events += QVector<Qt3DCore::QSceneChangePtr>::fromStdVector(e);
+ events += QVector<Qt3DCore::QSceneChangePtr>(e.begin(), e.end());
}
Qt3DCore::QAbstractPostman *TestArbiter::postman() const
@@ -83,8 +83,27 @@ Qt3DCore::QAbstractPostman *TestArbiter::postman() const
void TestArbiter::setArbiterOnNode(Qt3DCore::QNode *node)
{
Qt3DCore::QNodePrivate::get(node)->setArbiter(this);
- Q_FOREACH (Qt3DCore::QNode *n, node->childNodes())
+ const auto childNodes = node->childNodes();
+ for (Qt3DCore::QNode *n : childNodes)
setArbiterOnNode(n);
}
+void TestArbiter::addDirtyFrontEndNode(Qt3DCore::QNode *node)
+{
+ if (!dirtyNodes.contains(node))
+ dirtyNodes << node;
+}
+
+void TestArbiter::addDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QNode *subNode, const char *property, Qt3DCore::ChangeFlag change)
+{
+ if (!dirtyNodes.contains(node))
+ dirtyNodes << node;
+ dirtySubNodes.push_back({node, subNode, change, property});
+}
+
+void TestArbiter::removeDirtyFrontEndNode(Qt3DCore::QNode *node)
+{
+ dirtyNodes.removeOne(node);
+}
+
QT_END_NAMESPACE
diff --git a/tests/auto/core/common/testpostmanarbiter.h b/tests/auto/core/common/testpostmanarbiter.h
index 7d7e4e49b..6649c7bbe 100644
--- a/tests/auto/core/common/testpostmanarbiter.h
+++ b/tests/auto/core/common/testpostmanarbiter.h
@@ -28,7 +28,7 @@
#include <Qt3DCore/private/qpostman_p.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qscenechange_p.h>
QT_BEGIN_NAMESPACE
@@ -66,8 +66,13 @@ public:
Qt3DCore::QAbstractPostman *postman() const final;
QVector<Qt3DCore::QSceneChangePtr> events;
+ QVector<Qt3DCore::QNode *> dirtyNodes;
+ QVector<Qt3DCore::NodeRelationshipChange> dirtySubNodes;
void setArbiterOnNode(Qt3DCore::QNode *node);
+ void addDirtyFrontEndNode(Qt3DCore::QNode *node) final;
+ void addDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QNode *subNode, const char *property, Qt3DCore::ChangeFlag change) final;
+ void removeDirtyFrontEndNode(Qt3DCore::QNode *node) final;
private:
TestPostman *m_postman;
diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp
index dad66c5d5..b5291cab7 100644
--- a/tests/auto/core/nodes/tst_nodes.cpp
+++ b/tests/auto/core/nodes/tst_nodes.cpp
@@ -30,14 +30,19 @@
#include <Qt3DCore/qnode.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qcomponent.h>
+#include <Qt3DCore/qaspectengine.h>
+#include <Qt3DCore/qabstractaspect.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qcomponentaddedchange.h>
#include <Qt3DCore/qcomponentremovedchange.h>
#include <Qt3DCore/qnodedestroyedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <Qt3DCore/private/qscenechange_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <private/qabstractaspect_p.h>
#include <private/qpostman_p.h>
#include <Qt3DCore/private/qlockableobserverinterface_p.h>
@@ -74,6 +79,8 @@ private slots:
void checkParentChangeToOtherParent();
void checkParentChangeFromExistingBackendParentToNewlyCreatedParent();
void checkBackendNodesCreatedFromTopDown(); //QTBUG-74106
+ void checkBackendNodesCreatedFromTopDownWithReparenting();
+ void checkAllBackendCreationDoneInSingleFrame();
void removingSingleChildNodeFromNode();
void removingMultipleChildNodesFromNode();
@@ -87,6 +94,7 @@ private slots:
void checkConstructionWithNonRootParent(); // QTBUG-73986
void checkConstructionAsListElement();
void checkSceneIsSetOnConstructionWithParent(); // QTBUG-69352
+ void checkSubNodePostConstructIsCalledWhenReferincingNodeProperty(); // QTBUG-79350
void appendingComponentToEntity();
void appendingParentlessComponentToEntityWithoutScene();
@@ -103,6 +111,8 @@ private slots:
void checkEnabledUpdate();
void checkPropertyTrackModeUpdate();
void checkTrackedPropertyNamesUpdate();
+
+ void checkNodeRemovedFromDirtyListOnDestruction();
};
class ObserverSpy;
@@ -113,8 +123,8 @@ public:
: m_spy(spy)
{}
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) final {};
- void setScene(Qt3DCore::QScene *) final {};
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) final {}
+ void setScene(Qt3DCore::QScene *) final {}
void notifyBackend(const Qt3DCore::QSceneChangePtr &change) final;
bool shouldNotifyFrontend(const Qt3DCore::QSceneChangePtr &changee) final { Q_UNUSED(changee); return false; }
@@ -143,9 +153,7 @@ public:
{
}
- ~ObserverSpy()
- {
- }
+ ~ObserverSpy();
void sceneChangeEventWithLock(const Qt3DCore::QSceneChangePtr &e) override
{
@@ -169,10 +177,31 @@ public:
return m_postman.data();
}
+ void addDirtyFrontEndNode(Qt3DCore::QNode *node) final {
+ if (!dirtyNodes.contains(node))
+ dirtyNodes << node;
+ }
+
+ void addDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QNode *subNode, const char *property, Qt3DCore::ChangeFlag change) final {
+ if (!dirtyNodes.contains(node))
+ dirtyNodes << node;
+ dirtySubNodes.push_back({node, subNode, change, property});
+ }
+
+ void removeDirtyFrontEndNode(Qt3DCore::QNode *node) final {
+ dirtyNodes.removeOne(node);
+ }
+
+ QVector<Qt3DCore::QNode *> dirtyNodes;
+ QVector<Qt3DCore::NodeRelationshipChange> dirtySubNodes;
QList<ChangeRecord> events;
QScopedPointer<SimplePostman> m_postman;
};
+ObserverSpy::~ObserverSpy()
+{
+}
+
void SimplePostman::notifyBackend(const Qt3DCore::QSceneChangePtr &change)
{
m_spy->sceneChangeEventWithLock(change);
@@ -186,7 +215,7 @@ class MyQNode : public Qt3DCore::QNode
Q_PROPERTY(QString customProperty READ customProperty WRITE setCustomProperty NOTIFY customPropertyChanged)
Q_PROPERTY(MyQNode *nodeProperty READ nodeProperty WRITE setNodeProperty NOTIFY nodePropertyChanged)
public:
- explicit MyQNode(Qt3DCore::QNode *parent = 0)
+ explicit MyQNode(Qt3DCore::QNode *parent = nullptr)
: QNode(parent)
, m_nodeProperty(nullptr)
{}
@@ -264,22 +293,15 @@ public slots:
if (!attribute->parent())
attribute->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueAdded);
}
}
void removeAttribute(MyQNode *attribute)
{
Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved);
+
m_attributes.removeOne(attribute);
// Remove bookkeeping connection
d->unregisterDestructionHelper(attribute);
@@ -298,8 +320,9 @@ protected:
class MyQEntity : public Qt3DCore::QEntity
{
Q_OBJECT
+ Q_PROPERTY(MyQNode *nodeProperty READ nodeProperty WRITE setNodeProperty NOTIFY nodePropertyChanged)
public:
- explicit MyQEntity(Qt3DCore::QNode *parent = 0)
+ explicit MyQEntity(Qt3DCore::QNode *parent = nullptr)
: QEntity(parent)
{}
@@ -317,17 +340,85 @@ public:
Qt3DCore::QNodePrivate::get(this)->setArbiter(arbiter);
}
+ void setArbiterAndEngine(Qt3DCore::QAbstractArbiter *arbiter,
+ Qt3DCore::QAspectEngine *engine)
+ {
+ Q_ASSERT(arbiter);
+ Q_ASSERT(engine);
+ auto scene = Qt3DCore::QAspectEnginePrivate::get(engine)->m_scene;
+ Qt3DCore::QNodePrivate::get(this)->setScene(scene);
+ Qt3DCore::QNodePrivate::get(this)->setArbiter(arbiter);
+
+ if (scene) {
+ scene->setArbiter(arbiter);
+ engine->setRootEntity(Qt3DCore::QEntityPtr(this, [](QEntity *) {}));
+ scene->setArbiter(arbiter);
+ Qt3DCore::QNodePrivate::get(this)->setArbiter(arbiter);
+ }
+ }
+
void setSimulateBackendCreated(bool created)
{
Qt3DCore::QNodePrivate::get(this)->m_hasBackendNode = created;
}
+
+ MyQNode *nodeProperty() const { return m_nodeProperty; }
+
+ void addAttribute(MyQNode *attribute)
+ {
+ Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(this);
+ if (!m_attributes.contains(attribute)) {
+ m_attributes.append(attribute);
+
+ // Ensures proper bookkeeping
+ d->registerDestructionHelper(attribute, &MyQNode::removeAttribute, m_attributes);
+
+ // We need to add it as a child of the current node if it has been declared inline
+ // Or not previously added as a child of the current node so that
+ // 1) The backend gets notified about it's creation
+ // 2) When the current node is destroyed, it gets destroyed as well
+ if (!attribute->parent())
+ attribute->setParent(this);
+
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved);
+ }
+ }
+
+public slots:
+ void setNodeProperty(MyQNode *node)
+ {
+ Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(this);
+ if (m_nodeProperty == node)
+ return;
+
+ if (m_nodeProperty)
+ d->unregisterDestructionHelper(m_nodeProperty);
+
+ if (node && !node->parent())
+ node->setParent(this);
+
+ m_nodeProperty = node;
+
+ // Ensures proper bookkeeping
+ if (m_nodeProperty)
+ d->registerDestructionHelper(m_nodeProperty, &MyQEntity::setNodeProperty, m_nodeProperty);
+
+ emit nodePropertyChanged(node);
+ }
+
+signals:
+ void nodePropertyChanged(MyQNode *node);
+
+private:
+ MyQNode *m_nodeProperty;
+ QVector<MyQNode *> m_attributes;
};
class MyQComponent : public Qt3DCore::QComponent
{
Q_OBJECT
public:
- explicit MyQComponent(Qt3DCore::QNode *parent = 0) : QComponent(parent)
+ explicit MyQComponent(Qt3DCore::QNode *parent = nullptr) : QComponent(parent)
{}
void setArbiter(Qt3DCore::QAbstractArbiter *arbiter)
{
@@ -336,6 +427,148 @@ public:
}
};
+class MyFakeMaterial : public Qt3DCore::QComponent
+{
+ Q_OBJECT
+public:
+ explicit MyFakeMaterial(Qt3DCore::QNode *parent = nullptr)
+ : QComponent(parent)
+ , m_effect(new MyQNode(this))
+ , m_technique(new MyQNode(m_effect))
+ , m_renderPass(new MyQNode(m_technique))
+ {
+ }
+
+ void setArbiter(Qt3DCore::QAbstractArbiter *arbiter)
+ {
+ Q_ASSERT(arbiter);
+ Qt3DCore::QComponentPrivate::get(this)->setArbiter(arbiter);
+ }
+
+ MyQNode *m_effect;
+ MyQNode *m_technique;
+ MyQNode *m_renderPass;
+};
+
+class TestAspectPrivate;
+class TestAspect : public Qt3DCore::QAbstractAspect
+{
+ Q_OBJECT
+public:
+ explicit TestAspect(QObject *parent = nullptr);
+
+ enum ChangeType { Creation, Destruction };
+
+ void clearNodes()
+ {
+ events.clear();
+ allNodes.clear();
+ }
+
+ void addEvent(const Qt3DCore::QNodeId &id, ChangeType change)
+ {
+ events.push_back(Event{ change, id});
+ }
+
+ QVector<Qt3DCore::QNodeId> filteredEvents(ChangeType change) const
+ {
+ QVector<Qt3DCore::QNodeId> result;
+ for (const auto &event : events) {
+ if (event.type == change)
+ result.push_back(event.nodeId);
+ }
+ return result;
+ }
+
+ struct Event{
+ ChangeType type;
+ Qt3DCore::QNodeId nodeId;
+ };
+
+ mutable QVector<Event> events;
+ mutable QHash<Qt3DCore::QNodeId, Qt3DCore::QNode *> allNodes;
+
+private:
+ Q_DECLARE_PRIVATE(TestAspect)
+ explicit TestAspect(TestAspectPrivate &dd, QObject *parent);
+};
+
+class TestFunctor : public Qt3DCore::QBackendNodeMapper
+{
+public:
+ TestFunctor(TestAspect *aspect) : m_aspect(aspect) {}
+
+ Qt3DCore::QBackendNode *create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const override
+ {
+ auto node = new Qt3DCore::QBackendNode;
+ m_Nodes.insert(change->subjectId(), node);
+ m_aspect->addEvent(change->subjectId(), TestAspect::Creation);
+ return node;
+ }
+
+ Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const override
+ {
+ return m_Nodes.value(id, nullptr);
+ }
+
+ void destroy(Qt3DCore::QNodeId id) const override
+ {
+ if (m_Nodes.contains(id)) {
+ m_aspect->addEvent(id, TestAspect::Destruction);
+ delete m_Nodes.take(id);
+ }
+ }
+
+private:
+ mutable QHash<Qt3DCore::QNodeId, Qt3DCore::QBackendNode *> m_Nodes;
+ TestAspect *m_aspect;
+};
+
+class TestAspectPrivate : public Qt3DCore::QAbstractAspectPrivate
+{
+public:
+ TestAspectPrivate() = default;
+ void syncDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QBackendNode *backend,
+ bool firstTime) const override
+ {
+ Q_UNUSED(backend)
+ auto q = q_func();
+ if (firstTime)
+ q->allNodes.insert(node->id(), node);
+ }
+
+ Q_DECLARE_PUBLIC(TestAspect)
+};
+
+TestAspect::TestAspect(QObject *parent) : TestAspect(*new TestAspectPrivate, parent)
+{
+ Q_D(TestAspect);
+ d->registerBackendType<Qt3DCore::QEntity, true>(QSharedPointer<TestFunctor>::create(this));
+ d->registerBackendType<MyQEntity, true>(QSharedPointer<TestFunctor>::create(this));
+ d->registerBackendType<MyQNode, true>(QSharedPointer<TestFunctor>::create(this));
+ d->registerBackendType<Qt3DCore::QNode, true>(QSharedPointer<TestFunctor>::create(this));
+}
+
+TestAspect::TestAspect(TestAspectPrivate &dd, QObject *parent)
+ : Qt3DCore::QAbstractAspect(dd, parent)
+{
+ setObjectName(QStringLiteral("Test Aspect"));
+}
+
+namespace {
+void verifyChildrenCreatedBeforeParents(Qt3DCore::QNode *root, TestAspect *aspect)
+{
+ QSet<Qt3DCore::QNodeId> processedNodes;
+ processedNodes.insert(root->id());
+ for (const auto &nodeId : aspect->filteredEvents(TestAspect::Creation)) {
+ const auto node = aspect->allNodes.value(nodeId);
+ Q_ASSERT(node);
+ const auto parentNode = node->parentNode();
+ QVERIFY(parentNode == nullptr || processedNodes.contains(parentNode->id()));
+ processedNodes.insert(nodeId);
+ }
+}
+}
void tst_Nodes::initTestCase()
{
@@ -496,19 +729,10 @@ void tst_Nodes::appendSingleChildNodeToNodeSceneExplicitParenting()
// THEN
QVERIFY(child->parent() == node.data());
QVERIFY(child->parentNode() == node.data());
- QCOMPARE(spy.events.size(), 2); // Created + Child Added
+ QCOMPARE(spy.events.size(), 1); // Child Added
QCOMPARE(node->children().count(), 1);
QVERIFY(Qt3DCore::QNodePrivate::get(child.data())->scene() != nullptr);
- // Creation event
- QVERIFY(spy.events.first().wasLocked());
- Qt3DCore::QNodeCreatedChangeBasePtr creationEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(creationEvent);
- QCOMPARE(creationEvent->subjectId(), child->id());
- QCOMPARE(creationEvent->metaObject(), child->metaObject());
- QCOMPARE(creationEvent->isNodeEnabled(), child->isEnabled());
- QCOMPARE(creationEvent->parentId(), child->parentNode()->id());
-
// Node Added event
QVERIFY(spy.events.first().wasLocked());
Qt3DCore::QPropertyNodeAddedChangePtr additionEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
@@ -540,19 +764,10 @@ void tst_Nodes::appendSingleChildNodeToNodeSceneImplicitParenting()
QVERIFY(child->parentNode() == node.data());
QVERIFY(Qt3DCore::QNodePrivate::get(child.data())->scene() != nullptr);
- QCOMPARE(spy.events.size(), 2);
+ QCOMPARE(spy.events.size(), 1);
QVERIFY(spy.events.first().wasLocked());
QCOMPARE(node->children().count(), 1);
- // Creation event
- QVERIFY(spy.events.first().wasLocked());
- Qt3DCore::QNodeCreatedChangeBasePtr creationEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(creationEvent);
- QCOMPARE(creationEvent->subjectId(), child->id());
- QCOMPARE(creationEvent->metaObject(), child->metaObject());
- QCOMPARE(creationEvent->isNodeEnabled(), child->isEnabled());
- QCOMPARE(creationEvent->parentId(), child->parentNode()->id());
-
// Node Added event
QVERIFY(spy.events.first().wasLocked());
Qt3DCore::QPropertyNodeAddedChangePtr additionEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
@@ -616,33 +831,22 @@ void tst_Nodes::appendMultipleChildNodesToNodeScene()
// With this in mind, the recorded events should show:
//
// for each odd child:
- // odd child creation
// child addition to parent of odd child
//
// followed by:
//
// for each even child:
- // even child construction
// child addition to parent of even child
//
- const auto expectedEventCount = 2 * childCount;
- QCOMPARE(spy.events.size(), 10 * 2);
-
- for (auto i = 0; i < expectedEventCount; i += 2) {
- const auto creationRecord = spy.events.at(i);
- QVERIFY(creationRecord.wasLocked());
- const auto childIndex = i < 10
- ? (i / 2) * 2 + 1
- : (i - 10) / 2 * 2;
- Qt3DCore::QNode *child = node->childNodes().at(childIndex);
+ const auto expectedEventCount = childCount;
+ QCOMPARE(spy.events.size(), 10);
- const Qt3DCore::QNodeCreatedChangeBasePtr event = creationRecord.change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(event != nullptr);
- QCOMPARE(event->subjectId(), child->id());
- QCOMPARE(event->metaObject(), child->metaObject());
- QCOMPARE(event->isNodeEnabled(), child->isEnabled());
+ for (auto i = 0; i < expectedEventCount; ++i) {
+ const auto childIndex = i;
+ Qt3DCore::QNode *child = node->childNodes().at(childIndex);
- const auto additionRecord = spy.events.at(i + 1);
+ const auto recordIndex = (i % 2 == 0) ? expectedEventCount / 2 + i / 2 : i / 2;
+ const auto additionRecord = spy.events.at(recordIndex);
Qt3DCore::QPropertyNodeAddedChangePtr additionEvent = additionRecord.change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
QCOMPARE(additionEvent->subjectId(), node->id());
QCOMPARE(additionEvent->addedNodeId(), child->id());
@@ -664,7 +868,7 @@ void tst_Nodes::checkParentChangeToNull()
// THEN
QVERIFY(child->parent() == root.data());
- QCOMPARE(spy.events.size(), 2);
+ QCOMPARE(spy.events.size(), 1);
QCOMPARE(root->children().size(), 1);
// WHEN
@@ -674,23 +878,7 @@ void tst_Nodes::checkParentChangeToNull()
// THEN
QVERIFY(child->parent() == nullptr);
QCOMPARE(root->children().size(), 0);
- QCOMPARE(spy.events.size(), 2);
-
- QVERIFY(spy.events.first().wasLocked());
- const Qt3DCore::QPropertyNodeRemovedChangePtr removalEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QVERIFY(removalEvent);
- QCOMPARE(removalEvent->subjectId(), root->id());
- QCOMPARE(removalEvent->removedNodeId(), child->id());
- QCOMPARE(removalEvent->metaObject(), child->metaObject());
-
- QVERIFY(spy.events.first().wasLocked());
- const Qt3DCore::QNodeDestroyedChangePtr destructionEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeDestroyedChange>();
- QVERIFY(destructionEvent);
- QCOMPARE(destructionEvent->type(), Qt3DCore::NodeDeleted);
- QCOMPARE(destructionEvent->subjectId(), child->id());
- QCOMPARE(destructionEvent->subtreeIdsAndTypes().size(), 1);
- QCOMPARE(destructionEvent->subtreeIdsAndTypes().first().id, child->id());
- QCOMPARE(destructionEvent->subtreeIdsAndTypes().first().type, child->metaObject());
+ QCOMPARE(spy.events.size(), 0);
}
void tst_Nodes::checkParentChangeToOtherParent()
@@ -705,7 +893,7 @@ void tst_Nodes::checkParentChangeToOtherParent()
QCoreApplication::processEvents();
// THEN
- QCOMPARE(spy.events.size(), 4); // 2 x (1 node created change, 1 node added to children change)
+ QCOMPARE(spy.events.size(), 2); // 2 x (1 node added to children change)
// WHEN
spy.events.clear();
@@ -717,7 +905,7 @@ void tst_Nodes::checkParentChangeToOtherParent()
QCOMPARE(parent1->children().size(), 1);
QCOMPARE(parent2->children().size(), 0);
QVERIFY(Qt3DCore::QNodePrivate::get(child.data())->scene() != nullptr);
- QCOMPARE(spy.events.size(), 2); // 1 node created change, 1 node added to children change
+ QCOMPARE(spy.events.size(), 1); // 1 node added to children change
// WHEN
spy.events.clear();
@@ -727,15 +915,20 @@ void tst_Nodes::checkParentChangeToOtherParent()
QVERIFY(child->parent() == parent2.data());
QCOMPARE(parent1->children().size(), 0);
QCOMPARE(parent2->children().size(), 1);
- QCOMPARE(spy.events.size(), 2);
+ QCOMPARE(spy.events.size(), 1);
// CHECK event 1 is a Node Removed event
- QVERIFY(spy.events.first().wasLocked());
- const Qt3DCore::QPropertyNodeRemovedChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(event->type(), Qt3DCore::PropertyValueRemoved);
- QCOMPARE(event->subjectId(), parent1->id());
- QCOMPARE(event->removedNodeId(), child->id());
- QCOMPARE(event->metaObject(), child->metaObject());
+ // this no longer generated because nodes don't have backends yet
+
+ QVERIFY(!Qt3DCore::QNodePrivate::get(child.data())->m_hasBackendNode);
+
+
+// QVERIFY(spy.events.first().wasLocked());
+// const Qt3DCore::QPropertyNodeRemovedChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeRemovedChange>();
+// QCOMPARE(event->type(), Qt3DCore::PropertyValueRemoved);
+// QCOMPARE(event->subjectId(), parent1->id());
+// QCOMPARE(event->removedNodeId(), child->id());
+// QCOMPARE(event->metaObject(), child->metaObject());
// CHECK event 2 is a Node Added event
QVERIFY(spy.events.last().wasLocked());
@@ -749,21 +942,31 @@ void tst_Nodes::checkParentChangeToOtherParent()
void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
{
// GIVEN
- Qt3DCore::QScene scene;
ObserverSpy spy;
- QScopedPointer<MyQNode> root(new MyQNode());
- root->setArbiterAndScene(&spy, &scene);
+ Qt3DCore::QAspectEngine engine;
+ QScopedPointer<MyQEntity> root(new MyQEntity());
+ root->setArbiterAndEngine(&spy, &engine);
+ auto aspect = new TestAspect;
+ engine.registerAspect(aspect);
+
MyQNode *child(new MyQNode(root.data()));
MyQNode *child2(new MyQNode(root.data()));
+
QCoreApplication::processEvents();
- // Due to the way we create root, it never has a backend
- QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->m_hasBackendNode == false);
+ // Due to the way we create root, it has a backend
+ QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->m_hasBackendNode == true);
+ QCOMPARE(aspect->events.count(), 2);
+ QCOMPARE(aspect->events[0].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[0].nodeId, child->id());
+ QCOMPARE(aspect->events[1].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[1].nodeId, child2->id());
// THEN
- QCOMPARE(spy.events.size(), 4); // 2 x (1 node created change, 1 child added to parent change)
+ QCOMPARE(spy.events.size(), 2); // 2 x (1 child added to parent change)
// WHEN -> Reparenting child with backend node to new parent with no backend yet
+ aspect->clearNodes();
spy.events.clear();
QScopedPointer<Qt3DCore::QNode> newParent(new MyQNode(root.data()));
child->setParent(newParent.data());
@@ -782,9 +985,9 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
QCoreApplication::processEvents();
// THEN
- QCOMPARE(spy.events.size(), 5);
- // 1 node removed change, 1 node destroyed change,
- // 2 node created change, 1 node added to children change
+ QCOMPARE(spy.events.size(), 2);
+ // 1 node removed change
+ // 1 node added to children change
QVERIFY(Qt3DCore::QNodePrivate::get(newParent.data())->m_hasBackendNode == true);
QVERIFY(Qt3DCore::QNodePrivate::get(child)->m_hasBackendNode == true);
@@ -797,33 +1000,27 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
QCOMPARE(event->removedNodeId(), child->id());
QCOMPARE(event->metaObject(), child->metaObject());
- // CHECK event 2 is a Node Destroyed
- QVERIFY(spy.events.first().wasLocked());
- const Qt3DCore::QNodeDestroyedChangePtr event2 = spy.events.takeFirst().change().staticCast<Qt3DCore::QNodeDestroyedChange>();
- QCOMPARE(event2->type(), Qt3DCore::NodeDeleted);
- QCOMPARE(event2->subtreeIdsAndTypes().size(), 1);
- QCOMPARE(event2->subtreeIdsAndTypes().first().id, child->id());
-
- // CHECK event 3 and 4 are Node Created events
- const Qt3DCore::QNodeCreatedChangeBasePtr event3 = spy.events.takeFirst().change().staticCast<Qt3DCore::QNodeCreatedChangeBase>();
- const Qt3DCore::QNodeCreatedChangeBasePtr event4 = spy.events.takeFirst().change().staticCast<Qt3DCore::QNodeCreatedChangeBase>();
+ const Qt3DCore::QPropertyNodeAddedChangePtr event2 = spy.events.takeFirst().change().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
+ QCOMPARE(event2->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(event2->addedNodeId(), newParent->id());
+ QCOMPARE(event2->metaObject(), newParent->metaObject());
+ QCOMPARE(event2->subjectId(), root->id());
- QCOMPARE(event3->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event3->parentId(), root->id());
- QCOMPARE(event3->subjectId(), newParent->id());
+ QCOMPARE(aspect->events.count(), 3);
- QCOMPARE(event4->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event4->parentId(), newParent->id());
- QCOMPARE(event4->subjectId(), child->id());
+ // child backend is destroyed because it was reparented to node without backend (newParent)
+ QCOMPARE(aspect->events[0].type, TestAspect::Destruction);
+ QCOMPARE(aspect->events[0].nodeId, child->id());
- const Qt3DCore::QPropertyNodeAddedChangePtr event5 = spy.events.takeFirst().change().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(event5->type(), Qt3DCore::PropertyValueAdded);
- QCOMPARE(event5->addedNodeId(), newParent->id());
- QCOMPARE(event5->metaObject(), newParent->metaObject());
- QCOMPARE(event5->subjectId(), root->id());
+ // newParent and child both get backends created
+ QCOMPARE(aspect->events[1].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[1].nodeId, newParent->id());
+ QCOMPARE(aspect->events[2].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[2].nodeId, child->id());
}
// WHEN -> Changing parent to node with existing backend
+ aspect->clearNodes();
child->setParent(child2);
// THEN
@@ -864,9 +1061,9 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
QCoreApplication::processEvents();
// THEN
- QCOMPARE(spy.events.size(), 5);
- // 1 node removed change, 1 node destroyed change,
- // 2 node created change, 1 node added to children change
+ QCOMPARE(spy.events.size(), 2);
+ // 1 node removed change
+ // 1 node added to children change
{
// CHECK event 1 is a Node Removed event
QVERIFY(spy.events.first().wasLocked());
@@ -876,30 +1073,15 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
QCOMPARE(event->removedNodeId(), child->id());
QCOMPARE(event->metaObject(), child->metaObject());
- // CHECK event 2 is a Node Destroyed
- QVERIFY(spy.events.first().wasLocked());
- const Qt3DCore::QNodeDestroyedChangePtr event2 = spy.events.takeFirst().change().staticCast<Qt3DCore::QNodeDestroyedChange>();
- QCOMPARE(event2->type(), Qt3DCore::NodeDeleted);
- QCOMPARE(event2->subtreeIdsAndTypes().size(), 1);
- QCOMPARE(event2->subtreeIdsAndTypes().first().id, child->id());
-
- // CHECK event 3 and 4 are Node Created events
- const Qt3DCore::QNodeCreatedChangeBasePtr event3 = spy.events.takeFirst().change().staticCast<Qt3DCore::QNodeCreatedChangeBase>();
- const Qt3DCore::QNodeCreatedChangeBasePtr event4 = spy.events.takeFirst().change().staticCast<Qt3DCore::QNodeCreatedChangeBase>();
-
- QCOMPARE(event3->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event3->parentId(), root->id());
- QCOMPARE(event3->subjectId(), newParent2->id());
-
- QCOMPARE(event4->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event4->parentId(), newParent2->id());
- QCOMPARE(event4->subjectId(), child->id());
+ const Qt3DCore::QPropertyNodeAddedChangePtr event2 = spy.events.takeFirst().change().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
+ QCOMPARE(event2->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(event2->addedNodeId(), newParent2->id());
+ QCOMPARE(event2->metaObject(), newParent2->metaObject());
+ QCOMPARE(event2->subjectId(), root->id());
- const Qt3DCore::QPropertyNodeAddedChangePtr event5 = spy.events.takeFirst().change().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(event5->type(), Qt3DCore::PropertyValueAdded);
- QCOMPARE(event5->addedNodeId(), newParent2->id());
- QCOMPARE(event5->metaObject(), newParent2->metaObject());
- QCOMPARE(event5->subjectId(), root->id());
+ // child backend is destroyed because it was reparented to node without backend (newParent)
+ QCOMPARE(aspect->events[0].type, TestAspect::Destruction);
+ QCOMPARE(aspect->events[0].nodeId, child->id());
}
}
@@ -909,10 +1091,13 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
void tst_Nodes::checkBackendNodesCreatedFromTopDown()
{
// GIVEN
- Qt3DCore::QScene scene;
ObserverSpy spy;
- QScopedPointer<MyQNode> root(new MyQNode());
- root->setArbiterAndScene(&spy, &scene);
+ Qt3DCore::QAspectEngine engine;
+ auto aspect = new TestAspect;
+ engine.registerAspect(aspect);
+ QScopedPointer<MyQEntity> root(new MyQEntity());
+
+ root->setArbiterAndEngine(&spy, &engine);
QScopedPointer<Qt3DCore::QNode> parentWithBackend(new MyQNode(root.data()));
// create parent backend node
@@ -925,7 +1110,7 @@ void tst_Nodes::checkBackendNodesCreatedFromTopDown()
MyQNode *dummyParent(new MyQNode(parentWithBackend.data()));
MyQNode *child1(new MyQNode(parentWithBackend.data()));
MyQNode *child2(new MyQNode(dummyParent));
- child2->setNodeProperty(child1);
+ child1->setNodeProperty(child2);
// THEN - we should have no events because the new nodes have no backend yet
QCOMPARE(spy.events.count(), 0);
@@ -939,59 +1124,88 @@ void tst_Nodes::checkBackendNodesCreatedFromTopDown()
QVERIFY(child2->parent() == dummyParent);
// THEN
- QCOMPARE(spy.events.size(), 5);
- // 2 node creation change for dummyParent subtree (dummyParent and child2)
+ QCOMPARE(spy.events.size(), 2);
// 1 node added to children change (dummyParent to parent)
- // 1 node created change for child1
// 1 node added to children change (child1 to parent)
{
- // 1st event: dummyParent creation
- const auto event1 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!event1.isNull());
- QCOMPARE(event1->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event1->parentId(), parentWithBackend->id());
- QCOMPARE(event1->subjectId(), dummyParent->id());
-
- // 2nd event: child2 creation (even though we constructed child1 first)
- const auto event2 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!event2.isNull());
- QCOMPARE(event2->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event2->parentId(), dummyParent->id());
- QCOMPARE(event2->subjectId(), child2->id());
+ QVERIFY(Qt3DCore::QNodePrivate::get(dummyParent)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(child1)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(child2)->m_hasBackendNode);
+
+ // 1st event: dummyParent added to parent
+ const auto event = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
+ QCOMPARE(event->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(event->addedNodeId(), dummyParent->id());
+ QCOMPARE(event->subjectId(), parentWithBackend->id());
+
+ // 2nd event: child 1 added to parent
+ const auto event2 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
+ QCOMPARE(event2->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(event2->addedNodeId(), child1->id());
+ QCOMPARE(event2->subjectId(), parentWithBackend->id());
- // 3rd event: dummyParent added to parent
- const auto event3 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(event3->type(), Qt3DCore::PropertyValueAdded);
- QCOMPARE(event3->addedNodeId(), dummyParent->id());
- QCOMPARE(event3->subjectId(), parentWithBackend->id());
-
- // 4th event: child1 creation
- const auto event4 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!event4.isNull());
- QCOMPARE(event4->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event4->parentId(), parentWithBackend->id());
- QCOMPARE(event4->subjectId(), child1->id());
-
- // 5th event: child 1 added to parent
- const auto event5 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(event5->type(), Qt3DCore::PropertyValueAdded);
- QCOMPARE(event5->addedNodeId(), child1->id());
- QCOMPARE(event5->subjectId(), parentWithBackend->id());
+ verifyChildrenCreatedBeforeParents(root.get(), aspect);
}
+
}
+void tst_Nodes::checkBackendNodesCreatedFromTopDownWithReparenting()
+{
+ // GIVEN
+ ObserverSpy spy;
+ Qt3DCore::QAspectEngine engine;
+ auto aspect = new TestAspect;
+ engine.registerAspect(aspect);
+ QScopedPointer<MyQEntity> root(new MyQEntity());
+
+ root->setArbiterAndEngine(&spy, &engine);
+ QScopedPointer<Qt3DCore::QNode> parentWithBackend(new MyQNode(root.data()));
+
+ // create parent backend node
+ QCoreApplication::processEvents();
+ QCoreApplication::processEvents();
+ QVERIFY(Qt3DCore::QNodePrivate::get(parentWithBackend.get())->m_hasBackendNode);
+
+ // WHEN -> creating a node with a parent with backend, then reparenting it to another
+ // parent with backend created after it.
+ spy.events.clear();
+ auto node1 = new MyQNode(parentWithBackend.data());
+ auto parent1 = new MyQNode(parentWithBackend.data());
+ node1->setParent(parent1);
+
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(node1->parent() == parent1);
+ QVERIFY(parent1->parent() == parentWithBackend.data());
+ verifyChildrenCreatedBeforeParents(root.get(), aspect);
+
+
+ // WHEN -> creating 2 nodes with no parent and reparenting the first to the second
+ auto node2 = new MyQNode(nullptr);
+ auto parent2 = new MyQNode(nullptr);
+ node2->setParent(parent2);
+ parent2->setParent(parentWithBackend.get());
+
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(node2->parent() == parent2);
+ QVERIFY(parent2->parent() == parentWithBackend.data());
+ verifyChildrenCreatedBeforeParents(root.get(), aspect);
+}
void tst_Nodes::removingSingleChildNodeFromNode()
{
// GIVEN
- Qt3DCore::QScene scene;
ObserverSpy spy;
- QScopedPointer<MyQNode> root(new MyQNode());
+ Qt3DCore::QAspectEngine engine;
+ QScopedPointer<MyQEntity> root(new MyQEntity());
QScopedPointer<Qt3DCore::QNode> child(new MyQNode());
// WHEN
- root->setArbiterAndScene(&spy, &scene);
+ root->setArbiterAndEngine(&spy, &engine);
root->setSimulateBackendCreated(true);
child->setParent(root.data());
@@ -1009,32 +1223,70 @@ void tst_Nodes::removingSingleChildNodeFromNode()
QVERIFY(child->parent() == nullptr);
QVERIFY(root->children().count() == 0);
- QCOMPARE(spy.events.size(), 2);
+ QCOMPARE(spy.events.size(), 1);
QVERIFY(spy.events.first().wasLocked());
const Qt3DCore::QPropertyNodeRemovedChangePtr removalEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeRemovedChange>();
QCOMPARE(removalEvent->subjectId(), root->id());
QCOMPARE(removalEvent->removedNodeId(), child->id());
QCOMPARE(removalEvent->metaObject(), child->metaObject());
+}
- QVERIFY(spy.events.first().wasLocked());
- const Qt3DCore::QNodeDestroyedChangePtr destructionEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeDestroyedChange>();
- QCOMPARE(destructionEvent->type(), Qt3DCore::NodeDeleted);
- QCOMPARE(destructionEvent->subjectId(), child->id());
- QCOMPARE(destructionEvent->subtreeIdsAndTypes().size(), 1);
- QCOMPARE(destructionEvent->subtreeIdsAndTypes().first().id, child->id());
- QCOMPARE(destructionEvent->subtreeIdsAndTypes().first().type, child->metaObject());
+void tst_Nodes::checkAllBackendCreationDoneInSingleFrame()
+{
+ // GIVEN
+ ObserverSpy spy;
+ Qt3DCore::QAspectEngine engine;
+ auto aspect = new TestAspect;
+ engine.registerAspect(aspect);
+
+ QScopedPointer<MyQEntity> root(new MyQEntity());
+ root->setArbiterAndEngine(&spy, &engine);
+
+ QCoreApplication::processEvents();
+
+ // THEN
+ // Due to the way we create root, it has a backend
+ QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->m_hasBackendNode == true);
+ QCOMPARE(aspect->events.count(), 1);
+ QCOMPARE(aspect->events[0].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[0].nodeId, root->id());
+
+ // WHEN -> create 2 children:
+ // 1. a child with parent with backend node
+ // 2. a child with no parent that is then reparented to a parent with backend node
+ aspect->clearNodes();
+ auto child1 = new MyQNode(root.data());
+ auto child2 = new MyQNode;
+ child2->setParent(root.data());
+
+ // THEN - reparented child should have a backend node, but other child should
+ // still be waiting
+ QCOMPARE(child1->parent(), root.data());
+ QCOMPARE(child2->parent(), root.data());
+ QVERIFY(Qt3DCore::QNodePrivate::get(child1)->m_hasBackendNode == false);
+ QVERIFY(Qt3DCore::QNodePrivate::get(child2)->m_hasBackendNode == true);
+
+ // WHEN
+ QCoreApplication::processEvents();
+
+ // THEN - both children have their backend nodes actually created.
+ QCOMPARE(aspect->events.count(), 2);
+ QCOMPARE(aspect->events[0].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[0].nodeId, child2->id());
+ QCOMPARE(aspect->events[1].type, TestAspect::Creation);
+ QCOMPARE(aspect->events[1].nodeId, child1->id());
}
void tst_Nodes::removingMultipleChildNodesFromNode()
{
// GIVEN
- Qt3DCore::QScene scene;
ObserverSpy spy;
- QScopedPointer<MyQNode> root(new MyQNode());
+ Qt3DCore::QAspectEngine engine;
+ QScopedPointer<MyQEntity> root(new MyQEntity());
// WHEN
- root->setArbiterAndScene(&spy, &scene);
+ root->setArbiterAndEngine(&spy, &engine);
// THEN
QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->scene() != nullptr);
@@ -1050,33 +1302,23 @@ void tst_Nodes::removingMultipleChildNodesFromNode()
// THEN
QCOMPARE(root->children().count(), 10);
- QCOMPARE(spy.events.size(), 20);
+ QCOMPARE(spy.events.size(), 10);
// WHEN
spy.events.clear();
- Q_FOREACH (QObject *c, root->children())
- delete c;
+ qDeleteAll(root->children());
// THEN
QVERIFY(root->children().count() == 0);
- QCOMPARE(spy.events.size(), 20);
+ QCOMPARE(spy.events.size(), 10);
int i = 0;
- Q_FOREACH (const ObserverSpy::ChangeRecord &r, spy.events) {
+ for (const ObserverSpy::ChangeRecord &r : qAsConst(spy.events)) {
QVERIFY(r.wasLocked());
- const Qt3DCore::QNodeId childId = childIds.at(i / 2);
- if (i % 2 == 0) {
- Qt3DCore::QPropertyNodeRemovedChangePtr additionEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(additionEvent->subjectId(), root->id());
- QCOMPARE(additionEvent->removedNodeId(), childId);
- QCOMPARE(additionEvent->metaObject(), &MyQNode::staticMetaObject);
- } else {
- const Qt3DCore::QNodeDestroyedChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeDestroyedChange>();
- QCOMPARE(event->subjectId(), childId);
- QCOMPARE(event->subtreeIdsAndTypes().count(), 1);
- QCOMPARE(event->subtreeIdsAndTypes().first().id, childId);
- QCOMPARE(event->subtreeIdsAndTypes().first().type, &MyQNode::staticMetaObject);
- QCOMPARE(event->type(), Qt3DCore::NodeDeleted);
- }
+ const Qt3DCore::QNodeId childId = childIds.at(i);
+ Qt3DCore::QPropertyNodeRemovedChangePtr additionEvent = r.change().dynamicCast<Qt3DCore::QPropertyNodeRemovedChange>();
+ QCOMPARE(additionEvent->subjectId(), root->id());
+ QCOMPARE(additionEvent->removedNodeId(), childId);
+ QCOMPARE(additionEvent->metaObject(), &MyQNode::staticMetaObject);
++i;
}
}
@@ -1123,11 +1365,13 @@ void tst_Nodes::checkConstructionSetParentMix()
{
// GIVEN
ObserverSpy spy;
- Qt3DCore::QScene scene;
- QScopedPointer<MyQNode> root(new MyQNode());
+ Qt3DCore::QAspectEngine engine;
+ auto aspect = new TestAspect;
+ engine.registerAspect(aspect);
+ QScopedPointer<MyQEntity> root(new MyQEntity());
// WHEN
- root->setArbiterAndScene(&spy, &scene);
+ root->setArbiterAndEngine(&spy, &engine);
root->setSimulateBackendCreated(true);
// THEN
@@ -1145,13 +1389,10 @@ void tst_Nodes::checkConstructionSetParentMix()
QCoreApplication::processEvents();
QCOMPARE(root->children().count(), 1);
QCOMPARE(subTreeRoot->children().count(), 100);
- QCOMPARE(spy.events.size(), 102); // 1 subTreeRoot creation change, 100 child creation, 1 child added (subTree to root)
+ QCOMPARE(spy.events.size(), 1); // 1 child added (subTree to root)
// Ensure first event is subTreeRoot
- const Qt3DCore::QNodeCreatedChangeBasePtr firstEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!firstEvent.isNull());
- QCOMPARE(firstEvent->subjectId(), subTreeRoot->id());
- QCOMPARE(firstEvent->parentId(), root->id());
+ verifyChildrenCreatedBeforeParents(root.data(), aspect);
const Qt3DCore::QPropertyNodeAddedChangePtr lastEvent = spy.events.takeLast().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
QVERIFY(!lastEvent.isNull());
@@ -1164,11 +1405,11 @@ void tst_Nodes::checkParentingQEntityToQNode()
{
// GIVEN
ObserverSpy spy;
- Qt3DCore::QScene scene;
- QScopedPointer<MyQNode> root(new MyQNode());
+ Qt3DCore::QAspectEngine engine;
+ QScopedPointer<MyQEntity> root(new MyQEntity());
// WHEN
- root->setArbiterAndScene(&spy, &scene);
+ root->setArbiterAndEngine(&spy, &engine);
root->setSimulateBackendCreated(true);
// THEN
@@ -1181,35 +1422,22 @@ void tst_Nodes::checkParentingQEntityToQNode()
// THEN
QCoreApplication::processEvents();
+ QCOMPARE(spy.events.size(), 1);
- // Ensure first event is subTreeRoot creation
- const Qt3DCore::QNodeCreatedChangeBasePtr firstEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!firstEvent.isNull());
- QCOMPARE(firstEvent->subjectId(), subTreeRoot->id());
- QCOMPARE(firstEvent->parentId(), root->id());
-
- // Ensure 2nd event is childEntity creation
- const Qt3DCore::QNodeCreatedChangeBasePtr secondEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!secondEvent.isNull());
- QCOMPARE(secondEvent->subjectId(), childEntity->id());
- QCOMPARE(secondEvent->parentId(), subTreeRoot->id());
-
- // Ensure 3rd event is childNode creation
- const Qt3DCore::QNodeCreatedChangeBasePtr thirdEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!thirdEvent.isNull());
- QCOMPARE(thirdEvent->subjectId(), childNode->id());
- QCOMPARE(thirdEvent->parentId(), subTreeRoot->id());
-
+ QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(subTreeRoot)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(childEntity)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(childNode)->m_hasBackendNode);
// WHEN we reparent the childEntity to the childNode (QNode)
-
spy.events.clear();
childEntity->setParent(childNode);
+ QCoreApplication::processEvents();
+
// THEN we should get
// - one child removed change for childEntity->subTreeRoot,
// - one child added change for childEntity->childNode,
- // - and one property updated event specifying the correct QEntity parent (subTreeRoot)
- QCOMPARE(spy.events.size(), 3);
+ QCOMPARE(spy.events.size(), 2);
const auto removedEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeRemovedChange>();
QVERIFY(!removedEvent.isNull());
@@ -1219,22 +1447,26 @@ void tst_Nodes::checkParentingQEntityToQNode()
QVERIFY(!addedEvent.isNull());
QCOMPARE(addedEvent->subjectId(), childNode->id());
- const auto parentChangeEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyUpdatedChange>();
- QVERIFY(!parentChangeEvent.isNull());
- QCOMPARE(parentChangeEvent->subjectId(), childEntity->id());
- QCOMPARE(parentChangeEvent->propertyName(), "parentEntityUpdated");
- QCOMPARE(parentChangeEvent->value().value<Qt3DCore::QNodeId>(), subTreeRoot->id());
+ // The arbiter's dirtyNodes should contain the childEntity and
+ // - the dirty node's parent should be childNode
+ // - the dirty node's parent entity should be the subTreeRoot
+ QCOMPARE(spy.dirtyNodes.size(), 1);
+ const auto dirtyEntity = qobject_cast<Qt3DCore::QEntity*>(spy.dirtyNodes.takeFirst());
+ QVERIFY(dirtyEntity);
+ QCOMPARE(dirtyEntity, childEntity);
+ QCOMPARE(dirtyEntity->parent(), childNode);
+ QCOMPARE(dirtyEntity->parentEntity(), subTreeRoot);
}
void tst_Nodes::checkConstructionWithParent()
{
// GIVEN
ObserverSpy spy;
- Qt3DCore::QScene scene;
- QScopedPointer<MyQNode> root(new MyQNode());
+ Qt3DCore::QAspectEngine engine;
+ QScopedPointer<MyQEntity> root(new MyQEntity());
// WHEN
- root->setArbiterAndScene(&spy, &scene);
+ root->setArbiterAndEngine(&spy, &engine);
root->setSimulateBackendCreated(true);
// THEN
@@ -1244,16 +1476,10 @@ void tst_Nodes::checkConstructionWithParent()
auto *node = new MyQNode(root.data());
root->setNodeProperty(node);
- // THEN we should get one creation change, one child added change
- // and one property change event, in that order.
+ // THEN we should get one child added change
QCoreApplication::processEvents();
QCOMPARE(root->children().count(), 1);
- QCOMPARE(spy.events.size(), 3); // 1 creation change, 1 child added change, 1 property change
-
- // Ensure first event is child node's creation change
- const auto creationEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!creationEvent.isNull());
- QCOMPARE(creationEvent->subjectId(), node->id());
+ QCOMPARE(spy.events.size(), 1); // 1 child added change
const auto newChildEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
QVERIFY(!newChildEvent.isNull());
@@ -1261,23 +1487,21 @@ void tst_Nodes::checkConstructionWithParent()
QCOMPARE(newChildEvent->propertyName(), "children");
QCOMPARE(newChildEvent->addedNodeId(), node->id());
- // Ensure second and last event is property set change
- const auto propertyEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyUpdatedChange>();
- QVERIFY(!propertyEvent.isNull());
- QCOMPARE(propertyEvent->subjectId(), root->id());
- QCOMPARE(propertyEvent->propertyName(), "nodeProperty");
- QCOMPARE(propertyEvent->value().value<Qt3DCore::QNodeId>(), node->id());
+ // Ensure the parent node is dirty
+ QCOMPARE(spy.events.size(), 0);
+ QCOMPARE(spy.dirtyNodes.size(), 1);
+ QCOMPARE(spy.dirtyNodes.front(), root.data());
}
void tst_Nodes::checkConstructionWithNonRootParent()
{
// GIVEN
ObserverSpy spy;
- Qt3DCore::QScene scene;
- QScopedPointer<MyQNode> root(new MyQNode());
+ Qt3DCore::QAspectEngine engine;
+ QScopedPointer<MyQEntity> root(new MyQEntity());
// WHEN
- root->setArbiterAndScene(&spy, &scene);
+ root->setArbiterAndEngine(&spy, &engine);
root->setSimulateBackendCreated(true);
QScopedPointer<MyQNode> parent(new MyQNode(root.data()));
@@ -1299,16 +1523,7 @@ void tst_Nodes::checkConstructionWithNonRootParent()
QCOMPARE(root->children().count(), 1);
QCOMPARE(parent->children().count(), 1);
- QCOMPARE(spy.events.size(), 4); // 2 creation changes, 1 child added changes, 1 property change
-
- // Ensure first event is parent node's creation change
- const auto parentCreationEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!parentCreationEvent.isNull());
- QCOMPARE(parentCreationEvent->subjectId(), parent->id());
-
- const auto childCreationEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!childCreationEvent.isNull());
- QCOMPARE(childCreationEvent->subjectId(), child->id());
+ QCOMPARE(spy.events.size(), 1); // 1 child added changes
const auto parentNewChildEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
QVERIFY(!parentNewChildEvent.isNull());
@@ -1317,22 +1532,19 @@ void tst_Nodes::checkConstructionWithNonRootParent()
QCOMPARE(parentNewChildEvent->addedNodeId(), parent->id());
// Ensure second and last event is property set change
- const auto propertyEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyUpdatedChange>();
- QVERIFY(!propertyEvent.isNull());
- QCOMPARE(propertyEvent->subjectId(), root->id());
- QCOMPARE(propertyEvent->propertyName(), "nodeProperty");
- QCOMPARE(propertyEvent->value().value<Qt3DCore::QNodeId>(), child->id());
+ QCOMPARE(spy.dirtyNodes.size(), 1);
+ QCOMPARE(spy.dirtyNodes.front(), root.data());
}
void tst_Nodes::checkConstructionAsListElement()
{
// GIVEN
ObserverSpy spy;
- Qt3DCore::QScene scene;
- QScopedPointer<MyQNode> root(new MyQNode());
+ Qt3DCore::QAspectEngine engine;
+ QScopedPointer<MyQEntity> root(new MyQEntity());
// WHEN
- root->setArbiterAndScene(&spy, &scene);
+ root->setArbiterAndEngine(&spy, &engine);
root->setSimulateBackendCreated(true);
// THEN
@@ -1347,25 +1559,8 @@ void tst_Nodes::checkConstructionAsListElement()
QCoreApplication::processEvents();
QCOMPARE(root->children().count(), 1);
- QCOMPARE(spy.events.size(), 3); // 1 creation change, 1 child added change, 1 property change
-
- // Ensure first event is child node's creation change
- const auto creationEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!creationEvent.isNull());
- QCOMPARE(creationEvent->subjectId(), node->id());
-
- const auto newChildEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
- QVERIFY(!newChildEvent.isNull());
- QCOMPARE(newChildEvent->subjectId(), root->id());
- QCOMPARE(newChildEvent->propertyName(), "children");
- QCOMPARE(newChildEvent->addedNodeId(), node->id());
-
- // Ensure second and last event is property set change
- const auto propertyEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
- QVERIFY(!propertyEvent.isNull());
- QCOMPARE(propertyEvent->subjectId(), root->id());
- QCOMPARE(propertyEvent->propertyName(), "attribute");
- QCOMPARE(newChildEvent->addedNodeId(), node->id());
+ QCOMPARE(spy.dirtyNodes.size(), 1); // 1 property change
+ QCOMPARE(spy.dirtySubNodes.size(), 1); // 1 child added change
}
void tst_Nodes::checkSceneIsSetOnConstructionWithParent()
@@ -1399,8 +1594,7 @@ void tst_Nodes::checkSceneIsSetOnConstructionWithParent()
QCoreApplication::processEvents();
QCOMPARE(root->children().count(), 1);
QCOMPARE(subTreeRoot->children().count(), 5);
- QCOMPARE(spy.events.size(), 12); // 1 subTreeRoot creation change, 5 child creation, 5 cmp creation, 1 child added (subTree to root)
-
+ QCOMPARE(spy.events.size(), 1); // 1 child added (subTree to root)
spy.events.clear();
@@ -1411,7 +1605,54 @@ void tst_Nodes::checkSceneIsSetOnConstructionWithParent()
}
// THEN
- QCOMPARE(spy.events.size(), 10); // 5 QComponentAddedChange(entity, cmp) and 5 QComponentAddedChange(cmp, entity)
+ QCOMPARE(spy.events.size(), 0);
+ QCOMPARE(spy.dirtySubNodes.size(), 5); // 5 entities changed
+}
+
+void tst_Nodes::checkSubNodePostConstructIsCalledWhenReferincingNodeProperty()
+{
+ // GIVEN
+ ObserverSpy spy;
+ Qt3DCore::QAspectEngine engine;
+ Qt3DCore::QScene scene(&engine);
+ QScopedPointer<MyQNode> root(new MyQNode());
+
+ // WHEN
+ root->setArbiterAndScene(&spy, &scene);
+ root->setSimulateBackendCreated(true);
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->scene() != nullptr);
+
+ // WHEN
+ Qt3DCore::QEntity *subTreeRoot = new Qt3DCore::QEntity(root.data());
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(subTreeRoot)->m_hasBackendNode);
+
+ // WHEN
+ MyFakeMaterial *material = new MyFakeMaterial(subTreeRoot);
+ subTreeRoot->addComponent(material);
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(material)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(material->m_effect)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(material->m_technique)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(material->m_renderPass)->m_hasBackendNode);
+
+ // WHEN
+ MyQNode *fakeRenderState = new MyQNode(material);
+ Qt3DCore::QNodePrivate *dPtr = Qt3DCore::QNodePrivate::get(fakeRenderState);
+
+ // THEN
+ QVERIFY(!dPtr->m_hasBackendNode);
+
+ // WHEN
+ material->m_renderPass->addAttribute(fakeRenderState);
+
+ // THEN
+ QVERIFY(dPtr->m_hasBackendNode);
}
void tst_Nodes::appendingParentlessComponentToEntityWithoutScene()
@@ -1440,33 +1681,21 @@ void tst_Nodes::appendingParentlessComponentToEntityWithoutScene()
QVERIFY(entity->components().count() == 1);
QVERIFY(entity->components().first() == comp);
QVERIFY(comp->parentNode() == entity.data());
- QCOMPARE(entitySpy.events.size(), 1);
- QVERIFY(entitySpy.events.first().wasLocked());
- QCOMPARE(componentSpy.events.size(), 1);
+ QCOMPARE(entitySpy.events.size(), 0);
+ QCOMPARE(entitySpy.dirtyNodes.size(), 1);
+ QCOMPARE(entitySpy.dirtySubNodes.size(), 1);
+
+ const auto event = entitySpy.dirtySubNodes.first();
+ QCOMPARE(event.change, Qt3DCore::ComponentAdded);
+ QCOMPARE(event.node, entity.data());
+ QCOMPARE(event.subNode, comp);
+ QCOMPARE(event.property, nullptr);
// Note: since QEntity has no scene in this test case, we only have the
// ComponentAdded event In theory we should also get the NodeCreated event
// when setting the parent but that doesn't happen since no scene is
// actually set on the entity and that QNodePrivate::_q_addChild will
// return early in such a case.
-
- // Check that we received ComponentAdded
- {
- const auto event = entitySpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>();
- QCOMPARE(event->type(), Qt3DCore::ComponentAdded);
- QCOMPARE(event->subjectId(), entity->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
- }
- {
- const auto event = componentSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>();
- QCOMPARE(event->type(), Qt3DCore::ComponentAdded);
- QCOMPARE(event->subjectId(), comp->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
- }
}
}
@@ -1474,11 +1703,11 @@ void tst_Nodes::appendingParentlessComponentToNonRootEntity()
{
// GIVEN
ObserverSpy eventSpy;
- Qt3DCore::QScene scene;
+ Qt3DCore::QAspectEngine engine;
{
QScopedPointer<MyQEntity> root(new MyQEntity());
- root->setArbiterAndScene(&eventSpy, &scene);
+ root->setArbiterAndEngine(&eventSpy, &engine);
root->setSimulateBackendCreated(true);
QCoreApplication::processEvents();
@@ -1504,26 +1733,13 @@ void tst_Nodes::appendingParentlessComponentToNonRootEntity()
QVERIFY(entity->components().first() == comp);
QVERIFY(comp->parentNode() == entity.data());
- QCOMPARE(eventSpy.events.size(), 5);
- // - entity created
- // - comp created
+ QCOMPARE(eventSpy.events.size(), 1);
// - entity added as child to root
- // - component added for entity
- // - component added for compontent
QVERIFY(eventSpy.events.first().wasLocked());
- {
- const auto event = eventSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!event.isNull());
- QCOMPARE(event->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event->subjectId(), entity->id());
- }
- {
- const auto event = eventSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!event.isNull());
- QCOMPARE(event->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event->subjectId(), comp->id());
- }
+ QVERIFY(Qt3DCore::QNodePrivate::get(entity.data())->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(comp)->m_hasBackendNode);
+
{
const auto event = eventSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
QVERIFY(!event.isNull());
@@ -1532,24 +1748,6 @@ void tst_Nodes::appendingParentlessComponentToNonRootEntity()
QCOMPARE(event->propertyName(), QByteArrayLiteral("children"));
QCOMPARE(event->addedNodeId(), entity->id());
}
- {
- const auto event = eventSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>();
- QVERIFY(!event.isNull());
- QCOMPARE(event->type(), Qt3DCore::ComponentAdded);
- QCOMPARE(event->subjectId(), entity->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
- }
- {
- const auto event = eventSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>();
- QVERIFY(!event.isNull());
- QCOMPARE(event->type(), Qt3DCore::ComponentAdded);
- QCOMPARE(event->subjectId(), comp->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
- }
}
}
@@ -1557,11 +1755,11 @@ void tst_Nodes::appendingParentlessComponentToEntityWithScene()
{
// GIVEN
ObserverSpy eventSpy;
- Qt3DCore::QScene scene;
+ Qt3DCore::QAspectEngine engine;
{
QScopedPointer<MyQEntity> entity(new MyQEntity());
- entity->setArbiterAndScene(&eventSpy, &scene);
+ entity->setArbiterAndEngine(&eventSpy, &engine);
entity->setSimulateBackendCreated(true);
QCoreApplication::processEvents();
@@ -1583,20 +1781,11 @@ void tst_Nodes::appendingParentlessComponentToEntityWithScene()
QVERIFY(entity->components().first() == comp);
QVERIFY(comp->parentNode() == entity.data());
- QCOMPARE(eventSpy.events.size(), 4);
- // - entity created
+ QCOMPARE(eventSpy.events.size(), 1);
// - child added
- // - component added for entity
- // - component added for compontent
QVERIFY(eventSpy.events.first().wasLocked());
{
- const auto event = eventSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
- QVERIFY(!event.isNull());
- QCOMPARE(event->type(), Qt3DCore::NodeCreated);
- QCOMPARE(event->subjectId(), comp->id());
- }
- {
const auto event = eventSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
QVERIFY(!event.isNull());
QCOMPARE(event->type(), Qt3DCore::PropertyValueAdded);
@@ -1604,24 +1793,6 @@ void tst_Nodes::appendingParentlessComponentToEntityWithScene()
QCOMPARE(event->propertyName(), QByteArrayLiteral("children"));
QCOMPARE(event->addedNodeId(), comp->id());
}
- {
- const auto event = eventSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>();
- QVERIFY(!event.isNull());
- QCOMPARE(event->type(), Qt3DCore::ComponentAdded);
- QCOMPARE(event->subjectId(), entity->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
- }
- {
- const auto event = eventSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>();
- QVERIFY(!event.isNull());
- QCOMPARE(event->type(), Qt3DCore::ComponentAdded);
- QCOMPARE(event->subjectId(), comp->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
- }
}
}
@@ -1651,24 +1822,15 @@ void tst_Nodes::appendingComponentToEntity()
QVERIFY(entity->components().count() == 1);
QVERIFY(entity->components().first() == comp);
QVERIFY(comp->parentNode() == entity.data());
- QCOMPARE(entitySpy.events.size(), 1);
- QVERIFY(entitySpy.events.first().wasLocked());
- {
- const auto event = entitySpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>();
- QCOMPARE(event->type(), Qt3DCore::ComponentAdded);
- QCOMPARE(event->subjectId(), entity->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
- }
- {
- const auto event = componentSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentAddedChange>();
- QCOMPARE(event->type(), Qt3DCore::ComponentAdded);
- QCOMPARE(event->subjectId(), comp->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
- }
+ QCOMPARE(entitySpy.events.size(), 0);
+ QCOMPARE(entitySpy.dirtyNodes.size(), 1);
+ QCOMPARE(entitySpy.dirtySubNodes.size(), 1);
+ QCOMPARE(entitySpy.dirtyNodes.first(), entity.data());
+ const auto event = entitySpy.dirtySubNodes.takeFirst();
+ QCOMPARE(event.node, entity.data());
+ QCOMPARE(event.subNode, comp);
+ QCOMPARE(event.change, Qt3DCore::ComponentAdded);
+ QCOMPARE(event.property, nullptr);
}
}
@@ -1693,6 +1855,8 @@ void tst_Nodes::removingComponentFromEntity()
// WHEN
entitySpy.events.clear();
+ entitySpy.dirtyNodes.clear();
+ entitySpy.dirtySubNodes.clear();
componentSpy.events.clear();
entity->removeComponent(comp);
@@ -1700,24 +1864,17 @@ void tst_Nodes::removingComponentFromEntity()
QVERIFY(entity->components().count() == 0);
QVERIFY(comp->parent() == entity.data());
QVERIFY(entity->children().count() == 1);
- QCOMPARE(entitySpy.events.size(), 1);
- QVERIFY(entitySpy.events.first().wasLocked());
- QCOMPARE(componentSpy.events.size(), 1);
- {
- const auto event = entitySpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentRemovedChange>();
- QCOMPARE(event->type(), Qt3DCore::ComponentRemoved);
- QCOMPARE(event->subjectId(), entity->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
- }
+ QCOMPARE(entitySpy.events.size(), 0);
+ QCOMPARE(entitySpy.dirtyNodes.size(), 1);
+ QCOMPARE(entitySpy.dirtySubNodes.size(), 1);
+ QCOMPARE(componentSpy.events.size(), 0);
{
- const auto event = componentSpy.events.takeFirst().change().dynamicCast<Qt3DCore::QComponentRemovedChange>();
- QCOMPARE(event->type(), Qt3DCore::ComponentRemoved);
- QCOMPARE(event->subjectId(), comp->id());
- QCOMPARE(event->entityId(), entity->id());
- QCOMPARE(event->componentId(), comp->id());
- QCOMPARE(event->componentMetaObject(), comp->metaObject());
+ const auto event = entitySpy.dirtySubNodes.takeFirst();
+ qDebug() << event.change;
+ QCOMPARE(event.change, Qt3DCore::ComponentRemoved);
+ QCOMPARE(event.node, entity.data());
+ QCOMPARE(event.subNode, comp);
+ QCOMPARE(event.property, nullptr);
}
}
}
@@ -1731,12 +1888,8 @@ void tst_Nodes::changeCustomProperty()
// WHEN
node->setCustomProperty(QStringLiteral("foo"));
// THEN
- QCOMPARE(spy.events.size(), 1);
- QVERIFY(spy.events.first().wasLocked());
- Qt3DCore::QPropertyUpdatedChangePtr event = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(event->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(event->propertyName(), "customProperty");
- QCOMPARE(event->value().toString(), QString("foo"));
+ QCOMPARE(spy.dirtyNodes.size(), 1);
+ QCOMPARE(spy.dirtyNodes.front(), node.data());
}
void tst_Nodes::checkDestruction()
@@ -1919,25 +2072,22 @@ void tst_Nodes::checkEnabledUpdate()
{
// WHEN
node.setEnabled(false);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "enabled");
- QCOMPARE(change->value().value<bool>(), node.isEnabled());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &node);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
node.setEnabled(false);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -1996,6 +2146,60 @@ void tst_Nodes::checkTrackedPropertyNamesUpdate()
}
+void tst_Nodes::checkNodeRemovedFromDirtyListOnDestruction()
+{
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DCore::QScene scene;
+
+ {
+ // GIVEN
+ QScopedPointer<MyQNode> node(new MyQNode());
+ node->setArbiterAndScene(&arbiter, &scene);
+
+ // WHEN
+ node->setEnabled(false);
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), node.data());
+
+ // WHEN
+ // scene should be unset and node removed from arbiter dirtyList
+ node.reset();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
+ }
+ {
+ // GIVEN
+ QScopedPointer<MyQNode> node(new MyQNode());
+ node->setArbiterAndScene(&arbiter, &scene);
+
+
+ Qt3DCore::QNode *child = new Qt3DCore::QNode(node.data());
+ // Wait for deferred initialization of child node
+ QCoreApplication::processEvents();
+
+ // WHEN
+ child->setEnabled(false);
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1); // childAdded
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), child);
+
+ // WHEN
+ // scene should be unset and child node removed from arbiter dirtyList
+ node.reset();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1); // childRemoved (no destroyed change since we had no backend)
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
+ }
+}
QTEST_MAIN(tst_Nodes)
diff --git a/tests/auto/core/qarmature/tst_qarmature.cpp b/tests/auto/core/qarmature/tst_qarmature.cpp
index f624b998f..098efd1af 100644
--- a/tests/auto/core/qarmature/tst_qarmature.cpp
+++ b/tests/auto/core/qarmature/tst_qarmature.cpp
@@ -30,7 +30,6 @@
#include <Qt3DCore/qarmature.h>
#include <Qt3DCore/private/qarmature_p.h>
#include <Qt3DCore/qskeleton.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
@@ -98,33 +97,22 @@ private Q_SLOTS:
// WHEN
QSkeleton *skeleton = new QSkeleton(armature.data());
- QCoreApplication::processEvents();
- arbiter.events.clear();
-
armature->setSkeleton(skeleton);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "skeleton");
- QCOMPARE(change->value().value<QNodeId>(), skeleton->id());
- QCOMPARE(change->type(), PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), armature.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
armature->setSkeleton(nullptr);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "skeleton");
- QCOMPARE(change->value().value<QNodeId>(), QNodeId());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), armature.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkSkeletonBookkeeping()
diff --git a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp
index 94519f5e5..eb20536e6 100644
--- a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp
+++ b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp
@@ -92,7 +92,7 @@ private: \
\
QVariant executeCommand(const QStringList &args) override \
{ \
- if (args.size() >= 2 && args.first() == QLatin1Literal("echo")) { \
+ if (args.size() >= 2 && args.first() == QLatin1String("echo")) { \
QStringList list = args; \
list.removeFirst(); \
return QString("%1 said '%2'").arg(metaObject()->className()).arg(list.join(QLatin1Char(' '))); \
diff --git a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp
index 4beb28bc2..e54193398 100644
--- a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp
+++ b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp
@@ -43,7 +43,6 @@
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qcomponent.h>
#include <Qt3DCore/qbackendnode.h>
-#include <Qt3DCore/private/qsceneobserverinterface_p.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <QThread>
@@ -350,38 +349,6 @@ private:
bool m_allowFrontendNotifications;
};
-class tst_SceneObserver : public Qt3DCore::QSceneObserverInterface
-{
- // QSceneObserverInterface interface
-public:
- void sceneNodeAdded(Qt3DCore::QSceneChangePtr &e)
- {
- QVERIFY(!e.isNull());
- QVERIFY(e->type() == Qt3DCore::NodeCreated);
- m_lastChange = e;
- }
-
- void sceneNodeRemoved(Qt3DCore::QSceneChangePtr &e)
- {
- QVERIFY(!e.isNull());
- QVERIFY((e->type() == Qt3DCore::NodeDeleted));
- m_lastChange = e;
- }
-
- void sceneNodeUpdated(Qt3DCore::QSceneChangePtr &e)
- {
- m_lastChange = e;
- }
-
- Qt3DCore::QSceneChangePtr lastChange() const
- {
- return m_lastChange;
- }
-
-private:
- Qt3DCore::QSceneChangePtr m_lastChange;
-};
-
void tst_QChangeArbiter::registerObservers()
{
// GIVEN
@@ -411,12 +378,12 @@ void tst_QChangeArbiter::registerObservers()
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers)
+ for (tst_SimpleObserver *o : qAsConst(observers))
QVERIFY(o->lastChange().isNull());
child->setParent(root);
arbiter->syncChanges();
- Q_FOREACH (tst_SimpleObserver *o, observers) {
+ for (tst_SimpleObserver *o : qAsConst(observers)) {
QCOMPARE(o->lastChanges().size(), 1);
QVERIFY(o->lastChanges().last()->type() == Qt3DCore::PropertyValueAdded);
}
@@ -452,48 +419,31 @@ void tst_QChangeArbiter::registerSceneObserver()
observers << s;
}
- QList<tst_SceneObserver *> sceneObservers;
- for (int i = 0; i < 5; i++) {
- tst_SceneObserver *s = new tst_SceneObserver();
- arbiter->registerSceneObserver(s);
- sceneObservers << s;
- }
-
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers)
+ for (tst_SimpleObserver *o : qAsConst(observers))
QVERIFY(o->lastChange().isNull());
- Q_FOREACH (tst_SceneObserver *s, sceneObservers)
- QVERIFY(s->lastChange().isNull());
// WHEN
child->setParent(root);
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers) {
+ for (tst_SimpleObserver *o : qAsConst(observers)) {
QVERIFY(!o->lastChange().isNull());
QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded);
}
- Q_FOREACH (tst_SceneObserver *s, sceneObservers) {
- QVERIFY(!s->lastChange().isNull());
- QVERIFY(s->lastChange()->type() == Qt3DCore::NodeCreated);
- }
// WHEN
root->sendComponentAddedNotification(&dummyComponent);
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers) {
+ for (tst_SimpleObserver *o : qAsConst(observers)) {
QVERIFY(!o->lastChange().isNull());
QVERIFY(o->lastChange()->type() == Qt3DCore::ComponentAdded);
}
- Q_FOREACH (tst_SceneObserver *s, sceneObservers) {
- QVERIFY(!s->lastChange().isNull());
- QVERIFY(s->lastChange()->type() == Qt3DCore::NodeCreated);
- }
Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data());
}
@@ -527,7 +477,7 @@ void tst_QChangeArbiter::unregisterObservers()
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers)
+ for (tst_SimpleObserver *o : qAsConst(observers))
QVERIFY(o->lastChange().isNull());
// WHEN
@@ -535,20 +485,20 @@ void tst_QChangeArbiter::unregisterObservers()
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers) {
+ for (tst_SimpleObserver *o : qAsConst(observers)) {
QVERIFY(!o->lastChange().isNull());
QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded);
}
// WHEN
- Q_FOREACH (tst_SimpleObserver *o, observers)
+ for (tst_SimpleObserver *o : qAsConst(observers))
arbiter->unregisterObserver(o, root->id());
root->sendAllChangesNotification();
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers) {
+ for (tst_SimpleObserver *o : qAsConst(observers)) {
QVERIFY(!o->lastChange().isNull());
QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded);
}
@@ -575,6 +525,7 @@ void tst_QChangeArbiter::unregisterSceneObservers()
Qt3DCore::QNode *child = new tst_Node();
Qt3DCore::QNodePrivate::get(root)->setScene(scene.data());
Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true;
+ Qt3DCore::QNodePrivate::get(child)->m_hasBackendNode = true;
scene->addObservable(root);
QList<tst_SimpleObserver *> observers;
@@ -584,79 +535,51 @@ void tst_QChangeArbiter::unregisterSceneObservers()
observers << s;
}
- QList<tst_SceneObserver *> sceneObservers;
- for (int i = 0; i < 5; i++) {
- tst_SceneObserver *s = new tst_SceneObserver();
- arbiter->registerSceneObserver(s);
- sceneObservers << s;
- }
-
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers)
+ for (tst_SimpleObserver *o : qAsConst(observers))
QVERIFY(o->lastChange().isNull());
- Q_FOREACH (tst_SceneObserver *s, sceneObservers)
- QVERIFY(s->lastChange().isNull());
// WHEN
child->setParent(root);
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers) {
+ for (tst_SimpleObserver *o : qAsConst(observers)) {
QVERIFY(!o->lastChange().isNull());
QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded);
}
- Q_FOREACH (tst_SceneObserver *s, sceneObservers) {
- QVERIFY(!s->lastChange().isNull());
- QVERIFY(s->lastChange()->type() == Qt3DCore::NodeCreated);
- }
// WHEN
root->sendComponentAddedNotification(&dummyComponent);
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers) {
+ for (tst_SimpleObserver *o : qAsConst(observers)) {
QVERIFY(!o->lastChange().isNull());
QVERIFY(o->lastChange()->type() == Qt3DCore::ComponentAdded);
}
- Q_FOREACH (tst_SceneObserver *s, sceneObservers) {
- QVERIFY(!s->lastChange().isNull());
- QVERIFY(s->lastChange()->type() == Qt3DCore::NodeCreated);
- }
// WHEN
child->setParent(Q_NODE_NULLPTR);
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers) {
+ for (tst_SimpleObserver *o : qAsConst(observers)) {
QVERIFY(!o->lastChange().isNull());
QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueRemoved);
}
- Q_FOREACH (tst_SceneObserver *s, sceneObservers) {
- QVERIFY(!s->lastChange().isNull());
- QVERIFY(s->lastChange()->type() == Qt3DCore::NodeDeleted);
- }
-
- Q_FOREACH (tst_SceneObserver *s, sceneObservers)
- arbiter->unregisterSceneObserver(s);
// WHEN
child->setParent(root);
arbiter->syncChanges();
// THEN
- Q_FOREACH (tst_SimpleObserver *o, observers) {
+ for (tst_SimpleObserver *o : qAsConst(observers)) {
QVERIFY(!o->lastChange().isNull());
QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded);
}
- Q_FOREACH (tst_SceneObserver *s, sceneObservers) {
- QVERIFY(!s->lastChange().isNull());
- QVERIFY(s->lastChange()->type() == Qt3DCore::NodeDeleted);
- }
Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data());
}
@@ -810,25 +733,19 @@ void tst_QChangeArbiter::distributePropertyChanges()
// WHEN
root->setProp1(root->prop1() + 1);
- arbiter->syncChanges();
// THEN
- QVERIFY(!rootObserver->lastChange().isNull());
- QCOMPARE(rootObserver->lastChange()->type(), Qt3DCore::PropertyUpdated);
- Qt3DCore::QPropertyUpdatedChangePtr propChange = qSharedPointerDynamicCast<Qt3DCore::QPropertyUpdatedChange>(rootObserver->lastChange());
- QCOMPARE(root->id(), propChange->subjectId());
- QCOMPARE(QString(propChange->propertyName()), QString("prop1"));
+ auto dirtyNodes = arbiter->takeDirtyFrontEndNodes();
+ QCOMPARE(dirtyNodes.size(), 1);
+ QCOMPARE(dirtyNodes.front(), root);
// WHEN
root->setProp2(root->prop2() + 1.f);
- arbiter->syncChanges();
// THEN
- QVERIFY(!rootObserver->lastChange().isNull());
- QCOMPARE(rootObserver->lastChange()->type(), Qt3DCore::PropertyUpdated);
- propChange = qSharedPointerDynamicCast<Qt3DCore::QPropertyUpdatedChange>(rootObserver->lastChange());
- QCOMPARE(root->id(), propChange->subjectId());
- QCOMPARE(QString(propChange->propertyName()), QString("prop2"));
+ dirtyNodes = arbiter->takeDirtyFrontEndNodes();
+ QCOMPARE(dirtyNodes.size(), 1);
+ QCOMPARE(dirtyNodes.front(), root);
// Test change notifications made to an entity that was added to the scene
// via QNode::setParent()
@@ -839,14 +756,11 @@ void tst_QChangeArbiter::distributePropertyChanges()
tst_SimpleObserver *setParentChildObserver = new tst_SimpleObserver();
arbiter->registerObserver(setParentChildObserver, setParentChild->id());
setParentChild->setProp2(setParentChild->prop2() + 1.f);
- arbiter->syncChanges();
// THEN
- QVERIFY(!setParentChildObserver->lastChange().isNull());
- QCOMPARE(setParentChildObserver->lastChange()->type(), Qt3DCore::PropertyUpdated);
- propChange = qSharedPointerDynamicCast<Qt3DCore::QPropertyUpdatedChange>(setParentChildObserver->lastChange());
- QCOMPARE(setParentChild->id(), propChange->subjectId());
- QCOMPARE(QString(propChange->propertyName()), QString("prop2"));
+ dirtyNodes = arbiter->takeDirtyFrontEndNodes();
+ QCOMPARE(dirtyNodes.size(), 1);
+ QCOMPARE(dirtyNodes.front(), setParentChild);
// Test change notifications made to an entity that was added to the scene
// via the QNode() constructor parent parameter
@@ -857,14 +771,11 @@ void tst_QChangeArbiter::distributePropertyChanges()
tst_SimpleObserver *directChildObserver = new tst_SimpleObserver();
arbiter->registerObserver(directChildObserver, directChild->id());
directChild->setProp1(directChild->prop1() + 1);
- arbiter->syncChanges();
// THEN
- QVERIFY(!directChildObserver->lastChange().isNull());
- QCOMPARE(directChildObserver->lastChange()->type(), Qt3DCore::PropertyUpdated);
- propChange = qSharedPointerDynamicCast<Qt3DCore::QPropertyUpdatedChange>(directChildObserver->lastChange());
- QCOMPARE(directChild->id(), propChange->subjectId());
- QCOMPARE(QString(propChange->propertyName()), QString("prop1"));
+ dirtyNodes = arbiter->takeDirtyFrontEndNodes();
+ QCOMPARE(dirtyNodes.size(), 1);
+ QCOMPARE(dirtyNodes.front(), directChild);
Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data());
}
diff --git a/tests/auto/core/qframeallocator/tst_qframeallocator.cpp b/tests/auto/core/qframeallocator/tst_qframeallocator.cpp
index a098792ee..3d2355eb8 100644
--- a/tests/auto/core/qframeallocator/tst_qframeallocator.cpp
+++ b/tests/auto/core/qframeallocator/tst_qframeallocator.cpp
@@ -566,19 +566,19 @@ void tst_QFrameAllocator::testAllocationComposedValues()
t.list.append(i);
}
- QList<composed *> composedValues;
+ composed *composedValues[30];
- for (int i = 0; i < 30; i++) {
- composed *v = f.allocate<composed>();
+ for (auto &v : composedValues) {
+ v = f.allocate<composed>();
QVERIFY(v);
- for (int j = 0; j < 1; j++) {
+ for (int j = 0; j < 100; j++) {
v->vec.append(j);
v->list.append(j);
v->t = 100;
}
}
- Q_FOREACH (composed *c, composedValues) {
+ for (composed *c : composedValues) {
QCOMPARE(c->vec.size(), 100);
QCOMPARE(c->list.size(), 100);
QCOMPARE(c->t, 100);
@@ -605,7 +605,7 @@ void tst_QFrameAllocator::allocateSubclass()
QCOMPARE(composeds.count(), 256);
- Q_FOREACH (composed *c, composeds) {
+ for (composed *c : qAsConst(composeds)) {
subclass *s = static_cast<subclass *>(c);
s->toto = 2586.0f;
}
diff --git a/tests/auto/core/qjoint/tst_qjoint.cpp b/tests/auto/core/qjoint/tst_qjoint.cpp
index ec1a45f90..2fff33b8f 100644
--- a/tests/auto/core/qjoint/tst_qjoint.cpp
+++ b/tests/auto/core/qjoint/tst_qjoint.cpp
@@ -29,7 +29,6 @@
#include <QtTest/QTest>
#include <Qt3DCore/qjoint.h>
#include <Qt3DCore/private/qjoint_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <QObject>
@@ -317,69 +316,54 @@ private Q_SLOTS:
{
// WHEN
joint.setScale(QVector3D(2.0f, 1.0f, 3.0f));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "scale");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<QVector3D>(), joint.scale());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &joint);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
joint.setScale(QVector3D(2.0f, 1.0f, 3.0f));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
{
// WHEN
const auto newValue = QQuaternion::fromAxisAndAngle(1.0f, 1.0f, 1.0f, 45.0f);
joint.setRotation(newValue);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "rotation");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<QQuaternion>(), newValue);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &joint);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
joint.setRotation(newValue);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
{
// WHEN
const QVector3D newValue(1.0f, 2.0f, 3.0f);
joint.setTranslation(newValue);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "translation");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<QVector3D>(), newValue);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &joint);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
joint.setTranslation(newValue);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
{
@@ -387,23 +371,18 @@ private Q_SLOTS:
QMatrix4x4 newValue;
newValue.rotate(90.0f, 1.0f, 0.0f, 0.0f);
joint.setInverseBindMatrix(newValue);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "inverseBindMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().value<QMatrix4x4>(), newValue);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &joint);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
joint.setInverseBindMatrix(newValue);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
};
diff --git a/tests/auto/core/qpostman/tst_qpostman.cpp b/tests/auto/core/qpostman/tst_qpostman.cpp
index 6fcb6e840..f548d38fa 100644
--- a/tests/auto/core/qpostman/tst_qpostman.cpp
+++ b/tests/auto/core/qpostman/tst_qpostman.cpp
@@ -34,7 +34,7 @@
#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include "testpostmanarbiter.h"
diff --git a/tests/auto/core/qscene/qscene.pro b/tests/auto/core/qscene/qscene.pro
index 829130997..150b86f71 100644
--- a/tests/auto/core/qscene/qscene.pro
+++ b/tests/auto/core/qscene/qscene.pro
@@ -6,3 +6,5 @@ QT += testlib core-private 3dcore 3dcore-private
SOURCES += \
tst_qscene.cpp
+
+include(../common/common.pri)
diff --git a/tests/auto/core/qscene/tst_qscene.cpp b/tests/auto/core/qscene/tst_qscene.cpp
index 36ec14b4e..ecc72e992 100644
--- a/tests/auto/core/qscene/tst_qscene.cpp
+++ b/tests/auto/core/qscene/tst_qscene.cpp
@@ -34,6 +34,7 @@
#include <Qt3DCore/private/qobservableinterface_p.h>
#include <Qt3DCore/private/qlockableobserverinterface_p.h>
#include <private/qnode_p.h>
+#include "testpostmanarbiter.h"
class tst_QScene : public QObject
{
@@ -60,14 +61,6 @@ private slots:
void nodeUpdatePropertyTrackData();
};
-class tst_LockableObserver : public Qt3DCore::QLockableObserverInterface
-{
-public:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &) override {}
- void sceneChangeEventWithLock(const Qt3DCore::QSceneChangePtr &) override {}
- void sceneChangeEventWithLock(const Qt3DCore::QSceneChangeList &) override {}
-};
-
class tst_Observable : public Qt3DCore::QObservableInterface
{
public:
@@ -111,7 +104,7 @@ void tst_QScene::addObservable()
observables.append(new tst_Observable());
Qt3DCore::QScene *scene = new Qt3DCore::QScene;
- scene->setArbiter(new tst_LockableObserver);
+ scene->setArbiter(new TestArbiter);
// WHEN
for (int i = 0; i < 5; i++)
@@ -120,18 +113,18 @@ void tst_QScene::addObservable()
for (int i = 0; i < 5; i++)
scene->addObservable(observables.at(i + 5), node2->id());
- Qt3DCore::QObservableList obs1 = scene->lookupObservables(node1->id());
- Qt3DCore::QObservableList obs2 = scene->lookupObservables(node2->id());
+ const Qt3DCore::QObservableList obs1 = scene->lookupObservables(node1->id());
+ const Qt3DCore::QObservableList obs2 = scene->lookupObservables(node2->id());
// THEN
QCOMPARE(obs1.count(), 5);
QCOMPARE(obs2.count(), obs1.count());
- Q_FOREACH (Qt3DCore::QObservableInterface *o, obs1) {
+ for (Qt3DCore::QObservableInterface *o : obs1) {
QVERIFY(scene->nodeIdFromObservable(o) == node1->id());
QVERIFY(scene->lookupNode(node1->id()) == nullptr);
}
- Q_FOREACH (Qt3DCore::QObservableInterface *o, obs2) {
+ for (Qt3DCore::QObservableInterface *o : obs2) {
QVERIFY(scene->nodeIdFromObservable(o) == node2->id());
QVERIFY(scene->lookupNode(node2->id()) == nullptr);
}
@@ -146,14 +139,14 @@ void tst_QScene::addNodeObservable()
nodes.append(new tst_Node());
Qt3DCore::QScene *scene = new Qt3DCore::QScene;
- scene->setArbiter(new tst_LockableObserver);
+ scene->setArbiter(new TestArbiter);
// WHEN
for (int i = 0; i < 10; i++)
scene->addObservable(nodes.at(i));
// THEN
- Q_FOREACH (Qt3DCore::QNode *n, nodes) {
+ for (Qt3DCore::QNode *n : qAsConst(nodes)) {
QVERIFY(n == scene->lookupNode(n->id()));
QVERIFY(scene->lookupObservables(n->id()).isEmpty());
}
@@ -171,7 +164,7 @@ void tst_QScene::removeObservable()
observables.append(new tst_Observable());
Qt3DCore::QScene *scene = new Qt3DCore::QScene;
- scene->setArbiter(new tst_LockableObserver);
+ scene->setArbiter(new TestArbiter);
// WHEN
for (int i = 0; i < 5; i++)
@@ -222,7 +215,7 @@ void tst_QScene::removeNodeObservable()
observables.append(new tst_Observable());
Qt3DCore::QScene *scene = new Qt3DCore::QScene;
- scene->setArbiter(new tst_LockableObserver);
+ scene->setArbiter(new TestArbiter);
// WHEN
scene->addObservable(node1);
@@ -281,7 +274,7 @@ void tst_QScene::addChildNode()
QCoreApplication::processEvents();
// THEN
- Q_FOREACH (Qt3DCore::QNode *n, nodes) {
+ for (Qt3DCore::QNode *n : qAsConst(nodes)) {
QVERIFY(scene->lookupNode(n->id()) == n);
}
}
@@ -311,10 +304,12 @@ void tst_QScene::deleteChildNode()
for (int i = 0; i < 10; i++) {
Qt3DCore::QNode *child1 = new tst_Node();
child1->setParent(nodes1.isEmpty() ? root1 : nodes1.last());
+ Qt3DCore::QNodePrivate::get(child1)->m_hasBackendNode = true;
nodes1.append(child1);
Qt3DCore::QNode *child2 = new tst_Node();
child2->setParent(nodes2.isEmpty() ? root2 : nodes2.last());
+ Qt3DCore::QNodePrivate::get(child2)->m_hasBackendNode = true;
nodes2.append(child2);
}
QCoreApplication::processEvents();
@@ -370,6 +365,7 @@ void tst_QScene::removeChildNode()
child->setParent(root);
else
child->setParent(nodes.last());
+ Qt3DCore::QNodePrivate::get(child)->m_hasBackendNode = true;
nodes.append(child);
}
diff --git a/tests/auto/core/qskeleton/tst_qskeleton.cpp b/tests/auto/core/qskeleton/tst_qskeleton.cpp
index f66e07cbe..5c88bd754 100644
--- a/tests/auto/core/qskeleton/tst_qskeleton.cpp
+++ b/tests/auto/core/qskeleton/tst_qskeleton.cpp
@@ -30,9 +30,6 @@
#include <Qt3DCore/qskeleton.h>
#include <Qt3DCore/private/qskeleton_p.h>
#include <Qt3DCore/qjoint.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
@@ -109,33 +106,24 @@ private Q_SLOTS:
// WHEN
QJoint *joint = new QJoint(skeleton.data());
- QCoreApplication::processEvents();
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
skeleton->setRootJoint(joint);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "rootJoint");
- QCOMPARE(change->value().value<QNodeId>(), joint->id());
- QCOMPARE(change->type(), PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), skeleton.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
skeleton->setRootJoint(nullptr);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "rootJoint");
- QCOMPARE(change->value().value<QNodeId>(), QNodeId());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), skeleton.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkRootJointBookkeeping()
@@ -171,38 +159,6 @@ private Q_SLOTS:
// THEN Should not crash when the joint is destroyed (tests for failed removal of destruction helper)
}
}
-
- void checkJointCountPropertyUpdate()
- {
- // GIVEN
- TestArbiter arbiter;
- arbiter.setArbiterOnNode(this);
- QSignalSpy spy(this, SIGNAL(jointCountChanged(int)));
- const int newJointCount = 99;
-
- // THEN
- QVERIFY(spy.isValid());
-
- // WHEN
- auto valueChange = QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- valueChange->setPropertyName("jointCount");
- valueChange->setValue(QVariant(newJointCount));
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 1);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(jointCount(), newJointCount);
-
- // WHEN
- spy.clear();
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 0);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(jointCount(), newJointCount);
- }
};
QTEST_MAIN(tst_QSkeleton)
diff --git a/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp
index 1386429d4..f0f4c3872 100644
--- a/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp
+++ b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp
@@ -169,12 +169,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "source");
- QCOMPARE(change->type(), PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes[0], &skeleton);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -184,21 +183,20 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
-
{
// WHEN
skeleton.setCreateJointsEnabled(true);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "createJointsEnabled");
- QCOMPARE(change->type(), PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes[0], &skeleton);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -208,67 +206,9 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.events.size(), 0);
}
}
-
- void checkStatusPropertyUpdate()
- {
- // GIVEN
- qRegisterMetaType<Qt3DCore::QSkeletonLoader::Status>("Status");
- TestArbiter arbiter;
- arbiter.setArbiterOnNode(this);
- QSignalSpy spy(this, SIGNAL(statusChanged(Status)));
- const QSkeletonLoader::Status newStatus = QSkeletonLoader::Error;
-
- // THEN
- QVERIFY(spy.isValid());
-
- // WHEN
- QPropertyUpdatedChangePtr valueChange(new QPropertyUpdatedChange(QNodeId()));
- valueChange->setPropertyName("status");
- valueChange->setValue(QVariant::fromValue(newStatus));
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 1);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(status(), newStatus);
-
- // WHEN
- spy.clear();
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 0);
- QCOMPARE(arbiter.events.size(), 0);
- QCOMPARE(status(), newStatus);
- }
-
- void checkRootJointPropertyUpdate()
- {
- // GIVEN
- qRegisterMetaType<Qt3DCore::QJoint*>();
- TestArbiter arbiter;
- arbiter.setArbiterOnNode(this);
- QSignalSpy spy(this, SIGNAL(rootJointChanged(Qt3DCore::QJoint*)));
- std::unique_ptr<QJoint> root(new QJoint());
-
- // THEN
- QVERIFY(spy.isValid());
- QVERIFY(rootJoint() == nullptr);
-
- // WHEN
- auto valueChange = QJointChangePtr::create(id());
- valueChange->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes);
- valueChange->setPropertyName("rootJoint");
- valueChange->data = std::move(root);
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(spy.count(), 1);
- QCOMPARE(arbiter.events.size(), 1);
- QVERIFY(rootJoint() != nullptr);
- }
};
QTEST_MAIN(tst_QSkeletonLoader)
diff --git a/tests/auto/core/qtransform/tst_qtransform.cpp b/tests/auto/core/qtransform/tst_qtransform.cpp
index f5527ebf5..37848ffd6 100644
--- a/tests/auto/core/qtransform/tst_qtransform.cpp
+++ b/tests/auto/core/qtransform/tst_qtransform.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include <QtTest/QtTest>
+#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/qcomponent.h>
#include <Qt3DCore/private/qtransform_p.h>
@@ -36,6 +37,15 @@
using namespace Qt3DCore;
+class FakeTransform : public Qt3DCore::QTransform
+{
+public:
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override
+ {
+ Qt3DCore::QTransform::sceneChangeEvent(change);
+ }
+};
+
class tst_QTransform : public QObject
{
Q_OBJECT
@@ -49,6 +59,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(transform.isShareable(), false);
QCOMPARE(transform.matrix(), QMatrix4x4());
+ QCOMPARE(transform.worldMatrix(), QMatrix4x4());
QCOMPARE(transform.scale(), 1.0f);
QCOMPARE(transform.scale3D(), QVector3D(1.0f, 1.0f, 1.0f));
QCOMPARE(transform.rotation(), QQuaternion());
@@ -112,6 +123,7 @@ private Q_SLOTS:
QCOMPARE(transform->translation(), cloneData.translation);
QCOMPARE(transform->scale3D(), cloneData.scale);
QCOMPARE(transform->rotation(), cloneData.rotation);
+ QCOMPARE(transform->worldMatrix(), QMatrix4x4());
}
void checkPropertyUpdates()
@@ -123,74 +135,54 @@ private Q_SLOTS:
// WHEN
transform->setTranslation(QVector3D(454.0f, 427.0f, 383.0f));
- QCoreApplication::processEvents();
// THEN
- Qt3DCore::QPropertyUpdatedChangePtr change;
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "translation");
- QCOMPARE(change->value().value<QVector3D>(), QVector3D(454.0f, 427.0f, 383.0f));
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), transform.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
QQuaternion q = Qt3DCore::QTransform::fromAxisAndAngle(QVector3D(0.0f, 1.0f, 0.0f), 90.0f);
transform->setRotation(q);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "rotation");
- QCOMPARE(change->value().value<QQuaternion>(), q);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), transform.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
transform->setScale3D(QVector3D(883.0f, 1200.0f, 1340.0f));
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "scale3D");
- QCOMPARE(change->value().value<QVector3D>(), QVector3D(883.0f, 1200.0f, 1340.0f));
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), transform.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
// Force the transform to update its matrix
(void)transform->matrix();
transform->setMatrix(QMatrix4x4());
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 3);
- change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "scale3D");
- QCOMPARE(change->value().value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f));
- change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "rotation");
- QCOMPARE(change->value().value<QQuaternion>(), QQuaternion());
- change = arbiter.events.takeFirst().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "translation");
- QCOMPARE(change->value().value<QVector3D>(), QVector3D());
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), transform.data());
+
+ arbiter.dirtyNodes.clear();
// WHEN
transform->setRotationX(20.0f);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "rotation");
- QCOMPARE(change->value().value<QQuaternion>().toEulerAngles().x(), 20.0f);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), transform.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkSignalEmittion()
@@ -342,6 +334,44 @@ private Q_SLOTS:
// Note: t.matrix() != t2.matrix() since different matrices
// can result in the same scale, rotation, translation
}
+
+ void checkUpdateWorldTransform()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ FakeTransform t;
+ arbiter.setArbiterOnNode(&t);
+
+ // WHEN
+ QSignalSpy spy(&t, SIGNAL(worldMatrixChanged(QMatrix4x4)));
+
+ // THEN
+ QVERIFY(spy.isValid());
+
+ // WHEN
+ Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
+ valueChange->setPropertyName("worldMatrix");
+ const QMatrix4x4 newValue(1.0f, 2.0f, 3.0f, 4.0f,
+ 5.0f, 6.0f, 7.0f, 8.0f,
+ 9.0f, 10.0f, 11.0f, 12.0f,
+ 13.0f, 14.0f, 15.0f, 16.0f);
+ valueChange->setValue(newValue);
+ t.sceneChangeEvent(valueChange);
+
+ // THEN
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(t.worldMatrix(), newValue);
+
+ // WHEN
+ spy.clear();
+ t.sceneChangeEvent(valueChange);
+
+ // THEN
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(t.worldMatrix(), newValue);
+ }
};
QTEST_MAIN(tst_QTransform)
diff --git a/tests/auto/core/threadpooler/tst_threadpooler.cpp b/tests/auto/core/threadpooler/tst_threadpooler.cpp
index 98cbbc92d..a656c25c1 100644
--- a/tests/auto/core/threadpooler/tst_threadpooler.cpp
+++ b/tests/auto/core/threadpooler/tst_threadpooler.cpp
@@ -33,6 +33,7 @@
#include <QtCore/QMutex>
#include <QtGui/QVector3D>
#include <QtGui/QMatrix4x4>
+#include <QtCore/QElapsedTimer>
#include <QtCore/QTimer>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
@@ -292,8 +293,8 @@ void tst_ThreadPooler::massTest()
QVector3D data[3 * mass];
// WHEN
- QTime time;
- time.start();
+ QElapsedTimer timer;
+ timer.start();
for (int i = 0; i < mass; i++) {
QSharedPointer<MassAspectJob> job1(new MassAspectJob(massTestFunction, &(data[i * 3 + 0])));
@@ -310,7 +311,7 @@ void tst_ThreadPooler::massTest()
m_jobManager->waitForAllJobs();
// THEN
- qDebug() << "time.elapsed() = " << time.elapsed() << " ms";
+ qDebug() << "timer.elapsed() = " << timer.elapsed() << " ms";
}
class PerThreadUniqueTester {
diff --git a/tests/auto/coretest/coretest.pro b/tests/auto/coretest/coretest.pro
index 9bcc56c1b..9a96dcc6f 100644
--- a/tests/auto/coretest/coretest.pro
+++ b/tests/auto/coretest/coretest.pro
@@ -2,7 +2,7 @@ TARGET = Qt3DCoreTest
MODULE = 3dcoretest
CONFIG += static internal_module
-DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_FOREACH
+DEFINES += QT_NO_CAST_FROM_ASCII
PRECOMPILED_HEADER =
INCLUDEPATH += $$PWD
diff --git a/tests/auto/coretest/testpostmanarbiter.cpp b/tests/auto/coretest/testpostmanarbiter.cpp
index b4c1b03af..d1263b8f7 100644
--- a/tests/auto/coretest/testpostmanarbiter.cpp
+++ b/tests/auto/coretest/testpostmanarbiter.cpp
@@ -29,6 +29,9 @@
#include "testpostmanarbiter_p.h"
#include <Qt3DCore/private/qnode_p.h>
+#include <algorithm>
+#include <iterator>
+
QT_BEGIN_NAMESPACE
TestPostman::TestPostman(TestArbiter *arbiter)
@@ -72,7 +75,7 @@ void TestArbiter::sceneChangeEventWithLock(const Qt3DCore::QSceneChangePtr &e)
void TestArbiter::sceneChangeEventWithLock(const Qt3DCore::QSceneChangeList &e)
{
- events += QVector<Qt3DCore::QSceneChangePtr>::fromStdVector(e);
+ std::copy(e.cbegin(), e.cend(), std::back_inserter(events));
}
Qt3DCore::QAbstractPostman *TestArbiter::postman() const
diff --git a/tests/auto/coretest/testpostmanarbiter_p.h b/tests/auto/coretest/testpostmanarbiter_p.h
index 26c0cbc67..8954357fe 100644
--- a/tests/auto/coretest/testpostmanarbiter_p.h
+++ b/tests/auto/coretest/testpostmanarbiter_p.h
@@ -42,7 +42,6 @@
#include <Qt3DCore/private/qpostman_p.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
QT_BEGIN_NAMESPACE
diff --git a/tests/auto/extras/extras.pro b/tests/auto/extras/extras.pro
index bbdf118b3..e5ae28e97 100644
--- a/tests/auto/extras/extras.pro
+++ b/tests/auto/extras/extras.pro
@@ -6,5 +6,6 @@ contains(QT_CONFIG, private_tests) {
qtorusgeometry \
qforwardrenderer \
qfirstpersoncameracontroller \
- qorbitcameracontroller
+ qorbitcameracontroller \
+ qtext2dentity
}
diff --git a/tests/auto/extras/qtext2dentity/qtext2dentity.pro b/tests/auto/extras/qtext2dentity/qtext2dentity.pro
new file mode 100644
index 000000000..1b8bd0c6f
--- /dev/null
+++ b/tests/auto/extras/qtext2dentity/qtext2dentity.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+
+TARGET = tst_qtext2dentity
+
+QT += 3dcore 3dcore-private 3dextras 3dquickextras qml testlib
+
+CONFIG += testcase
+
+SOURCES += \
+ tst_qtext2dentity.cpp
+
+RESOURCES += qtext2dentity.qrc
+
diff --git a/tests/auto/extras/qtext2dentity/qtext2dentity.qml b/tests/auto/extras/qtext2dentity/qtext2dentity.qml
new file mode 100644
index 000000000..bc699acf6
--- /dev/null
+++ b/tests/auto/extras/qtext2dentity/qtext2dentity.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.0
+import Qt3D.Render 2.0
+import Qt3D.Input 2.0
+import Qt3D.Extras 2.9
+
+Entity {
+ id: sceneRoot
+ property alias text2DEntity: text
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ aspectRatio: 16/9
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 0.0, 140.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ OrbitCameraController {
+ camera: camera
+ }
+
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ clearColor: Qt.rgba(1, 1, 1, 1)
+ camera: camera
+ }
+ },
+ // Event Source will be set by the Qt3DQuickWindow
+ InputSettings { }
+ ]
+
+ Text2DEntity {
+ id: text
+ text: "foo"
+ width: 200
+ height: 40
+ color: "darkgrey"
+ }
+}
diff --git a/tests/auto/extras/qtext2dentity/qtext2dentity.qrc b/tests/auto/extras/qtext2dentity/qtext2dentity.qrc
new file mode 100644
index 000000000..424d200ae
--- /dev/null
+++ b/tests/auto/extras/qtext2dentity/qtext2dentity.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource>
+ <file>qtext2dentity.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/extras/qtext2dentity/tst_qtext2dentity.cpp b/tests/auto/extras/qtext2dentity/tst_qtext2dentity.cpp
new file mode 100644
index 000000000..6fcc2e637
--- /dev/null
+++ b/tests/auto/extras/qtext2dentity/tst_qtext2dentity.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <Qt3DExtras/QText2DEntity>
+#include <Qt3DQuickExtras/qt3dquickwindow.h>
+#include <Qt3DQuick/QQmlAspectEngine>
+#include <Qt3DCore/private/qnode_p.h>
+
+QVector<Qt3DCore::QNode *>lookupNodeByClassName(Qt3DCore::QNode *root, const QString &className)
+{
+ auto children = root->childNodes();
+ QVector<Qt3DCore::QNode *> childrenList;
+ for (auto i : children) {
+ if (i->metaObject()->className() == className)
+ childrenList << i;
+ else
+ childrenList << lookupNodeByClassName(i, className);
+ }
+ return childrenList;
+}
+
+class tst_qtext2dentity : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void checkChangeArbiter();
+};
+
+void tst_qtext2dentity::checkChangeArbiter()
+{
+#if !defined(QT_OPENGL_ES_2_ANGLE)
+ // GIVEN
+ Qt3DExtras::Quick::Qt3DQuickWindow view;
+ view.setSource(QUrl("qrc:/qtext2dentity.qml"));
+ view.show();
+ QCoreApplication::processEvents();
+
+ // THEN
+ auto rootEntity = view.engine()->aspectEngine()->rootEntity();
+ QVERIFY(rootEntity != nullptr);
+ auto atlases = lookupNodeByClassName(rootEntity.data(), "Qt3DExtras::QTextureAtlas");
+ QVERIFY(atlases.length() == 1);
+ auto atlas = atlases[0];
+ QTRY_VERIFY(Qt3DCore::QNodePrivate::get(atlas)->m_changeArbiter);
+#endif
+}
+
+QTEST_MAIN(tst_qtext2dentity)
+#include "tst_qtext2dentity.moc"
diff --git a/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp b/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp
index 1390b6b49..94f02bc1e 100644
--- a/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp
+++ b/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp
@@ -30,11 +30,9 @@
#include <qbackendnodetester.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/abstractaxisinput_p.h>
#include <Qt3DInput/QAbstractAxisInput>
#include <Qt3DInput/private/qabstractaxisinput_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "testdevice.h"
class DummyAxisInput : public Qt3DInput::QAbstractAxisInput
@@ -89,7 +87,7 @@ private Q_SLOTS:
axisInput.setSourceDevice(&sourceDevice);
// WHEN
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
// THEN
QCOMPARE(backendAxisInput.peerId(), axisInput.id());
@@ -114,7 +112,7 @@ private Q_SLOTS:
axisInput.setSourceDevice(&sourceDevice);
// WHEN
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
backendAxisInput.cleanup();
// THEN
@@ -125,23 +123,21 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ DummyAxisInput axisInput;
DummyAxisInputBackend backendAxisInput;
+ simulateInitializationSync(&axisInput, &backendAxisInput);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setEnabled(false);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
- QCOMPARE(backendAxisInput.isEnabled(), true);
+ QCOMPARE(backendAxisInput.isEnabled(), false);
// WHEN
TestDevice device;
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("sourceDevice");
- updateChange->setValue(QVariant::fromValue(device.id()));
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setSourceDevice(&device);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QCOMPARE(backendAxisInput.sourceDevice(), device.id());
diff --git a/tests/auto/input/action/tst_action.cpp b/tests/auto/input/action/tst_action.cpp
index 7ef9bca1e..cc40cef2f 100644
--- a/tests/auto/input/action/tst_action.cpp
+++ b/tests/auto/input/action/tst_action.cpp
@@ -30,7 +30,6 @@
#include <qbackendnodetester.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DInput/private/action_p.h>
@@ -64,7 +63,7 @@ private Q_SLOTS:
action.addInput(&actionInput);
// WHEN
- simulateInitialization(&action, &backendAction);
+ simulateInitializationSync(&action, &backendAction);
// THEN
QCOMPARE(backendAction.peerId(), action.id());
@@ -96,7 +95,7 @@ private Q_SLOTS:
action.addInput(&axisInput);
// WHEN
- simulateInitialization(&action, &backendAction);
+ simulateInitializationSync(&action, &backendAction);
backendAction.setActionTriggered(true);
backendAction.cleanup();
@@ -109,70 +108,35 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DInput::QAction action;
Qt3DInput::Input::Action backendAction;
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
+ simulateInitializationSync(&action, &backendAction);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendAction.sceneChangeEvent(updateChange);
+ action.setEnabled(false);
+ backendAction.syncFromFrontEnd(&action, false);
// THEN
- QCOMPARE(backendAction.isEnabled(), true);
+ QCOMPARE(backendAction.isEnabled(), false);
// WHEN
DummyActionInput input;
const Qt3DCore::QNodeId inputId = input.id();
- const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &input);
- nodeAddedChange->setPropertyName("input");
- backendAction.sceneChangeEvent(nodeAddedChange);
+ action.addInput(&input);
+ backendAction.syncFromFrontEnd(&action, false);
// THEN
QCOMPARE(backendAction.inputs().size(), 1);
QCOMPARE(backendAction.inputs().first(), inputId);
// WHEN
- const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &input);
- nodeRemovedChange->setPropertyName("input");
- backendAction.sceneChangeEvent(nodeRemovedChange);
+ action.removeInput(&input);
+ backendAction.syncFromFrontEnd(&action, false);
// THEN
QCOMPARE(backendAction.inputs().size(), 0);
}
- void checkActivePropertyBackendNotification()
- {
- // GIVEN
- TestArbiter arbiter;
- Qt3DInput::Input::Action backendAction;
- backendAction.setEnabled(true);
- Qt3DCore::QBackendNodePrivate::get(&backendAction)->setArbiter(&arbiter);
- const bool currentActionTriggeredValue = backendAction.actionTriggered();
-
- // WHEN
- backendAction.setActionTriggered(true);
-
- // THEN
- QVERIFY(currentActionTriggeredValue != backendAction.actionTriggered());
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "active");
- QCOMPARE(change->value().toBool(), backendAction.actionTriggered());
-
-
- arbiter.events.clear();
-
- // WHEN
- backendAction.setActionTriggered(true);
-
- // THEN
- QVERIFY(currentActionTriggeredValue != backendAction.actionTriggered());
- QCOMPARE(arbiter.events.count(), 0);
-
- arbiter.events.clear();
- }
-
void shouldNotActivateWhenDisabled()
{
// GIVEN
diff --git a/tests/auto/input/actioninput/tst_actioninput.cpp b/tests/auto/input/actioninput/tst_actioninput.cpp
index 23dfaad64..3c9918da0 100644
--- a/tests/auto/input/actioninput/tst_actioninput.cpp
+++ b/tests/auto/input/actioninput/tst_actioninput.cpp
@@ -30,7 +30,6 @@
#include <qbackendnodetester.h>
#include "testdevice.h"
-#include <Qt3DCore/QPropertyUpdatedChange>
#include <Qt3DInput/private/actioninput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/QActionInput>
@@ -50,7 +49,7 @@ private Q_SLOTS:
actionInput.setSourceDevice(&sourceDevice);
// WHEN
- simulateInitialization(&actionInput, &backendActionInput);
+ simulateInitializationSync(&actionInput, &backendActionInput);
// THEN
QCOMPARE(backendActionInput.peerId(), actionInput.id());
@@ -78,7 +77,7 @@ private Q_SLOTS:
actionInput.setSourceDevice(&sourceDevice);
// WHEN
- simulateInitialization(&actionInput, &backendActionInput);
+ simulateInitializationSync(&actionInput, &backendActionInput);
backendActionInput.cleanup();
// THEN
@@ -90,32 +89,28 @@ private Q_SLOTS:
void shouldHandlePropertyChanges()
{
// GIVEN
+ Qt3DInput::QActionInput actionInput;
Qt3DInput::Input::ActionInput backendActionInput;
+ simulateInitializationSync(&actionInput, &backendActionInput);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(QVariant::fromValue(QVector<int>() << 64));
- updateChange->setPropertyName("buttons");
- backendActionInput.sceneChangeEvent(updateChange);
+ actionInput.setButtons(QVector<int>() << 64);
+ backendActionInput.syncFromFrontEnd(&actionInput, false);
// THEN
QCOMPARE(backendActionInput.buttons(), QVector<int>() << 64);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendActionInput.sceneChangeEvent(updateChange);
+ actionInput.setEnabled(false);
+ backendActionInput.syncFromFrontEnd(&actionInput, false);
// THEN
- QCOMPARE(backendActionInput.isEnabled(), true);
+ QCOMPARE(backendActionInput.isEnabled(), false);
// WHEN
TestDevice device;
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("sourceDevice");
- updateChange->setValue(QVariant::fromValue(device.id()));
- backendActionInput.sceneChangeEvent(updateChange);
+ actionInput.setSourceDevice(&device);
+ backendActionInput.syncFromFrontEnd(&actionInput, false);
// THEN
QCOMPARE(backendActionInput.sourceDevice(), device.id());
@@ -135,7 +130,7 @@ private Q_SLOTS:
actionInput.setEnabled(true);
actionInput.setButtons(QVector<int>() << Qt::Key_Space << Qt::Key_Return);
actionInput.setSourceDevice(device);
- simulateInitialization(&actionInput, &backendActionInput);
+ simulateInitializationSync(&actionInput, &backendActionInput);
// WHEN
deviceBackend->setButtonPressed(Qt::Key_Up, true);
@@ -188,7 +183,7 @@ private Q_SLOTS:
actionInput.setEnabled(false);
actionInput.setButtons(QVector<int>() << Qt::Key_Space << Qt::Key_Return);
actionInput.setSourceDevice(device);
- simulateInitialization(&actionInput, &backendActionInput);
+ simulateInitializationSync(&actionInput, &backendActionInput);
// WHEN
deviceBackend->setButtonPressed(Qt::Key_Space, true);
diff --git a/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp b/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp
index a37c37e96..6f91ce337 100644
--- a/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp
+++ b/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp
@@ -32,11 +32,9 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/analogaxisinput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/QAnalogAxisInput>
-#include <Qt3DCore/qpropertyupdatedchange.h>
class tst_AnalogAxisInput: public Qt3DCore::QBackendNodeTester
{
@@ -55,7 +53,7 @@ private Q_SLOTS:
axisInput.setSourceDevice(&sourceDevice);
// WHEN
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
// THEN
QCOMPARE(backendAxisInput.peerId(), axisInput.id());
@@ -83,7 +81,7 @@ private Q_SLOTS:
axisInput.setSourceDevice(&sourceDevice);
// WHEN
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
backendAxisInput.cleanup();
// THEN
@@ -95,32 +93,28 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DInput::QAnalogAxisInput axisInput;
Qt3DInput::Input::AnalogAxisInput backendAxisInput;
+ simulateInitializationSync(&axisInput, &backendAxisInput);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(32);
- updateChange->setPropertyName("axis");
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setAxis(32);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QCOMPARE(backendAxisInput.axis(), 32);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setEnabled(false);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
- QCOMPARE(backendAxisInput.isEnabled(), true);
+ QCOMPARE(backendAxisInput.isEnabled(), false);
// WHEN
TestDevice device;
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("sourceDevice");
- updateChange->setValue(QVariant::fromValue(device.id()));
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setSourceDevice(&device);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QCOMPARE(backendAxisInput.sourceDevice(), device.id());
@@ -142,7 +136,7 @@ private Q_SLOTS:
axisInput.setEnabled(true);
axisInput.setAxis(2);
axisInput.setSourceDevice(device);
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
QCOMPARE(backendAxisInput.axis(), 2);
// WHEN
@@ -176,7 +170,7 @@ private Q_SLOTS:
axisInput.setEnabled(false);
axisInput.setAxis(2);
axisInput.setSourceDevice(device);
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
QCOMPARE(backendAxisInput.axis(), 2);
// WHEN
diff --git a/tests/auto/input/axis/tst_axis.cpp b/tests/auto/input/axis/tst_axis.cpp
index 42f7f56fc..ddd59b395 100644
--- a/tests/auto/input/axis/tst_axis.cpp
+++ b/tests/auto/input/axis/tst_axis.cpp
@@ -30,7 +30,6 @@
#include <qbackendnodetester.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DInput/private/axis_p.h>
@@ -65,7 +64,7 @@ private Q_SLOTS:
axis.addInput(&axisInput);
// WHEN
- simulateInitialization(&axis, &backendAxis);
+ simulateInitializationSync(&axis, &backendAxis);
// THEN
QCOMPARE(backendAxis.peerId(), axis.id());
@@ -97,7 +96,7 @@ private Q_SLOTS:
axis.addInput(&axisInput);
// WHEN
- simulateInitialization(&axis, &backendAxis);
+ simulateInitializationSync(&axis, &backendAxis);
backendAxis.setAxisValue(883.0f);
backendAxis.cleanup();
@@ -110,69 +109,35 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DInput::QAxis axis;
Qt3DInput::Input::Axis backendAxis;
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
+ simulateInitializationSync(&axis, &backendAxis);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendAxis.sceneChangeEvent(updateChange);
+ axis.setEnabled(false);
+ backendAxis.syncFromFrontEnd(&axis, false);
// THEN
- QCOMPARE(backendAxis.isEnabled(), true);
+ QCOMPARE(backendAxis.isEnabled(), false);
// WHEN
DummyAxisInput input;
const Qt3DCore::QNodeId inputId = input.id();
- const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &input);
- nodeAddedChange->setPropertyName("input");
- backendAxis.sceneChangeEvent(nodeAddedChange);
+ axis.addInput(&input);
+ backendAxis.syncFromFrontEnd(&axis, false);
// THEN
QCOMPARE(backendAxis.inputs().size(), 1);
QCOMPARE(backendAxis.inputs().first(), inputId);
// WHEN
- const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &input);
- nodeRemovedChange->setPropertyName("input");
- backendAxis.sceneChangeEvent(nodeRemovedChange);
+ axis.removeInput(&input);
+ backendAxis.syncFromFrontEnd(&axis, false);
// THEN
QCOMPARE(backendAxis.inputs().size(), 0);
}
- void checkValuePropertyBackendNotification()
- {
- // GIVEN
- TestArbiter arbiter;
- Qt3DInput::Input::Axis backendAxis;
- backendAxis.setEnabled(true);
- Qt3DCore::QBackendNodePrivate::get(&backendAxis)->setArbiter(&arbiter);
-
- // WHEN
- backendAxis.setAxisValue(454.0f);
-
- // THEN
- QCOMPARE(backendAxis.axisValue(), 454.0f);
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "value");
- QCOMPARE(change->value().toFloat(), backendAxis.axisValue());
-
- arbiter.events.clear();
-
- // WHEN
- backendAxis.setAxisValue(454.0f);
-
- // THEN
- QCOMPARE(backendAxis.axisValue(), 454.0f);
- QCOMPARE(arbiter.events.count(), 0);
-
- arbiter.events.clear();
-
- }
-
void shouldNotChangeValueWhenDisabled()
{
// GIVEN
diff --git a/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp b/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp
index 8e0b499fd..f8d4adcd2 100644
--- a/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp
+++ b/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp
@@ -30,9 +30,6 @@
#include <qbackendnodetester.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DInput/private/axis_p.h>
#include <Qt3DInput/private/axisaccumulator_p.h>
#include <Qt3DInput/private/qabstractaxisinput_p.h>
@@ -61,7 +58,7 @@ private Q_SLOTS:
axisAccumulator.setScale(2.0f);
// WHEN
- simulateInitialization(&axisAccumulator, &backendAccumulator);
+ simulateInitializationSync(&axisAccumulator, &backendAccumulator);
// THEN
QCOMPARE(backendAccumulator.peerId(), axisAccumulator.id());
@@ -95,7 +92,7 @@ private Q_SLOTS:
axisAccumulator.setEnabled(true);
// WHEN
- simulateInitialization(&axisAccumulator, &backendAxisAccumulator);
+ simulateInitializationSync(&axisAccumulator, &backendAxisAccumulator);
backendAxisAccumulator.cleanup();
// THEN
@@ -110,100 +107,41 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DInput::QAxisAccumulator axisAccumulator;
Qt3DInput::Input::AxisAccumulator backendAxisAccumulator;
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
+ simulateInitializationSync(&axisAccumulator, &backendAxisAccumulator);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendAxisAccumulator.sceneChangeEvent(updateChange);
+ axisAccumulator.setEnabled(false);
+ backendAxisAccumulator.syncFromFrontEnd(&axisAccumulator, false);
// THEN
- QCOMPARE(backendAxisAccumulator.isEnabled(), true);
+ QCOMPARE(backendAxisAccumulator.isEnabled(), false);
// WHEN
Qt3DInput::QAxis axis;
const Qt3DCore::QNodeId axisId = axis.id();
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("sourceAxis");
- updateChange->setValue(QVariant::fromValue(axisId));
- backendAxisAccumulator.sceneChangeEvent(updateChange);
+ axisAccumulator.setSourceAxis(&axis);
+ backendAxisAccumulator.syncFromFrontEnd(&axisAccumulator, false);
// THEN
QCOMPARE(backendAxisAccumulator.sourceAxisId(), axisId);
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("sourceAxisType");
- updateChange->setValue(Qt3DInput::QAxisAccumulator::Acceleration);
- backendAxisAccumulator.sceneChangeEvent(updateChange);
+ axisAccumulator.setSourceAxisType(Qt3DInput::QAxisAccumulator::Acceleration);
+ backendAxisAccumulator.syncFromFrontEnd(&axisAccumulator, false);
// THEN
QCOMPARE(backendAxisAccumulator.sourceAxisType(), Qt3DInput::QAxisAccumulator::Acceleration);
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("scale");
- updateChange->setValue(3.0f);
- backendAxisAccumulator.sceneChangeEvent(updateChange);
+ axisAccumulator.setScale(3.f);
+ backendAxisAccumulator.syncFromFrontEnd(&axisAccumulator, false);
// THEN
QCOMPARE(backendAxisAccumulator.scale(), 3.0f);
}
- void checkValuePropertyBackendNotification()
- {
- // GIVEN
- TestArbiter arbiter;
- Qt3DInput::Input::AxisAccumulator backendAxisAccumulator;
- backendAxisAccumulator.setEnabled(true);
- Qt3DCore::QBackendNodePrivate::get(&backendAxisAccumulator)->setArbiter(&arbiter);
-
- // WHEN
- backendAxisAccumulator.setValue(454.0f);
-
- // THEN
- QCOMPARE(backendAxisAccumulator.value(), 454.0f);
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "value");
- QCOMPARE(change->value().toFloat(), backendAxisAccumulator.value());
-
- arbiter.events.clear();
-
- // WHEN
- backendAxisAccumulator.setValue(454.0f);
-
- // THEN
- QCOMPARE(backendAxisAccumulator.value(), 454.0f);
- QCOMPARE(arbiter.events.count(), 0);
-
- arbiter.events.clear();
-
-
- // WHEN
- backendAxisAccumulator.setVelocity(383.0f);
-
- // THEN
- QCOMPARE(backendAxisAccumulator.velocity(), 383.0f);
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr velocityChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(velocityChange->propertyName(), "velocity");
- QCOMPARE(velocityChange->value().toFloat(), backendAxisAccumulator.velocity());
-
- arbiter.events.clear();
-
- // WHEN
- backendAxisAccumulator.setVelocity(383.0f);
-
- // THEN
- QCOMPARE(backendAxisAccumulator.velocity(), 383.0f);
- QCOMPARE(arbiter.events.count(), 0);
-
- arbiter.events.clear();
- }
-
void shouldNotChangeValueWhenDisabled()
{
// GIVEN
@@ -288,7 +226,7 @@ private Q_SLOTS:
axisAccumulator.setScale(scale);
axisAccumulator.setSourceAxisType(sourceAxisType);
axisAccumulator.setEnabled(true);
- simulateInitialization(&axisAccumulator, &backendAxisAccumulator);
+ simulateInitializationSync(&axisAccumulator, &backendAxisAccumulator);
backendAxisAccumulator.stepIntegration(&axisManager, dt);
diff --git a/tests/auto/input/axisaccumulatorjob/tst_axisaccumulatorjob.cpp b/tests/auto/input/axisaccumulatorjob/tst_axisaccumulatorjob.cpp
index fa3bca3d2..91085357a 100644
--- a/tests/auto/input/axisaccumulatorjob/tst_axisaccumulatorjob.cpp
+++ b/tests/auto/input/axisaccumulatorjob/tst_axisaccumulatorjob.cpp
@@ -30,9 +30,6 @@
#include <qbackendnodetester.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DInput/private/axis_p.h>
#include <Qt3DInput/private/axisaccumulator_p.h>
#include <Qt3DInput/private/axisaccumulatorjob_p.h>
@@ -79,7 +76,7 @@ private Q_SLOTS:
axisAccumulator->setSourceAxis(axis);
axisAccumulator->setScale(scale);
axisAccumulator->setSourceAxisType(sourceAxisType);
- simulateInitialization(axisAccumulator, backendAxisAccumulator);
+ simulateInitializationSync(axisAccumulator, backendAxisAccumulator);
}
// WHEN
diff --git a/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp b/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp
index 18887cfe6..e315ed1dc 100644
--- a/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp
+++ b/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp
@@ -32,11 +32,9 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/buttonaxisinput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/QButtonAxisInput>
-#include <Qt3DCore/qpropertyupdatedchange.h>
class tst_ButtonAxisInput: public Qt3DCore::QBackendNodeTester
{
@@ -58,7 +56,7 @@ private Q_SLOTS:
axisInput.setSourceDevice(&sourceDevice);
// WHEN
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
// THEN
QCOMPARE(backendAxisInput.peerId(), axisInput.id());
@@ -98,7 +96,7 @@ private Q_SLOTS:
axisInput.setSourceDevice(&sourceDevice);
// WHEN
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
backendAxisInput.cleanup();
// THEN
@@ -115,77 +113,63 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DInput::QButtonAxisInput axisInput;
Qt3DInput::Input::ButtonAxisInput backendAxisInput;
+ simulateInitializationSync(&axisInput, &backendAxisInput);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(QVariant::fromValue(QVector<int>() << 64));
- updateChange->setPropertyName("buttons");
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setButtons(QVector<int>() << 64);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QCOMPARE(backendAxisInput.buttons(), QVector<int>() << 64);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(0.5f);
- updateChange->setPropertyName("scale");
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setScale(0.5f);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QCOMPARE(backendAxisInput.scale(), 0.5f);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setEnabled(false);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
- QCOMPARE(backendAxisInput.isEnabled(), true);
+ QCOMPARE(backendAxisInput.isEnabled(), false);
// WHEN
TestDevice device;
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("sourceDevice");
- updateChange->setValue(QVariant::fromValue(device.id()));
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setSourceDevice(&device);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QCOMPARE(backendAxisInput.sourceDevice(), device.id());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(0.42f);
- updateChange->setPropertyName("acceleration");
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setAcceleration(0.42f);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QCOMPARE(backendAxisInput.acceleration(), 0.42f);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(-0.42f);
- updateChange->setPropertyName("acceleration");
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setAcceleration(-0.42f);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QVERIFY(qIsInf(backendAxisInput.acceleration()));
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(0.43f);
- updateChange->setPropertyName("deceleration");
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setDeceleration(0.43f);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QCOMPARE(backendAxisInput.deceleration(), 0.43f);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(-0.43f);
- updateChange->setPropertyName("deceleration");
- backendAxisInput.sceneChangeEvent(updateChange);
+ axisInput.setDeceleration(-0.43f);
+ backendAxisInput.syncFromFrontEnd(&axisInput, false);
// THEN
QVERIFY(qIsInf(backendAxisInput.deceleration()));
@@ -210,7 +194,7 @@ private Q_SLOTS:
axisInput.setAcceleration(0.15f);
axisInput.setDeceleration(0.3f);
axisInput.setSourceDevice(device);
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
QCOMPARE(backendAxisInput.speedRatio(), 0.0f);
QCOMPARE(backendAxisInput.lastUpdateTime(), 0);
@@ -311,7 +295,7 @@ private Q_SLOTS:
axisInput.setAcceleration(0.15f);
axisInput.setDeceleration(0.3f);
axisInput.setSourceDevice(device);
- simulateInitialization(&axisInput, &backendAxisInput);
+ simulateInitializationSync(&axisInput, &backendAxisInput);
QCOMPARE(backendAxisInput.speedRatio(), 0.0f);
QCOMPARE(backendAxisInput.lastUpdateTime(), 0);
diff --git a/tests/auto/input/commons/testdeviceproxy.h b/tests/auto/input/commons/testdeviceproxy.h
index 13e10d501..737eadfe7 100644
--- a/tests/auto/input/commons/testdeviceproxy.h
+++ b/tests/auto/input/commons/testdeviceproxy.h
@@ -103,9 +103,10 @@ public:
return d->m_device;
}
- void simulateSceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
+ void setDevice(TestPhysicalDevice *device)
{
- Qt3DInput::QAbstractPhysicalDeviceProxy::sceneChangeEvent(change);
+ Q_D(TestProxy);
+ d->setDevice(device);
}
private:
diff --git a/tests/auto/input/input.pro b/tests/auto/input/input.pro
index 6169d3f7c..7799c2b89 100644
--- a/tests/auto/input/input.pro
+++ b/tests/auto/input/input.pro
@@ -29,5 +29,6 @@ qtConfig(private_tests) {
mousedevice \
utils \
axisaccumulator \
- axisaccumulatorjob
+ axisaccumulatorjob \
+ qmouseevent
}
diff --git a/tests/auto/input/inputchord/tst_inputchord.cpp b/tests/auto/input/inputchord/tst_inputchord.cpp
index 093bd29f7..e34fc4abe 100644
--- a/tests/auto/input/inputchord/tst_inputchord.cpp
+++ b/tests/auto/input/inputchord/tst_inputchord.cpp
@@ -30,9 +30,6 @@
#include <qbackendnodetester.h>
#include "testdevice.h"
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
#include <Qt3DInput/private/actioninput_p.h>
#include <Qt3DInput/private/inputchord_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
@@ -55,7 +52,7 @@ private Q_SLOTS:
inputChord.addChord(&actionInput);
// WHEN
- simulateInitialization(&inputChord, &backendInputChord);
+ simulateInitializationSync(&inputChord, &backendInputChord);
// THEN
QCOMPARE(backendInputChord.peerId(), inputChord.id());
@@ -89,7 +86,7 @@ private Q_SLOTS:
inputChord.addChord(&actionInput);
// WHEN
- simulateInitialization(&inputChord, &backendInputChord);
+ simulateInitializationSync(&inputChord, &backendInputChord);
backendInputChord.cleanup();
// THEN
@@ -101,41 +98,37 @@ private Q_SLOTS:
void shouldHandlePropertyChanges()
{
// GIVEN
+ Qt3DInput::QInputChord inputChord;
Qt3DInput::Input::InputChord backendInputChord;
+ simulateInitializationSync(&inputChord, &backendInputChord);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(250);
- updateChange->setPropertyName("timeout");
- backendInputChord.sceneChangeEvent(updateChange);
+ inputChord.setTimeout(250);
+ backendInputChord.syncFromFrontEnd(&inputChord, false);
// THEN
QCOMPARE(backendInputChord.timeout(), 250000000);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendInputChord.sceneChangeEvent(updateChange);
+ inputChord.setEnabled(false);
+ backendInputChord.syncFromFrontEnd(&inputChord, false);
// THEN
- QCOMPARE(backendInputChord.isEnabled(), true);
+ QCOMPARE(backendInputChord.isEnabled(), false);
// WHEN
Qt3DInput::QActionInput input;
const Qt3DCore::QNodeId inputId = input.id();
- const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &input);
- nodeAddedChange->setPropertyName("chord");
- backendInputChord.sceneChangeEvent(nodeAddedChange);
+ inputChord.addChord(&input);
+ backendInputChord.syncFromFrontEnd(&inputChord, false);
// THEN
QCOMPARE(backendInputChord.chords().size(), 1);
QCOMPARE(backendInputChord.chords().first(), inputId);
// WHEN
- const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &input);
- nodeRemovedChange->setPropertyName("chord");
- backendInputChord.sceneChangeEvent(nodeRemovedChange);
+ inputChord.removeChord(&input);
+ backendInputChord.syncFromFrontEnd(&inputChord, false);
// THEN
QCOMPARE(backendInputChord.chords().size(), 0);
@@ -154,13 +147,13 @@ private Q_SLOTS:
firstInput->setButtons(QVector<int>() << Qt::Key_Q << Qt::Key_W);
firstInput->setSourceDevice(device);
auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
- simulateInitialization(firstInput, backendFirstInput);
+ simulateInitializationSync(firstInput, backendFirstInput);
auto secondInput = new Qt3DInput::QActionInput;
secondInput->setButtons(QVector<int>() << Qt::Key_A << Qt::Key_S);
secondInput->setSourceDevice(device);
auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
- simulateInitialization(secondInput, backendSecondInput);
+ simulateInitializationSync(secondInput, backendSecondInput);
Qt3DInput::Input::InputChord backendInputChord;
Qt3DInput::QInputChord inputChord;
@@ -168,7 +161,7 @@ private Q_SLOTS:
inputChord.setTimeout(300);
inputChord.addChord(firstInput);
inputChord.addChord(secondInput);
- simulateInitialization(&inputChord, &backendInputChord);
+ simulateInitializationSync(&inputChord, &backendInputChord);
// WHEN
deviceBackend->setButtonPressed(Qt::Key_Up, true);
@@ -242,13 +235,13 @@ private Q_SLOTS:
firstInput->setButtons(QVector<int>() << Qt::Key_Q);
firstInput->setSourceDevice(device);
auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
- simulateInitialization(firstInput, backendFirstInput);
+ simulateInitializationSync(firstInput, backendFirstInput);
auto secondInput = new Qt3DInput::QActionInput;
secondInput->setButtons(QVector<int>() << Qt::Key_W);
secondInput->setSourceDevice(device);
auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
- simulateInitialization(secondInput, backendSecondInput);
+ simulateInitializationSync(secondInput, backendSecondInput);
Qt3DInput::Input::InputChord backendInputChord;
Qt3DInput::QInputChord inputChord;
@@ -256,7 +249,7 @@ private Q_SLOTS:
inputChord.setTimeout(300);
inputChord.addChord(firstInput);
inputChord.addChord(secondInput);
- simulateInitialization(&inputChord, &backendInputChord);
+ simulateInitializationSync(&inputChord, &backendInputChord);
// WHEN
deviceBackend->setButtonPressed(Qt::Key_Q, true);
@@ -290,13 +283,13 @@ private Q_SLOTS:
firstInput->setButtons(QVector<int>() << Qt::Key_Q);
firstInput->setSourceDevice(device);
auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
- simulateInitialization(firstInput, backendFirstInput);
+ simulateInitializationSync(firstInput, backendFirstInput);
auto secondInput = new Qt3DInput::QActionInput;
secondInput->setButtons(QVector<int>() << Qt::Key_W);
secondInput->setSourceDevice(device);
auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
- simulateInitialization(secondInput, backendSecondInput);
+ simulateInitializationSync(secondInput, backendSecondInput);
Qt3DInput::Input::InputChord backendInputChord;
Qt3DInput::QInputChord inputChord;
@@ -304,7 +297,7 @@ private Q_SLOTS:
inputChord.setTimeout(300);
inputChord.addChord(firstInput);
inputChord.addChord(secondInput);
- simulateInitialization(&inputChord, &backendInputChord);
+ simulateInitializationSync(&inputChord, &backendInputChord);
// WHEN
deviceBackend->setButtonPressed(Qt::Key_Q, true);
diff --git a/tests/auto/input/inputsequence/tst_inputsequence.cpp b/tests/auto/input/inputsequence/tst_inputsequence.cpp
index b5630ddb5..6059d7e9c 100644
--- a/tests/auto/input/inputsequence/tst_inputsequence.cpp
+++ b/tests/auto/input/inputsequence/tst_inputsequence.cpp
@@ -30,9 +30,6 @@
#include <qbackendnodetester.h>
#include "testdevice.h"
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
#include <Qt3DInput/private/actioninput_p.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
@@ -56,7 +53,7 @@ private Q_SLOTS:
inputSequence.addSequence(&actionInput);
// WHEN
- simulateInitialization(&inputSequence, &backendInputSequence);
+ simulateInitializationSync(&inputSequence, &backendInputSequence);
// THEN
QCOMPARE(backendInputSequence.peerId(), inputSequence.id());
@@ -93,7 +90,7 @@ private Q_SLOTS:
inputSequence.addSequence(&actionInput);
// WHEN
- simulateInitialization(&inputSequence, &backendInputSequence);
+ simulateInitializationSync(&inputSequence, &backendInputSequence);
backendInputSequence.cleanup();
// THEN
@@ -106,50 +103,44 @@ private Q_SLOTS:
void shouldHandlePropertyChanges()
{
// GIVEN
+ Qt3DInput::QInputSequence inputSequence;
Qt3DInput::Input::InputSequence backendInputSequence;
+ simulateInitializationSync(&inputSequence, &backendInputSequence);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(250);
- updateChange->setPropertyName("timeout");
- backendInputSequence.sceneChangeEvent(updateChange);
+ inputSequence.setTimeout(250);
+ backendInputSequence.syncFromFrontEnd(&inputSequence, false);
// THEN
QCOMPARE(backendInputSequence.timeout(), 250000000);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(150);
- updateChange->setPropertyName("buttonInterval");
- backendInputSequence.sceneChangeEvent(updateChange);
+ inputSequence.setButtonInterval(150);
+ backendInputSequence.syncFromFrontEnd(&inputSequence, false);
// THEN
QCOMPARE(backendInputSequence.buttonInterval(), 150000000);
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendInputSequence.sceneChangeEvent(updateChange);
+ inputSequence.setEnabled(false);
+ backendInputSequence.syncFromFrontEnd(&inputSequence, false);
// THEN
- QCOMPARE(backendInputSequence.isEnabled(), true);
+ QCOMPARE(backendInputSequence.isEnabled(), false);
// WHEN
Qt3DInput::QActionInput input;
const Qt3DCore::QNodeId inputId = input.id();
- const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &input);
- nodeAddedChange->setPropertyName("sequence");
- backendInputSequence.sceneChangeEvent(nodeAddedChange);
+ inputSequence.addSequence(&input);
+ backendInputSequence.syncFromFrontEnd(&inputSequence, false);
// THEN
QCOMPARE(backendInputSequence.sequences().size(), 1);
QCOMPARE(backendInputSequence.sequences().first(), inputId);
// WHEN
- const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &input);
- nodeRemovedChange->setPropertyName("sequence");
- backendInputSequence.sceneChangeEvent(nodeRemovedChange);
+ inputSequence.removeSequence(&input);
+ backendInputSequence.syncFromFrontEnd(&inputSequence, false);
// THEN
QCOMPARE(backendInputSequence.sequences().size(), 0);
@@ -168,19 +159,19 @@ private Q_SLOTS:
firstInput->setButtons(QVector<int>() << Qt::Key_Q << Qt::Key_A);
firstInput->setSourceDevice(device);
auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
- simulateInitialization(firstInput, backendFirstInput);
+ simulateInitializationSync(firstInput, backendFirstInput);
auto secondInput = new Qt3DInput::QActionInput;
secondInput->setButtons(QVector<int>() << Qt::Key_S << Qt::Key_W);
secondInput->setSourceDevice(device);
auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
- simulateInitialization(secondInput, backendSecondInput);
+ simulateInitializationSync(secondInput, backendSecondInput);
auto thirdInput = new Qt3DInput::QActionInput;
thirdInput->setButtons(QVector<int>() << Qt::Key_D << Qt::Key_E);
thirdInput->setSourceDevice(device);
auto backendThirdInput = handler.actionInputManager()->getOrCreateResource(thirdInput->id());
- simulateInitialization(thirdInput, backendThirdInput);
+ simulateInitializationSync(thirdInput, backendThirdInput);
Qt3DInput::Input::InputSequence backendInputSequence;
Qt3DInput::QInputSequence inputSequence;
@@ -190,7 +181,7 @@ private Q_SLOTS:
inputSequence.addSequence(firstInput);
inputSequence.addSequence(secondInput);
inputSequence.addSequence(thirdInput);
- simulateInitialization(&inputSequence, &backendInputSequence);
+ simulateInitializationSync(&inputSequence, &backendInputSequence);
// WHEN
deviceBackend->setButtonPressed(Qt::Key_Up, true);
@@ -294,19 +285,19 @@ private Q_SLOTS:
firstInput->setButtons(QVector<int>() << Qt::Key_Q << Qt::Key_A);
firstInput->setSourceDevice(device);
auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
- simulateInitialization(firstInput, backendFirstInput);
+ simulateInitializationSync(firstInput, backendFirstInput);
auto secondInput = new Qt3DInput::QActionInput;
secondInput->setButtons(QVector<int>() << Qt::Key_S << Qt::Key_W);
secondInput->setSourceDevice(device);
auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
- simulateInitialization(secondInput, backendSecondInput);
+ simulateInitializationSync(secondInput, backendSecondInput);
auto thirdInput = new Qt3DInput::QActionInput;
thirdInput->setButtons(QVector<int>() << Qt::Key_D << Qt::Key_E);
thirdInput->setSourceDevice(device);
auto backendThirdInput = handler.actionInputManager()->getOrCreateResource(thirdInput->id());
- simulateInitialization(thirdInput, backendThirdInput);
+ simulateInitializationSync(thirdInput, backendThirdInput);
Qt3DInput::Input::InputSequence backendInputSequence;
Qt3DInput::QInputSequence inputSequence;
@@ -316,7 +307,7 @@ private Q_SLOTS:
inputSequence.addSequence(firstInput);
inputSequence.addSequence(secondInput);
inputSequence.addSequence(thirdInput);
- simulateInitialization(&inputSequence, &backendInputSequence);
+ simulateInitializationSync(&inputSequence, &backendInputSequence);
// WHEN
deviceBackend->setButtonPressed(Qt::Key_Q, true);
@@ -352,19 +343,19 @@ private Q_SLOTS:
firstInput->setButtons(QVector<int>() << Qt::Key_Q << Qt::Key_A);
firstInput->setSourceDevice(device);
auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
- simulateInitialization(firstInput, backendFirstInput);
+ simulateInitializationSync(firstInput, backendFirstInput);
auto secondInput = new Qt3DInput::QActionInput;
secondInput->setButtons(QVector<int>() << Qt::Key_S << Qt::Key_W);
secondInput->setSourceDevice(device);
auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
- simulateInitialization(secondInput, backendSecondInput);
+ simulateInitializationSync(secondInput, backendSecondInput);
auto thirdInput = new Qt3DInput::QActionInput;
thirdInput->setButtons(QVector<int>() << Qt::Key_D << Qt::Key_E);
thirdInput->setSourceDevice(device);
auto backendThirdInput = handler.actionInputManager()->getOrCreateResource(thirdInput->id());
- simulateInitialization(thirdInput, backendThirdInput);
+ simulateInitializationSync(thirdInput, backendThirdInput);
Qt3DInput::Input::InputSequence backendInputSequence;
Qt3DInput::QInputSequence inputSequence;
@@ -374,7 +365,7 @@ private Q_SLOTS:
inputSequence.addSequence(firstInput);
inputSequence.addSequence(secondInput);
inputSequence.addSequence(thirdInput);
- simulateInitialization(&inputSequence, &backendInputSequence);
+ simulateInitializationSync(&inputSequence, &backendInputSequence);
// WHEN
deviceBackend->setButtonPressed(Qt::Key_Q, true);
@@ -410,13 +401,13 @@ private Q_SLOTS:
firstInput->setButtons(QVector<int>() << Qt::Key_Q);
firstInput->setSourceDevice(device);
auto backendFirstInput = handler.actionInputManager()->getOrCreateResource(firstInput->id());
- simulateInitialization(firstInput, backendFirstInput);
+ simulateInitializationSync(firstInput, backendFirstInput);
auto secondInput = new Qt3DInput::QActionInput;
secondInput->setButtons(QVector<int>() << Qt::Key_S);
secondInput->setSourceDevice(device);
auto backendSecondInput = handler.actionInputManager()->getOrCreateResource(secondInput->id());
- simulateInitialization(secondInput, backendSecondInput);
+ simulateInitializationSync(secondInput, backendSecondInput);
Qt3DInput::Input::InputSequence backendInputSequence;
Qt3DInput::QInputSequence inputSequence;
@@ -425,7 +416,7 @@ private Q_SLOTS:
inputSequence.setTimeout(450);
inputSequence.addSequence(firstInput);
inputSequence.addSequence(secondInput);
- simulateInitialization(&inputSequence, &backendInputSequence);
+ simulateInitializationSync(&inputSequence, &backendInputSequence);
// WHEN
deviceBackend->setButtonPressed(Qt::Key_Q, true);
diff --git a/tests/auto/input/keyboardhandler/tst_keyboardhandler.cpp b/tests/auto/input/keyboardhandler/tst_keyboardhandler.cpp
index 3681f3554..b0280df05 100644
--- a/tests/auto/input/keyboardhandler/tst_keyboardhandler.cpp
+++ b/tests/auto/input/keyboardhandler/tst_keyboardhandler.cpp
@@ -31,7 +31,6 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
@@ -54,7 +53,7 @@ private Q_SLOTS:
auto keyboardDevice = new Qt3DInput::QKeyboardDevice;
auto backendKeyboardDevice = inputHandler.keyboardDeviceManager()->getOrCreateResource(keyboardDevice->id());
backendKeyboardDevice->setInputHandler(&inputHandler);
- simulateInitialization(keyboardDevice, backendKeyboardDevice);
+ simulateInitializationSync(keyboardDevice, backendKeyboardDevice);
Qt3DInput::QKeyboardHandler keyboardHandler;
auto backendKeyboardHandler = inputHandler.keyboardInputManager()->getOrCreateResource(keyboardHandler.id());
@@ -64,7 +63,7 @@ private Q_SLOTS:
keyboardHandler.setSourceDevice(keyboardDevice);
// WHEN
- simulateInitialization(&keyboardHandler, backendKeyboardHandler);
+ simulateInitializationSync(&keyboardHandler, backendKeyboardHandler);
// THEN
QCOMPARE(backendKeyboardHandler->peerId(), keyboardHandler.id());
@@ -90,50 +89,45 @@ private Q_SLOTS:
// GIVEN
Qt3DInput::Input::InputHandler inputHandler;
+ Qt3DInput::QKeyboardHandler keyboardHandler;
+ keyboardHandler.setEnabled(false);
+ Qt3DInput::Input::KeyboardHandler backendKeyboardHandler;
+ backendKeyboardHandler.setInputHandler(&inputHandler);
+
Qt3DInput::QKeyboardDevice device;
Qt3DInput::Input::KeyboardDevice *backendKeyboardDevice =
inputHandler.keyboardDeviceManager()->getOrCreateResource(device.id());
backendKeyboardDevice->setInputHandler(&inputHandler);
- Qt3DInput::Input::KeyboardHandler *backendKeyboardHandler
- = inputHandler.keyboardInputManager()->getOrCreateResource(Qt3DCore::QNodeId::createId());
- backendKeyboardHandler->setInputHandler(&inputHandler);
+ simulateInitializationSync(&keyboardHandler, &backendKeyboardHandler);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("sourceDevice");
- updateChange->setValue(QVariant::fromValue(device.id()));
- backendKeyboardHandler->sceneChangeEvent(updateChange);
+ keyboardHandler.setSourceDevice(&device);
+ backendKeyboardHandler.syncFromFrontEnd(&keyboardHandler, false);
// THEN
- QCOMPARE(backendKeyboardHandler->keyboardDevice(), device.id());
+ QCOMPARE(backendKeyboardHandler.keyboardDevice(), device.id());
// WHEN (still disabled, nothing should happen)
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("focus");
- updateChange->setValue(true);
- backendKeyboardHandler->sceneChangeEvent(updateChange);
+ keyboardHandler.setFocus(true);
+ backendKeyboardHandler.syncFromFrontEnd(&keyboardHandler, false);
// THEN
QVERIFY(backendKeyboardDevice->lastKeyboardInputRequester().isNull());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendKeyboardHandler->sceneChangeEvent(updateChange);
+ keyboardHandler.setEnabled(true);
+ backendKeyboardHandler.syncFromFrontEnd(&keyboardHandler, false);
// THEN
- QCOMPARE(backendKeyboardHandler->isEnabled(), true);
+ QCOMPARE(backendKeyboardHandler.isEnabled(), true);
// WHEN (now enabled, should request focus)
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("focus");
- updateChange->setValue(true);
- backendKeyboardHandler->sceneChangeEvent(updateChange);
+ keyboardHandler.setFocus(true);
+ backendKeyboardHandler.syncFromFrontEnd(&keyboardHandler, false);
// THEN
- QCOMPARE(backendKeyboardDevice->lastKeyboardInputRequester(), backendKeyboardHandler->peerId());
+ QCOMPARE(backendKeyboardDevice->lastKeyboardInputRequester(), backendKeyboardHandler.peerId());
}
};
diff --git a/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp b/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp
index a436959cc..c5322eda6 100644
--- a/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp
+++ b/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp
@@ -33,7 +33,6 @@
#include <Qt3DInput/private/inputhandler_p.h>
#include <Qt3DInput/private/physicaldeviceproxy_p.h>
#include <Qt3DInput/private/qinputdeviceintegration_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include "qbackendnodetester.h"
#include "testdeviceproxy.h"
@@ -118,13 +117,14 @@ private Q_SLOTS:
{
backendProxy->setManager(manager);
Qt3DCore::QBackendNodeTester backendNodeCreator;
- backendNodeCreator.simulateInitialization(&proxy, backendProxy);
+ backendNodeCreator.simulateInitializationSync(&proxy, backendProxy);
Qt3DCore::QBackendNodePrivate::get(backendProxy)->setArbiter(&arbiter);
}
// THEN
QCOMPARE(manager->lookupResource(proxy.id()), backendProxy);
QCOMPARE(backendProxy->deviceName(), QStringLiteral("TestProxy"));
+ QVERIFY(backendProxy->physicalDeviceId().isNull());
const QVector<Qt3DCore::QNodeId> pendingProxies = manager->takePendingProxiesToLoad();
QCOMPARE(pendingProxies.size(), 1);
@@ -138,11 +138,7 @@ private Q_SLOTS:
job.run();
// THEN -> PhysicalDeviceWrapper::setDevice should have been called
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "device");
- QVERIFY(change->value().value<Qt3DInput::QAbstractPhysicalDevice *>() != nullptr);
- QCOMPARE(change->subjectId(), proxy.id());
+ QVERIFY(!backendProxy->physicalDeviceId().isNull());
}
// WHEN -> invalid name
@@ -155,7 +151,7 @@ private Q_SLOTS:
{
backendProxy->setManager(manager);
Qt3DCore::QBackendNodeTester backendNodeCreator;
- backendNodeCreator.simulateInitialization(&proxy, backendProxy);
+ backendNodeCreator.simulateInitializationSync(&proxy, backendProxy);
Qt3DCore::QBackendNodePrivate::get(backendProxy)->setArbiter(&arbiter);
}
diff --git a/tests/auto/input/logicaldevice/tst_logicaldevice.cpp b/tests/auto/input/logicaldevice/tst_logicaldevice.cpp
index 58c8c7fcb..94994886a 100644
--- a/tests/auto/input/logicaldevice/tst_logicaldevice.cpp
+++ b/tests/auto/input/logicaldevice/tst_logicaldevice.cpp
@@ -33,9 +33,6 @@
#include <Qt3DInput/qaxis.h>
#include <Qt3DInput/private/qlogicaldevice_p.h>
#include <Qt3DInput/private/logicaldevice_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include "qbackendnodetester.h"
class tst_LogicalDevice : public Qt3DCore::QBackendNodeTester
@@ -59,24 +56,19 @@ private Q_SLOTS:
void checkCleanupState()
{
// GIVEN
+ Qt3DInput::QLogicalDevice logicalDevice;
Qt3DInput::Input::LogicalDevice backendLogicalDevice;
+ simulateInitializationSync(&logicalDevice, &backendLogicalDevice);
// WHEN
backendLogicalDevice.setEnabled(true);
// WHEN
- {
- Qt3DInput::QAxis newValue;
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &newValue);
- change->setPropertyName("axis");
- backendLogicalDevice.sceneChangeEvent(change);
- }
- {
- Qt3DInput::QAction newValue;
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &newValue);
- change->setPropertyName("action");
- backendLogicalDevice.sceneChangeEvent(change);
- }
+ Qt3DInput::QAxis newAxisValue;
+ Qt3DInput::QAction newActionValue;
+ logicalDevice.addAxis(&newAxisValue);
+ logicalDevice.addAction(&newActionValue);
+ backendLogicalDevice.syncFromFrontEnd(&logicalDevice, false);
// THEN
QCOMPARE(backendLogicalDevice.axes().size(), 1);
@@ -104,7 +96,7 @@ private Q_SLOTS:
{
// WHEN
Qt3DInput::Input::LogicalDevice backendLogicalDevice;
- simulateInitialization(&logicalDevice, &backendLogicalDevice);
+ simulateInitializationSync(&logicalDevice, &backendLogicalDevice);
// THEN
QCOMPARE(backendLogicalDevice.isEnabled(), true);
@@ -118,7 +110,7 @@ private Q_SLOTS:
// WHEN
Qt3DInput::Input::LogicalDevice backendLogicalDevice;
logicalDevice.setEnabled(false);
- simulateInitialization(&logicalDevice, &backendLogicalDevice);
+ simulateInitializationSync(&logicalDevice, &backendLogicalDevice);
// THEN
QCOMPARE(backendLogicalDevice.isEnabled(), false);
@@ -128,15 +120,15 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DInput::QLogicalDevice logicalDevice;
Qt3DInput::Input::LogicalDevice backendLogicalDevice;
+ simulateInitializationSync(&logicalDevice, &backendLogicalDevice);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendLogicalDevice.sceneChangeEvent(change);
+ logicalDevice.setEnabled(newValue);
+ backendLogicalDevice.syncFromFrontEnd(&logicalDevice, false);
// THEN
QCOMPARE(backendLogicalDevice.isEnabled(), newValue);
@@ -144,18 +136,16 @@ private Q_SLOTS:
{
// WHEN
Qt3DInput::QAxis newValue;
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &newValue);
- change->setPropertyName("axis");
- backendLogicalDevice.sceneChangeEvent(change);
+ logicalDevice.addAxis(&newValue);
+ backendLogicalDevice.syncFromFrontEnd(&logicalDevice, false);
// THEN
QCOMPARE(backendLogicalDevice.axes().size(), 1);
QCOMPARE(backendLogicalDevice.axes().first(), newValue.id());
// WHEN
- const auto change2 = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &newValue);
- change2->setPropertyName("axis");
- backendLogicalDevice.sceneChangeEvent(change2);
+ logicalDevice.removeAxis(&newValue);
+ backendLogicalDevice.syncFromFrontEnd(&logicalDevice, false);
// THEN
QCOMPARE(backendLogicalDevice.axes().size(), 0);
@@ -163,18 +153,16 @@ private Q_SLOTS:
{
// WHEN
Qt3DInput::QAction newValue;
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &newValue);
- change->setPropertyName("action");
- backendLogicalDevice.sceneChangeEvent(change);
+ logicalDevice.addAction(&newValue);
+ backendLogicalDevice.syncFromFrontEnd(&logicalDevice, false);
// THEN
QCOMPARE(backendLogicalDevice.actions().size(), 1);
QCOMPARE(backendLogicalDevice.actions().first(), newValue.id());
// WHEN
- const auto change2 = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &newValue);
- change2->setPropertyName("action");
- backendLogicalDevice.sceneChangeEvent(change2);
+ logicalDevice.removeAction(&newValue);
+ backendLogicalDevice.syncFromFrontEnd(&logicalDevice, false);
// THEN
QCOMPARE(backendLogicalDevice.actions().size(), 0);
diff --git a/tests/auto/input/mousedevice/tst_mousedevice.cpp b/tests/auto/input/mousedevice/tst_mousedevice.cpp
index 64447d0de..f245e399d 100644
--- a/tests/auto/input/mousedevice/tst_mousedevice.cpp
+++ b/tests/auto/input/mousedevice/tst_mousedevice.cpp
@@ -31,7 +31,6 @@
#include <Qt3DInput/qmousedevice.h>
#include <Qt3DInput/private/qmousedevice_p.h>
#include <Qt3DInput/private/mousedevice_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
class tst_MouseDevice : public Qt3DCore::QBackendNodeTester
@@ -70,7 +69,7 @@ private Q_SLOTS:
{
// WHEN
Qt3DInput::Input::MouseDevice backendMouseDevice;
- simulateInitialization(&mouseDevice, &backendMouseDevice);
+ simulateInitializationSync(&mouseDevice, &backendMouseDevice);
// THEN
QCOMPARE(backendMouseDevice.isEnabled(), true);
@@ -91,7 +90,7 @@ private Q_SLOTS:
// WHEN
Qt3DInput::Input::MouseDevice backendMouseDevice;
mouseDevice.setEnabled(false);
- simulateInitialization(&mouseDevice, &backendMouseDevice);
+ simulateInitializationSync(&mouseDevice, &backendMouseDevice);
// THEN
QCOMPARE(backendMouseDevice.peerId(), mouseDevice.id());
@@ -220,15 +219,15 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DInput::QMouseDevice mouseDevice;
Qt3DInput::Input::MouseDevice backendMouseDevice;
+ simulateInitializationSync(&mouseDevice, &backendMouseDevice);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendMouseDevice.sceneChangeEvent(change);
+ mouseDevice.setEnabled(newValue);
+ backendMouseDevice.syncFromFrontEnd(&mouseDevice, false);
// THEN
QCOMPARE(backendMouseDevice.isEnabled(), newValue);
@@ -236,10 +235,8 @@ private Q_SLOTS:
{
// WHEN
const float newValue = 99.0f;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("sensitivity");
- change->setValue(QVariant::fromValue(newValue));
- backendMouseDevice.sceneChangeEvent(change);
+ mouseDevice.setSensitivity(newValue);
+ backendMouseDevice.syncFromFrontEnd(&mouseDevice, false);
// THEN
QCOMPARE(backendMouseDevice.sensitivity(), newValue);
diff --git a/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp b/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp
index d19e69ecc..bd5da8e3f 100644
--- a/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp
+++ b/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp
@@ -32,9 +32,7 @@
#include <Qt3DInput/private/qabstractphysicaldeviceproxy_p_p.h>
#include <Qt3DInput/private/physicaldeviceproxy_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include "qbackendnodetester.h"
#include "testdeviceproxy.h"
#include "testpostmanarbiter.h"
@@ -69,7 +67,7 @@ private Q_SLOTS:
// WHEN
Qt3DInput::Input::PhysicalDeviceProxy backendPhysicalDeviceProxy;
backendPhysicalDeviceProxy.setManager(&manager);
- simulateInitialization(&PhysicalDeviceProxy, &backendPhysicalDeviceProxy);
+ simulateInitializationSync(&PhysicalDeviceProxy, &backendPhysicalDeviceProxy);
// THEN
QCOMPARE(backendPhysicalDeviceProxy.isEnabled(), true);
@@ -83,7 +81,7 @@ private Q_SLOTS:
Qt3DInput::Input::PhysicalDeviceProxy backendPhysicalDeviceProxy;
backendPhysicalDeviceProxy.setManager(&manager);
PhysicalDeviceProxy.setEnabled(false);
- simulateInitialization(&PhysicalDeviceProxy, &backendPhysicalDeviceProxy);
+ simulateInitializationSync(&PhysicalDeviceProxy, &backendPhysicalDeviceProxy);
// THEN
QCOMPARE(backendPhysicalDeviceProxy.peerId(), PhysicalDeviceProxy.id());
@@ -100,7 +98,7 @@ private Q_SLOTS:
// WHEN
backendPhysicalDeviceProxy.setManager(&manager);
- simulateInitialization(&deviceProxy, &backendPhysicalDeviceProxy);
+ simulateInitializationSync(&deviceProxy, &backendPhysicalDeviceProxy);
// THEN
QCOMPARE(backendPhysicalDeviceProxy.deviceName(), QStringLiteral("TestProxy"));
@@ -109,27 +107,6 @@ private Q_SLOTS:
QCOMPARE(pendingWrappers.first(), deviceProxy.id());
}
- void checkDeviceLoadedNotification()
- {
- // GIVEN
- Qt3DInput::Input::PhysicalDeviceProxy backendPhysicalDeviceProxy;
- TestPhysicalDevice physicalDevice;
- TestArbiter arbiter;
-
- // WHEN
- Qt3DCore::QBackendNodePrivate::get(&backendPhysicalDeviceProxy)->setArbiter(&arbiter);
-
- backendPhysicalDeviceProxy.setDevice(&physicalDevice);
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "device");
- QCOMPARE(change->value().value<Qt3DInput::QAbstractPhysicalDevice *>(), &physicalDevice);
- QCOMPARE(change->subjectId(), backendPhysicalDeviceProxy.peerId());
- QCOMPARE(backendPhysicalDeviceProxy.physicalDeviceId(), physicalDevice.id());
- }
-
void checkCleanupState()
{
// GIVEN
@@ -139,7 +116,7 @@ private Q_SLOTS:
// WHEN
backendPhysicalDeviceProxy.setManager(&manager);
- simulateInitialization(&deviceProxy, &backendPhysicalDeviceProxy);
+ simulateInitializationSync(&deviceProxy, &backendPhysicalDeviceProxy);
backendPhysicalDeviceProxy.cleanup();
diff --git a/tests/auto/input/qabstractaxisinput/tst_qabstractaxisinput.cpp b/tests/auto/input/qabstractaxisinput/tst_qabstractaxisinput.cpp
index 87f738367..4e9f609c4 100644
--- a/tests/auto/input/qabstractaxisinput/tst_qabstractaxisinput.cpp
+++ b/tests/auto/input/qabstractaxisinput/tst_qabstractaxisinput.cpp
@@ -29,7 +29,6 @@
#include <QtTest/QTest>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DInput/QAbstractAxisInput>
#include <Qt3DInput/QAbstractPhysicalDevice>
@@ -72,16 +71,12 @@ private Q_SLOTS:
arbiter.events.clear();
axisInput->setSourceDevice(device);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceDevice");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), device->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axisInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkSourceDeviceBookkeeping()
diff --git a/tests/auto/input/qabstractphysicaldevicebackendnode/tst_qabstractphysicaldevicebackendnode.cpp b/tests/auto/input/qabstractphysicaldevicebackendnode/tst_qabstractphysicaldevicebackendnode.cpp
index d146a80e7..247a881ad 100644
--- a/tests/auto/input/qabstractphysicaldevicebackendnode/tst_qabstractphysicaldevicebackendnode.cpp
+++ b/tests/auto/input/qabstractphysicaldevicebackendnode/tst_qabstractphysicaldevicebackendnode.cpp
@@ -36,9 +36,6 @@
#include <Qt3DInput/private/qinputaspect_p.h>
#include <Qt3DInput/private/inputmanagers_p.h>
#include <Qt3DInput/private/axissetting_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include "testdevice.h"
@@ -143,7 +140,7 @@ private Q_SLOTS:
{
// WHEN
TestPhysicalDeviceBackendNode backendQAbstractPhysicalDeviceBackendNode;
- simulateInitialization(&physicalDeviceNode, &backendQAbstractPhysicalDeviceBackendNode);
+ simulateInitializationSync(&physicalDeviceNode, &backendQAbstractPhysicalDeviceBackendNode);
// THEN
QCOMPARE(backendQAbstractPhysicalDeviceBackendNode.isEnabled(), true);
@@ -153,7 +150,7 @@ private Q_SLOTS:
// WHEN
TestPhysicalDeviceBackendNode backendQAbstractPhysicalDeviceBackendNode;
physicalDeviceNode.setEnabled(false);
- simulateInitialization(&physicalDeviceNode, &backendQAbstractPhysicalDeviceBackendNode);
+ simulateInitializationSync(&physicalDeviceNode, &backendQAbstractPhysicalDeviceBackendNode);
// THEN
QCOMPARE(backendQAbstractPhysicalDeviceBackendNode.peerId(), physicalDeviceNode.id());
@@ -164,17 +161,17 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ TestDevice physicalDeviceNode;
TestPhysicalDeviceBackendNode backendQAbstractPhysicalDeviceBackendNode;
Qt3DInput::QInputAspect aspect;
backendQAbstractPhysicalDeviceBackendNode.setInputAspect(&aspect);
+ simulateInitializationSync(&physicalDeviceNode, &backendQAbstractPhysicalDeviceBackendNode);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendQAbstractPhysicalDeviceBackendNode.sceneChangeEvent(change);
+ physicalDeviceNode.setEnabled(newValue);
+ backendQAbstractPhysicalDeviceBackendNode.syncFromFrontEnd(&physicalDeviceNode, false);
// THEN
QCOMPARE(backendQAbstractPhysicalDeviceBackendNode.isEnabled(), newValue);
@@ -195,47 +192,43 @@ private Q_SLOTS:
Qt3DInput::Input::InputHandler *handler = aspectPrivate->m_inputHandler.data();
Qt3DInput::Input::AxisSetting *backendSetting1 = handler->axisSettingManager()->getOrCreateResource(settings1.id());
Qt3DInput::Input::AxisSetting *backendSetting2 = handler->axisSettingManager()->getOrCreateResource(settings2.id());
- simulateInitialization(&settings1, backendSetting1);
- simulateInitialization(&settings2, backendSetting2);
+ simulateInitializationSync(&settings1, backendSetting1);
+ simulateInitializationSync(&settings2, backendSetting2);
}
// Adding AxisSettings
{
// WHEN
- auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &settings1);
- change->setPropertyName("axisSettings");
- backendQAbstractPhysicalDeviceBackendNode.sceneChangeEvent(change);
+ physicalDeviceNode.addAxisSetting(&settings1);
+ backendQAbstractPhysicalDeviceBackendNode.syncFromFrontEnd(&physicalDeviceNode, false);
// THEN
QCOMPARE(priv->m_axisSettings.size(), 1);
// WHEN
- change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &settings2);
- change->setPropertyName("axisSettings");
- backendQAbstractPhysicalDeviceBackendNode.sceneChangeEvent(change);
+ physicalDeviceNode.addAxisSetting(&settings2);
+ backendQAbstractPhysicalDeviceBackendNode.syncFromFrontEnd(&physicalDeviceNode, false);
// THEN
QCOMPARE(priv->m_axisSettings.size(), 2);
}
+
// Removing AxisSettings
{
// WHEN
- auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &settings1);
- change->setPropertyName("axisSettings");
- backendQAbstractPhysicalDeviceBackendNode.sceneChangeEvent(change);
+ physicalDeviceNode.removeAxisSetting(&settings1);
+ backendQAbstractPhysicalDeviceBackendNode.syncFromFrontEnd(&physicalDeviceNode, false);
// THEN
QCOMPARE(priv->m_axisSettings.size(), 1);
// WHEN
- change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &settings2);
- change->setPropertyName("axisSettings");
- backendQAbstractPhysicalDeviceBackendNode.sceneChangeEvent(change);
+ physicalDeviceNode.removeAxisSetting(&settings2);
+ backendQAbstractPhysicalDeviceBackendNode.syncFromFrontEnd(&physicalDeviceNode, false);
// THEN
QCOMPARE(priv->m_axisSettings.size(), 0);
}
-
}
}
diff --git a/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp b/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp
index b4dfef05e..bbe184e0e 100644
--- a/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp
+++ b/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp
@@ -29,7 +29,6 @@
#include <QtTest/QTest>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testdeviceproxy.h"
@@ -55,30 +54,6 @@ private Q_SLOTS:
QVERIFY(abstractPhysicalDeviceProxy.device() == nullptr);
}
-
- void checkDeviceLoading()
- {
- // GIVEN
- TestProxy abstractPhysicalDeviceProxy;
-
- // WHEN
- TestPhysicalDevice *device = new TestPhysicalDevice();
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("device");
- change->setValue(QVariant::fromValue(device));
-
- abstractPhysicalDeviceProxy.simulateSceneChangeEvent(change);
-
- // THEN
- QCOMPARE(abstractPhysicalDeviceProxy.deviceName(), QLatin1String("TestProxy"));
- QCOMPARE(abstractPhysicalDeviceProxy.status(), Qt3DInput::QAbstractPhysicalDeviceProxy::Ready);
- QCOMPARE(abstractPhysicalDeviceProxy.axisCount(), device->axisCount());
- QCOMPARE(abstractPhysicalDeviceProxy.buttonCount(), device->buttonCount());
- QCOMPARE(abstractPhysicalDeviceProxy.axisNames(), device->axisNames());
- QCOMPARE(abstractPhysicalDeviceProxy.buttonNames(), device->buttonNames());
- QVERIFY(abstractPhysicalDeviceProxy.device() == device);
- }
-
void checkDeviceBookkeeping()
{
// GIVEN
@@ -86,11 +61,7 @@ private Q_SLOTS:
// WHEN
TestPhysicalDevice *device = new TestPhysicalDevice();
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("device");
- change->setValue(QVariant::fromValue(device));
-
- abstractPhysicalDeviceProxy->simulateSceneChangeEvent(change);
+ abstractPhysicalDeviceProxy->setDevice(device);
// THEN
QVERIFY(abstractPhysicalDeviceProxy->device() == device);
diff --git a/tests/auto/input/qaction/tst_qaction.cpp b/tests/auto/input/qaction/tst_qaction.cpp
index 4becee318..13c4a2d83 100644
--- a/tests/auto/input/qaction/tst_qaction.cpp
+++ b/tests/auto/input/qaction/tst_qaction.cpp
@@ -36,10 +36,6 @@
#include <Qt3DInput/private/qaction_p.h>
#include <Qt3DInput/private/qactioninput_p.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
-
#include "testpostmanarbiter.h"
// We need to call QNode::clone which is protected
@@ -116,44 +112,24 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeAddedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "input");
- QCOMPARE(change->addedNodeId(), input->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), action.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
action->removeInput(input);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeRemovedChangePtr nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "input");
- QCOMPARE(nodeRemovedChange->removedNodeId(), input->id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), action.data());
arbiter.events.clear();
}
- void checkActivePropertyChanged()
- {
- // GIVEN
- QCOMPARE(isActive(), false);
-
- // Note: simulate backend change to frontend
- // WHEN
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("active");
- valueChange->setValue(true);
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(isActive(), true);
- }
-
void checkActionInputBookkeeping()
{
// GIVEN
diff --git a/tests/auto/input/qactioninput/tst_qactioninput.cpp b/tests/auto/input/qactioninput/tst_qactioninput.cpp
index 3b6030673..be06cd8b2 100644
--- a/tests/auto/input/qactioninput/tst_qactioninput.cpp
+++ b/tests/auto/input/qactioninput/tst_qactioninput.cpp
@@ -101,16 +101,12 @@ private Q_SLOTS:
// WHEN
QVector<int> buttons = QVector<int>() << 555;
actionInput->setButtons(buttons);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "buttons");
- QCOMPARE(change->value().value<QVector<int>>(), buttons);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), actionInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
TestDevice *device = new TestDevice(actionInput.data());
@@ -118,16 +114,12 @@ private Q_SLOTS:
arbiter.events.clear();
actionInput->setSourceDevice(device);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceDevice");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), device->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), actionInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkSourceDeviceBookkeeping()
diff --git a/tests/auto/input/qanalogaxisinput/tst_qanalogaxisinput.cpp b/tests/auto/input/qanalogaxisinput/tst_qanalogaxisinput.cpp
index da22ca165..c9abd0f4b 100644
--- a/tests/auto/input/qanalogaxisinput/tst_qanalogaxisinput.cpp
+++ b/tests/auto/input/qanalogaxisinput/tst_qanalogaxisinput.cpp
@@ -97,16 +97,12 @@ private Q_SLOTS:
// WHEN
axisInput->setAxis(350);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "axis");
- QCOMPARE(change->value().toInt(), 350);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axisInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
TestDevice *device = new TestDevice(axisInput.data());
@@ -114,16 +110,12 @@ private Q_SLOTS:
arbiter.events.clear();
axisInput->setSourceDevice(device);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceDevice");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), device->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axisInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
};
diff --git a/tests/auto/input/qaxis/tst_qaxis.cpp b/tests/auto/input/qaxis/tst_qaxis.cpp
index 35cee0bba..9b3068442 100644
--- a/tests/auto/input/qaxis/tst_qaxis.cpp
+++ b/tests/auto/input/qaxis/tst_qaxis.cpp
@@ -35,16 +35,9 @@
#include <Qt3DInput/QAnalogAxisInput>
#include <Qt3DInput/private/qaxis_p.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
-
#include "testpostmanarbiter.h"
-// We need to call QNode::clone which is protected
-// We need to call QAxis::sceneChangeEvent which is protected
-// So we sublcass QAxis instead of QObject
-class tst_QAxis: public Qt3DInput::QAxis
+class tst_QAxis: public QObject
{
Q_OBJECT
public:
@@ -113,44 +106,24 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeAddedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "input");
- QCOMPARE(change->addedNodeId(), input->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axis.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
axis->removeInput(input);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeRemovedChangePtr nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "input");
- QCOMPARE(nodeRemovedChange->removedNodeId(), input->id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axis.data());
arbiter.events.clear();
}
- void checkValuePropertyChanged()
- {
- // GIVEN
- QCOMPARE(value(), 0.0f);
-
- // Note: simulate backend change to frontend
- // WHEN
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("value");
- valueChange->setValue(383.0f);
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(value(), 383.0f);
- }
-
void checkAxisInputBookkeeping()
{
// GIVEN
diff --git a/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp b/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp
index 2447c564d..9f96cd845 100644
--- a/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp
+++ b/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp
@@ -35,10 +35,6 @@
#include <Qt3DInput/qaxisaccumulator.h>
#include <Qt3DInput/private/qaxisaccumulator_p.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
-
#include "testpostmanarbiter.h"
class tst_QAxisAccumulator: public Qt3DInput::QAxisAccumulator
@@ -131,69 +127,31 @@ private Q_SLOTS:
// WHEN
accumulator->setSourceAxis(axis);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceAxis");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), axis->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), accumulator.data());
+
+ arbiter.dirtyNodes.clear();
- arbiter.events.clear();
// WHEN
accumulator->setScale(2.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "scale");
- QCOMPARE(change->value().toFloat(), 2.0f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), accumulator.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
accumulator->setSourceAxisType(Qt3DInput::QAxisAccumulator::Acceleration);
- QCoreApplication::processEvents();
-
- // THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceAxisType");
- QCOMPARE(change->value().value<Qt3DInput::QAxisAccumulator::SourceAxisType>(), Qt3DInput::QAxisAccumulator::Acceleration);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
- }
-
- void checkValuePropertyChanged()
- {
- // GIVEN
- QCOMPARE(value(), 0.0f);
-
- // Note: simulate backend change to frontend
- // WHEN
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("value");
- valueChange->setValue(383.0f);
- sceneChangeEvent(valueChange);
// THEN
- QCOMPARE(value(), 383.0f);
- QCOMPARE(velocity(), 0.0f);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), accumulator.data());
- // WHEN
- valueChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- valueChange->setPropertyName("velocity");
- valueChange->setValue(123.0f);
- sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(value(), 383.0f);
- QCOMPARE(velocity(), 123.0f);
+ arbiter.dirtyNodes.clear();
}
void checkAxisInputBookkeeping()
diff --git a/tests/auto/input/qbuttonaxisinput/tst_qbuttonaxisinput.cpp b/tests/auto/input/qbuttonaxisinput/tst_qbuttonaxisinput.cpp
index 618c75d42..e8ab3e172 100644
--- a/tests/auto/input/qbuttonaxisinput/tst_qbuttonaxisinput.cpp
+++ b/tests/auto/input/qbuttonaxisinput/tst_qbuttonaxisinput.cpp
@@ -27,7 +27,6 @@
****************************************************************************/
#include <QtTest/QTest>
-#include <Qt3DCore/QPropertyUpdatedChange>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
@@ -121,72 +120,50 @@ private Q_SLOTS:
// WHEN
QVector<int> buttons = QVector<int>() << 555;
axisInput->setButtons(buttons);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "buttons");
- QCOMPARE(change->value().value<QVector<int>>(), buttons);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axisInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
axisInput->setScale(1340.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "scale");
- QCOMPARE(change->value().toFloat(), 1340.0f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axisInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
TestDevice *device = new TestDevice(axisInput.data());
- QCoreApplication::processEvents();
- arbiter.events.clear();
axisInput->setSourceDevice(device);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceDevice");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), device->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axisInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
axisInput->setAcceleration(42.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "acceleration");
- QCOMPARE(change->value().toFloat(), 42.0f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axisInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
axisInput->setDeceleration(43.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "deceleration");
- QCOMPARE(change->value().toFloat(), 43.0f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), axisInput.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
};
diff --git a/tests/auto/input/qkeyboardhandler/tst_qkeyboardhandler.cpp b/tests/auto/input/qkeyboardhandler/tst_qkeyboardhandler.cpp
index f35d6490f..3f1e7fd09 100644
--- a/tests/auto/input/qkeyboardhandler/tst_qkeyboardhandler.cpp
+++ b/tests/auto/input/qkeyboardhandler/tst_qkeyboardhandler.cpp
@@ -27,7 +27,6 @@
****************************************************************************/
#include <QtTest/QTest>
-#include <Qt3DCore/QPropertyUpdatedChange>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
@@ -96,16 +95,12 @@ private Q_SLOTS:
// WHEN
keyboardHandler->setFocus(true);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "focus");
- QCOMPARE(change->value().toBool(), true);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), keyboardHandler.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
auto device = new Qt3DInput::QKeyboardDevice(keyboardHandler.data());
@@ -113,16 +108,12 @@ private Q_SLOTS:
arbiter.events.clear();
keyboardHandler->setSourceDevice(device);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceDevice");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), device->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), keyboardHandler.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkSourceDeviceBookkeeping()
diff --git a/tests/auto/input/qlogicaldevice/tst_qlogicaldevice.cpp b/tests/auto/input/qlogicaldevice/tst_qlogicaldevice.cpp
index f81fcee41..c7236ac7d 100644
--- a/tests/auto/input/qlogicaldevice/tst_qlogicaldevice.cpp
+++ b/tests/auto/input/qlogicaldevice/tst_qlogicaldevice.cpp
@@ -36,10 +36,6 @@
#include <Qt3DInput/QAxis>
#include <Qt3DInput/QAction>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
-
#include "testpostmanarbiter.h"
class tst_QLogicalDevice: public QObject
@@ -122,56 +118,48 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeAddedChangePtr nodeAddedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(nodeAddedChange->propertyName(), "action");
- QCOMPARE(nodeAddedChange->addedNodeId(), action->id());
- QCOMPARE(nodeAddedChange->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), logicalDevice.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
logicalDevice->removeAction(action);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeRemovedChangePtr nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "action");
- QCOMPARE(nodeRemovedChange->removedNodeId(), action->id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), logicalDevice.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
Qt3DInput::QAxis *axis = new Qt3DInput::QAxis(logicalDevice.data());
QCoreApplication::processEvents();
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
logicalDevice->addAxis(axis);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- nodeAddedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(nodeAddedChange->propertyName(), "axis");
- QCOMPARE(nodeAddedChange->addedNodeId(), axis->id());
- QCOMPARE(nodeAddedChange->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), logicalDevice.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
logicalDevice->removeAxis(axis);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "axis");
- QCOMPARE(nodeRemovedChange->removedNodeId(), axis->id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), logicalDevice.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkAxisBookkeeping()
diff --git a/tests/auto/input/qmousedevice/tst_qmousedevice.cpp b/tests/auto/input/qmousedevice/tst_qmousedevice.cpp
index 6ea085184..fd2c8e603 100644
--- a/tests/auto/input/qmousedevice/tst_qmousedevice.cpp
+++ b/tests/auto/input/qmousedevice/tst_qmousedevice.cpp
@@ -33,7 +33,6 @@
#include <Qt3DInput/private/qmousedevice_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -161,25 +160,17 @@ private Q_SLOTS:
{
// WHEN
mouseDevice.setSensitivity(0.7f);
- QCoreApplication::processEvents();
-
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sensitivity");
- QCOMPARE(change->value().value<float>(), mouseDevice.sensitivity());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mouseDevice);
}
{
// WHEN
mouseDevice.setSensitivity(0.7f);
- QCoreApplication::processEvents();
- // THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mouseDevice);
}
}
diff --git a/tests/auto/input/qmouseevent/qmouseevent.pro b/tests/auto/input/qmouseevent/qmouseevent.pro
new file mode 100644
index 000000000..70f4c6eda
--- /dev/null
+++ b/tests/auto/input/qmouseevent/qmouseevent.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+TARGET = tst_qmouseevent
+
+QT += 3dcore 3dcore-private 3dinput 3dinput-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_qmouseevent.cpp
+
+include(../commons/commons.pri)
diff --git a/tests/auto/input/qmouseevent/tst_qmouseevent.cpp b/tests/auto/input/qmouseevent/tst_qmouseevent.cpp
new file mode 100644
index 000000000..b48afb99d
--- /dev/null
+++ b/tests/auto/input/qmouseevent/tst_qmouseevent.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QTest>
+#include <Qt3DInput/qmouseevent.h>
+#include <QtGui/QMouseEvent>
+#include <QObject>
+#include <QSignalSpy>
+
+class tst_QMouseEvent : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void checkModifiers()
+ {
+ {
+ // GIVEN
+ QT_PREPEND_NAMESPACE(QMouseEvent) event(QEvent::MouseButtonPress,
+ QPointF(500, 500),
+ QPointF(500, 500),
+ Qt::LeftButton,
+ Qt::LeftButton,
+ Qt::NoModifier);
+
+ // WHEN
+ Qt3DInput::QMouseEvent event3D(event);
+
+ // THEN
+ QCOMPARE(event3D.modifiers(), Qt3DInput::QMouseEvent::NoModifier);
+ }
+ {
+ // GIVEN
+ QT_PREPEND_NAMESPACE(QMouseEvent) event(QEvent::MouseButtonPress,
+ QPointF(500, 500),
+ QPointF(500, 500),
+ Qt::LeftButton,
+ Qt::LeftButton,
+ Qt::ShiftModifier);
+
+ // WHEN
+ Qt3DInput::QMouseEvent event3D(event);
+
+ // THEN
+ QCOMPARE(event3D.modifiers(), Qt3DInput::QMouseEvent::ShiftModifier);
+ }
+ {
+ // GIVEN
+ QT_PREPEND_NAMESPACE(QMouseEvent) event(QEvent::MouseButtonPress,
+ QPointF(500, 500),
+ QPointF(500, 500),
+ Qt::LeftButton,
+ Qt::LeftButton,
+ Qt::ShiftModifier|Qt::ControlModifier);
+
+ // WHEN
+ Qt3DInput::QMouseEvent event3D(event);
+
+ // THEN
+ QCOMPARE(int(event3D.modifiers()), int(Qt3DInput::QMouseEvent::ShiftModifier|Qt3DInput::QMouseEvent::ControlModifier));
+ }
+ }
+};
+
+QTEST_MAIN(tst_QMouseEvent)
+
+#include "tst_qmouseevent.moc"
diff --git a/tests/auto/input/utils/tst_utils.cpp b/tests/auto/input/utils/tst_utils.cpp
index d90034a3f..14a289556 100644
--- a/tests/auto/input/utils/tst_utils.cpp
+++ b/tests/auto/input/utils/tst_utils.cpp
@@ -31,7 +31,6 @@
#include <Qt3DInput/private/utils_p.h>
#include <Qt3DInput/private/axis_p.h>
#include <Qt3DInput/qanalogaxisinput.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include "testdeviceproxy.h"
@@ -94,7 +93,7 @@ private Q_SLOTS:
// WHEN -> Create backend AnalogAxisInput
Qt3DInput::Input::AnalogAxisInput *backendAxisInput = handler.analogAxisInputManager()->getOrCreateResource(analogAxisInput.id());
- simulateInitialization(&analogAxisInput, backendAxisInput);
+ simulateInitializationSync(&analogAxisInput, backendAxisInput);
// THEN
QCOMPARE(backendAxisInput->axis(), analogAxisInput.axis());
@@ -125,7 +124,7 @@ private Q_SLOTS:
// WHEN -> Create backend AnalogAxisInput
Qt3DInput::Input::AnalogAxisInput *backendAxisInput = handler.analogAxisInputManager()->getOrCreateResource(analogAxisInput.id());
- simulateInitialization(&analogAxisInput, backendAxisInput);
+ simulateInitializationSync(&analogAxisInput, backendAxisInput);
// THEN
QCOMPARE(backendAxisInput->axis(), analogAxisInput.axis());
@@ -165,7 +164,7 @@ private Q_SLOTS:
// WHEN -> Create backend AnalogAxisInput
Qt3DInput::Input::AnalogAxisInput *backendAxisInput = handler.analogAxisInputManager()->getOrCreateResource(analogAxisInput.id());
- simulateInitialization(&analogAxisInput, backendAxisInput);
+ simulateInitializationSync(&analogAxisInput, backendAxisInput);
// THEN
QCOMPARE(backendAxisInput->axis(), analogAxisInput.axis());
@@ -196,7 +195,7 @@ private Q_SLOTS:
// WHEN -> Create backend AnalogAxisInput
Qt3DInput::Input::AnalogAxisInput *backendAxisInput = handler.analogAxisInputManager()->getOrCreateResource(analogAxisInput.id());
- simulateInitialization(&analogAxisInput, backendAxisInput);
+ simulateInitializationSync(&analogAxisInput, backendAxisInput);
// THEN
QCOMPARE(backendAxisInput->axis(), analogAxisInput.axis());
diff --git a/tests/auto/quick3d/3dcore/3dcore.qml b/tests/auto/quick3d/3dcore/3dcore.qml
index 72514591c..d0a5c6f09 100644
--- a/tests/auto/quick3d/3dcore/3dcore.qml
+++ b/tests/auto/quick3d/3dcore/3dcore.qml
@@ -30,6 +30,7 @@
import Qt3D.Core 2.0 as QQ3Core20
import Qt3D.Core 2.9 as QQ3Core29
import Qt3D.Core 2.10 as QQ3Core210
+import Qt3D.Core 2.14 as QQ3Core214
import QtQuick 2.0
Item {
@@ -47,4 +48,6 @@ Item {
QQ3Core210.Armature {}
QQ3Core210.SkeletonLoader {}
QQ3Core210.Joint {}
+
+ QQ3Core214.Transform {}
}
diff --git a/tests/auto/quick3d/3drender/3drender.qml b/tests/auto/quick3d/3drender/3drender.qml
index c20ce6c45..8c200f3c0 100644
--- a/tests/auto/quick3d/3drender/3drender.qml
+++ b/tests/auto/quick3d/3drender/3drender.qml
@@ -31,6 +31,7 @@ import Qt3D.Render 2.0 as QQ3Render20
import Qt3D.Render 2.1 as QQ3Render21
import Qt3D.Render 2.10 as QQ3Render210
import Qt3D.Render 2.13 as QQ3Render213
+import Qt3D.Render 2.14 as QQ3Render214
import QtQuick 2.0
Item {
@@ -58,6 +59,7 @@ Item {
//QQ3Render20.QShaderData // (uncreatable) Qt3DRender::QShaderData
QQ3Render20.ShaderDataArray {} //Qt3DRender::Render::Quick::Quick3DShaderDataArray
QQ3Render20.ShaderData {} //Qt3DRender::Render::Quick::Quick3DShaderData
+ QQ3Render214.ShaderImage {}
// Camera
QQ3Render20.Camera {} //Qt3DRender::QCamera
@@ -161,4 +163,7 @@ Item {
QQ3Render20.StencilOperation {} //Qt3DRender::QStencilOperation
QQ3Render20.StencilMask {} //Qt3DRender::QStencilMask
+ QQ3Render214.DepthRange {}
+ QQ3Render214.RasterMode {}
+
}
diff --git a/tests/auto/render/armature/tst_armature.cpp b/tests/auto/render/armature/tst_armature.cpp
index 2c481db7a..99b9aa7a5 100644
--- a/tests/auto/render/armature/tst_armature.cpp
+++ b/tests/auto/render/armature/tst_armature.cpp
@@ -32,7 +32,6 @@
#include <Qt3DCore/qskeleton.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
@@ -56,7 +55,7 @@ private Q_SLOTS:
armature.setSkeleton(skeleton);
// WHEN
- simulateInitialization(&armature, &backendArmature);
+ simulateInitializationSync(&armature, &backendArmature);
// THEN
QCOMPARE(backendArmature.peerId(), armature.id());
@@ -80,7 +79,7 @@ private Q_SLOTS:
armature.setSkeleton(skeleton);
// WHEN
- simulateInitialization(&armature, &backendArmature);
+ simulateInitializationSync(&armature, &backendArmature);
backendArmature.cleanup();
// THEN
@@ -91,24 +90,21 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ QArmature armature;
Armature backendArmature;
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
+ simulateInitializationSync(&armature, &backendArmature);
// WHEN
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendArmature.sceneChangeEvent(updateChange);
+ armature.setEnabled(false);
+ backendArmature.syncFromFrontEnd(&armature, false);
// THEN
- QCOMPARE(backendArmature.isEnabled(), true);
+ QCOMPARE(backendArmature.isEnabled(), false);
// WHEN
auto newSkeleton = new QSkeleton();
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("skeleton");
- updateChange->setValue(QVariant::fromValue(newSkeleton->id()));
- backendArmature.sceneChangeEvent(updateChange);
+ armature.setSkeleton(newSkeleton);
+ backendArmature.syncFromFrontEnd(&armature, false);
// THEN
QCOMPARE(backendArmature.skeletonId(), newSkeleton->id());
diff --git a/tests/auto/render/attribute/tst_attribute.cpp b/tests/auto/render/attribute/tst_attribute.cpp
index e0f6f6b5c..5571ef334 100644
--- a/tests/auto/render/attribute/tst_attribute.cpp
+++ b/tests/auto/render/attribute/tst_attribute.cpp
@@ -30,18 +30,20 @@
#include <qbackendnodetester.h>
#include <Qt3DRender/private/attribute_p.h>
#include <Qt3DRender/qbuffer.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "testrenderer.h"
class tst_Attribute : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
+
private Q_SLOTS:
void checkPeerPropertyMirroring()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::Attribute renderAttribute;
+ renderAttribute.setRenderer(&renderer);
Qt3DRender::QAttribute attribute;
attribute.setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
@@ -59,7 +61,7 @@ private Q_SLOTS:
attribute.setBuffer(&buffer);
// WHEN
- simulateInitialization(&attribute, &renderAttribute);
+ simulateInitializationSync(&attribute, &renderAttribute);
// THEN
QCOMPARE(renderAttribute.peerId(), attribute.id());
@@ -111,7 +113,7 @@ private Q_SLOTS:
attribute.setBuffer(&buffer);
// WHEN
- simulateInitialization(&attribute, &renderAttribute);
+ simulateInitializationSync(&attribute, &renderAttribute);
renderAttribute.cleanup();
// THEN
@@ -130,17 +132,20 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
+ Qt3DRender::QAttribute attribute;
TestRenderer renderer;
Qt3DRender::Render::Attribute renderAttribute;
renderAttribute.setRenderer(&renderer);
+ simulateInitializationSync(&attribute, &renderAttribute);
+ renderAttribute.cleanup();
+ renderer.resetDirty();
QVERIFY(!renderAttribute.isDirty());
+ QVERIFY(!renderer.dirtyBits());
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(static_cast<int>(Qt3DRender::QAttribute::Int));
- updateChange->setPropertyName("vertexBaseType");
- renderAttribute.sceneChangeEvent(updateChange);
+ attribute.setVertexBaseType(Qt3DRender::QAttribute::Int);
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
QCOMPARE(renderAttribute.vertexBaseType(), Qt3DRender::QAttribute::Int);
@@ -153,10 +158,8 @@ private Q_SLOTS:
QVERIFY(!renderer.dirtyBits());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(3);
- updateChange->setPropertyName("vertexSize");
- renderAttribute.sceneChangeEvent(updateChange);
+ attribute.setVertexSize(3);
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
QCOMPARE(renderAttribute.vertexSize(), 3U);
@@ -168,10 +171,8 @@ private Q_SLOTS:
QVERIFY(!renderAttribute.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(static_cast<int>(Qt3DRender::QAttribute::IndexAttribute));
- updateChange->setPropertyName("attributeType");
- renderAttribute.sceneChangeEvent(updateChange);
+ attribute.setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
QCOMPARE(renderAttribute.attributeType(), Qt3DRender::QAttribute::IndexAttribute);
@@ -183,10 +184,8 @@ private Q_SLOTS:
QVERIFY(!renderAttribute.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(static_cast<int>(Qt3DRender::QAttribute::DrawIndirectAttribute));
- updateChange->setPropertyName("attributeType");
- renderAttribute.sceneChangeEvent(updateChange);
+ attribute.setAttributeType(Qt3DRender::QAttribute::DrawIndirectAttribute);
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
QCOMPARE(renderAttribute.attributeType(), Qt3DRender::QAttribute::DrawIndirectAttribute);
@@ -198,10 +197,8 @@ private Q_SLOTS:
QVERIFY(!renderAttribute.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(1340);
- updateChange->setPropertyName("count");
- renderAttribute.sceneChangeEvent(updateChange);
+ attribute.setCount(1340);
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
QCOMPARE(renderAttribute.count(), 1340U);
@@ -213,10 +210,8 @@ private Q_SLOTS:
QVERIFY(!renderAttribute.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QStringLiteral("L88"));
- updateChange->setPropertyName("name");
- renderAttribute.sceneChangeEvent(updateChange);
+ attribute.setName(QStringLiteral("L88"));
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
QCOMPARE(renderAttribute.name(), QStringLiteral("L88"));
@@ -228,10 +223,8 @@ private Q_SLOTS:
QVERIFY(!renderAttribute.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(555);
- updateChange->setPropertyName("byteOffset");
- renderAttribute.sceneChangeEvent(updateChange);
+ attribute.setByteOffset(555U);
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
QCOMPARE(renderAttribute.byteOffset(), 555U);
@@ -243,10 +236,8 @@ private Q_SLOTS:
QVERIFY(!renderAttribute.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(454);
- updateChange->setPropertyName("byteStride");
- renderAttribute.sceneChangeEvent(updateChange);
+ attribute.setByteStride(454);
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
QCOMPARE(renderAttribute.byteStride(), 454U);
@@ -258,10 +249,8 @@ private Q_SLOTS:
QVERIFY(!renderAttribute.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(1450);
- updateChange->setPropertyName("divisor");
- renderAttribute.sceneChangeEvent(updateChange);
+ attribute.setDivisor(1450);
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
QCOMPARE(renderAttribute.divisor(), 1450U);
@@ -273,14 +262,12 @@ private Q_SLOTS:
QVERIFY(!renderAttribute.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- Qt3DCore::QNodeId bufferId = Qt3DCore::QNodeId::createId();
- updateChange->setValue(QVariant::fromValue(bufferId));
- updateChange->setPropertyName("buffer");
- renderAttribute.sceneChangeEvent(updateChange);
+ auto buffer = new Qt3DRender::QBuffer();
+ attribute.setBuffer(buffer);
+ renderAttribute.syncFromFrontEnd(&attribute, false);
// THEN
- QCOMPARE(renderAttribute.bufferId(), bufferId);
+ QCOMPARE(renderAttribute.bufferId(), buffer->id());
QVERIFY(renderAttribute.isDirty());
QVERIFY(renderer.dirtyBits() != 0);
diff --git a/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp b/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp
index 9232aa70f..ccac64eea 100644
--- a/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp
+++ b/tests/auto/render/blitframebuffer/tst_blitframebuffer.cpp
@@ -31,7 +31,6 @@
#include <Qt3DRender/qblitframebuffer.h>
#include <Qt3DRender/private/qblitframebuffer_p.h>
#include <Qt3DRender/private/blitframebuffer_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
@@ -62,6 +61,7 @@ private Q_SLOTS:
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QRenderTarget *sourceTarget = new Qt3DRender::QRenderTarget;
Qt3DRender::QRenderTarget *destinationTarget = new Qt3DRender::QRenderTarget;
Qt3DRender::QBlitFramebuffer blitFramebuffer;
@@ -76,7 +76,8 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer;
- simulateInitialization(&blitFramebuffer, &backendBlitFramebuffer);
+ backendBlitFramebuffer.setRenderer(&renderer);
+ simulateInitializationSync(&blitFramebuffer, &backendBlitFramebuffer);
// THEN
QCOMPARE(backendBlitFramebuffer.isEnabled(), true);
@@ -88,16 +89,20 @@ private Q_SLOTS:
QCOMPARE(backendBlitFramebuffer.sourceAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color1);
QCOMPARE(backendBlitFramebuffer.destinationAttachmentPoint(), Qt3DRender::QRenderTargetOutput::Color1);
QCOMPARE(backendBlitFramebuffer.interpolationMethod(), Qt3DRender::QBlitFramebuffer::Nearest);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer;
+ backendBlitFramebuffer.setRenderer(&renderer);
blitFramebuffer.setEnabled(false);
- simulateInitialization(&blitFramebuffer, &backendBlitFramebuffer);
+ simulateInitializationSync(&blitFramebuffer, &backendBlitFramebuffer);
// THEN
QCOMPARE(backendBlitFramebuffer.peerId(), blitFramebuffer.id());
QCOMPARE(backendBlitFramebuffer.isEnabled(), false);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
}
@@ -105,98 +110,84 @@ private Q_SLOTS:
{
// GIVEN
Qt3DRender::Render::BlitFramebuffer backendBlitFramebuffer;
+ Qt3DRender::QBlitFramebuffer blitFramebuffer;
TestRenderer renderer;
backendBlitFramebuffer.setRenderer(&renderer);
+ simulateInitializationSync(&blitFramebuffer, &backendBlitFramebuffer);
{
- // WHEN
- const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendBlitFramebuffer.sceneChangeEvent(change);
-
- // THEN
+ // WHEN
+ const bool newValue = false;
+ blitFramebuffer.setEnabled(newValue);
+ backendBlitFramebuffer.syncFromFrontEnd(&blitFramebuffer, false);
+
+ // THEN
QCOMPARE(backendBlitFramebuffer.isEnabled(), newValue);
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
{
- // WHEN
- const Qt3DRender::QRenderTarget sourceRenderTarget;
- const Qt3DCore::QNodeId newValue = sourceRenderTarget.id();
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("sourceRenderTarget");
- change->setValue(QVariant::fromValue(newValue));
- backendBlitFramebuffer.sceneChangeEvent(change);
-
- // THEN
- QCOMPARE(backendBlitFramebuffer.sourceRenderTargetId(), newValue);
+ // WHEN
+ Qt3DRender::QRenderTarget sourceRenderTarget;
+ blitFramebuffer.setSource(&sourceRenderTarget);
+ backendBlitFramebuffer.syncFromFrontEnd(&blitFramebuffer, false);
+
+ // THEN
+ QCOMPARE(backendBlitFramebuffer.sourceRenderTargetId(), sourceRenderTarget.id());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
{
- // WHEN
- const Qt3DRender::QRenderTarget destinationRenderTarget;
- const Qt3DCore::QNodeId newValue = destinationRenderTarget.id();
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("destinationRenderTarget");
- change->setValue(QVariant::fromValue(newValue));
- backendBlitFramebuffer.sceneChangeEvent(change);
-
- // THEN
- QCOMPARE(backendBlitFramebuffer.destinationRenderTargetId(), newValue);
+ // WHEN
+ Qt3DRender::QRenderTarget destinationRenderTarget;
+ blitFramebuffer.setDestination(&destinationRenderTarget);
+ backendBlitFramebuffer.syncFromFrontEnd(&blitFramebuffer, false);
+
+ // THEN
+ QCOMPARE(backendBlitFramebuffer.destinationRenderTargetId(), destinationRenderTarget.id());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
{
- // WHEN
+ // WHEN
const auto newValue = QRect(0,0,1,1);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("sourceRect");
- change->setValue(QVariant::fromValue(newValue));
- backendBlitFramebuffer.sceneChangeEvent(change);
+ blitFramebuffer.setSourceRect(newValue);
+ backendBlitFramebuffer.syncFromFrontEnd(&blitFramebuffer, false);
- // THEN
+ // THEN
QCOMPARE(backendBlitFramebuffer.sourceRect(), newValue);
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
{
- // WHEN
+ // WHEN
const auto newValue = QRect(0,0,1,1);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("destinationRect");
- change->setValue(QVariant::fromValue(newValue));
- backendBlitFramebuffer.sceneChangeEvent(change);
+ blitFramebuffer.setDestinationRect(newValue);
+ backendBlitFramebuffer.syncFromFrontEnd(&blitFramebuffer, false);
- // THEN
+ // THEN
QCOMPARE(backendBlitFramebuffer.destinationRect(), newValue);
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
{
- // WHEN
+ // WHEN
const auto newValue = Qt3DRender::QRenderTargetOutput::Color1;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("sourceAttachmentPoint");
- change->setValue(QVariant::fromValue(newValue));
- backendBlitFramebuffer.sceneChangeEvent(change);
+ blitFramebuffer.setSourceAttachmentPoint(newValue);
+ backendBlitFramebuffer.syncFromFrontEnd(&blitFramebuffer, false);
- // THEN
+ // THEN
QCOMPARE(backendBlitFramebuffer.sourceAttachmentPoint(), newValue);
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
{
- // WHEN
+ // WHEN
const auto newValue = Qt3DRender::QRenderTargetOutput::Color1;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("destinationAttachmentPoint");
- change->setValue(QVariant::fromValue(newValue));
- backendBlitFramebuffer.sceneChangeEvent(change);
+ blitFramebuffer.setDestinationAttachmentPoint(newValue);
+ backendBlitFramebuffer.syncFromFrontEnd(&blitFramebuffer, false);
- // THEN
+ // THEN
QCOMPARE(backendBlitFramebuffer.destinationAttachmentPoint(), newValue);
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
diff --git a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp
index 0379c883e..34d195221 100644
--- a/tests/auto/render/boundingsphere/tst_boundingsphere.cpp
+++ b/tests/auto/render/boundingsphere/tst_boundingsphere.cpp
@@ -34,8 +34,8 @@
#include <QtTest/QTest>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
#include <QtQuick/qquickwindow.h>
#include <Qt3DRender/QCamera>
@@ -55,7 +55,6 @@
#include <Qt3DRender/private/calcboundingvolumejob_p.h>
#include <Qt3DRender/private/calcgeometrytrianglevolumes_p.h>
#include <Qt3DRender/private/loadbufferjob_p.h>
-#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/private/sphere_p.h>
@@ -72,6 +71,47 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+QVector<Qt3DCore::QNode *> getNodesForCreation(Qt3DCore::QNode *root)
+{
+ using namespace Qt3DCore;
+
+ QVector<QNode *> nodes;
+ Qt3DCore::QNodeVisitor visitor;
+ visitor.traverse(root, [&nodes](QNode *node) {
+ nodes.append(node);
+
+ // Store the metaobject of the node in the QNode so that we have it available
+ // to us during destruction in the QNode destructor. This allows us to send
+ // the QNodeId and the metaobject as typeinfo to the backend aspects so they
+ // in turn can find the correct QBackendNodeMapper object to handle the destruction
+ // of the corresponding backend nodes.
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(QNodePrivate::findStaticMetaObject(node->metaObject()));
+
+ // Mark this node as having been handled for creation so that it is picked up
+ d->m_hasBackendNode = true;
+ });
+
+ return nodes;
+}
+
+QVector<Qt3DCore::NodeTreeChange> nodeTreeChangesForNodes(const QVector<Qt3DCore::QNode *> nodes)
+{
+ QVector<Qt3DCore::NodeTreeChange> nodeTreeChanges;
+ nodeTreeChanges.reserve(nodes.size());
+
+ for (Qt3DCore::QNode *n : nodes) {
+ nodeTreeChanges.push_back({
+ n->id(),
+ Qt3DCore::QNodePrivate::get(n)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ n
+ });
+ }
+
+ return nodeTreeChanges;
+}
+
class TestAspect : public Qt3DRender::QRenderAspect
{
public:
@@ -81,10 +121,9 @@ public:
{
QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), creationChanges);
+ const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root);
+ const QVector<Qt3DCore::NodeTreeChange> nodeTreeChanges = nodeTreeChangesForNodes(nodes);
+ d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), nodeTreeChanges);
Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
@@ -117,10 +156,6 @@ namespace {
void runRequiredJobs(Qt3DRender::TestAspect *test)
{
- Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob;
- updateEntitiesJob.setManager(test->nodeManagers());
- updateEntitiesJob.run();
-
Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform;
updateWorldTransform.setRoot(test->sceneRoot());
updateWorldTransform.setManagers(test->nodeManagers());
@@ -412,13 +447,13 @@ private Q_SLOTS:
Qt3DRender::Render::Buffer *vbufferBackend = test->nodeManagers()->bufferManager()->getOrCreateResource(vbuffer->id());
vbufferBackend->setRenderer(test->renderer());
vbufferBackend->setManager(test->nodeManagers()->bufferManager());
- simulateInitialization(vbuffer, vbufferBackend);
+ simulateInitializationSync(vbuffer, vbufferBackend);
ibuffer->setData(idata);
Qt3DRender::Render::Buffer *ibufferBackend = test->nodeManagers()->bufferManager()->getOrCreateResource(ibuffer->id());
ibufferBackend->setRenderer(test->renderer());
ibufferBackend->setManager(test->nodeManagers()->bufferManager());
- simulateInitialization(ibuffer, ibufferBackend);
+ simulateInitializationSync(ibuffer, ibufferBackend);
Qt3DRender::QGeometry *g = new Qt3DRender::QGeometry;
for (int i = 0; i < 2; ++i)
@@ -452,23 +487,23 @@ private Q_SLOTS:
Qt3DRender::Render::Attribute *attr0Backend = test->nodeManagers()->attributeManager()->getOrCreateResource(attrs[0]->id());
attr0Backend->setRenderer(test->renderer());
- simulateInitialization(attrs[0], attr0Backend);
+ simulateInitializationSync(attrs[0], attr0Backend);
Qt3DRender::Render::Attribute *attr1Backend = test->nodeManagers()->attributeManager()->getOrCreateResource(attrs[1]->id());
attr1Backend->setRenderer(test->renderer());
- simulateInitialization(attrs[1], attr1Backend);
+ simulateInitializationSync(attrs[1], attr1Backend);
Qt3DRender::Render::Geometry *gBackend = test->nodeManagers()->geometryManager()->getOrCreateResource(g->id());
gBackend->setRenderer(test->renderer());
- simulateInitialization(g, gBackend);
+ simulateInitializationSync(g, gBackend);
Qt3DRender::Render::GeometryRenderer *grBackend = test->nodeManagers()->geometryRendererManager()->getOrCreateResource(gr->id());
grBackend->setRenderer(test->renderer());
grBackend->setManager(test->nodeManagers()->geometryRendererManager());
- simulateInitialization(gr, grBackend);
+ simulateInitializationSync(gr, grBackend);
Qt3DRender::Render::Entity *entityBackend = test->nodeManagers()->renderNodesManager()->getOrCreateResource(entity->id());
entityBackend->setRenderer(test->renderer());
- simulateInitialization(entity.data(), entityBackend);
+ simulateInitializationSync(entity.data(), entityBackend);
Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume;
calcBVolume.setManagers(test->nodeManagers());
@@ -523,7 +558,7 @@ private Q_SLOTS:
Qt3DRender::Render::Buffer *vbufferBackend = test->nodeManagers()->bufferManager()->getOrCreateResource(vbuffer->id());
vbufferBackend->setRenderer(test->renderer());
vbufferBackend->setManager(test->nodeManagers()->bufferManager());
- simulateInitialization(vbuffer, vbufferBackend);
+ simulateInitializationSync(vbuffer, vbufferBackend);
Qt3DRender::QGeometry *g = new Qt3DRender::QGeometry;
g->addAttribute(new Qt3DRender::QAttribute);
@@ -545,20 +580,20 @@ private Q_SLOTS:
Qt3DRender::Render::Attribute *attr0Backend = test->nodeManagers()->attributeManager()->getOrCreateResource(attrs[0]->id());
attr0Backend->setRenderer(test->renderer());
- simulateInitialization(attrs[0], attr0Backend);
+ simulateInitializationSync(attrs[0], attr0Backend);
Qt3DRender::Render::Geometry *gBackend = test->nodeManagers()->geometryManager()->getOrCreateResource(g->id());
gBackend->setRenderer(test->renderer());
- simulateInitialization(g, gBackend);
+ simulateInitializationSync(g, gBackend);
Qt3DRender::Render::GeometryRenderer *grBackend = test->nodeManagers()->geometryRendererManager()->getOrCreateResource(gr->id());
grBackend->setRenderer(test->renderer());
grBackend->setManager(test->nodeManagers()->geometryRendererManager());
- simulateInitialization(gr, grBackend);
+ simulateInitializationSync(gr, grBackend);
Qt3DRender::Render::Entity *entityBackend = test->nodeManagers()->renderNodesManager()->getOrCreateResource(entity->id());
entityBackend->setRenderer(test->renderer());
- simulateInitialization(entity.data(), entityBackend);
+ simulateInitializationSync(entity.data(), entityBackend);
Qt3DRender::Render::CalculateBoundingVolumeJob calcBVolume;
calcBVolume.setManagers(test->nodeManagers());
diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp
index da853d4e9..fa1491914 100644
--- a/tests/auto/render/buffer/tst_buffer.cpp
+++ b/tests/auto/render/buffer/tst_buffer.cpp
@@ -65,6 +65,7 @@ private:
class tst_RenderBuffer : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
+
private Q_SLOTS:
void checkPeerPropertyMirroring()
@@ -82,7 +83,7 @@ private Q_SLOTS:
// WHEN
renderBuffer.setRenderer(&renderer);
renderBuffer.setManager(&bufferManager);
- simulateInitialization(&buffer, &renderBuffer);
+ simulateInitializationSync(&buffer, &renderBuffer);
// THEN
QCOMPARE(renderBuffer.peerId(), buffer.id());
@@ -98,170 +99,220 @@ private Q_SLOTS:
void checkInitialAndCleanedUpState()
{
// GIVEN
- Qt3DRender::Render::Buffer renderBuffer;
+ Qt3DRender::Render::Buffer backendBuffer;
Qt3DRender::Render::BufferManager bufferManager;
TestRenderer renderer;
// THEN
- QCOMPARE(renderBuffer.isDirty(), false);
- QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::StaticDraw);
- QVERIFY(renderBuffer.data().isEmpty());
- QVERIFY(renderBuffer.peerId().isNull());
- QVERIFY(renderBuffer.dataGenerator().isNull());
- QVERIFY(renderBuffer.pendingBufferUpdates().empty());
+ QCOMPARE(backendBuffer.isDirty(), false);
+ QCOMPARE(backendBuffer.usage(), Qt3DRender::QBuffer::StaticDraw);
+ QVERIFY(backendBuffer.data().isEmpty());
+ QVERIFY(backendBuffer.peerId().isNull());
+ QVERIFY(backendBuffer.dataGenerator().isNull());
+ QVERIFY(backendBuffer.pendingBufferUpdates().empty());
// GIVEN
- Qt3DRender::QBuffer buffer;
- buffer.setUsage(Qt3DRender::QBuffer::DynamicCopy);
- buffer.setData(QByteArrayLiteral("C7"));
- buffer.setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(73)));
+ Qt3DRender::QBuffer frontendBuffer;
// WHEN
- renderBuffer.setManager(&bufferManager);
- renderBuffer.setRenderer(&renderer);
- simulateInitialization(&buffer, &renderBuffer);
+ backendBuffer.setManager(&bufferManager);
+ backendBuffer.setRenderer(&renderer);
+ simulateInitializationSync(&frontendBuffer, &backendBuffer);
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- Qt3DRender::QBufferUpdate updateData;
- updateData.offset = 2;
- updateData.data = QByteArrayLiteral("LS5");
- updateChange->setValue(QVariant::fromValue(updateData));
- updateChange->setPropertyName("updateData");
- renderBuffer.sceneChangeEvent(updateChange);
+ // THEN
+ QCOMPARE(backendBuffer.isDirty(), true);
+ QCOMPARE(backendBuffer.usage(), Qt3DRender::QBuffer::StaticDraw);
+ QVERIFY(backendBuffer.data().isEmpty());
+ QVERIFY(backendBuffer.dataGenerator().isNull());
+ QVERIFY(backendBuffer.pendingBufferUpdates().empty());
+
+ // WHEN
+ frontendBuffer.setUsage(Qt3DRender::QBuffer::DynamicCopy);
+ frontendBuffer.setData(QByteArrayLiteral("C7KR4"));
+ frontendBuffer.setDataGenerator(Qt3DRender::QBufferDataGeneratorPtr(new TestFunctor(73)));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
// THEN
- QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::DynamicCopy);
- QCOMPARE(renderBuffer.isDirty(), true);
- QCOMPARE(renderBuffer.data(), QByteArrayLiteral("C7LS5"));
- QVERIFY(!renderBuffer.dataGenerator().isNull());
- QVERIFY(!renderBuffer.pendingBufferUpdates().empty());
+ QCOMPARE(backendBuffer.usage(), Qt3DRender::QBuffer::DynamicCopy);
+ QCOMPARE(backendBuffer.isDirty(), true);
+ QCOMPARE(backendBuffer.data(), QByteArrayLiteral("C7KR4"));
+ QVERIFY(!backendBuffer.dataGenerator().isNull());
+ QVERIFY(!backendBuffer.pendingBufferUpdates().empty());
+
+ // WHEN
+ frontendBuffer.updateData(2, QByteArrayLiteral("LS5"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
+
+ // THEN
+ QCOMPARE(backendBuffer.isDirty(), true);
+ QCOMPARE(backendBuffer.data(), QByteArrayLiteral("C7LS5"));
+ // WHEN
+ backendBuffer.cleanup();
+
+ // THEN
+ QCOMPARE(backendBuffer.isDirty(), false);
+ QCOMPARE(backendBuffer.usage(), Qt3DRender::QBuffer::StaticDraw);
+ QVERIFY(backendBuffer.data().isEmpty());
+ QVERIFY(backendBuffer.dataGenerator().isNull());
+ QVERIFY(backendBuffer.pendingBufferUpdates().empty());
+ }
+
+
+ void checkForceFullUploadOnFirstTime()
+ {
+ // GIVEN
+ Qt3DRender::Render::Buffer backendBuffer;
+ Qt3DRender::Render::BufferManager bufferManager;
+ TestRenderer renderer;
+ Qt3DRender::QBuffer frontendBuffer;
+
+ QByteArray data("111456789\0");
+
+ frontendBuffer.setData(data);
+ frontendBuffer.updateData(1, QByteArray("23\0"));
+
+ // THEN
+ QCOMPARE(frontendBuffer.data(), QByteArray("123456789\0"));
+
+ // WHEN
+ backendBuffer.setManager(&bufferManager);
+ backendBuffer.setRenderer(&renderer);
+ simulateInitializationSync(&frontendBuffer, &backendBuffer);
+
+ // THEN
+ QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1);
+ Qt3DRender::QBufferUpdate fullUpdate = backendBuffer.pendingBufferUpdates().first();
+ QCOMPARE(fullUpdate.offset, -1);
+ QVERIFY(fullUpdate.data.isEmpty());
+ QCOMPARE(frontendBuffer.data(), backendBuffer.data());
+
+ backendBuffer.pendingBufferUpdates().clear();
// WHEN
- renderBuffer.cleanup();
+ frontendBuffer.updateData(1, QByteArray("00\0"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
// THEN
- QCOMPARE(renderBuffer.isDirty(), false);
- QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::StaticDraw);
- QVERIFY(renderBuffer.data().isEmpty());
- QVERIFY(renderBuffer.dataGenerator().isNull());
- QVERIFY(renderBuffer.pendingBufferUpdates().empty());
+ QCOMPARE(frontendBuffer.data(), QByteArray("100456789\0"));
+ QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1);
+ fullUpdate = backendBuffer.pendingBufferUpdates().first();
+ QCOMPARE(fullUpdate.offset, 1);
+ QCOMPARE(fullUpdate.data, QByteArray("00\0"));
+ QCOMPARE(frontendBuffer.data(), backendBuffer.data());
+
+ // WHEN
+ frontendBuffer.updateData(1, QByteArray("22\0"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, true);
+
+ // THEN
+ QCOMPARE(frontendBuffer.data(), QByteArray("122456789\0"));
+ fullUpdate = backendBuffer.pendingBufferUpdates().first();
+ QCOMPARE(fullUpdate.offset, -1);
+ QVERIFY(fullUpdate.data.isEmpty());
+ QCOMPARE(frontendBuffer.data(), backendBuffer.data());
}
void checkPropertyChanges()
{
// GIVEN
TestRenderer renderer;
- Qt3DRender::Render::Buffer renderBuffer;
- renderBuffer.setRenderer(&renderer);
+ Qt3DRender::QBuffer frontendBuffer;
+ Qt3DRender::Render::Buffer backendBuffer;
+ backendBuffer.setRenderer(&renderer);
+ simulateInitializationSync(&frontendBuffer, &backendBuffer);
// THEN
- QVERIFY(renderBuffer.data().isEmpty());
- QVERIFY(renderBuffer.usage() != Qt3DRender::QBuffer::DynamicRead);
- QVERIFY(!renderBuffer.isDirty());
- QVERIFY(!(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty));
+ QVERIFY(backendBuffer.data().isEmpty());
+ QVERIFY(backendBuffer.usage() != Qt3DRender::QBuffer::DynamicRead);
+ QVERIFY(!backendBuffer.isDirty());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(static_cast<int>(Qt3DRender::QBuffer::DynamicRead));
- updateChange->setPropertyName("usage");
- renderBuffer.sceneChangeEvent(updateChange);
+ frontendBuffer.setUsage(Qt3DRender::QBuffer::DynamicRead);
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
// THEN
- QCOMPARE(renderBuffer.usage(), Qt3DRender::QBuffer::DynamicRead);
- QVERIFY(renderBuffer.isDirty());
+ QCOMPARE(backendBuffer.usage(), Qt3DRender::QBuffer::DynamicRead);
+ QVERIFY(backendBuffer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderBuffer.unsetDirty();
- QVERIFY(!renderBuffer.isDirty());
+ backendBuffer.unsetDirty();
+ QVERIFY(!backendBuffer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QByteArrayLiteral("LS9"));
- updateChange->setPropertyName("data");
- renderBuffer.sceneChangeEvent(updateChange);
+ frontendBuffer.setData(QByteArrayLiteral("LS9SL"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
// THEN
- QCOMPARE(renderBuffer.data(), QByteArrayLiteral("LS9"));
- QVERIFY(renderBuffer.isDirty());
- QCOMPARE(renderBuffer.pendingBufferUpdates().size(), 1);
- QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, -1);
+ QCOMPARE(backendBuffer.data(), QByteArrayLiteral("LS9SL"));
+ QVERIFY(backendBuffer.isDirty());
+ QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1);
+ QCOMPARE(backendBuffer.pendingBufferUpdates().first().offset, -1);
- renderBuffer.pendingBufferUpdates().clear();
+ backendBuffer.pendingBufferUpdates().clear();
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderBuffer.unsetDirty();
- QVERIFY(!renderBuffer.isDirty());
+ backendBuffer.unsetDirty();
+ QVERIFY(!backendBuffer.isDirty());
// WHEN
Qt3DRender::QBufferDataGeneratorPtr functor(new TestFunctor(355));
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(functor));
- updateChange->setPropertyName("dataGenerator");
- renderBuffer.sceneChangeEvent(updateChange);
+ frontendBuffer.setDataGenerator(functor);
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
// THEN
- QCOMPARE(renderBuffer.dataGenerator(), functor);
- QVERIFY(renderBuffer.isDirty());
+ QCOMPARE(backendBuffer.dataGenerator(), functor);
+ QVERIFY(backendBuffer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderBuffer.unsetDirty();
- QVERIFY(!renderBuffer.isDirty());
+ backendBuffer.unsetDirty();
+ QVERIFY(!backendBuffer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(true);
- updateChange->setPropertyName("syncData");
- renderBuffer.sceneChangeEvent(updateChange);
+ frontendBuffer.setSyncData(true);
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
// THEN
- QCOMPARE(renderBuffer.isSyncData(), true);
- QVERIFY(!renderBuffer.isDirty());
+ QCOMPARE(backendBuffer.isSyncData(), true);
+ QVERIFY(!backendBuffer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
// WHEN
TestArbiter arbiter;
- Qt3DCore::QBackendNodePrivate::get(&renderBuffer)->setArbiter(&arbiter);
- renderBuffer.executeFunctor();
+ Qt3DCore::QBackendNodePrivate::get(&backendBuffer)->setArbiter(&arbiter);
+ backendBuffer.executeFunctor();
// THEN
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "data");
- QCOMPARE(change->value().toByteArray(), QByteArrayLiteral("454"));
- QCOMPARE(renderBuffer.pendingBufferUpdates().size(), 1);
- QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, -1);
+ QCOMPARE(arbiter.events.count(), 0);
+ QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1);
+ QCOMPARE(backendBuffer.pendingBufferUpdates().first().offset, -1);
arbiter.events.clear();
- renderBuffer.pendingBufferUpdates().clear();
+ backendBuffer.pendingBufferUpdates().clear();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- Qt3DRender::QBufferUpdate updateData;
- updateData.offset = 2;
- updateData.data = QByteArrayLiteral("LS5");
- updateChange->setValue(QVariant::fromValue(updateData));
- updateChange->setPropertyName("updateData");
- renderBuffer.sceneChangeEvent(updateChange);
+ frontendBuffer.updateData(2, QByteArrayLiteral("LS5"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
// THEN
- QVERIFY(!renderBuffer.pendingBufferUpdates().empty());
- QCOMPARE(renderBuffer.pendingBufferUpdates().first().offset, 2);
- QVERIFY(renderBuffer.isDirty());
+ QVERIFY(!backendBuffer.pendingBufferUpdates().empty());
+ QCOMPARE(backendBuffer.pendingBufferUpdates().first().offset, 2);
+ QVERIFY(backendBuffer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderBuffer.unsetDirty();
- QVERIFY(!renderBuffer.isDirty());
+ backendBuffer.unsetDirty();
+ QVERIFY(!backendBuffer.isDirty());
}
void checkBufferManagerReferenceCount()
@@ -275,7 +326,7 @@ private Q_SLOTS:
// WHEN
renderBuffer.setRenderer(&renderer);
renderBuffer.setManager(&bufferManager);
- simulateInitialization(&buffer, &renderBuffer);
+ simulateInitializationSync(&buffer, &renderBuffer);
// THEN
QVERIFY(bufferManager.takeBuffersToRelease().empty());
@@ -305,7 +356,7 @@ private Q_SLOTS:
QCOMPARE(renderer.dirtyBits(), 0);
// WHEN
- simulateInitialization(&buffer, &renderBuffer);
+ simulateInitializationSync(&buffer, &renderBuffer);
// THEN
QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::BuffersDirty);
diff --git a/tests/auto/render/commons/testaspect.cpp b/tests/auto/render/commons/testaspect.cpp
index ffe9fb0e6..87ffc56d7 100644
--- a/tests/auto/render/commons/testaspect.cpp
+++ b/tests/auto/render/commons/testaspect.cpp
@@ -35,11 +35,38 @@
****************************************************************************/
#include "testaspect.h"
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qnode_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+QVector<Qt3DCore::QNode *> getNodesForCreation(Qt3DCore::QNode *root)
+{
+ using namespace Qt3DCore;
+
+ QVector<QNode *> nodes;
+ Qt3DCore::QNodeVisitor visitor;
+ visitor.traverse(root, [&nodes](QNode *node) {
+ nodes.append(node);
+
+ // Store the metaobject of the node in the QNode so that we have it available
+ // to us during destruction in the QNode destructor. This allows us to send
+ // the QNodeId and the metaobject as typeinfo to the backend aspects so they
+ // in turn can find the correct QBackendNodeMapper object to handle the destruction
+ // of the corresponding backend nodes.
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(QNodePrivate::findStaticMetaObject(node->metaObject()));
+
+ // Mark this node as having been handled for creation so that it is picked up
+ d->m_hasBackendNode = true;
+ });
+
+ return nodes;
+}
+
TestAspect::TestAspect(Qt3DCore::QNode *root)
: Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous)
, m_jobManager(new Qt3DCore::QAspectJobManager())
@@ -47,11 +74,15 @@ TestAspect::TestAspect(Qt3DCore::QNode *root)
Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data();
QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
+ const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root);
- for (const Qt3DCore::QNodeCreatedChangeBasePtr change : creationChanges)
- d_func()->createBackendNode(change);
+ for (Qt3DCore::QNode *node : nodes)
+ d_func()->createBackendNode({
+ node->id(),
+ Qt3DCore::QNodePrivate::get(node)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ node
+ });
}
TestAspect::~TestAspect()
diff --git a/tests/auto/render/commons/testaspect.h b/tests/auto/render/commons/testaspect.h
index 79a7e17d1..a0da98721 100644
--- a/tests/auto/render/commons/testaspect.h
+++ b/tests/auto/render/commons/testaspect.h
@@ -42,7 +42,6 @@
#include <Qt3DRender/private/abstractrenderer_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
#include <Qt3DRender/private/qrenderaspect_p.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
QT_BEGIN_NAMESPACE
diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h
index f19b3211b..8d27998a0 100644
--- a/tests/auto/render/commons/testrenderer.h
+++ b/tests/auto/render/commons/testrenderer.h
@@ -52,7 +52,7 @@ public:
void shutdown() override {}
void releaseGraphicsResources() override {}
void render() override {}
- void doRender(bool scene3dBlocking = false) override { Q_UNUSED(scene3dBlocking); }
+ void doRender(bool swapBuffers) override { Q_UNUSED(swapBuffers); }
void cleanGraphicsResources() override {}
bool isRunning() const override { return true; }
bool shouldRender() override { return true; }
@@ -61,9 +61,9 @@ public:
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override { return QVector<Qt3DCore::QAspectJobPtr>(); }
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); }
Qt3DCore::QAspectJobPtr rayCastingJob() override { return Qt3DCore::QAspectJobPtr(); }
- Qt3DCore::QAspectJobPtr syncTextureLoadingJob() override { return Qt3DCore::QAspectJobPtr(); }
+ Qt3DCore::QAspectJobPtr syncLoadingJobs() override { return Qt3DCore::QAspectJobPtr(); }
Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); }
- void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Qt3DRender::Render::Entity *root) override { Q_UNUSED(factory); Q_UNUSED(root); }
+ void setSceneRoot(Qt3DRender::Render::Entity *root) override { Q_UNUSED(root); }
Qt3DRender::Render::Entity *sceneRoot() const override { return nullptr; }
Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const override { return nullptr; }
Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override { return nullptr; }
diff --git a/tests/auto/render/computecommand/tst_computecommand.cpp b/tests/auto/render/computecommand/tst_computecommand.cpp
index 1c8380f73..2046ecc76 100644
--- a/tests/auto/render/computecommand/tst_computecommand.cpp
+++ b/tests/auto/render/computecommand/tst_computecommand.cpp
@@ -31,12 +31,37 @@
#include <Qt3DRender/qcomputecommand.h>
#include <Qt3DRender/private/qcomputecommand_p.h>
#include <Qt3DRender/private/computecommand_p.h>
+#include <Qt3DRender/private/renderer_p.h>
+#include <Qt3DRender/private/nodemanagers_p.h>
+#include <Qt3DRender/private/managers_p.h>
#include <Qt3DCore/private/qbackendnode_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
#include "testpostmanarbiter.h"
+
+// tst_Renderer is a friend class of Renderer
+class tst_Renderer : public Qt3DRender::Render::Renderer
+{
+public:
+ tst_Renderer()
+ : Qt3DRender::Render::Renderer(Qt3DRender::QRenderAspect::Synchronous)
+ {}
+
+ ~tst_Renderer() {
+ shutdown();
+ }
+
+ Qt3DRender::Render::SynchronizerPostFramePtr sendDisablesToFrontendJob() const
+ {
+ return m_sendDisablesToFrontendJob;
+ }
+};
+
+
class tst_ComputeCommand : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
@@ -54,6 +79,7 @@ private Q_SLOTS:
QCOMPARE(backendComputeCommand.x(), 1);
QCOMPARE(backendComputeCommand.y(), 1);
QCOMPARE(backendComputeCommand.z(), 1);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false);
QCOMPARE(backendComputeCommand.runType(), Qt3DRender::QComputeCommand::Continuous);
QCOMPARE(backendComputeCommand.frameCount(), 0);
}
@@ -61,20 +87,33 @@ private Q_SLOTS:
void checkCleanupState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::ComputeCommand backendComputeCommand;
+ Qt3DRender::QComputeCommand computeCommand;
+ computeCommand.setWorkGroupX(256);
+ computeCommand.setWorkGroupY(512);
+ computeCommand.setWorkGroupZ(128);
+ computeCommand.setRunType(Qt3DRender::QComputeCommand::Manual);
+ computeCommand.trigger(1);
// WHEN
+ backendComputeCommand.setRenderer(&renderer);
+ simulateInitializationSync(&computeCommand, &backendComputeCommand);
+
backendComputeCommand.setEnabled(true);
+ backendComputeCommand.hasReachedFrameCount();
backendComputeCommand.cleanup();
// THEN
QCOMPARE(backendComputeCommand.isEnabled(), false);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false);
}
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QComputeCommand computeCommand;
computeCommand.setWorkGroupX(256);
computeCommand.setWorkGroupY(512);
@@ -85,7 +124,8 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::ComputeCommand backendComputeCommand;
- simulateInitialization(&computeCommand, &backendComputeCommand);
+ backendComputeCommand.setRenderer(&renderer);
+ simulateInitializationSync(&computeCommand, &backendComputeCommand);
// THEN
QCOMPARE(backendComputeCommand.isEnabled(), true);
@@ -95,16 +135,20 @@ private Q_SLOTS:
QCOMPARE(backendComputeCommand.z(), computeCommand.workGroupZ());
QCOMPARE(backendComputeCommand.runType(), computeCommand.runType());
QCOMPARE(backendComputeCommand.frameCount(), 6);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::ComputeDirty);
}
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
Qt3DRender::Render::ComputeCommand backendComputeCommand;
+ backendComputeCommand.setRenderer(&renderer);
computeCommand.setEnabled(false);
- simulateInitialization(&computeCommand, &backendComputeCommand);
+ simulateInitializationSync(&computeCommand, &backendComputeCommand);
// THEN
QCOMPARE(backendComputeCommand.peerId(), computeCommand.id());
QCOMPARE(backendComputeCommand.isEnabled(), false);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::ComputeDirty);
}
}
@@ -112,16 +156,16 @@ private Q_SLOTS:
{
// GIVEN
Qt3DRender::Render::ComputeCommand backendComputeCommand;
+ Qt3DRender::QComputeCommand computeCommand;
TestRenderer renderer;
backendComputeCommand.setRenderer(&renderer);
+ simulateInitializationSync(&computeCommand, &backendComputeCommand);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendComputeCommand.sceneChangeEvent(change);
+ computeCommand.setEnabled(newValue);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
// THEN
QCOMPARE(backendComputeCommand.isEnabled(), newValue);
@@ -129,10 +173,8 @@ private Q_SLOTS:
{
// WHEN
const int newValue = 128;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("workGroupX");
- change->setValue(newValue);
- backendComputeCommand.sceneChangeEvent(change);
+ computeCommand.setWorkGroupX(newValue);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
// THEN
QCOMPARE(backendComputeCommand.x(), newValue);
@@ -140,10 +182,8 @@ private Q_SLOTS:
{
// WHEN
const int newValue = 64;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("workGroupY");
- change->setValue(newValue);
- backendComputeCommand.sceneChangeEvent(change);
+ computeCommand.setWorkGroupY(newValue);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
// THEN
QCOMPARE(backendComputeCommand.y(), newValue);
@@ -151,10 +191,8 @@ private Q_SLOTS:
{
// WHEN
const int newValue = 32;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("workGroupZ");
- change->setValue(newValue);
- backendComputeCommand.sceneChangeEvent(change);
+ computeCommand.setWorkGroupZ(newValue);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
// THEN
QCOMPARE(backendComputeCommand.z(), newValue);
@@ -162,10 +200,8 @@ private Q_SLOTS:
{
// WHEN
const Qt3DRender::QComputeCommand::RunType newValue = Qt3DRender::QComputeCommand::Manual;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("runType");
- change->setValue(newValue);
- backendComputeCommand.sceneChangeEvent(change);
+ computeCommand.setRunType(newValue);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
// THEN
QCOMPARE(backendComputeCommand.runType(), newValue);
@@ -173,10 +209,8 @@ private Q_SLOTS:
{
// WHEN
const int newValue = 32;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("frameCount");
- change->setValue(newValue);
- backendComputeCommand.sceneChangeEvent(change);
+ computeCommand.trigger(newValue);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
// THEN
QCOMPARE(backendComputeCommand.frameCount(), newValue);
@@ -202,7 +236,7 @@ private Q_SLOTS:
Qt3DCore::QBackendNodePrivate::get(&backendComputeCommand)->setArbiter(&arbiter);
backendComputeCommand.setRenderer(&renderer);
- simulateInitialization(&computeCommand, &backendComputeCommand);
+ simulateInitializationSync(&computeCommand, &backendComputeCommand);
for (int i = 0; i < 5; ++i) {
// WHEN
@@ -211,6 +245,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(backendComputeCommand.frameCount(), 6 - (i + 1));
QCOMPARE(backendComputeCommand.isEnabled(), true);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false);
QCOMPARE(arbiter.events.size(), 0);
}
@@ -218,15 +253,103 @@ private Q_SLOTS:
backendComputeCommand.updateFrameCount();
// THEN
- QCOMPARE(backendComputeCommand.frameCount(), false);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), true);
+ QCOMPARE(backendComputeCommand.frameCount(), 0);
+ // Backend stays with enabled == true, frontend will be updated
+ // to be disabled and backend should be disabled on the next sync
+
+ // WHEN
+ computeCommand.setEnabled(false);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
+
+ // THEN
QCOMPARE(backendComputeCommand.isEnabled(), false);
- QCOMPARE(arbiter.events.size(), 1);
- {
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "enabled");
- QCOMPARE(change->value().value<int>(), false);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
+ QCOMPARE(backendComputeCommand.frameCount(), 0);
+
+ // WHEN
+ computeCommand.trigger(1);
+ backendComputeCommand.syncFromFrontEnd(&computeCommand, false);
+
+ // THEN
+ QCOMPARE(computeCommand.isEnabled(), true);
+ QCOMPARE(backendComputeCommand.isEnabled(), true);
+ QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false);
+ QCOMPARE(backendComputeCommand.frameCount(), 1);
+ }
+
+ void checkDisablesFrontend()
+ {
+ // GIVEN
+ Qt3DRender::Render::NodeManagers nodeManager;
+ tst_Renderer renderer;
+ TestArbiter arbiter;
+
+ Qt3DCore::QAspectManager manager;
+ Qt3DCore::QScene scene;
+
+ Qt3DCore::QEntity rootEntity;
+ Qt3DCore::QNodePrivate::get(&rootEntity)->setScene(&scene);
+
+ Qt3DRender::QComputeCommand computeCommand;
+ Qt3DRender::Render::ComputeCommand *backendComputeCommand = nullptr;
+
+ renderer.setNodeManagers(&nodeManager);
+
+ // WHEN
+ computeCommand.setParent(&rootEntity);
+ // RootEntity is the entry point to retrieve the scene instance for lookups
+ manager.setRootEntity(&rootEntity, {});
+
+ // THEN
+ QVERIFY(scene.lookupNode(computeCommand.id()) != nullptr);
+
+ // WHEN
+ auto handle = nodeManager.computeJobManager()->getOrAcquireHandle(computeCommand.id());
+ backendComputeCommand = nodeManager.computeJobManager()->data(handle);
+
+ // WHEN
+ computeCommand.setWorkGroupX(256);
+ computeCommand.setWorkGroupY(512);
+ computeCommand.setWorkGroupZ(128);
+ computeCommand.setRunType(Qt3DRender::QComputeCommand::Manual);
+ computeCommand.trigger(1);
+
+ Qt3DCore::QBackendNodePrivate::get(backendComputeCommand)->setArbiter(&arbiter);
+ backendComputeCommand->setRenderer(&renderer);
+ simulateInitializationSync(&computeCommand, backendComputeCommand);
+
+ // THEN
+ QCOMPARE(backendComputeCommand->frameCount(),1);
+ QCOMPARE(backendComputeCommand->isEnabled(), true);
+ QCOMPARE(computeCommand.isEnabled(), true);
+ QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false);
+
+ // WHEN
+ backendComputeCommand->updateFrameCount();
+
+ // THEN
+ QCOMPARE(backendComputeCommand->frameCount(), 0);
+ QCOMPARE(backendComputeCommand->hasReachedFrameCount(), true);
+
+
+ // Still enabled as we have yet to notify the fronted
+ QCOMPARE(backendComputeCommand->isEnabled(), true);
+ QCOMPARE(computeCommand.isEnabled(), true);
+
+ // WHEN
+ auto sendDisablesJob = renderer.sendDisablesToFrontendJob();
+ Qt3DCore::QAspectJobPrivate::get(sendDisablesJob.data())->postFrame(&manager);
+
+ // THEN
+ QCOMPARE(computeCommand.isEnabled(), false);
+ QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false);
+
+ // WHEN
+ backendComputeCommand->syncFromFrontEnd(&computeCommand, false);
+
+ // THEN
+ QCOMPARE(backendComputeCommand->frameCount(), 0);
+ QCOMPARE(backendComputeCommand->isEnabled(), false);
}
};
diff --git a/tests/auto/render/coordinatereader/tst_coordinatereader.cpp b/tests/auto/render/coordinatereader/tst_coordinatereader.cpp
index afb18fe55..417684245 100644
--- a/tests/auto/render/coordinatereader/tst_coordinatereader.cpp
+++ b/tests/auto/render/coordinatereader/tst_coordinatereader.cpp
@@ -101,7 +101,7 @@ private Q_SLOTS:
->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
bool ret = reader.setGeometry(backendRenderer, QString(""));
@@ -149,7 +149,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -167,18 +167,18 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()
->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()
->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()
->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
bool ret = reader.setGeometry(backendRenderer,
@@ -232,7 +232,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -250,18 +250,18 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()
->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()
->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()
->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
bool ret = reader.setGeometry(backendRenderer,
@@ -326,7 +326,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -344,18 +344,18 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()
->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()
->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()
->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
bool ret = reader.setGeometry(backendRenderer,
@@ -415,7 +415,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -443,23 +443,23 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(
positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendTexcoordAttribute = nodeManagers->attributeManager()
->getOrCreateResource(texcoordAttribute->id());
backendTexcoordAttribute->setRenderer(&renderer);
- simulateInitialization(texcoordAttribute.data(), backendTexcoordAttribute);
+ simulateInitializationSync(texcoordAttribute.data(), backendTexcoordAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()
->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()
->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
bool ret = reader.setGeometry(backendRenderer,
diff --git a/tests/auto/render/effect/tst_effect.cpp b/tests/auto/render/effect/tst_effect.cpp
index 30df242f4..369cdf793 100644
--- a/tests/auto/render/effect/tst_effect.cpp
+++ b/tests/auto/render/effect/tst_effect.cpp
@@ -34,9 +34,6 @@
#include <Qt3DRender/private/qeffect_p.h>
#include <Qt3DRender/private/effect_p.h>
#include <Qt3DRender/private/shaderparameterpack_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
@@ -72,7 +69,7 @@ private Q_SLOTS:
Qt3DRender::QParameter parameter;
effect.addTechnique(&technique);
effect.addParameter(&parameter);
- simulateInitialization(&effect, &backendEffect);
+ simulateInitializationSync(&effect, &backendEffect);
}
backendEffect.cleanup();
@@ -95,7 +92,7 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::Effect backendEffect;
- simulateInitialization(&effect, &backendEffect);
+ simulateInitializationSync(&effect, &backendEffect);
// THEN
QCOMPARE(backendEffect.isEnabled(), true);
@@ -109,7 +106,7 @@ private Q_SLOTS:
// WHEN
Qt3DRender::Render::Effect backendEffect;
effect.setEnabled(false);
- simulateInitialization(&effect, &backendEffect);
+ simulateInitializationSync(&effect, &backendEffect);
// THEN
QCOMPARE(backendEffect.peerId(), effect.id());
@@ -120,17 +117,17 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DRender::QEffect effect;
Qt3DRender::Render::Effect backendEffect;
TestRenderer renderer;
backendEffect.setRenderer(&renderer);
+ simulateInitializationSync(&effect, &backendEffect);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendEffect.sceneChangeEvent(change);
+ effect.setEnabled(newValue);
+ backendEffect.syncFromFrontEnd(&effect, false);
// THEN
QCOMPARE(backendEffect.isEnabled(), newValue);
@@ -139,9 +136,8 @@ private Q_SLOTS:
Qt3DRender::QTechnique technique;
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &technique);
- change->setPropertyName("technique");
- backendEffect.sceneChangeEvent(change);
+ effect.addTechnique(&technique);
+ backendEffect.syncFromFrontEnd(&effect, false);
// THEN
QCOMPARE(backendEffect.techniques().size(), 1);
@@ -149,9 +145,8 @@ private Q_SLOTS:
}
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &technique);
- change->setPropertyName("technique");
- backendEffect.sceneChangeEvent(change);
+ effect.removeTechnique(&technique);
+ backendEffect.syncFromFrontEnd(&effect, false);
// THEN
QCOMPARE(backendEffect.techniques().size(), 0);
@@ -162,9 +157,8 @@ private Q_SLOTS:
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &parameter);
- change->setPropertyName("parameter");
- backendEffect.sceneChangeEvent(change);
+ effect.addParameter(&parameter);
+ backendEffect.syncFromFrontEnd(&effect, false);
// THEN
QCOMPARE(backendEffect.parameters().size(), 1);
@@ -172,9 +166,8 @@ private Q_SLOTS:
}
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &parameter);
- change->setPropertyName("parameter");
- backendEffect.sceneChangeEvent(change);
+ effect.removeParameter(&parameter);
+ backendEffect.syncFromFrontEnd(&effect, false);
// THEN
QCOMPARE(backendEffect.parameters().size(), 0);
diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp
index cd0616bbe..e3b8e756e 100644
--- a/tests/auto/render/entity/tst_entity.cpp
+++ b/tests/auto/render/entity/tst_entity.cpp
@@ -28,16 +28,14 @@
#include <QtTest/QtTest>
#include <Qt3DRender/private/entity_p.h>
+#include <Qt3DRender/private/entity_p_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/entityvisitor_p.h>
#include <Qt3DRender/private/entityaccumulator_p.h>
#include <Qt3DRender/QCameraLens>
-#include <Qt3DCore/QPropertyUpdatedChange>
#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QComponentAddedChange>
-#include <Qt3DCore/QComponentRemovedChange>
#include <Qt3DCore/QTransform>
#include <Qt3DRender/QEnvironmentLight>
@@ -120,7 +118,7 @@ private slots:
void checkInitialAndCleanUpState()
{
// GIVEN
- QFETCH(QList<QComponent*>, components);
+ QFETCH(const QList<QComponent*>, components);
TestRenderer renderer;
NodeManagers nodeManagers;
@@ -145,19 +143,18 @@ private slots:
QVERIFY(entity.layerIds().isEmpty());
// WHEN
- Q_FOREACH (QComponent *component, components) {
- const auto addChange = QComponentAddedChangePtr::create(&dummyFrontendEntity, component);
- entity.sceneChangeEvent(addChange);
- }
+ for (QComponent *component : components)
+ EntityPrivate::get(&entity)->componentAdded(component);
Qt3DCore::QEntity dummyFrontendEntityChild;
// Create nodes in the backend manager
nodeManagers.renderNodesManager()->getOrCreateResource(dummyFrontendEntity.id());
nodeManagers.renderNodesManager()->getOrCreateResource(dummyFrontendEntityChild.id());
- // Send children added event to entity
- const auto addEntityChange = QPropertyNodeAddedChangePtr::create(dummyFrontendEntity.id(), &dummyFrontendEntityChild);
- entity.sceneChangeEvent(addEntityChange);
+// TODOSYNC clean up
+// // Send children added event to entity
+// const auto addEntityChange = QPropertyNodeAddedChangePtr::create(dummyFrontendEntity.id(), &dummyFrontendEntityChild);
+// entity.sceneChangeEvent(addEntityChange);
// THEN
QVERIFY(!entity.componentUuid<Transform>().isNull());
@@ -182,7 +179,6 @@ private slots:
entity.cleanup();
// THEN
- QVERIFY(entity.parentEntityId().isNull());
QVERIFY(entity.componentUuid<Transform>().isNull());
QVERIFY(entity.componentUuid<CameraLens>().isNull());
QVERIFY(entity.componentUuid<Material>().isNull());
@@ -201,29 +197,18 @@ private slots:
QVERIFY(!containsAll);
}
- void checkRebuildingEntityHierarchy()
+ void checkEntityReparenting()
{
// GIVEN
TestRenderer renderer;
NodeManagers nodeManagers;
Qt3DCore::QEntity frontendEntityA, frontendEntityB, frontendEntityC;
- auto entityCreator = [&nodeManagers, &renderer](const Qt3DCore::QEntity &frontEndEntity) {
- Entity *entity = nodeManagers.renderNodesManager()->getOrCreateResource(frontEndEntity.id());
- entity->setNodeManagers(&nodeManagers);
- entity->setRenderer(&renderer);
- return entity;
- };
-
- auto backendA = entityCreator(frontendEntityA);
- auto backendB = entityCreator(frontendEntityB);
- auto backendC = entityCreator(frontendEntityC);
+ auto backendA = createEntity(renderer, nodeManagers, frontendEntityA);
+ auto backendB = createEntity(renderer, nodeManagers, frontendEntityB);
+ auto backendC = createEntity(renderer, nodeManagers, frontendEntityC);
// THEN
- QVERIFY(backendA->parentEntityId().isNull());
- QVERIFY(backendB->parentEntityId().isNull());
- QVERIFY(backendC->parentEntityId().isNull());
-
QVERIFY(backendA->parent() == nullptr);
QVERIFY(backendB->parent() == nullptr);
QVERIFY(backendC->parent() == nullptr);
@@ -233,17 +218,9 @@ private slots:
QVERIFY(backendC->childrenHandles().isEmpty());
// WHEN
- renderer.clearDirtyBits(0);
- QVERIFY(renderer.dirtyBits() == 0);
-
auto sendParentChange = [&nodeManagers](const Qt3DCore::QEntity &entity) {
- const auto parentChange = QPropertyUpdatedChangePtr::create(entity.id());
- parentChange->setPropertyName("parentEntityUpdated");
- auto parent = entity.parentEntity();
- parentChange->setValue(QVariant::fromValue(parent ? parent->id() : Qt3DCore::QNodeId()));
-
Entity *backendEntity = nodeManagers.renderNodesManager()->getOrCreateResource(entity.id());
- backendEntity->sceneChangeEvent(parentChange);
+ backendEntity->syncFromFrontEnd(&entity, false);
};
// reparent B to A and C to B.
@@ -253,68 +230,111 @@ private slots:
sendParentChange(frontendEntityC);
// THEN
- QVERIFY(renderer.dirtyBits() & AbstractRenderer::EntityHierarchyDirty);
+ QVERIFY(backendA->parent() == nullptr);
+ QVERIFY(backendB->parent() == backendA);
+ QVERIFY(backendC->parent() == backendB);
+
+ QCOMPARE(backendA->childrenHandles().count(), 1);
+ QCOMPARE(backendB->childrenHandles().count(), 1);
+ QVERIFY(backendC->childrenHandles().isEmpty());
- QVERIFY(backendA->parentEntityId().isNull());
- QVERIFY(backendB->parentEntityId() == frontendEntityA.id());
- QVERIFY(backendC->parentEntityId() == frontendEntityB.id());
+ // WHEN - reparent C to A
+ frontendEntityC.setParent(&frontendEntityA);
+ sendParentChange(frontendEntityC);
+
+ // THEN
+ QVERIFY(backendA->parent() == nullptr);
+ QVERIFY(backendB->parent() == backendA);
+ QVERIFY(backendC->parent() == backendA);
+
+ QCOMPARE(backendA->childrenHandles().size(), 2);
+ QVERIFY(backendB->childrenHandles().isEmpty());
+ QVERIFY(backendC->childrenHandles().isEmpty());
+
+ // WHEN - reparent B to null.
+ frontendEntityB.setParent(static_cast<Qt3DCore::QNode *>(nullptr));
+ sendParentChange(frontendEntityB);
+ // THEN
QVERIFY(backendA->parent() == nullptr);
QVERIFY(backendB->parent() == nullptr);
- QVERIFY(backendC->parent() == nullptr);
+ QVERIFY(backendC->parent() == backendA);
- QVERIFY(backendA->childrenHandles().isEmpty());
+ QCOMPARE(backendA->childrenHandles().count(), 1);
+ QVERIFY(!backendA->childrenHandles().contains(backendB->handle()));
QVERIFY(backendB->childrenHandles().isEmpty());
QVERIFY(backendC->childrenHandles().isEmpty());
+ }
+
+ void checkEntityCleanup()
+ {
+ // GIVEN
+ TestRenderer renderer;
+ NodeManagers nodeManagers;
+ Qt3DCore::QEntity frontendEntityA, frontendEntityB, frontendEntityC;
+
+ auto backendA = createEntity(renderer, nodeManagers, frontendEntityA);
+ auto backendB = createEntity(renderer, nodeManagers, frontendEntityB);
+ auto backendC = createEntity(renderer, nodeManagers, frontendEntityC);
// WHEN
- auto rebuildHierarchy = [](Entity *backend) {
- backend->clearEntityHierarchy();
- backend->rebuildEntityHierarchy();
+ auto sendParentChange = [&nodeManagers](const Qt3DCore::QEntity &entity) {
+ Entity *backendEntity = nodeManagers.renderNodesManager()->getOrCreateResource(entity.id());
+ backendEntity->syncFromFrontEnd(&entity, false);
};
- rebuildHierarchy(backendA);
- rebuildHierarchy(backendB);
- rebuildHierarchy(backendC);
+
+ // reparent B and C to A.
+ frontendEntityB.setParent(&frontendEntityA);
+ sendParentChange(frontendEntityB);
+ frontendEntityC.setParent(&frontendEntityA);
+ sendParentChange(frontendEntityC);
// THEN
QVERIFY(backendA->parent() == nullptr);
QVERIFY(backendB->parent() == backendA);
- QVERIFY(backendC->parent() == backendB);
+ QVERIFY(backendC->parent() == backendA);
- QVERIFY(!backendA->childrenHandles().isEmpty());
- QVERIFY(!backendB->childrenHandles().isEmpty());
+ QCOMPARE(backendA->childrenHandles().count(), 2);
+ QVERIFY(backendB->childrenHandles().isEmpty());
QVERIFY(backendC->childrenHandles().isEmpty());
- // WHEN - reparent B to null.
- frontendEntityB.setParent(static_cast<Qt3DCore::QNode *>(nullptr));
- sendParentChange(frontendEntityB);
- rebuildHierarchy(backendA);
- rebuildHierarchy(backendB);
- rebuildHierarchy(backendC);
+ // WHEN - cleaning up a child
+ backendC->cleanup();
- QVERIFY(backendA->parentEntityId().isNull());
- QVERIFY(backendB->parentEntityId().isNull());
- QVERIFY(backendC->parentEntityId() == frontendEntityB.id());
+ // THEN - the child's parent should be null and it
+ // should be removed from its parent's list of children
+ QVERIFY(backendA->parent() == nullptr);
+ QVERIFY(backendB->parent() == backendA);
+ QVERIFY(backendC->parent() == nullptr);
+
+ QCOMPARE(backendA->childrenHandles().count(), 1);
+ QVERIFY(!backendA->childrenHandles().contains(backendC->handle()));
+ QVERIFY(backendB->childrenHandles().isEmpty());
+ QVERIFY(backendC->childrenHandles().isEmpty());
+
+ // WHEN (cleaning up parent)
+ backendA->cleanup();
+ // THEN (it's children's parent should be set to null)
QVERIFY(backendA->parent() == nullptr);
QVERIFY(backendB->parent() == nullptr);
- QVERIFY(backendC->parent() == backendB);
+ QVERIFY(backendC->parent() == nullptr);
QVERIFY(backendA->childrenHandles().isEmpty());
- QVERIFY(!backendB->childrenHandles().isEmpty());
+ QVERIFY(backendB->childrenHandles().isEmpty());
QVERIFY(backendC->childrenHandles().isEmpty());
- // WHEN - cleanup
- backendA->cleanup();
+ // WHEN
backendB->cleanup();
- backendC->cleanup();
- // THEN
- QVERIFY(backendA->parentEntityId().isNull());
- QVERIFY(backendB->parentEntityId().isNull());
- QVERIFY(backendC->parentEntityId().isNull());
+ // THEN nothing should change
+ QVERIFY(backendA->childrenHandles().isEmpty());
+ QVERIFY(backendB->childrenHandles().isEmpty());
+ QVERIFY(backendC->childrenHandles().isEmpty());
- QVERIFY(renderer.dirtyBits() != 0);
+ QVERIFY(backendA->parent() == nullptr);
+ QVERIFY(backendB->parent() == nullptr);
+ QVERIFY(backendC->parent() == nullptr);
}
void shouldHandleSingleComponentEvents_data()
@@ -360,8 +380,7 @@ private slots:
QVERIFY(method(&entity).isNull());
// WHEN
- const auto addChange = QComponentAddedChangePtr::create(&dummyFrontendEntity, component);
- entity.sceneChangeEvent(addChange);
+ EntityPrivate::get(&entity)->componentAdded(component);
// THEN
QCOMPARE(method(&entity), component->id());
@@ -369,8 +388,7 @@ private slots:
// WHEN
renderer.resetDirty();
- const auto removeChange = QComponentRemovedChangePtr::create(&dummyFrontendEntity, component);
- entity.sceneChangeEvent(removeChange);
+ EntityPrivate::get(&entity)->componentRemoved(component);
// THEN
QVERIFY(method(&entity).isNull());
@@ -402,7 +420,7 @@ private slots:
void shouldHandleComponentsEvents()
{
// GIVEN
- QFETCH(QList<QComponent*>, components);
+ QFETCH(const QList<QComponent*>, components);
QFETCH(void*, functionPtr);
UuidListMethod method = reinterpret_cast<UuidListMethod>(functionPtr);
@@ -415,22 +433,19 @@ private slots:
QVERIFY(method(&entity).isEmpty());
// WHEN
- Q_FOREACH (QComponent *component, components) {
- const auto addChange = QComponentAddedChangePtr::create(&dummyFrontendEntity, component);
- entity.sceneChangeEvent(addChange);
- }
+ for (QComponent *component : components)
+ EntityPrivate::get(&entity)->componentAdded(component);
// THEN
QCOMPARE(method(&entity).size(), components.size());
- Q_FOREACH (QComponent *component, components) {
+ for (QComponent *component : components) {
QVERIFY(method(&entity).contains(component->id()));
}
QVERIFY(renderer.dirtyBits() != 0);
// WHEN
renderer.resetDirty();
- const auto removeChange = QComponentRemovedChangePtr::create(&dummyFrontendEntity, components.first());
- entity.sceneChangeEvent(removeChange);
+ EntityPrivate::get(&entity)->componentRemoved(components.first());
// THEN
QCOMPARE(method(&entity).size(), components.size() - 1);
@@ -446,27 +461,13 @@ private slots:
NodeManagers nodeManagers;
Qt3DCore::QEntity frontendEntityA, frontendEntityB, frontendEntityC;
- auto entityCreator = [&nodeManagers, &renderer](const Qt3DCore::QEntity &frontEndEntity) {
- HEntity renderNodeHandle = nodeManagers.renderNodesManager()->getOrAcquireHandle(frontEndEntity.id());
- Entity *entity = nodeManagers.renderNodesManager()->data(renderNodeHandle);
- entity->setNodeManagers(&nodeManagers);
- entity->setHandle(renderNodeHandle);
- entity->setRenderer(&renderer);
- return entity;
- };
-
- auto backendA = entityCreator(frontendEntityA);
- auto backendB = entityCreator(frontendEntityB);
- auto backendC = entityCreator(frontendEntityC);
+ auto backendA = createEntity(renderer, nodeManagers, frontendEntityA);
+ createEntity(renderer, nodeManagers, frontendEntityB);
+ createEntity(renderer, nodeManagers, frontendEntityC);
auto sendParentChange = [&nodeManagers](const Qt3DCore::QEntity &entity) {
- const auto parentChange = QPropertyUpdatedChangePtr::create(entity.id());
- parentChange->setPropertyName("parentEntityUpdated");
- auto parent = entity.parentEntity();
- parentChange->setValue(QVariant::fromValue(parent ? parent->id() : Qt3DCore::QNodeId()));
-
Entity *backendEntity = nodeManagers.renderNodesManager()->getOrCreateResource(entity.id());
- backendEntity->sceneChangeEvent(parentChange);
+ backendEntity->syncFromFrontEnd(&entity, false);
};
// reparent B to A and C to B.
@@ -475,14 +476,6 @@ private slots:
frontendEntityC.setParent(&frontendEntityB);
sendParentChange(frontendEntityC);
- auto rebuildHierarchy = [](Entity *backend) {
- backend->clearEntityHierarchy();
- backend->rebuildEntityHierarchy();
- };
- rebuildHierarchy(backendA);
- rebuildHierarchy(backendB);
- rebuildHierarchy(backendC);
-
// WHEN
int visitCount = 0;
auto counter = [&visitCount](const Entity *) { ++visitCount; };
@@ -499,27 +492,17 @@ private slots:
NodeManagers nodeManagers;
Qt3DCore::QEntity frontendEntityA, frontendEntityB, frontendEntityC;
- auto entityCreator = [&nodeManagers, &renderer](const Qt3DCore::QEntity &frontEndEntity) {
- HEntity renderNodeHandle = nodeManagers.renderNodesManager()->getOrAcquireHandle(frontEndEntity.id());
- Entity *entity = nodeManagers.renderNodesManager()->data(renderNodeHandle);
- entity->setNodeManagers(&nodeManagers);
- entity->setHandle(renderNodeHandle);
- entity->setRenderer(&renderer);
- return entity;
- };
+ frontendEntityA.setEnabled(false);
+ frontendEntityB.setEnabled(false);
+ frontendEntityC.setEnabled(false);
- auto backendA = entityCreator(frontendEntityA);
- auto backendB = entityCreator(frontendEntityB);
- auto backendC = entityCreator(frontendEntityC);
+ auto backendA = createEntity(renderer, nodeManagers, frontendEntityA);
+ createEntity(renderer, nodeManagers, frontendEntityB);
+ createEntity(renderer, nodeManagers, frontendEntityC);
auto sendParentChange = [&nodeManagers](const Qt3DCore::QEntity &entity) {
- const auto parentChange = QPropertyUpdatedChangePtr::create(entity.id());
- parentChange->setPropertyName("parentEntityUpdated");
- auto parent = entity.parentEntity();
- parentChange->setValue(QVariant::fromValue(parent ? parent->id() : Qt3DCore::QNodeId()));
-
Entity *backendEntity = nodeManagers.renderNodesManager()->getOrCreateResource(entity.id());
- backendEntity->sceneChangeEvent(parentChange);
+ backendEntity->syncFromFrontEnd(&entity, false);
};
// reparent B to A and C to B.
@@ -528,14 +511,6 @@ private slots:
frontendEntityC.setParent(&frontendEntityB);
sendParentChange(frontendEntityC);
- auto rebuildHierarchy = [](Entity *backend) {
- backend->clearEntityHierarchy();
- backend->rebuildEntityHierarchy();
- };
- rebuildHierarchy(backendA);
- rebuildHierarchy(backendB);
- rebuildHierarchy(backendC);
-
// WHEN
CompleteVisitor v1(&nodeManagers);
EnabledVisitor v2(&nodeManagers);
@@ -547,8 +522,8 @@ private slots:
// THEN
QCOMPARE(v1.count, 3);
- QCOMPARE(v2.count, 1); // nodes disabled by default but the first one is still visited before visitation finds out it's disabled
- QCOMPARE(v3.count, 0); // nodes disabled by default
+ QCOMPARE(v2.count, 1); // nodes disabled but the first one is still visited before visitation finds out it's disabled
+ QCOMPARE(v3.count, 0); // nodes disabled
}
void accumulator()
@@ -558,27 +533,17 @@ private slots:
NodeManagers nodeManagers;
Qt3DCore::QEntity frontendEntityA, frontendEntityB, frontendEntityC;
- auto entityCreator = [&nodeManagers, &renderer](const Qt3DCore::QEntity &frontEndEntity) {
- HEntity renderNodeHandle = nodeManagers.renderNodesManager()->getOrAcquireHandle(frontEndEntity.id());
- Entity *entity = nodeManagers.renderNodesManager()->data(renderNodeHandle);
- entity->setNodeManagers(&nodeManagers);
- entity->setHandle(renderNodeHandle);
- entity->setRenderer(&renderer);
- return entity;
- };
+ frontendEntityA.setEnabled(false);
+ frontendEntityB.setEnabled(false);
+ frontendEntityC.setEnabled(false);
- auto backendA = entityCreator(frontendEntityA);
- auto backendB = entityCreator(frontendEntityB);
- auto backendC = entityCreator(frontendEntityC);
+ auto backendA = createEntity(renderer, nodeManagers, frontendEntityA);
+ createEntity(renderer, nodeManagers, frontendEntityB);
+ createEntity(renderer, nodeManagers, frontendEntityC);
auto sendParentChange = [&nodeManagers](const Qt3DCore::QEntity &entity) {
- const auto parentChange = QPropertyUpdatedChangePtr::create(entity.id());
- parentChange->setPropertyName("parentEntityUpdated");
- auto parent = entity.parentEntity();
- parentChange->setValue(QVariant::fromValue(parent ? parent->id() : Qt3DCore::QNodeId()));
-
Entity *backendEntity = nodeManagers.renderNodesManager()->getOrCreateResource(entity.id());
- backendEntity->sceneChangeEvent(parentChange);
+ backendEntity->syncFromFrontEnd(&entity, false);
};
// reparent B to A and C to B.
@@ -587,14 +552,6 @@ private slots:
frontendEntityC.setParent(&frontendEntityB);
sendParentChange(frontendEntityC);
- auto rebuildHierarchy = [](Entity *backend) {
- backend->clearEntityHierarchy();
- backend->rebuildEntityHierarchy();
- };
- rebuildHierarchy(backendA);
- rebuildHierarchy(backendB);
- rebuildHierarchy(backendC);
-
// WHEN
EntityAccumulator v1(&nodeManagers);
EntityAccumulator v2([](Entity *e) { return e->isEnabled(); }, &nodeManagers);
@@ -605,6 +562,18 @@ private slots:
QCOMPARE(r1.count(), 3);
QCOMPARE(r2.count(), 0);
}
+
+private:
+ Entity *createEntity(TestRenderer &renderer, NodeManagers &nodeManagers, const Qt3DCore::QEntity &frontEndEntity) {
+ HEntity renderNodeHandle = nodeManagers.renderNodesManager()->getOrAcquireHandle(frontEndEntity.id());
+ Entity *entity = nodeManagers.renderNodesManager()->data(renderNodeHandle);
+ entity->setNodeManagers(&nodeManagers);
+ entity->setHandle(renderNodeHandle);
+ entity->setRenderer(&renderer);
+ entity->syncFromFrontEnd(&frontEndEntity, true);
+ return entity;
+ }
+
};
QTEST_APPLESS_MAIN(tst_RenderEntity)
diff --git a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST
index 8fdc2accf..7cbc7c4c0 100644
--- a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST
+++ b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST
@@ -1,8 +1,6 @@
-#[checkRunRendererNotRunning]
-#windows
#[checkRunRendererRunning]
+windows-7
+windows-7sp1
#QTBUG-64271
-windows
-
# Offscreen platform does not support OpenGL context creation
b2qt
diff --git a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp
index 7a199e9e6..25262a772 100644
--- a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp
+++ b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp
@@ -29,7 +29,8 @@
#include <QtTest/QTest>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/qentity.h>
#include <Qt3DRender/qtechnique.h>
#include <Qt3DRender/qviewport.h>
@@ -70,12 +71,22 @@ public:
Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data();
QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- for (const Qt3DCore::QNodeCreatedChangeBasePtr change : creationChanges)
- d_func()->createBackendNode(change);
-
+ QVector<Qt3DCore::QNode *> nodes;
+ Qt3DCore::QNodeVisitor v;
+ v.traverse(root, [&nodes](Qt3DCore::QNode *node) {
+ Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject()));
+ d->m_hasBackendNode = true;
+ nodes << node;
+ });
+
+ for (const auto node: nodes)
+ d_func()->createBackendNode({
+ node->id(),
+ Qt3DCore::QNodePrivate::get(node)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ node
+ });
}
~TestAspect()
diff --git a/tests/auto/render/filterkey/tst_filterkey.cpp b/tests/auto/render/filterkey/tst_filterkey.cpp
index 15d07d65f..6a08bc539 100644
--- a/tests/auto/render/filterkey/tst_filterkey.cpp
+++ b/tests/auto/render/filterkey/tst_filterkey.cpp
@@ -31,7 +31,6 @@
#include <Qt3DRender/qfilterkey.h>
#include <Qt3DRender/private/qfilterkey_p.h>
#include <Qt3DRender/private/filterkey_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
@@ -56,16 +55,18 @@ private Q_SLOTS:
void checkCleanupState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::FilterKey backendFilterKey;
// WHEN
+ backendFilterKey.setRenderer(&renderer);
backendFilterKey.setEnabled(true);
{
Qt3DRender::QFilterKey filterKey;
filterKey.setName(QStringLiteral("Tim"));
filterKey.setValue(QVariant(QStringLiteral("McGraw")));
- simulateInitialization(&filterKey, &backendFilterKey);
+ simulateInitializationSync(&filterKey, &backendFilterKey);
}
backendFilterKey.cleanup();
@@ -79,6 +80,7 @@ private Q_SLOTS:
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QFilterKey filterKey;
filterKey.setName(QStringLiteral("Dallas"));
filterKey.setValue(QVariant(QStringLiteral("Smith")));
@@ -86,7 +88,8 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::FilterKey backendFilterKey;
- simulateInitialization(&filterKey, &backendFilterKey);
+ backendFilterKey.setRenderer(&renderer);
+ simulateInitializationSync(&filterKey, &backendFilterKey);
// THEN
QCOMPARE(backendFilterKey.isEnabled(), true);
@@ -97,8 +100,9 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::FilterKey backendFilterKey;
+ backendFilterKey.setRenderer(&renderer);
filterKey.setEnabled(false);
- simulateInitialization(&filterKey, &backendFilterKey);
+ simulateInitializationSync(&filterKey, &backendFilterKey);
// THEN
QCOMPARE(backendFilterKey.peerId(), filterKey.id());
@@ -110,16 +114,16 @@ private Q_SLOTS:
{
// GIVEN
Qt3DRender::Render::FilterKey backendFilterKey;
+ Qt3DRender::QFilterKey frontend;
TestRenderer renderer;
backendFilterKey.setRenderer(&renderer);
+ simulateInitializationSync(&frontend, &backendFilterKey);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendFilterKey.sceneChangeEvent(change);
+ frontend.setEnabled(newValue);
+ backendFilterKey.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backendFilterKey.isEnabled(), newValue);
@@ -127,10 +131,8 @@ private Q_SLOTS:
{
// WHEN
const QVariant newValue(383.0f);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("value");
- change->setValue(QVariant::fromValue(newValue));
- backendFilterKey.sceneChangeEvent(change);
+ frontend.setValue(newValue);
+ backendFilterKey.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backendFilterKey.value(), newValue);
@@ -138,10 +140,8 @@ private Q_SLOTS:
{
// WHEN
const QString newValue = QStringLiteral("Alan");
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("name");
- change->setValue(QVariant::fromValue(newValue));
- backendFilterKey.sceneChangeEvent(change);
+ frontend.setName(newValue);
+ backendFilterKey.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backendFilterKey.name(), newValue);
@@ -151,10 +151,15 @@ private Q_SLOTS:
void checkComparison()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::FilterKey backendFilterKey1;
Qt3DRender::Render::FilterKey backendFilterKey2;
Qt3DRender::Render::FilterKey backendFilterKey3;
Qt3DRender::Render::FilterKey backendFilterKey4;
+ backendFilterKey1.setRenderer(&renderer);
+ backendFilterKey2.setRenderer(&renderer);
+ backendFilterKey3.setRenderer(&renderer);
+ backendFilterKey4.setRenderer(&renderer);
// WHEN
{
@@ -162,20 +167,20 @@ private Q_SLOTS:
filterKey1.setName(QStringLiteral("Dallas"));
filterKey1.setValue(QVariant(QStringLiteral("Smith")));
- simulateInitialization(&filterKey1, &backendFilterKey1);
- simulateInitialization(&filterKey1, &backendFilterKey4);
+ simulateInitializationSync(&filterKey1, &backendFilterKey1);
+ simulateInitializationSync(&filterKey1, &backendFilterKey4);
Qt3DRender::QFilterKey filterKey2;
filterKey2.setName(QStringLiteral("Tim"));
filterKey2.setValue(QVariant(QStringLiteral("Smith")));
- simulateInitialization(&filterKey2, &backendFilterKey2);
+ simulateInitializationSync(&filterKey2, &backendFilterKey2);
Qt3DRender::QFilterKey filterKey3;
filterKey3.setName(QStringLiteral("Dallas"));
filterKey3.setValue(QVariant(QStringLiteral("McGraw")));
- simulateInitialization(&filterKey3, &backendFilterKey3);
+ simulateInitializationSync(&filterKey3, &backendFilterKey3);
}
// THEN
diff --git a/tests/auto/render/framegraphnode/framegraphnode.pro b/tests/auto/render/framegraphnode/framegraphnode.pro
index 577bc9775..f47fc1866 100644
--- a/tests/auto/render/framegraphnode/framegraphnode.pro
+++ b/tests/auto/render/framegraphnode/framegraphnode.pro
@@ -8,3 +8,4 @@ CONFIG += testcase
SOURCES += tst_framegraphnode.cpp
include(../commons/commons.pri)
+include(../../core/common/common.pri)
diff --git a/tests/auto/render/framegraphnode/tst_framegraphnode.cpp b/tests/auto/render/framegraphnode/tst_framegraphnode.cpp
index 22bd872dc..a7cea2ef2 100644
--- a/tests/auto/render/framegraphnode/tst_framegraphnode.cpp
+++ b/tests/auto/render/framegraphnode/tst_framegraphnode.cpp
@@ -30,9 +30,9 @@
#include <QtTest/QTest>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include "testrenderer.h"
+#include "qbackendnodetester.h"
class MyFrameGraphNode : public Qt3DRender::Render::FrameGraphNode
{
@@ -52,12 +52,12 @@ public:
{}
};
-class tst_FrameGraphNode : public QObject
+class tst_FrameGraphNode : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
public:
tst_FrameGraphNode(QObject *parent = nullptr)
- : QObject(parent)
+ : Qt3DCore::QBackendNodeTester(parent)
{}
~tst_FrameGraphNode()
@@ -216,10 +216,9 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
- const Qt3DCore::QNodeId fgNode1Id = Qt3DCore::QNodeId::createId();
-
- Qt3DRender::Render::FrameGraphNode *backendFGNode = new MyFrameGraphNode();
+ Qt3DRender::QFrameGraphNode *frontendFGNode = new MyQFrameGraphNode();
Qt3DRender::QFrameGraphNode *frontendFGChild = new MyQFrameGraphNode();
+ Qt3DRender::Render::FrameGraphNode *backendFGNode = new MyFrameGraphNode();
Qt3DRender::Render::FrameGraphNode *backendFGChild = new MyFrameGraphNode();
QScopedPointer<Qt3DRender::Render::FrameGraphManager> manager(new Qt3DRender::Render::FrameGraphManager());
@@ -229,47 +228,62 @@ private Q_SLOTS:
backendFGNode->setRenderer(&renderer);
backendFGChild->setRenderer(&renderer);
- setIdInternal(backendFGNode, fgNode1Id);
+ setIdInternal(backendFGNode, frontendFGNode->id());
setIdInternal(backendFGChild, frontendFGChild->id());
- manager->appendNode(fgNode1Id, backendFGNode);
+ manager->appendNode(frontendFGNode->id(), backendFGNode);
manager->appendNode(frontendFGChild->id(), backendFGChild);
backendFGNode->setFrameGraphManager(manager.data());
backendFGChild->setFrameGraphManager(manager.data());
-
- // To geneate the type_info in the QNodePrivate of frontendFGChild
- Qt3DCore::QNodeCreatedChangeGenerator generator(frontendFGChild);
+ simulateInitializationSync(frontendFGNode, backendFGNode);
+ simulateInitializationSync(frontendFGChild, backendFGChild);
QCOMPARE(backendFGNode->childrenIds().size(), 0);
{
// WHEN
- renderer.clearDirtyBits(0);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(frontendFGChild->id());
- change->setPropertyName("parentFrameGraphUpdated");
- change->setValue(QVariant::fromValue(fgNode1Id));
- backendFGChild->sceneChangeEvent(change);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ frontendFGChild->setParent(frontendFGNode);
+ backendFGChild->syncFromFrontEnd(frontendFGChild, false);
// THEN
QCOMPARE(backendFGNode->childrenIds().size(), 1);
- QCOMPARE(backendFGChild->parentId(), fgNode1Id);
+ QCOMPARE(backendFGChild->parentId(), frontendFGNode->id());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
{
// WHEN
- renderer.clearDirtyBits(0);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(frontendFGChild->id());
- change->setPropertyName("parentFrameGraphUpdated");
- change->setValue(QVariant::fromValue(Qt3DCore::QNodeId()));
- backendFGChild->sceneChangeEvent(change);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ frontendFGChild->setParent(Q_NODE_NULLPTR);
+ backendFGChild->syncFromFrontEnd(frontendFGChild, false);
// THEN
QCOMPARE(backendFGNode->childrenIds().size(), 0);
QVERIFY(backendFGChild->parentId().isNull());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
}
+ void checCleanupMarksDirty()
+ {
+ // GIVEN
+ TestRenderer renderer;
+ Qt3DRender::Render::FrameGraphNode *backendFGNode = new MyFrameGraphNode();
+
+ backendFGNode->setRenderer(&renderer);
+
+ // THEN
+ QVERIFY(renderer.dirtyBits() == 0);
+
+ // WHEN
+ backendFGNode->cleanup();
+
+ // THEN
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
+ }
+
};
QTEST_MAIN(tst_FrameGraphNode)
diff --git a/tests/auto/render/geometry/tst_geometry.cpp b/tests/auto/render/geometry/tst_geometry.cpp
index 7e65d27aa..09dbb8eb3 100644
--- a/tests/auto/render/geometry/tst_geometry.cpp
+++ b/tests/auto/render/geometry/tst_geometry.cpp
@@ -32,8 +32,6 @@
#include <Qt3DRender/qgeometry.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include "testrenderer.h"
#include "testpostmanarbiter.h"
@@ -50,6 +48,7 @@ public:
class tst_RenderGeometry : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
+
private Q_SLOTS:
void checkPeerPropertyMirroring()
@@ -72,7 +71,7 @@ private Q_SLOTS:
renderGeometry.setRenderer(&renderer);
// WHEN
- simulateInitialization(&geometry, &renderGeometry);
+ simulateInitializationSync(&geometry, &renderGeometry);
// THEN
QCOMPARE(renderGeometry.peerId(), geometry.id());
@@ -80,8 +79,9 @@ private Q_SLOTS:
QCOMPARE(renderGeometry.attributes().count(), 4);
QCOMPARE(renderGeometry.boundingPositionAttribute(), attr1.id());
- for (int i = 0; i < 4; ++i)
- QCOMPARE(geometry.attributes().at(i)->id(), renderGeometry.attributes().at(i));
+ Qt3DCore::QNodeIdVector attribs = Qt3DCore::qIdsForNodes(geometry.attributes());
+ std::sort(std::begin(attribs), std::end(attribs));
+ QCOMPARE(attribs, renderGeometry.attributes());
}
void checkSetRendererDirtyOnInitialization()
@@ -97,7 +97,7 @@ private Q_SLOTS:
QCOMPARE(renderer.dirtyBits(), 0);
// WHEN
- simulateInitialization(&geometry, &renderGeometry);
+ simulateInitializationSync(&geometry, &renderGeometry);
// THEN
QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::GeometryDirty);
@@ -130,7 +130,7 @@ private Q_SLOTS:
geometry.addAttribute(&attr4);
// WHEN
- simulateInitialization(&geometry, &renderGeometry);
+ simulateInitializationSync(&geometry, &renderGeometry);
renderGeometry.cleanup();
// THEN
@@ -145,13 +145,15 @@ private Q_SLOTS:
TestRenderer renderer;
Qt3DRender::Render::Geometry renderGeometry;
renderGeometry.setRenderer(&renderer);
+ Qt3DRender::QGeometry geometry;
+
+ simulateInitializationSync(&geometry, &renderGeometry);
DummyAttribute attribute;
// WHEN
- const auto nodeAddedChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &attribute);
- nodeAddedChange->setPropertyName("attribute");
- renderGeometry.sceneChangeEvent(nodeAddedChange);
+ geometry.addAttribute(&attribute);
+ renderGeometry.syncFromFrontEnd(&geometry, false);
// THEN
QCOMPARE(renderGeometry.attributes().count(), 1);
@@ -163,9 +165,8 @@ private Q_SLOTS:
QVERIFY(!renderGeometry.isDirty());
// WHEN
- const auto nodeRemovedChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &attribute);
- nodeRemovedChange->setPropertyName("attribute");
- renderGeometry.sceneChangeEvent(nodeRemovedChange);
+ geometry.removeAttribute(&attribute);
+ renderGeometry.syncFromFrontEnd(&geometry, false);
// THEN
QCOMPARE(renderGeometry.attributes().count(), 0);
@@ -177,14 +178,11 @@ private Q_SLOTS:
QVERIFY(!renderGeometry.isDirty());
// WHEN
- const Qt3DCore::QNodeId boundingAttrId = Qt3DCore::QNodeId::createId();
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(QVariant::fromValue(boundingAttrId));
- updateChange->setPropertyName("boundingVolumePositionAttribute");
- renderGeometry.sceneChangeEvent(updateChange);
+ geometry.setBoundingVolumePositionAttribute(&attribute);
+ renderGeometry.syncFromFrontEnd(&geometry, false);
// THEN
- QCOMPARE(renderGeometry.boundingPositionAttribute(), boundingAttrId);
+ QCOMPARE(renderGeometry.boundingPositionAttribute(), attribute.id());
QVERIFY(!renderGeometry.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
diff --git a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp
index d07ec9914..0f6af16db 100644
--- a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp
+++ b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp
@@ -32,9 +32,6 @@
#include <Qt3DRender/private/geometryrenderermanager_p.h>
#include <Qt3DRender/qgeometry.h>
#include <Qt3DRender/qgeometryfactory.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include "testrenderer.h"
class TestFactory : public Qt3DRender::QGeometryFactory
@@ -75,6 +72,7 @@ public:
class tst_RenderGeometryRenderer : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
+
private Q_SLOTS:
void checkPeerPropertyMirroring()
@@ -102,7 +100,7 @@ private Q_SLOTS:
// WHEN
renderGeometryRenderer.setRenderer(&renderer);
renderGeometryRenderer.setManager(&geometryRendererManager);
- simulateInitialization(&geometryRenderer, &renderGeometryRenderer);
+ simulateInitializationSync(&geometryRenderer, &renderGeometryRenderer);
// THEN
QCOMPARE(renderGeometryRenderer.peerId(), geometryRenderer.id());
@@ -163,7 +161,7 @@ private Q_SLOTS:
// WHEN
renderGeometryRenderer.setRenderer(&renderer);
renderGeometryRenderer.setManager(&geometryRendererManager);
- simulateInitialization(&geometryRenderer, &renderGeometryRenderer);
+ simulateInitializationSync(&geometryRenderer, &renderGeometryRenderer);
renderGeometryRenderer.cleanup();
// THEN
@@ -184,210 +182,185 @@ private Q_SLOTS:
void checkPropertyChanges()
{
// GIVEN
- Qt3DRender::Render::GeometryRenderer renderGeometryRenderer;
+ Qt3DRender::QGeometryRenderer frontEndRenderer;
+ Qt3DRender::Render::GeometryRenderer backEndRenderer;
TestRenderer renderer;
- renderGeometryRenderer.setRenderer(&renderer);
+ backEndRenderer.setRenderer(&renderer);
- QVERIFY(!renderGeometryRenderer.isDirty());
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("instanceCount");
- updateChange->setValue(2);
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setInstanceCount(2);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.instanceCount(), 2);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.instanceCount(), 2);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("vertexCount");
- updateChange->setValue(56);
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setVertexCount(56);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.vertexCount(), 56);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.vertexCount(), 56);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("indexOffset");
- updateChange->setValue(65);
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setIndexOffset(65);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.indexOffset(), 65);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.indexOffset(), 65);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("firstInstance");
- updateChange->setValue(82);
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setFirstInstance(82);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.firstInstance(), 82);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.firstInstance(), 82);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("indexBufferByteOffset");
- updateChange->setValue(96);
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setIndexBufferByteOffset(96);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.indexBufferByteOffset(), 96);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.indexBufferByteOffset(), 96);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("restartIndexValue");
- updateChange->setValue(46);
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setRestartIndexValue(46);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.restartIndexValue(), 46);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.restartIndexValue(), 46);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("primitiveRestartEnabled");
- updateChange->setValue(true);
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setPrimitiveRestartEnabled(true);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.primitiveRestartEnabled(), true);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.primitiveRestartEnabled(), true);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("primitiveType");
- updateChange->setValue(static_cast<int>(Qt3DRender::QGeometryRenderer::LineLoop));
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::LineLoop);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.primitiveType(), Qt3DRender::QGeometryRenderer::LineLoop);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setPropertyName("geometryFactory");
Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(1450));
- updateChange->setValue(QVariant::fromValue(factory));
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setGeometryFactory(factory);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.geometryFactory(), factory);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.geometryFactory(), factory);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN we set an identical factory again
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("geometryFactory");
Qt3DRender::QGeometryFactoryPtr factory2(new TestFactory(1450));
- updateChange->setValue(QVariant::fromValue(factory2));
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setGeometryFactory(factory2);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN not dirty and still uses original factory
- QCOMPARE(renderGeometryRenderer.geometryFactory(), factory);
- QVERIFY(!renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.geometryFactory(), factory);
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
DummyGeometry geometry;
const Qt3DCore::QNodeId geometryId = geometry.id();
- const auto nodeAddedChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- nodeAddedChange->setPropertyName("geometry");
- nodeAddedChange->setValue(QVariant::fromValue(geometryId));
- renderGeometryRenderer.sceneChangeEvent(nodeAddedChange);
+ frontEndRenderer.setGeometry(&geometry);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.geometryId(), geometryId);
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.geometryId(), geometryId);
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- const auto nodeRemovedChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- nodeRemovedChange->setPropertyName("geometry");
- nodeRemovedChange->setValue(QVariant::fromValue(Qt3DCore::QNodeId()));
- renderGeometryRenderer.sceneChangeEvent(nodeRemovedChange);
+ frontEndRenderer.setGeometry(nullptr);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.geometryId(), Qt3DCore::QNodeId());
- QVERIFY(renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.geometryId(), Qt3DCore::QNodeId());
+ QVERIFY(backEndRenderer.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderGeometryRenderer.unsetDirty();
- QVERIFY(!renderGeometryRenderer.isDirty());
+ backEndRenderer.unsetDirty();
+ QVERIFY(!backEndRenderer.isDirty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(true));
- updateChange->setPropertyName("enabled");
- renderGeometryRenderer.sceneChangeEvent(updateChange);
+ frontEndRenderer.setEnabled(true);
+ backEndRenderer.syncFromFrontEnd(&frontEndRenderer, false);
// THEN
- QCOMPARE(renderGeometryRenderer.isEnabled(), true);
- QVERIFY(!renderGeometryRenderer.isDirty());
+ QCOMPARE(backEndRenderer.isEnabled(), true);
+ QVERIFY(!backEndRenderer.isDirty());
}
void checkSetRendererDirtyOnInitialization()
@@ -405,7 +378,7 @@ private Q_SLOTS:
QCOMPARE(renderer.dirtyBits(), 0);
// WHEN
- simulateInitialization(&geometryRenderer, &renderGeometryRenderer);
+ simulateInitializationSync(&geometryRenderer, &renderGeometryRenderer);
// THEN
QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::GeometryDirty);
diff --git a/tests/auto/render/gltexture/gltexture.pro b/tests/auto/render/gltexture/gltexture.pro
new file mode 100644
index 000000000..b21cea813
--- /dev/null
+++ b/tests/auto/render/gltexture/gltexture.pro
@@ -0,0 +1,13 @@
+TEMPLATE = app
+
+TARGET = tst_gltexture
+
+QT += 3dcore 3dcore-private 3drender 3drender-private testlib
+
+CONFIG += testcase
+
+SOURCES += \
+ tst_gltexture.cpp
+
+RESOURCES += \
+ resources.qrc
diff --git a/tests/auto/render/gltexture/image.jpg b/tests/auto/render/gltexture/image.jpg
new file mode 100644
index 000000000..495afa5ce
--- /dev/null
+++ b/tests/auto/render/gltexture/image.jpg
Binary files differ
diff --git a/tests/auto/render/gltexture/resources.qrc b/tests/auto/render/gltexture/resources.qrc
new file mode 100644
index 000000000..bfb2396da
--- /dev/null
+++ b/tests/auto/render/gltexture/resources.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>image.jpg</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/render/gltexture/tst_gltexture.cpp b/tests/auto/render/gltexture/tst_gltexture.cpp
new file mode 100644
index 000000000..e971078d0
--- /dev/null
+++ b/tests/auto/render/gltexture/tst_gltexture.cpp
@@ -0,0 +1,909 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <Qt3DRender/private/gltexture_p.h>
+#include <Qt3DRender/qabstracttexture.h>
+#include <Qt3DRender/qtexturegenerator.h>
+#include <Qt3DRender/private/qtexture_p.h>
+#include <Qt3DRender/private/qtextureimage_p.h>
+#include <QSurfaceFormat>
+#include <QWindow>
+#include <QUrl>
+#include <QOpenGLContext>
+#include <cstring>
+
+using namespace Qt3DRender;
+using namespace Qt3DRender::Render;
+
+namespace {
+
+QTextureDataUpdate generateDataUpdate()
+{
+ QByteArray rawPixelData;
+ rawPixelData.resize(512 * 4 * sizeof(uchar));
+ uchar *pixels = reinterpret_cast<uchar *>(rawPixelData.data());
+ std::memset(pixels, 128U, 512 * 4 * sizeof(uchar));
+
+ // QTextureImageData hold our raw content and size of subcontent
+ Qt3DRender::QTextureImageDataPtr imageData = Qt3DRender::QTextureImageDataPtr::create();
+ imageData->setWidth(512);
+ imageData->setHeight(1);
+ imageData->setMipLevels(1);
+ imageData->setLayers(1);
+ // We upload the 4 components of an RGBA pixel as 4 uchar
+ imageData->setPixelFormat(QOpenGLTexture::RGBA);
+ imageData->setPixelType(QOpenGLTexture::UInt8);
+ imageData->setData(rawPixelData, 4, false);
+
+ Qt3DRender::QTextureDataUpdate update;
+ update.setX(0);
+ update.setY(10);
+ update.setMipLevel(0);
+ update.setData(imageData);
+
+ return update;
+}
+
+} // anonymous
+
+class FakeTexture2DGenerator : public QTextureGenerator
+{
+public:
+ QT3D_FUNCTOR(FakeTexture2DGenerator)
+
+ QTextureDataPtr operator ()() override
+ {
+ QTextureDataPtr generatedData = QTextureDataPtr::create();
+ generatedData->setTarget(QAbstractTexture::Target2D);
+#ifndef QT_OPENGL_ES_2
+ generatedData->setFormat(QAbstractTexture::RGBA8_UNorm);
+#else
+ generatedData->setFormat(QAbstractTexture::RGBAFormat);
+#endif
+ generatedData->setWidth(512);
+ generatedData->setHeight(512);
+ generatedData->setDepth(1);
+ generatedData->setLayers(1);
+ return generatedData;
+ }
+
+ bool operator ==(const QTextureGenerator &) const override
+ {
+ return true;
+ }
+};
+
+class FakeTexture2DGeneratorAutomatic : public QTextureGenerator
+{
+public:
+ QT3D_FUNCTOR(FakeTexture2DGenerator)
+
+ QTextureDataPtr operator ()() override
+ {
+ QTextureDataPtr generatedData = QTextureDataPtr::create();
+ generatedData->setTarget(QAbstractTexture::TargetAutomatic);
+#ifndef QT_OPENGL_ES_2
+ generatedData->setFormat(QAbstractTexture::RGBA8_UNorm);
+#else
+ generatedData->setFormat(QAbstractTexture::RGBAFormat);
+#endif
+ generatedData->setWidth(512);
+ generatedData->setHeight(512);
+ generatedData->setDepth(1);
+ generatedData->setLayers(1);
+ return generatedData;
+ }
+
+ bool operator ==(const QTextureGenerator &) const override
+ {
+ return true;
+ }
+};
+
+class FakeDownloadTexture2DGenerator : public QTextureGenerator
+{
+public:
+ QT3D_FUNCTOR(FakeDownloadTexture2DGenerator)
+
+ QTextureDataPtr operator ()() override
+ {
+ if (m_hasBeenDownloaded) {
+ generatedData->setTarget(QAbstractTexture::Target2D);
+ generatedData->setFormat(QAbstractTexture::RGBA8_UNorm);
+ generatedData->setWidth(512);
+ generatedData->setHeight(512);
+ generatedData->setDepth(1);
+ generatedData->setLayers(1);
+ } else {
+ generatedData->setTarget(QAbstractTexture::TargetAutomatic);
+ }
+ return generatedData;
+ }
+
+ bool operator ==(const QTextureGenerator &) const override
+ {
+ return true;
+ }
+
+ void setHasBeenDownloaded(bool downloaded)
+ {
+ m_hasBeenDownloaded = downloaded;
+ }
+
+private:
+ QTextureDataPtr generatedData = QTextureDataPtr::create();
+ bool m_hasBeenDownloaded = false;
+};
+
+
+
+class tst_GLTexture : public QObject
+{
+ Q_OBJECT
+
+private:
+ QScopedPointer<QWindow> m_window;
+ QOpenGLContext m_glContext;
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ qRegisterMetaType<TextureProperties>("Qt3DRender::Render::TexturePropertiers");
+ }
+
+ void init()
+ {
+ m_window.reset(new QWindow);
+ m_window->setSurfaceType(QWindow::OpenGLSurface);
+ m_window->setGeometry(0, 0, 10, 10);
+ m_window->create();
+
+ if (!m_glContext.create()) {
+ qWarning() << "Failed to create OpenGL context";
+ return;
+ }
+
+ if (!m_glContext.makeCurrent(m_window.data())) {
+ qWarning() << "Failed to make OpenGL context current";
+ return;
+ }
+ }
+
+ void cleanup()
+ {
+ m_glContext.doneCurrent();
+ }
+
+ void checkDontCreateInternalTextureIfNothingSpecified()
+ {
+ // GIVEN
+ GLTexture texture;
+
+ // THEN
+ QVERIFY(texture.getGLTexture() == nullptr);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.hasImagesData());
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> shouldn't have created a texture since format and target
+ // were not specified
+ QVERIFY(texture.getGLTexture() == nullptr);
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkCreatesInternalTexture()
+ {
+ // GIVEN
+ GLTexture texture;
+
+ // WHEN
+ TextureProperties props;
+ props.target = QAbstractTexture::Target2D;
+#ifndef QT_OPENGL_ES_2
+ props.format = QAbstractTexture::RGBA8_SNorm;
+#else
+ props.format = QAbstractTexture::RGBAFormat;
+#endif
+ texture.setProperties(props);
+
+ // THEN
+ QCOMPARE(texture.dirtyFlags(), GLTexture::Properties);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QOpenGLTexture *internalTexture = texture.getGLTexture();
+ QCOMPARE(internalTexture->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTexture->width(), 1);
+ QCOMPARE(internalTexture->height(), 1);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.hasImagesData());
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkShouldnotCreateTextureIfTargetIsAutomaticOrFormatUnspecified()
+ {
+ // GIVEN
+ GLTexture texture;
+ TextureProperties props;
+
+ props.target = QAbstractTexture::TargetAutomatic;
+#ifndef QT_OPENGL_ES_2
+ props.format = QAbstractTexture::RGBA8_SNorm;
+#else
+ props.format = QAbstractTexture::RGBAFormat;
+#endif
+ // WHEN
+ texture.setProperties(props);
+
+ // THEN
+ QCOMPARE(texture.dirtyFlags(), GLTexture::Properties);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> shouldn't have created a texture since target is automatic
+ QVERIFY(texture.getGLTexture() == nullptr);
+ QCOMPARE(texture.dirtyFlags(), GLTexture::Properties);
+
+ // WHEN
+ props.target = QAbstractTexture::Target2D;
+ props.format = QAbstractTexture::NoFormat;
+ texture.setProperties(props);
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> shouldn't have created a texture since format is not specified
+ QVERIFY(texture.getGLTexture() == nullptr);
+ QCOMPARE(texture.dirtyFlags(), GLTexture::Properties);
+
+ // WHEN
+ props.target = QAbstractTexture::Target2D;
+ props.format = QAbstractTexture::Automatic;
+ texture.setProperties(props);
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> shouldn't have created a texture since format is not specified
+ QVERIFY(texture.getGLTexture() == nullptr);
+ QCOMPARE(texture.dirtyFlags(), GLTexture::Properties);
+
+ // WHEN
+ props.target = QAbstractTexture::Target2D;
+#ifndef QT_OPENGL_ES_2
+ props.format = QAbstractTexture::RGBA8_SNorm;
+#else
+ props.format = QAbstractTexture::RGBAFormat;
+#endif
+ texture.setProperties(props);
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QOpenGLTexture *internalTexture = texture.getGLTexture();
+ QCOMPARE(internalTexture->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTexture->width(), 1);
+ QCOMPARE(internalTexture->height(), 1);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.hasImagesData());
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkCreateTextureWithDataGenerator()
+ {
+ // GIVEN
+ GLTexture texture;
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QOpenGLTexture *internalTex = texture.getGLTexture();
+ QVERIFY(internalTex == nullptr);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.hasImagesData());
+
+ // WHEN
+ auto genTex2D = QSharedPointer<FakeTexture2DGenerator>::create();
+ texture.setGenerator(genTex2D);
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QVERIFY(texture.getGLTexture() != nullptr);
+ QVERIFY(texture.getGLTexture() != internalTex);
+
+ internalTex = texture.getGLTexture();
+ QCOMPARE(internalTex->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTex->width(), 512);
+ QCOMPARE(internalTex->height(), 512);
+
+ QVERIFY(texture.hasTextureData());
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.hasImagesData());
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkHandlesDelayedReceptionOfDataGenerator()
+ {
+ // GIVEN
+ GLTexture texture;
+
+ // WHEN
+ auto genDownloadTex2D = QSharedPointer<FakeDownloadTexture2DGenerator>::create();
+ texture.setGenerator(genDownloadTex2D);
+
+ // THEN
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(texture.isDirty());
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> shouldn't have created internal texture since target is automatic
+ // but generator should have run to return a QTextureDataPtr
+ QVERIFY(texture.getGLTexture() == nullptr);
+ QVERIFY(texture.isDirty());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.hasImagesData());
+
+ // WHEN
+ genDownloadTex2D->setHasBeenDownloaded(true);
+ texture.setGenerator(genDownloadTex2D);
+
+ // THEN
+ QVERIFY(texture.getGLTexture() == nullptr);
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(texture.isDirty());
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> Should have created the texture has target shouldn't be automatic
+ QVERIFY(texture.hasTextureData());
+ QVERIFY(!texture.isDirty());
+ QOpenGLTexture *internalTex = texture.getGLTexture();
+ QVERIFY(internalTex != nullptr);
+ QCOMPARE(internalTex->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTex->width(), 512);
+ QCOMPARE(internalTex->height(), 512);
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkTakesTargetFromGeneratorIfTargetNotSpecified()
+ {
+ // GIVEN
+ GLTexture texture;
+ TextureProperties props;
+ props.target = QAbstractTexture::TargetAutomatic;
+
+ // WHEN
+ auto genDownloadTex2D = QSharedPointer<FakeTexture2DGenerator>::create();
+ texture.setGenerator(genDownloadTex2D);
+ texture.setProperties(props);
+
+ // THEN
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(texture.isDirty());
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> Should have created the texture has target shouldn't be automatic
+ QVERIFY(texture.hasTextureData());
+ QVERIFY(!texture.isDirty());
+ QOpenGLTexture *internalTex = texture.getGLTexture();
+ QVERIFY(internalTex != nullptr);
+ QCOMPARE(internalTex->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTex->width(), 512);
+ QCOMPARE(internalTex->height(), 512);
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkKeepsSetTargetIfGeneratorTargetNotSpecified()
+ {
+ // GIVEN
+ GLTexture texture;
+ TextureProperties props;
+ props.target = QAbstractTexture::Target2D;
+
+ // WHEN
+ auto genDownloadTex2D = QSharedPointer<FakeTexture2DGeneratorAutomatic>::create();
+ texture.setGenerator(genDownloadTex2D);
+ texture.setProperties(props);
+
+ // THEN
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(texture.isDirty());
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> Should have created the texture has target shouldn't be automatic
+ QVERIFY(texture.hasTextureData());
+ QVERIFY(!texture.isDirty());
+ QOpenGLTexture *internalTex = texture.getGLTexture();
+ QVERIFY(internalTex != nullptr);
+ QCOMPARE(internalTex->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTex->width(), 512);
+ QCOMPARE(internalTex->height(), 512);
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkDontCreateTextureIfGeneratorAndTargetAreAutomatic()
+ {
+ // GIVEN
+ GLTexture texture;
+ TextureProperties props;
+ props.target = QAbstractTexture::TargetAutomatic;
+
+ // WHEN
+ auto genDownloadTex2D = QSharedPointer<FakeTexture2DGeneratorAutomatic>::create();
+ texture.setGenerator(genDownloadTex2D);
+ texture.setProperties(props);
+
+ // THEN
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(texture.isDirty());
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> Should have created the texture has target shouldn't be automatic
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(texture.isDirty());
+ QVERIFY(texture.getGLTexture() == nullptr);
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkRecreatesTextureOnPropertyChanged()
+ {
+ // GIVEN
+ GLTexture texture;
+
+ // WHEN
+ TextureProperties props;
+ props.target = QAbstractTexture::Target2D;
+#ifndef QT_OPENGL_ES_2
+ props.format = QAbstractTexture::RGBA8_SNorm;
+#else
+ props.format = QAbstractTexture::RGBAFormat;
+#endif
+ texture.setProperties(props);
+
+ // THEN
+ QCOMPARE(texture.dirtyFlags(), GLTexture::Properties);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QOpenGLTexture *internalTexture = texture.getGLTexture();
+ QCOMPARE(internalTexture->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTexture->width(), 1);
+ QCOMPARE(internalTexture->height(), 1);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.hasImagesData());
+
+ // WHEN
+ props.width = 256;
+ props.height = 256;
+ texture.setProperties(props);
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QOpenGLTexture *internalTexture2 = texture.getGLTexture();
+ QCOMPARE(internalTexture2->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTexture2->width(), 256);
+ QCOMPARE(internalTexture2->height(), 256);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.hasImagesData());
+ QVERIFY(texture.wasTextureRecreated());
+
+ // Technically pointer should be different but that's up to the system
+ // so can't really be tested
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkDoesntRecreateTextureOnParameterChanged()
+ {
+ // GIVEN
+ GLTexture texture;
+
+ // WHEN
+ TextureProperties props;
+ props.target = QAbstractTexture::Target2D;
+#ifndef QT_OPENGL_ES_2
+ props.format = QAbstractTexture::RGBA8_SNorm;
+#else
+ props.format = QAbstractTexture::RGBAFormat;
+#endif
+ texture.setProperties(props);
+
+ TextureParameters params;
+ params.magnificationFilter = QAbstractTexture::Linear;
+ params.minificationFilter = QAbstractTexture::Linear;
+ texture.setParameters(params);
+
+ // THEN
+ QCOMPARE(texture.dirtyFlags(), GLTexture::Properties|GLTexture::Parameters);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QOpenGLTexture *internalTexture = texture.getGLTexture();
+ QCOMPARE(internalTexture->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTexture->width(), 1);
+ QCOMPARE(internalTexture->height(), 1);
+ QCOMPARE(internalTexture->minificationFilter(), QOpenGLTexture::Linear);
+ QCOMPARE(internalTexture->magnificationFilter(), QOpenGLTexture::Linear);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.hasImagesData());
+
+ // WHEN
+ params.magnificationFilter = QAbstractTexture::Nearest;
+ params.minificationFilter = QAbstractTexture::Nearest;
+ texture.setParameters(params);
+
+ // THEN
+ QCOMPARE(texture.dirtyFlags(),GLTexture::Parameters);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QOpenGLTexture *internalTexture2 = texture.getGLTexture();
+ QCOMPARE(internalTexture->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTexture->width(), 1);
+ QCOMPARE(internalTexture->height(), 1);
+ QCOMPARE(internalTexture->minificationFilter(), QOpenGLTexture::Nearest);
+ QCOMPARE(internalTexture->magnificationFilter(), QOpenGLTexture::Nearest);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.hasImagesData());
+ QCOMPARE(internalTexture, internalTexture2);
+ QVERIFY(!texture.wasTextureRecreated());
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkDestroy()
+ {
+ // GIVEN
+ GLTexture texture;
+ TextureProperties props;
+ props.target = QAbstractTexture::Target2D;
+#ifndef QT_OPENGL_ES_2
+ props.format = QAbstractTexture::RGBA8_SNorm;
+#else
+ props.format = QAbstractTexture::RGBAFormat;
+#endif
+ texture.setProperties(props);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+ texture.setGenerator(QSharedPointer<FakeTexture2DGenerator>::create());
+ QVector<GLTexture::Image> images;
+ QImageTextureDataFunctorPtr gen = QImageTextureDataFunctorPtr::create(QUrl("qrc:/image.jpg"), true);
+ images.push_back({gen, 1, 0, QAbstractTexture::CubeMapPositiveX});
+ texture.setImages(images);
+
+ // THEN
+ QVERIFY(texture.getGLTexture() != nullptr);
+
+ // WHEN
+ texture.destroy();
+
+ // THEN
+ QVERIFY(texture.getGLTexture() == nullptr);
+ QVERIFY(!texture.isDirty());
+ QCOMPARE(texture.properties(), TextureProperties());
+ QCOMPARE(texture.parameters(), TextureParameters());
+ QCOMPARE(texture.images().size(), 0);
+ QVERIFY(!texture.hasImagesData());
+ QVERIFY(!texture.hasTextureData());
+ QVERIFY(!texture.dataGenerator());
+ }
+
+ void checkRecreateTextureOnNewImageDataChanged()
+ {
+ // GIVEN
+ GLTexture texture;
+ TextureProperties props;
+ props.target = QAbstractTexture::Target2D;
+#ifndef QT_OPENGL_ES_2
+ props.format = QAbstractTexture::RGBA8_UNorm;
+#else
+ props.format = QAbstractTexture::RGBAFormat;
+#endif
+ props.width = 1;
+ props.height = 1;
+ texture.setProperties(props);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QVERIFY(texture.getGLTexture() != nullptr);
+ QVERIFY(!texture.isDirty());
+
+ // WHEN
+ texture.setGenerator(QSharedPointer<FakeTexture2DGenerator>::create());
+ QVector<GLTexture::Image> images;
+ // Test image has a size of 512/512
+ QImageTextureDataFunctorPtr gen = QImageTextureDataFunctorPtr::create(QUrl("qrc:/image.jpg"), true);
+ images.push_back({gen, 1, 0, QAbstractTexture::CubeMapPositiveX});
+ texture.setImages(images);
+
+ // THEN
+ QCOMPARE(texture.dirtyFlags(), GLTexture::TextureImageData|GLTexture::TextureData);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QOpenGLTexture *internalTexture = texture.getGLTexture();
+ QCOMPARE(internalTexture->target(), QOpenGLTexture::Target2D);
+ QCOMPARE(internalTexture->width(), 512);
+ QCOMPARE(internalTexture->height(), 512);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(texture.hasTextureData());
+ QVERIFY(texture.wasTextureRecreated());
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkDoesntRecreateTextureOnNewTextureDataUpdate()
+ {
+ // GIVEN
+ GLTexture texture;
+ TextureProperties props;
+ props.target = QAbstractTexture::Target2D;
+#ifndef QT_OPENGL_ES_2
+ props.format = QAbstractTexture::RGBA8_UNorm;
+#else
+ props.format = QAbstractTexture::RGBAFormat;
+#endif
+ props.width = 512;
+ props.height = 512;
+ texture.setProperties(props);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QVERIFY(texture.getGLTexture() != nullptr);
+ QVERIFY(!texture.isDirty());
+
+ // WHEN
+ QByteArray rawPixelData;
+ rawPixelData.resize(512 * 4 * sizeof(uchar));
+ uchar *pixels = reinterpret_cast<uchar *>(rawPixelData.data());
+ std::memset(pixels, 128U, 512 * 4 * sizeof(uchar));
+
+ // QTextureImageData hold our raw content and size of subcontent
+ Qt3DRender::QTextureImageDataPtr imageData = Qt3DRender::QTextureImageDataPtr::create();
+ imageData->setWidth(512);
+ imageData->setHeight(1);
+ imageData->setMipLevels(1);
+ imageData->setLayers(1);
+ // We upload the 4 components of an RGBA pixel as 4 uchar
+ imageData->setPixelFormat(QOpenGLTexture::RGBA);
+ imageData->setPixelType(QOpenGLTexture::UInt8);
+ imageData->setData(rawPixelData, 4, false);
+
+ Qt3DRender::QTextureDataUpdate update;
+ update.setX(0);
+ update.setY(10);
+ update.setMipLevel(0);
+ update.setData(imageData);
+
+ texture.addTextureDataUpdates({update});
+
+ // THEN
+ QCOMPARE(texture.dirtyFlags(), GLTexture::TextureData);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+ QVERIFY(texture.getGLTexture() != nullptr);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.wasTextureRecreated());
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkDoesntCrashWhenSendingIncompatibleTextureDataUpdate_data()
+ {
+ QTest::addColumn<TextureProperties>("properties");
+ QTest::addColumn<Qt3DRender::QTextureDataUpdate>("update");
+
+ QTextureDataUpdate update;
+ TextureProperties props;
+ props.target = QAbstractTexture::Target2D;
+#ifndef QT_OPENGL_ES_2
+ props.format = QAbstractTexture::RGBA8_UNorm;
+#else
+ props.format = QAbstractTexture::RGBAFormat;
+#endif
+ props.width = 512;
+ props.height = 512;
+ QTest::newRow("empty") << props << update;
+
+ update = generateDataUpdate();
+ update.setMipLevel(4);
+ QTest::newRow("invalid_mip_level") << props << update;
+
+ update.setX(512);
+ QTest::newRow("out_of_bound_x") << props << update;
+
+ update.setX(0);
+ update.setY(512);
+ QTest::newRow("out_of_bound_y") << props << update;
+
+#ifndef QT_OPENGL_ES_2
+ update.setX(0);
+ update.setY(0);
+ update.setZ(512);
+ props.target = QAbstractTexture::Target3D;
+ props.depth = 512;
+ QTest::newRow("out_of_bound_z") << props << update;
+#endif
+ update.setY(0);
+ update.setZ(0);
+ update.setX(256);
+ update.data()->setWidth(512);
+ QTest::newRow("out_of_bound_width") << props << update;
+
+ update.setX(0);
+ update.setY(256);
+ update.setZ(0);
+ update.data()->setHeight(512);
+ QTest::newRow("out_of_bound_height") << props << update;
+
+#ifndef QT_OPENGL_ES_2
+ update.setX(0);
+ update.setY(0);
+ update.setZ(256);
+ update.data()->setDepth(512);
+ QTest::newRow("out_of_bound_depth") << props << update;
+
+ update.setX(0);
+ update.setY(0);
+ update.setZ(0);
+ update.data()->setDepth(0);
+ update.setLayer(8);
+ props.target = QAbstractTexture::Target2DArray;
+ props.layers = 4;
+ QTest::newRow("out_of_bound_layer") << props << update;
+#endif
+ }
+
+
+ void checkDoesntCrashWhenSendingIncompatibleTextureDataUpdate()
+ {
+ // GIVEN
+ GLTexture texture;
+ QFETCH(TextureProperties, properties);
+ QFETCH(QTextureDataUpdate, update);
+ texture.setProperties(properties);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QVERIFY(texture.getGLTexture() != nullptr);
+ QVERIFY(!texture.isDirty());
+
+ // WHEN
+ texture.addTextureDataUpdates({update});
+
+ // THEN
+ QCOMPARE(texture.dirtyFlags(), GLTexture::TextureData);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN -> shouldn't crash
+ QVERIFY(texture.getGLTexture() != nullptr);
+ QVERIFY(!texture.isDirty());
+ QVERIFY(!texture.wasTextureRecreated());
+
+ // Cleanup
+ texture.destroy();
+ }
+
+ void checkPropertiesAfterLoadTextureDataFromImages()
+ {
+ // GIVEN
+ GLTexture texture;
+ TextureProperties props;
+ props.target = QAbstractTexture::TargetCubeMap;
+ props.format = QAbstractTexture::Automatic;
+ props.width = 1;
+ props.height = 1;
+ texture.setProperties(props);
+ QVector<GLTexture::Image> images;
+ // test a image texture data generator whose url is invalid
+ QImageTextureDataFunctorPtr gen = QImageTextureDataFunctorPtr::create(QUrl(), true);
+ images.push_back({gen, 0, 0, QAbstractTexture::CubeMapPositiveX});
+ texture.setImages(images);
+
+ // WHEN
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QCOMPARE(texture.properties().format, QAbstractTexture::Automatic);
+
+ // WHEN
+ // test a image texture data generator whose url is valid
+ gen = QImageTextureDataFunctorPtr::create(QUrl("qrc:/image.jpg"), true);
+ images.clear();
+ images.push_back({gen, 0, 0, QAbstractTexture::CubeMapPositiveX});
+ texture.setImages(images);
+ texture.createOrUpdateGLTexture();
+
+ // THEN
+ QVERIFY(texture.properties().format != QAbstractTexture::Automatic);
+ QVERIFY(texture.properties().format != QAbstractTexture::NoFormat);
+
+ // Cleanup
+ texture.destroy();
+ }
+};
+
+QTEST_MAIN(tst_GLTexture);
+
+#include "tst_gltexture.moc"
diff --git a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp
index 6c756957f..ffafc2312 100644
--- a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp
+++ b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp
@@ -1557,6 +1557,24 @@ private Q_SLOTS:
// Not supported by GL2
}
+ void rasterMode()
+ {
+ if (!m_initializationSuccessful)
+ QSKIP("Initialization failed, OpenGL 2.0 functions not supported");
+
+ m_func->glGetError();
+
+ // WHEN
+ m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ // THEN
+ const GLint error = m_func->glGetError();
+ QVERIFY(error == 0);
+ GLint p;
+ m_func->glGetIntegerv(GL_POLYGON_MODE, &p);
+ QCOMPARE(p, GL_LINE);
+ }
+
private:
QScopedPointer<QWindow> m_window;
QOpenGLContext m_glContext;
diff --git a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp
index 5eb171827..840a7f6da 100644
--- a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp
+++ b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp
@@ -2250,6 +2250,23 @@ private Q_SLOTS:
QCOMPARE(m_func->glIsSync(sync), GL_FALSE);
}
+ void rasterMode()
+ {
+ if (!m_initializationSuccessful)
+ QSKIP("Initialization failed, OpenGL 3.2 functions not supported");
+
+ m_func->glGetError();
+
+ m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ // THEN
+ const GLint error = m_func->glGetError();
+ QVERIFY(error == 0);
+ GLint p;
+ m_func->glGetIntegerv(GL_POLYGON_MODE, &p);
+ QCOMPARE(p, GL_LINE);
+ }
+
private:
QScopedPointer<QWindow> m_window;
QOpenGLContext m_glContext;
diff --git a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp
index a88e36d5e..874c83f0b 100644
--- a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp
+++ b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp
@@ -2350,6 +2350,22 @@ private Q_SLOTS:
QCOMPARE(m_func->glIsSync(sync), GL_FALSE);
}
+ void rasterMode()
+ {
+ if (!m_initializationSuccessful)
+ QSKIP("Initialization failed, OpenGL 3.3 functions not supported");
+
+ m_func->glGetError();
+ m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ // THEN
+ const GLint error = m_func->glGetError();
+ QVERIFY(error == 0);
+ GLint p;
+ m_func->glGetIntegerv(GL_POLYGON_MODE, &p);
+ QCOMPARE(p, GL_LINE);
+ }
+
private:
QScopedPointer<QWindow> m_window;
QOpenGLContext m_glContext;
diff --git a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp
index 87eee19ac..6e5c54303 100644
--- a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp
+++ b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp
@@ -174,6 +174,28 @@ const QByteArray fragCodeSamplers = QByteArrayLiteral(
" texture(srect, texCoord);\n" \
"}\n");
+const QByteArray fragCodeImages = QByteArrayLiteral(
+ "#version 430 core\n" \
+ "in vec2 texCoord;\n" \
+ "out vec4 color;\n" \
+ "layout(location = 1, rgba32f) readonly uniform image1D s1;\n" \
+ "layout(location = 2, rg16f) readonly uniform image2D s2;\n" \
+ "layout(location = 3, r16f) readonly uniform image2DArray s2a;\n" \
+ "layout(location = 4, rg8) readonly uniform image3D s3;\n" \
+ "layout(location = 5, rgba16_snorm) readonly uniform imageCube scube;\n" \
+ "layout(location = 6, rg16) readonly uniform image2DRect srect;\n" \
+ "void main()\n" \
+ "{\n" \
+ " ivec2 coords = ivec2(texCoord);\n"\
+ " color = vec4(1, 0, 0, 1) *" \
+ " imageLoad(s1, coords.x) *" \
+ " imageLoad(s2, coords) *" \
+ " imageLoad(s2a, ivec3(coords, 0)) *" \
+ " imageLoad(s3, ivec3(coords, 0)) *" \
+ " imageLoad(scube, ivec3(coords, 0)) *" \
+ " imageLoad(srect, coords);\n" \
+ "}\n");
+
const QByteArray computeShader = QByteArrayLiteral(
"#version 430 core\n" \
"uniform float particleStep;\n" \
@@ -494,6 +516,37 @@ private Q_SLOTS:
m_func->glDeleteFramebuffers(1, &fboId);
}
+ void bindImageTexture()
+ {
+ if (!m_initializationSuccessful)
+ QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported");
+
+ // GIVEN
+ QOpenGLTexture texture(QOpenGLTexture::Target2D);
+ texture.setSize(512, 512);
+ texture.setFormat(QOpenGLTexture::RGBA8U);
+ texture.setMinificationFilter(QOpenGLTexture::Linear);
+ texture.setMagnificationFilter(QOpenGLTexture::Linear);
+ texture.create();
+ texture.allocateStorage();
+
+ // THEN
+ QVERIFY(texture.textureId() != 0 && texture.isCreated() && texture.isStorageAllocated());
+
+ // WHEN
+ m_glHelper.bindImageTexture(0,
+ texture.textureId(),
+ 0,
+ GL_FALSE,
+ 0,
+ GL_READ_WRITE,
+ GL_RGBA8UI);
+
+ // THEN
+ GLint error = m_func->glGetError();
+ QVERIFY(error == 0);
+ }
+
void bindShaderStorageBlock()
{
if (!m_initializationSuccessful)
@@ -1477,6 +1530,13 @@ private Q_SLOTS:
ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_3D, 4, 1, 4);
ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_CUBE, 5, 1, 4);
ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D_RECT, 6, 1, 4);
+
+ ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_1D, 1, 1, 4);
+ ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D, 2, 1, 4);
+ ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D_ARRAY, 3, 1, 4);
+ ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_3D, 4, 1, 4);
+ ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_CUBE, 5, 1, 4);
+ ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D_RECT, 6, 1, 4);
}
void uniformsByteSize()
@@ -2298,6 +2358,38 @@ private Q_SLOTS:
ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler);
ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE, UniformType::Sampler);
ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_1D, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_2D, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_3D, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_RECT, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_CUBE, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_BUFFER, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_1D_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_CUBE_MAP_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_MULTISAMPLE, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_1D, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D, UniformType::Image); ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_3D, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_RECT, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_CUBE, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_BUFFER, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_1D_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_CUBE_MAP_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_MULTISAMPLE, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_1D, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_3D, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_RECT, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_CUBE, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_BUFFER, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_1D_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, UniformType::Image);
+ ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image);
}
void uniformTypeFromGLType()
@@ -2448,6 +2540,22 @@ private Q_SLOTS:
QCOMPARE(m_func->glIsSync(sync), GL_FALSE);
}
+ void rasterMode()
+ {
+ if (!m_initializationSuccessful)
+ QSKIP("Initialization failed, OpenGL 4.3 functions not supported");
+
+ m_func->glGetError();
+ m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ // THEN
+ const GLint error = m_func->glGetError();
+ QVERIFY(error == 0);
+ GLint p;
+ m_func->glGetIntegerv(GL_POLYGON_MODE, &p);
+ QCOMPARE(p, GL_LINE);
+ }
+
private:
QScopedPointer<QWindow> m_window;
QOpenGLContext m_glContext;
diff --git a/tests/auto/render/joint/tst_joint.cpp b/tests/auto/render/joint/tst_joint.cpp
index 13aa915d2..0388f4a80 100644
--- a/tests/auto/render/joint/tst_joint.cpp
+++ b/tests/auto/render/joint/tst_joint.cpp
@@ -32,10 +32,6 @@
#include <Qt3DCore/qjoint.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <QtGui/qmatrix4x4.h>
#include <QtGui/qvector3d.h>
#include <qbackendnodetester.h>
@@ -60,6 +56,7 @@ private Q_SLOTS:
Joint backendJoint;
backendJoint.setRenderer(&renderer);
backendJoint.setJointManager(nodeManagers.jointManager());
+ backendJoint.setSkeletonManager(nodeManagers.skeletonManager());
QJoint joint;
joint.setTranslation(QVector3D(1.0f, 2.0f, 3.0f));
@@ -77,7 +74,7 @@ private Q_SLOTS:
}
// WHEN
- simulateInitialization(&joint, &backendJoint);
+ simulateInitializationSync(&joint, &backendJoint);
// THEN
QCOMPARE(backendJoint.peerId(), joint.id());
@@ -100,6 +97,7 @@ private Q_SLOTS:
Joint backendJoint;
backendJoint.setRenderer(&renderer);
backendJoint.setJointManager(nodeManagers.jointManager());
+ backendJoint.setSkeletonManager(nodeManagers.skeletonManager());
// THEN
QVERIFY(backendJoint.peerId().isNull());
@@ -128,7 +126,7 @@ private Q_SLOTS:
}
// WHEN
- simulateInitialization(&joint, &backendJoint);
+ simulateInitializationSync(&joint, &backendJoint);
backendJoint.cleanup();
// THEN
@@ -151,43 +149,36 @@ private Q_SLOTS:
backendJoint.setRenderer(&renderer);
backendJoint.setJointManager(nodeManagers.jointManager());
backendJoint.setSkeletonManager(nodeManagers.skeletonManager());
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
+ QJoint joint;
+ simulateInitializationSync(&joint, &backendJoint);
// WHEN
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendJoint.sceneChangeEvent(updateChange);
+ joint.setEnabled(false);
+ backendJoint.syncFromFrontEnd(&joint, false);
// THEN
- QCOMPARE(backendJoint.isEnabled(), true);
+ QCOMPARE(backendJoint.isEnabled(), false);
// WHEN
const QVector3D newTranslation = QVector3D(1.0f, 2.0f, 3.0f);
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("translation");
- updateChange->setValue(newTranslation);
- backendJoint.sceneChangeEvent(updateChange);
+ joint.setTranslation(newTranslation);
+ backendJoint.syncFromFrontEnd(&joint, false);
// THEN
QCOMPARE(backendJoint.translation(), newTranslation);
// WHEN
const QQuaternion newRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f);
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("rotation");
- updateChange->setValue(newRotation);
- backendJoint.sceneChangeEvent(updateChange);
+ joint.setRotation(newRotation);
+ backendJoint.syncFromFrontEnd(&joint, false);
// THEN
QCOMPARE(backendJoint.rotation(), newRotation);
// WHEN
const QVector3D newScale = QVector3D(1.5f, 2.5f, 3.5f);
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("scale");
- updateChange->setValue(newScale);
- backendJoint.sceneChangeEvent(updateChange);
+ joint.setScale(newScale);
+ backendJoint.syncFromFrontEnd(&joint, false);
// THEN
QCOMPARE(backendJoint.scale(), newScale);
@@ -195,44 +186,115 @@ private Q_SLOTS:
// WHEN
QMatrix4x4 newInverseBind;
newInverseBind.scale(5.4f);
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("inverseBindMatrix");
- updateChange->setValue(newInverseBind);
- backendJoint.sceneChangeEvent(updateChange);
+ joint.setInverseBindMatrix(newInverseBind);
+ backendJoint.syncFromFrontEnd(&joint, false);
// THEN
QCOMPARE(backendJoint.inverseBindMatrix(), newInverseBind);
// WHEN
QVector<QJoint *> childJoints;
- QPropertyNodeAddedChangePtr nodeAddedChange;
for (int i = 0; i < 10; ++i) {
const auto childJoint = new QJoint();
childJoints.push_back(childJoint);
+ joint.addChildJoint(childJoint);
+ }
+ backendJoint.syncFromFrontEnd(&joint, false);
+
+ // THEN
+ for (int i = 0; i < childJoints.size(); ++i)
+ QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id());
- nodeAddedChange.reset(new QPropertyNodeAddedChange(QNodeId(), childJoint));
- nodeAddedChange->setPropertyName("childJoint");
- backendJoint.sceneChangeEvent(nodeAddedChange);
+ for (int i = 0; i < 10; ++i) {
+ // WHEN
+ const auto childJoint = childJoints.takeLast();
+ joint.removeChildJoint(childJoint);
+ backendJoint.syncFromFrontEnd(&joint, false);
+
+ // THEN
+ for (int i = 0; i < childJoints.size(); ++i)
+ QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id());
}
+ }
+
+ void checkDirectPropertyChanges()
+ {
+ // GIVEN
+ TestRenderer renderer;
+ NodeManagers nodeManagers;
+ renderer.setNodeManagers(&nodeManagers);
+ Joint backendJoint;
+ backendJoint.setRenderer(&renderer);
+ backendJoint.setJointManager(nodeManagers.jointManager());
+ backendJoint.setSkeletonManager(nodeManagers.skeletonManager());
+
+ QJoint joint;
+ simulateInitializationSync(&joint, &backendJoint);
+
+ // WHEN
+ joint.setEnabled(false);
+ backendJoint.syncFromFrontEnd(&joint, false);
+
+ // THEN
+ QCOMPARE(backendJoint.isEnabled(), false);
+
+ // WHEN
+ const QVector3D newTranslation = QVector3D(1.0f, 2.0f, 3.0f);
+ joint.setTranslation(newTranslation);
+ backendJoint.syncFromFrontEnd(&joint, false);
+
+ // THEN
+ QCOMPARE(backendJoint.translation(), newTranslation);
+
+ // WHEN
+ const QQuaternion newRotation = QQuaternion::fromAxisAndAngle(1.0f, 0.0f, 0.0f, 45.0f);
+ joint.setRotation(newRotation);
+ backendJoint.syncFromFrontEnd(&joint, false);
+
+ // THEN
+ QCOMPARE(backendJoint.rotation(), newRotation);
+
+ // WHEN
+ const QVector3D newScale = QVector3D(1.5f, 2.5f, 3.5f);
+ joint.setScale(newScale);
+ backendJoint.syncFromFrontEnd(&joint, false);
+
+ // THEN
+ QCOMPARE(backendJoint.scale(), newScale);
+
+ // WHEN
+ QMatrix4x4 newInverseBind;
+ newInverseBind.scale(5.4f);
+ joint.setInverseBindMatrix(newInverseBind);
+ backendJoint.syncFromFrontEnd(&joint, false);
+
+ // THEN
+ QCOMPARE(backendJoint.inverseBindMatrix(), newInverseBind);
+
+ // WHEN
+ QVector<QJoint *> childJoints;
+ for (int i = 0; i < 10; ++i) {
+ const auto childJoint = new QJoint();
+ joint.addChildJoint(childJoint);
+ childJoints.push_back(childJoint);
+ }
+ backendJoint.syncFromFrontEnd(&joint, false);
// THEN
for (int i = 0; i < childJoints.size(); ++i) {
QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id());
}
- QPropertyNodeRemovedChangePtr nodeRemovedChange;
for (int i = 0; i < 10; ++i) {
// WHEN
const auto childJoint = childJoints.takeLast();
- nodeRemovedChange.reset(new QPropertyNodeRemovedChange(QNodeId(), childJoint));
- nodeRemovedChange->setPropertyName("childJoint");
- backendJoint.sceneChangeEvent(nodeAddedChange);
+ joint.removeChildJoint(childJoint);
+ backendJoint.syncFromFrontEnd(&joint, false);
// THEN
- for (int i = 0; i < childJoints.size(); ++i) {
- QCOMPARE(backendJoint.childJointIds()[i], childJoints[i]->id());
- }
+ for (int j = 0; j < childJoints.size(); ++j)
+ QCOMPARE(backendJoint.childJointIds()[j], childJoints[j]->id());
}
}
};
diff --git a/tests/auto/render/ktxtextures/data/16_16.png b/tests/auto/render/ktxtextures/data/16_16.png
new file mode 100644
index 000000000..aefb48dc4
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16.png
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_7.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_7.KTX
new file mode 100644
index 000000000..953f300ad
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_7.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_8.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_8.KTX
new file mode 100644
index 000000000..4c23241e4
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ASTC_8.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGBA_11.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGBA_11.KTX
new file mode 100644
index 000000000..01646e99a
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGBA_11.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGB_13.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGB_13.KTX
new file mode 100644
index 000000000..2d2efff1b
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC2_RGB_13.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/data/16_16_PNG_ETC_RGB_12.KTX b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC_RGB_12.KTX
new file mode 100644
index 000000000..15e30abc8
--- /dev/null
+++ b/tests/auto/render/ktxtextures/data/16_16_PNG_ETC_RGB_12.KTX
Binary files differ
diff --git a/tests/auto/render/ktxtextures/ktxtextures.pro b/tests/auto/render/ktxtextures/ktxtextures.pro
new file mode 100644
index 000000000..beca06dc2
--- /dev/null
+++ b/tests/auto/render/ktxtextures/ktxtextures.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+
+TARGET = tst_ktxtextures
+
+CONFIG += testcase
+
+SOURCES += tst_ktxtextures.cpp
+
+TESTDATA = data/*
+
+QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib
diff --git a/tests/auto/render/ktxtextures/tst_ktxtextures.cpp b/tests/auto/render/ktxtextures/tst_ktxtextures.cpp
new file mode 100644
index 000000000..57ccd3652
--- /dev/null
+++ b/tests/auto/render/ktxtextures/tst_ktxtextures.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <Qt3DRender/qtextureimagedata.h>
+#include <Qt3DRender/private/qtexture_p.h>
+
+class tst_KtxTextures : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void ktxImageData();
+};
+
+void tst_KtxTextures::ktxImageData()
+{
+ const struct TextureInfo {
+ const char *source;
+ int width;
+ int height;
+ int depth;
+ int faces;
+ int mipmapLevels;
+ QOpenGLTexture::TextureFormat format;
+ } textures[] = {
+ { "data/16_16_PNG_ASTC_7.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGBA_ASTC_4x4 },
+ { "data/16_16_PNG_ASTC_8.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGBA_ASTC_4x4 },
+ { "data/16_16_PNG_ETC2_RGB_13.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGB8_ETC2 },
+ { "data/16_16_PNG_ETC2_RGBA_11.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGBA8_ETC2_EAC },
+ { "data/16_16_PNG_ETC_RGB_12.KTX", 16, 16, 1, 1, 1, QOpenGLTexture::RGB8_ETC1 },
+ };
+
+ for (unsigned i = 0; i < sizeof(textures)/sizeof(*textures); i++) {
+ const TextureInfo *texture = &textures[i];
+
+ Qt3DRender::QTextureImageDataPtr data = Qt3DRender::TextureLoadingHelper::loadTextureData(QUrl::fromLocalFile(QFINDTESTDATA(texture->source)), true, false);
+
+ QVERIFY(data);
+ QCOMPARE(data->width(), texture->width);
+ QCOMPARE(data->height(), texture->height);
+ QCOMPARE(data->faces(), texture->faces);
+ QCOMPARE(data->mipLevels(), texture->mipmapLevels);
+ QCOMPARE(data->format(), texture->format);
+ }
+}
+
+QTEST_APPLESS_MAIN(tst_KtxTextures)
+
+#include "tst_ktxtextures.moc"
diff --git a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp
index 8c72829e0..255ff5ea8 100644
--- a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp
+++ b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp
@@ -33,7 +33,6 @@
#include <Qt3DRender/private/entity_p.h>
#include <Qt3DRender/private/filterlayerentityjob_p.h>
#include <Qt3DRender/private/updatetreeenabledjob_p.h>
-#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
#include <Qt3DRender/qlayer.h>
#include <Qt3DRender/qlayerfilter.h>
#include "testaspect.h"
@@ -634,10 +633,6 @@ private Q_SLOTS:
// WHEN
Qt3DRender::Render::Entity *backendRoot = aspect->nodeManagers()->renderNodesManager()->getOrCreateResource(entitySubtree->id());
- Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob;
- updateEntitiesJob.setManager(aspect->nodeManagers());
- updateEntitiesJob.run();
-
Qt3DRender::Render::UpdateTreeEnabledJob updateTreeEnabledJob;
updateTreeEnabledJob.setRoot(backendRoot);
updateTreeEnabledJob.setManagers(aspect->nodeManagers());
diff --git a/tests/auto/render/levelofdetail/tst_levelofdetail.cpp b/tests/auto/render/levelofdetail/tst_levelofdetail.cpp
index 148c54e58..5005ca2d1 100644
--- a/tests/auto/render/levelofdetail/tst_levelofdetail.cpp
+++ b/tests/auto/render/levelofdetail/tst_levelofdetail.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/QLevelOfDetailBoundingSphere>
#include <Qt3DRender/private/levelofdetail_p.h>
#include <Qt3DRender/private/qlevelofdetail_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include "testpostmanarbiter.h"
#include "testrenderer.h"
@@ -45,11 +44,13 @@ private Q_SLOTS:
void checkPeerPropertyMirroring()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::LevelOfDetail renderLod;
Qt3DRender::QLevelOfDetail lod;
// WHEN
- simulateInitialization(&lod, &renderLod);
+ renderLod.setRenderer(&renderer);
+ simulateInitializationSync(&lod, &renderLod);
// THEN
QCOMPARE(renderLod.peerId(), lod.id());
@@ -82,7 +83,7 @@ private Q_SLOTS:
// WHEN
renderLod.setRenderer(&renderer);
- simulateInitialization(&lod, &renderLod);
+ simulateInitializationSync(&lod, &renderLod);
// THEN
QCOMPARE(renderLod.thresholdType(), lod.thresholdType());
@@ -92,8 +93,10 @@ private Q_SLOTS:
{
// GIVEN
TestRenderer renderer;
+ Qt3DRender::QLevelOfDetail lod;
Qt3DRender::Render::LevelOfDetail renderLod;
renderLod.setRenderer(&renderer);
+ simulateInitializationSync(&lod, &renderLod);
// THEN
QVERIFY(renderLod.thresholdType() != Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold);
@@ -101,38 +104,30 @@ private Q_SLOTS:
{
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(static_cast<int>(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold));
- updateChange->setPropertyName("thresholdType");
- renderLod.sceneChangeEvent(updateChange);
+ lod.setThresholdType(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold);
+ renderLod.syncFromFrontEnd(&lod, false);
// THEN
QCOMPARE(renderLod.thresholdType(), Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold);
- QVERIFY(renderer.dirtyBits() != 0);
- }
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::GeometryDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); }
{
- QVector<qreal> thresholds = {20.f, 30.f, 40.f};
- QVariant v;
- v.setValue<decltype(thresholds)>(thresholds);
+ const QVector<qreal> thresholds = {20.f, 30.f, 40.f};
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(v);
- updateChange->setPropertyName("thresholds");
- renderLod.sceneChangeEvent(updateChange);
-
+ lod.setThresholds(thresholds);
+ renderLod.syncFromFrontEnd(&lod, false);
// THEN
QCOMPARE(renderLod.thresholds(), thresholds);
}
{
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- Qt3DRender::QLevelOfDetailBoundingSphere sphere(QVector3D(1.0f, 2.0f, 3.0f), 1.0f);
- updateChange->setValue(QVariant::fromValue(sphere));
- updateChange->setPropertyName("volumeOverride");
- renderLod.sceneChangeEvent(updateChange);
+ const Qt3DRender::QLevelOfDetailBoundingSphere sphere(QVector3D(1.0f, 2.0f, 3.0f), 1.0f);
+ // WHEN
+ lod.setVolumeOverride(sphere);
+ renderLod.syncFromFrontEnd(&lod, false);
// THEN
QCOMPARE(renderLod.center(), QVector3D(1., 2., 3.));
diff --git a/tests/auto/render/loadscenejob/tst_loadscenejob.cpp b/tests/auto/render/loadscenejob/tst_loadscenejob.cpp
index 66c9271f7..044c3e0f4 100644
--- a/tests/auto/render/loadscenejob/tst_loadscenejob.cpp
+++ b/tests/auto/render/loadscenejob/tst_loadscenejob.cpp
@@ -148,27 +148,9 @@ private Q_SLOTS:
loadSceneJob.run();
// THEN
- QCOMPARE(arbiter.events.count(), 4);
- auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::None);
-
- change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Loading);
-
- change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "scene");
- QVERIFY(change->value().value<Qt3DCore::QEntity *>() != nullptr);
- delete change->value().value<Qt3DCore::QEntity *>();
-
- change = arbiter.events.at(3).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Ready);
+ Qt3DRender::Render::LoadSceneJobPrivate *dJob = static_cast<decltype(dJob)>(Qt3DCore::QAspectJobPrivate::get(&loadSceneJob));
+ QCOMPARE(dJob->m_status, Qt3DRender::QSceneLoader::Ready);
+ QVERIFY(dJob->m_sceneSubtree != nullptr);
}
void checkEmptySource()
@@ -192,21 +174,9 @@ private Q_SLOTS:
loadSceneJob.run();
// THEN
- QCOMPARE(arbiter.events.count(), 3);
- auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::None);
-
- change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "scene");
- QVERIFY(change->value().value<Qt3DCore::QEntity *>() == nullptr);
-
- change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::None);
+ Qt3DRender::Render::LoadSceneJobPrivate *dJob = static_cast<decltype(dJob)>(Qt3DCore::QAspectJobPrivate::get(&loadSceneJob));
+ QCOMPARE(dJob->m_status, Qt3DRender::QSceneLoader::None);
+ QVERIFY(dJob->m_sceneSubtree == nullptr);
}
void checkRunValidSourceUnsupportedFormat()
@@ -233,21 +203,9 @@ private Q_SLOTS:
loadSceneJob.run();
// THEN
- QCOMPARE(arbiter.events.count(), 3);
- auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::None);
-
- change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "scene");
- QVERIFY(change->value().value<Qt3DCore::QEntity *>() == nullptr);
-
- change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Error);
+ Qt3DRender::Render::LoadSceneJobPrivate *dJob = static_cast<decltype(dJob)>(Qt3DCore::QAspectJobPrivate::get(&loadSceneJob));
+ QCOMPARE(dJob->m_status, Qt3DRender::QSceneLoader::Error);
+ QVERIFY(dJob->m_sceneSubtree == nullptr);
}
void checkRunErrorAtLoading()
@@ -271,22 +229,10 @@ private Q_SLOTS:
loadSceneJob.run();
// THEN
- QCOMPARE(arbiter.events.count(), 3);
- auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::None);
-
- change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "scene");
- QVERIFY(change->value().value<Qt3DCore::QEntity *>() == nullptr);
- delete change->value().value<Qt3DCore::QEntity *>();
-
- change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), scene->peerId());
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Error);
+ // THEN
+ Qt3DRender::Render::LoadSceneJobPrivate *dJob = static_cast<decltype(dJob)>(Qt3DCore::QAspectJobPrivate::get(&loadSceneJob));
+ QCOMPARE(dJob->m_status, Qt3DRender::QSceneLoader::Error);
+ QVERIFY(dJob->m_sceneSubtree == nullptr);
}
};
diff --git a/tests/auto/render/material/tst_material.cpp b/tests/auto/render/material/tst_material.cpp
index 7e288b02a..4e66f7e30 100644
--- a/tests/auto/render/material/tst_material.cpp
+++ b/tests/auto/render/material/tst_material.cpp
@@ -33,9 +33,6 @@
#include <Qt3DRender/QMaterial>
#include <Qt3DRender/QParameter>
#include <Qt3DRender/QEffect>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
#include "testrenderer.h"
using namespace Qt3DCore;
@@ -45,6 +42,7 @@ using namespace Qt3DRender::Render;
class tst_RenderMaterial : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
+
public:
tst_RenderMaterial() {}
@@ -112,18 +110,22 @@ void tst_RenderMaterial::shouldHavePropertiesMirroringFromItsPeer()
{
// WHEN
QFETCH(QMaterial *, frontendMaterial);
+ TestRenderer renderer;
Material backend;
// GIVEN
- simulateInitialization(frontendMaterial, &backend);
+ backend.setRenderer(&renderer);
+ simulateInitializationSync(frontendMaterial, &backend);
// THEN
QVERIFY(backend.isEnabled() == frontendMaterial->isEnabled());
QCOMPARE(backend.effect(), frontendMaterial->effect() ? frontendMaterial->effect()->id() : QNodeId());
QCOMPARE(backend.parameters().count(), frontendMaterial->parameters().count());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::MaterialDirty);
int c = 0;
- Q_FOREACH (QParameter *p, frontendMaterial->parameters())
+ const auto frontendMaterialParameters = frontendMaterial->parameters();
+ for (QParameter *p : frontendMaterialParameters)
QCOMPARE(p->id(), backend.parameters().at(c++));
delete frontendMaterial;
@@ -132,15 +134,17 @@ void tst_RenderMaterial::shouldHavePropertiesMirroringFromItsPeer()
void tst_RenderMaterial::shouldHandleParametersPropertyChange()
{
// GIVEN
- QScopedPointer<QParameter> parameter(new QParameter());
+ QParameter *parameter = new QParameter();
Material backend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ QMaterial material;
+ simulateInitializationSync(&material, &backend);
+
// WHEN
- const auto addChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), parameter.data());
- addChange->setPropertyName("parameter");
- backend.sceneChangeEvent(addChange);
+ material.addParameter(parameter);
+ backend.syncFromFrontEnd(&material, false);
// THEN
QCOMPARE(backend.parameters().count(), 1);
@@ -148,9 +152,8 @@ void tst_RenderMaterial::shouldHandleParametersPropertyChange()
QVERIFY(renderer.dirtyBits() != 0);
// WHEN
- const auto removeChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), parameter.data());
- removeChange->setPropertyName("parameter");
- backend.sceneChangeEvent(removeChange);
+ material.removeParameter(parameter);
+ backend.syncFromFrontEnd(&material, false);
// THEN
QVERIFY(backend.parameters().isEmpty());
@@ -163,24 +166,23 @@ void tst_RenderMaterial::shouldHandleEnablePropertyChange()
TestRenderer renderer;
backend.setRenderer(&renderer);
+ QMaterial material;
+ simulateInitializationSync(&material, &backend);
+
// WHEN
- auto updateChange = QPropertyUpdatedChangePtr::create(QNodeId());
- updateChange->setValue(true);
- updateChange->setPropertyName("enabled");
- backend.sceneChangeEvent(updateChange);
+ material.setEnabled(false);
+ backend.syncFromFrontEnd(&material, false);
// THEN
- QVERIFY(backend.isEnabled());
+ QVERIFY(!backend.isEnabled());
QVERIFY(renderer.dirtyBits() != 0);
// WHEN
- auto secondUpdateChange = QPropertyUpdatedChangePtr::create(QNodeId());
- secondUpdateChange->setValue(false);
- secondUpdateChange->setPropertyName("enabled");
- backend.sceneChangeEvent(secondUpdateChange);
+ material.setEnabled(true);
+ backend.syncFromFrontEnd(&material, false);
// THEN
- QVERIFY(!backend.isEnabled());
+ QVERIFY(backend.isEnabled());
}
@@ -191,15 +193,16 @@ void tst_RenderMaterial::shouldHandleEffectPropertyChange()
TestRenderer renderer;
backend.setRenderer(&renderer);
+ QMaterial material;
+ simulateInitializationSync(&material, &backend);
+
// WHEN
- QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- Qt3DCore::QNodeId effectId = Qt3DCore::QNodeId::createId();
- updateChange->setValue(QVariant::fromValue(effectId));
- updateChange->setPropertyName("effect");
- backend.sceneChangeEvent(updateChange);
+ QEffect effect;
+ material.setEffect(&effect);
+ backend.syncFromFrontEnd(&material, false);
// THEN
- QCOMPARE(backend.effect(), effectId);
+ QCOMPARE(backend.effect(), effect.id());
QVERIFY(renderer.dirtyBits() != 0);
}
diff --git a/tests/auto/render/materialparametergathererjob/tst_materialparametergathererjob.cpp b/tests/auto/render/materialparametergathererjob/tst_materialparametergathererjob.cpp
index 902a511d8..236faa8f0 100644
--- a/tests/auto/render/materialparametergathererjob/tst_materialparametergathererjob.cpp
+++ b/tests/auto/render/materialparametergathererjob/tst_materialparametergathererjob.cpp
@@ -29,8 +29,9 @@
#include <QtTest/QTest>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
@@ -65,14 +66,25 @@ public:
Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data();
QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- for (const Qt3DCore::QNodeCreatedChangeBasePtr change : creationChanges)
- d_func()->createBackendNode(change);
+ QVector<Qt3DCore::QNode *> nodes;
+ Qt3DCore::QNodeVisitor v;
+ v.traverse(root, [&nodes](Qt3DCore::QNode *node) {
+ Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject()));
+ d->m_hasBackendNode = true;
+ nodes << node;
+ });
+
+ for (const auto node: nodes)
+ d_func()->createBackendNode({
+ node->id(),
+ Qt3DCore::QNodePrivate::get(node)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ node
+ });
const auto handles = nodeManagers()->techniqueManager()->activeHandles();
- for (const auto handle: handles) {
+ for (const auto &handle: handles) {
Render::Technique *technique = nodeManagers()->techniqueManager()->data(handle);
technique->setCompatibleWithRenderer(true);
}
diff --git a/tests/auto/render/memorybarrier/tst_memorybarrier.cpp b/tests/auto/render/memorybarrier/tst_memorybarrier.cpp
index 33a1247fa..0b1c581e4 100644
--- a/tests/auto/render/memorybarrier/tst_memorybarrier.cpp
+++ b/tests/auto/render/memorybarrier/tst_memorybarrier.cpp
@@ -31,7 +31,6 @@
#include <Qt3DRender/qmemorybarrier.h>
#include <Qt3DRender/private/qmemorybarrier_p.h>
#include <Qt3DRender/private/memorybarrier_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
@@ -56,28 +55,34 @@ private Q_SLOTS:
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QMemoryBarrier memoryBarrier;
memoryBarrier.setWaitOperations(Qt3DRender::QMemoryBarrier::VertexAttributeArray);
{
// WHEN
Qt3DRender::Render::MemoryBarrier backendMemoryBarrier;
- simulateInitialization(&memoryBarrier, &backendMemoryBarrier);
+ backendMemoryBarrier.setRenderer(&renderer);
+ simulateInitializationSync(&memoryBarrier, &backendMemoryBarrier);
// THEN
QCOMPARE(backendMemoryBarrier.isEnabled(), true);
QCOMPARE(backendMemoryBarrier.peerId(), memoryBarrier.id());
QCOMPARE(backendMemoryBarrier.waitOperations(), Qt3DRender::QMemoryBarrier::VertexAttributeArray);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
Qt3DRender::Render::MemoryBarrier backendMemoryBarrier;
+ backendMemoryBarrier.setRenderer(&renderer);
memoryBarrier.setEnabled(false);
- simulateInitialization(&memoryBarrier, &backendMemoryBarrier);
+ simulateInitializationSync(&memoryBarrier, &backendMemoryBarrier);
// THEN
QCOMPARE(backendMemoryBarrier.peerId(), memoryBarrier.id());
QCOMPARE(backendMemoryBarrier.isEnabled(), false);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
}
@@ -87,14 +92,15 @@ private Q_SLOTS:
Qt3DRender::Render::MemoryBarrier backendMemoryBarrier;
TestRenderer renderer;
backendMemoryBarrier.setRenderer(&renderer);
+ Qt3DRender::QMemoryBarrier memoryBarrier;
+
+ simulateInitializationSync(&memoryBarrier, &backendMemoryBarrier);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendMemoryBarrier.sceneChangeEvent(change);
+ memoryBarrier.setEnabled(newValue);
+ backendMemoryBarrier.syncFromFrontEnd(&memoryBarrier, false);
// THEN
QCOMPARE(backendMemoryBarrier.isEnabled(), newValue);
@@ -104,10 +110,8 @@ private Q_SLOTS:
{
// WHEN
const Qt3DRender::QMemoryBarrier::Operations newValue(Qt3DRender::QMemoryBarrier::AtomicCounter|Qt3DRender::QMemoryBarrier::ElementArray);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("waitOperations");
- change->setValue(QVariant::fromValue(newValue));
- backendMemoryBarrier.sceneChangeEvent(change);
+ memoryBarrier.setWaitOperations(newValue);
+ backendMemoryBarrier.syncFromFrontEnd(&memoryBarrier, false);
// THEN
QCOMPARE(backendMemoryBarrier.waitOperations(), newValue);
diff --git a/tests/auto/render/objectpicker/tst_objectpicker.cpp b/tests/auto/render/objectpicker/tst_objectpicker.cpp
index 644849102..24fa2159d 100644
--- a/tests/auto/render/objectpicker/tst_objectpicker.cpp
+++ b/tests/auto/render/objectpicker/tst_objectpicker.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/qpickevent.h>
#include <Qt3DRender/qobjectpicker.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "testpostmanarbiter.h"
#include "testrenderer.h"
@@ -44,13 +43,15 @@ private Q_SLOTS:
void checkPeerPropertyMirroring()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::ObjectPicker objectPicker;
Qt3DRender::QObjectPicker picker;
picker.setHoverEnabled(true);
picker.setPriority(883);
// WHEN
- simulateInitialization(&picker, &objectPicker);
+ objectPicker.setRenderer(&renderer);
+ simulateInitializationSync(&picker, &objectPicker);
// THEN
QVERIFY(!objectPicker.peerId().isNull());
@@ -61,6 +62,7 @@ private Q_SLOTS:
void checkInitialAndCleanedUpState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::ObjectPicker objectPicker;
// THEN
@@ -76,7 +78,8 @@ private Q_SLOTS:
picker.setPriority(1584);
// WHEN
- simulateInitialization(&picker, &objectPicker);
+ objectPicker.setRenderer(&renderer);
+ simulateInitializationSync(&picker, &objectPicker);
objectPicker.cleanup();
// THEN
@@ -90,107 +93,49 @@ private Q_SLOTS:
// GIVEN
TestRenderer renderer;
{
+ Qt3DRender::QObjectPicker picker;
Qt3DRender::Render::ObjectPicker objectPicker;
objectPicker.setRenderer(&renderer);
+ simulateInitializationSync(&picker, &objectPicker);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(true);
- updateChange->setPropertyName("hoverEnabled");
- objectPicker.sceneChangeEvent(updateChange);
+ picker.setHoverEnabled(true);
+ objectPicker.syncFromFrontEnd(&picker, false);
// THEN
QCOMPARE(objectPicker.isHoverEnabled(), true);
QVERIFY(renderer.dirtyBits() != 0);
}
{
+ Qt3DRender::QObjectPicker picker;
Qt3DRender::Render::ObjectPicker objectPicker;
objectPicker.setRenderer(&renderer);
+ simulateInitializationSync(&picker, &objectPicker);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(true);
- updateChange->setPropertyName("dragEnabled");
- objectPicker.sceneChangeEvent(updateChange);
+ picker.setDragEnabled(true);
+ objectPicker.syncFromFrontEnd(&picker, false);
+
// THEN
QCOMPARE(objectPicker.isDragEnabled(), true);
QVERIFY(renderer.dirtyBits() != 0);
}
{
+ Qt3DRender::QObjectPicker picker;
Qt3DRender::Render::ObjectPicker objectPicker;
objectPicker.setRenderer(&renderer);
+ simulateInitializationSync(&picker, &objectPicker);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(15);
- updateChange->setPropertyName("priority");
- objectPicker.sceneChangeEvent(updateChange);
+ picker.setPriority(15);
+ objectPicker.syncFromFrontEnd(&picker, false);
// THEN
QCOMPARE(objectPicker.priority(), 15);
QVERIFY(renderer.dirtyBits() != 0);
}
}
-
- void checkBackendPropertyNotifications()
- {
- // GIVEN
- TestArbiter arbiter;
- Qt3DRender::Render::ObjectPicker objectPicker;
- Qt3DCore::QBackendNodePrivate::get(&objectPicker)->setArbiter(&arbiter);
- Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent);
-
- // WHEN
- objectPicker.onPressed(event);
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
-
- arbiter.events.clear();
-
- // WHEN
- objectPicker.onReleased(event);
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
-
- arbiter.events.clear();
-
- // WHEN
- objectPicker.onClicked(event);
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "clicked");
-
- arbiter.events.clear();
-
- // WHEN
- objectPicker.onEntered();
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "entered");
-
- arbiter.events.clear();
-
- // WHEN
- objectPicker.onExited();
-
- // THEN
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "exited");
-
- arbiter.events.clear();
- }
};
diff --git a/tests/auto/render/parameter/tst_parameter.cpp b/tests/auto/render/parameter/tst_parameter.cpp
index 0043adc86..625256fc4 100644
--- a/tests/auto/render/parameter/tst_parameter.cpp
+++ b/tests/auto/render/parameter/tst_parameter.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/parameter_p.h>
#include <Qt3DRender/private/uniform_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
@@ -53,18 +52,21 @@ private Q_SLOTS:
QCOMPARE(backendParameter.name(), QString());
QCOMPARE(backendParameter.uniformValue(), Qt3DRender::Render::UniformValue());
QCOMPARE(backendParameter.nameId(), -1);
+ QCOMPARE(backendParameter.backendValue(), QVariant());
}
void checkCleanupState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::Parameter backendParameter;
Qt3DRender::QParameter parameter;
parameter.setName(QStringLiteral("Cutlass"));
parameter.setValue(QVariant(QColor(Qt::blue)));
// WHEN
- simulateInitialization(&parameter, &backendParameter);
+ backendParameter.setRenderer(&renderer);
+ simulateInitializationSync(&parameter, &backendParameter);
backendParameter.cleanup();
// THEN
@@ -72,11 +74,13 @@ private Q_SLOTS:
QCOMPARE(backendParameter.name(), QString());
QCOMPARE(backendParameter.uniformValue(), Qt3DRender::Render::UniformValue());
QCOMPARE(backendParameter.nameId(), -1);
+ QCOMPARE(backendParameter.backendValue(), QVariant());
}
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QParameter parameter;
parameter.setName(QStringLiteral("Chevelle"));
@@ -85,7 +89,8 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::Parameter backendParameter;
- simulateInitialization(&parameter, &backendParameter);
+ backendParameter.setRenderer(&renderer);
+ simulateInitializationSync(&parameter, &backendParameter);
// THEN
QCOMPARE(backendParameter.isEnabled(), true);
@@ -93,16 +98,20 @@ private Q_SLOTS:
QCOMPARE(backendParameter.name(), QStringLiteral("Chevelle"));
QCOMPARE(backendParameter.uniformValue(), Qt3DRender::Render::UniformValue::fromVariant(parameter.value()));
QCOMPARE(backendParameter.nameId(), Qt3DRender::Render::StringToInt::lookupId(QStringLiteral("Chevelle")));
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::ParameterDirty);
}
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
Qt3DRender::Render::Parameter backendParameter;
+ backendParameter.setRenderer(&renderer);
parameter.setEnabled(false);
- simulateInitialization(&parameter, &backendParameter);
+ simulateInitializationSync(&parameter, &backendParameter);
// THEN
QCOMPARE(backendParameter.peerId(), parameter.id());
QCOMPARE(backendParameter.isEnabled(), false);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::ParameterDirty);
}
}
@@ -113,40 +122,44 @@ private Q_SLOTS:
TestRenderer renderer;
backendParameter.setRenderer(&renderer);
+ Qt3DRender::QParameter parameter;
+ simulateInitializationSync(&parameter, &backendParameter);
+
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendParameter.sceneChangeEvent(change);
+ parameter.setEnabled(newValue);
+ backendParameter.syncFromFrontEnd(&parameter, false);
// THEN
QCOMPARE(backendParameter.isEnabled(), newValue);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::ParameterDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
{
// WHEN
const QString newValue = QStringLiteral("C7");
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("name");
- change->setValue(QVariant::fromValue(newValue));
- backendParameter.sceneChangeEvent(change);
+ parameter.setName(newValue);
+ backendParameter.syncFromFrontEnd(&parameter, false);
// THEN
QCOMPARE(backendParameter.name(), newValue);
QCOMPARE(backendParameter.nameId(), Qt3DRender::Render::StringToInt::lookupId(newValue));
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::ParameterDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
{
// WHEN
const QVariant value = QVariant::fromValue(QVector3D(350.0f, 427.0f, 454.0f));
const Qt3DRender::Render::UniformValue newValue = Qt3DRender::Render::UniformValue::fromVariant(value);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("value");
- change->setValue(value);
- backendParameter.sceneChangeEvent(change);
+ parameter.setValue(value);
+ backendParameter.syncFromFrontEnd(&parameter, false);
// THEN
QCOMPARE(backendParameter.uniformValue(), newValue);
+ QCOMPARE(backendParameter.backendValue(), value);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::ParameterDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
}
diff --git a/tests/auto/render/pickboundingvolumejob/pickboundingvolumejob.qrc b/tests/auto/render/pickboundingvolumejob/pickboundingvolumejob.qrc
index e1506de86..76150da31 100644
--- a/tests/auto/render/pickboundingvolumejob/pickboundingvolumejob.qrc
+++ b/tests/auto/render/pickboundingvolumejob/pickboundingvolumejob.qrc
@@ -11,5 +11,6 @@
<file>testscene_viewports.qml</file>
<file>testscene_cameraposition.qml</file>
<file>testscene_priorityoverlapping.qml</file>
+ <file>testscene_nopicking.qml</file>
</qresource>
</RCC>
diff --git a/tests/auto/render/pickboundingvolumejob/testscene_nopicking.qml b/tests/auto/render/pickboundingvolumejob/testscene_nopicking.qml
new file mode 100644
index 000000000..86471f8b2
--- /dev/null
+++ b/tests/auto/render/pickboundingvolumejob/testscene_nopicking.qml
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.0
+import Qt3D.Render 2.14
+import Qt3D.Extras 2.0
+import QtQuick.Window 2.0
+
+Entity {
+ id: sceneRoot
+
+ Window {
+ id: win
+ width: 600
+ height: 600
+ visible: true
+ }
+
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 0.0, -40.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ components: [
+ RenderSettings {
+ Viewport {
+ normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
+
+ RenderSurfaceSelector {
+
+ surface: win
+
+ ClearBuffers {
+ buffers : ClearBuffers.ColorDepthBuffer
+ NoDraw {}
+ }
+
+ CameraSelector {
+ camera: camera
+ NoPicking {
+
+ }
+ }
+ }
+ }
+ }
+ ]
+
+ CuboidMesh { id: cubeMesh }
+ PhongMaterial { id: material }
+
+ // Entity 1
+ Entity {
+ property ObjectPicker picker: ObjectPicker {
+ objectName: "Picker1"
+ dragEnabled: true
+ }
+
+ property Transform transform: Transform {
+ translation: Qt.vector3d(5, 0, 0)
+ scale: 2.0
+ }
+
+ components: [cubeMesh, material, picker, transform]
+ }
+
+ // Entity 2
+ Entity {
+ property ObjectPicker picker: ObjectPicker {
+ objectName: "Picker2"
+ dragEnabled: true
+ }
+
+ property Transform transform: Transform {
+ translation: Qt.vector3d(-5, 0, 0)
+ scale: 2.0
+ }
+
+ components: [cubeMesh, material, picker, transform]
+ }
+}
diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp
index d7903b8f7..5191b1a36 100644
--- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp
+++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp
@@ -32,12 +32,17 @@
#include <QtTest/QTest>
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <Qt3DCore/private/qaspectjob_p.h>
#include <QtQuick/qquickwindow.h>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QObjectPicker>
+#include <Qt3DRender/QNoPicking>
#include <Qt3DRender/QPickEvent>
#include <Qt3DRender/QPickTriangleEvent>
#include <Qt3DRender/private/nodemanagers_p.h>
@@ -47,7 +52,6 @@
#include <Qt3DRender/private/qrenderaspect_p.h>
#include <Qt3DRender/private/pickboundingvolumejob_p.h>
#include <Qt3DRender/private/pickboundingvolumeutils_p.h>
-#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
#include <Qt3DRender/private/updatemeshtrianglelistjob_p.h>
#include <Qt3DRender/private/updateworldboundingvolumejob_p.h>
#include <Qt3DRender/private/updateworldtransformjob_p.h>
@@ -57,6 +61,10 @@
#include <Qt3DRender/private/loadbufferjob_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
#include <Qt3DRender/private/geometryrenderermanager_p.h>
+#include <Qt3DRender/private/qobjectpicker_p.h>
+#include <Qt3DRender/private/nopicking_p.h>
+
+#include <QSignalSpy>
#include <private/qpickevent_p.h>
@@ -64,6 +72,47 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+QVector<Qt3DCore::QNode *> getNodesForCreation(Qt3DCore::QNode *root)
+{
+ using namespace Qt3DCore;
+
+ QVector<QNode *> nodes;
+ Qt3DCore::QNodeVisitor visitor;
+ visitor.traverse(root, [&nodes](QNode *node) {
+ nodes.append(node);
+
+ // Store the metaobject of the node in the QNode so that we have it available
+ // to us during destruction in the QNode destructor. This allows us to send
+ // the QNodeId and the metaobject as typeinfo to the backend aspects so they
+ // in turn can find the correct QBackendNodeMapper object to handle the destruction
+ // of the corresponding backend nodes.
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(QNodePrivate::findStaticMetaObject(node->metaObject()));
+
+ // Mark this node as having been handled for creation so that it is picked up
+ d->m_hasBackendNode = true;
+ });
+
+ return nodes;
+}
+
+QVector<Qt3DCore::NodeTreeChange> nodeTreeChangesForNodes(const QVector<Qt3DCore::QNode *> nodes)
+{
+ QVector<Qt3DCore::NodeTreeChange> nodeTreeChanges;
+ nodeTreeChanges.reserve(nodes.size());
+
+ for (Qt3DCore::QNode *n : nodes) {
+ nodeTreeChanges.push_back({
+ n->id(),
+ Qt3DCore::QNodePrivate::get(n)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ n
+ });
+ }
+
+ return nodeTreeChanges;
+}
+
class TestAspect : public Qt3DRender::QRenderAspect
{
public:
@@ -71,12 +120,18 @@ public:
: Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous)
, m_sceneRoot(nullptr)
{
- QRenderAspect::onRegistered();
-
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), creationChanges);
+ m_engine = new Qt3DCore::QAspectEngine(this);
+ m_engine->registerAspect(this);
+ Q_ASSERT(d_func()->m_aspectManager);
+
+ // do what QAspectEngine::setRootEntity does since we don't want to enter the simulation loop
+ Qt3DCore::QEntityPtr proot(qobject_cast<Qt3DCore::QEntity *>(root), [](Qt3DCore::QEntity *) { });
+ Qt3DCore::QAspectEnginePrivate *aed = Qt3DCore::QAspectEnginePrivate::get(m_engine);
+ aed->m_root = proot;
+ aed->initialize();
+ aed->initNodeTree(root);
+ const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root);
+ aed->m_aspectManager->setRootEntity(proot.data(), nodes);
Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
@@ -85,7 +140,17 @@ public:
~TestAspect()
{
- QRenderAspect::onUnregistered();
+ using namespace Qt3DCore;
+ QNodeVisitor visitor;
+ visitor.traverse(m_engine->rootEntity().data(), [](QNode *node) {
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_scene = nullptr;
+ d->m_changeArbiter = nullptr;
+ });
+
+ m_engine->unregisterAspect(this);
+ delete m_engine;
+ m_engine = nullptr;
}
void onRegistered() { QRenderAspect::onRegistered(); }
@@ -95,8 +160,10 @@ public:
Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const { return d_func()->m_renderer->frameGraphRoot(); }
Qt3DRender::Render::RenderSettings *renderSettings() const { return d_func()->m_renderer->settings(); }
Qt3DRender::Render::Entity *sceneRoot() const { return m_sceneRoot; }
-
+ Qt3DCore::QAspectManager *aspectManager() const { return d_func()->m_aspectManager; }
+ Qt3DCore::QChangeArbiter *arbiter() const { return d_func()->m_arbiter; }
private:
+ Qt3DCore::QAspectEngine *m_engine;
Render::Entity *m_sceneRoot;
};
@@ -108,10 +175,6 @@ namespace {
void runRequiredJobs(Qt3DRender::TestAspect *test)
{
- Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob;
- updateEntitiesJob.setManager(test->nodeManagers());
- updateEntitiesJob.run();
-
Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform;
updateWorldTransform.setRoot(test->sceneRoot());
updateWorldTransform.setManagers(test->nodeManagers());
@@ -248,7 +311,7 @@ private Q_SLOTS:
auto vca = results.first();
QCOMPARE(vca.area, QSize(600, 600));
QCOMPARE(vca.cameraId, camera->id());
- QCOMPARE(vca.viewport, QRectF(0.0f, 0.0f, 1.0f, 1.0f));
+ QCOMPARE(vca.viewport, QRectF(0., 0., 1., 1.));
}
void checkCurrentPickerChange_data()
@@ -307,7 +370,7 @@ private Q_SLOTS:
// WHEN
QList<QPair<QObject *,QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
@@ -320,7 +383,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207., 303.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -330,7 +393,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(390., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -343,7 +406,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(390.0f, 300.0f), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(390., 300.), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -403,7 +466,7 @@ private Q_SLOTS:
// WHEN
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 440.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 440.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -453,7 +516,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
@@ -510,7 +573,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
@@ -560,7 +623,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
@@ -571,7 +634,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -621,7 +684,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
@@ -632,7 +695,7 @@ private Q_SLOTS:
// WHEN
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
@@ -682,7 +745,7 @@ private Q_SLOTS:
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
const bool earlyReturn = !pickBVJob.runHelper();
@@ -703,6 +766,7 @@ private Q_SLOTS:
QmlSceneReader sceneReader(QUrl("qrc:/testscene_dragenabled.qml"));
QScopedPointer<Qt3DCore::QNode> root(qobject_cast<Qt3DCore::QNode *>(sceneReader.root()));
QVERIFY(root);
+ QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
QList<Qt3DRender::QRenderSettings *> renderSettings = root->findChildren<Qt3DRender::QRenderSettings *>();
QCOMPARE(renderSettings.size(), 1);
@@ -714,9 +778,7 @@ private Q_SLOTS:
settings->setPickMethod(pickMethod);
settings->setPickResultMode(pickResultMode);
settings->setFaceOrientationPickingMode(faceOrientationPickingMode);
-
- QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
- TestArbiter arbiter;
+ test->renderSettings()->syncFromFrontEnd(renderSettings.first(), false);
// Runs Required jobs
runRequiredJobs(test.data());
@@ -733,7 +795,7 @@ private Q_SLOTS:
Qt3DRender::Render::ObjectPicker *backendPicker1 = test->nodeManagers()->objectPickerManager()->lookupResource(picker1->id());
QVERIFY(backendPicker1);
- Qt3DCore::QBackendNodePrivate::get(backendPicker1)->setArbiter(&arbiter);
+ Qt3DCore::QBackendNodePrivate::get(backendPicker1)->setArbiter(test->arbiter());
QCOMPARE(test->renderSettings()->pickMethod(), pickMethod);
QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode);
@@ -748,94 +810,88 @@ private Q_SLOTS:
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
+ QSignalSpy mouseButtonPressedSpy(picker1, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker1, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker1, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker1, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- Qt3DRender::QPickEventPtr pickEvent = change->value().value<Qt3DRender::QPickEventPtr>();
- QVERIFY(pickEvent);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.data())->m_entity.isNull());
- if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking)
- QVERIFY(pickEvent.dynamicCast<Qt3DRender::QPickTriangleEvent>());
-
- arbiter.events.clear();
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
// WHEN -> Move on same object
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Moved
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "moved");
- pickEvent = change->value().value<Qt3DRender::QPickEventPtr>();
- QVERIFY(pickEvent);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.data())->m_entity.isNull());
- if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking)
- QVERIFY(pickEvent.dynamicCast<Qt3DRender::QPickTriangleEvent>());
-
- arbiter.events.clear();
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
// WHEN -> Release on object
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Released + Clicked
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
- pickEvent = change->value().value<Qt3DRender::QPickEventPtr>();
- QVERIFY(pickEvent);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.data())->m_entity.isNull());
- if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking)
- QVERIFY(pickEvent.dynamicCast<Qt3DRender::QPickTriangleEvent>());
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "clicked");
- pickEvent = change->value().value<Qt3DRender::QPickEventPtr>();
- QVERIFY(pickEvent);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.data())->m_entity.isNull());
- if (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking)
- QVERIFY(pickEvent.dynamicCast<Qt3DRender::QPickTriangleEvent>());
-
- arbiter.events.clear();
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseButtonReleasedSpy.count(), /*backAndFrontPicking ? 2 :*/ 1);
+ QCOMPARE(mouseClickedSpy.count(), 1);
+
+ mouseButtonPressedSpy.clear();
+ mouseMovedSpy.clear();
+ mouseButtonReleasedSpy.clear();
+ mouseClickedSpy.clear();
// WHEN -> Release outside of object
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0, 0.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Released
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 3 : 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
-
- arbiter.events.clear();
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 1);
}
void checkDispatchReleaseEventOnLastPickerWhenMovingOutOfViewport()
@@ -873,57 +929,70 @@ private Q_SLOTS:
QVERIFY(backendPicker1);
Qt3DCore::QBackendNodePrivate::get(backendPicker1)->setArbiter(&arbiter);
+ QSignalSpy mouseButtonPressedSpy(picker1, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker1, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker1, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker1, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- Qt3DRender::QPickEventPtr pickEvent = change->value().value<Qt3DRender::QPickEventPtr>();
- QVERIFY(pickEvent);
- QVERIFY(!Qt3DRender::QPickEventPrivate::get(pickEvent.data())->m_entity.isNull());
- QVERIFY(pickEvent.dynamicCast<Qt3DRender::QPickTriangleEvent>());
-
- arbiter.events.clear();
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
// WHEN -> Releasing out of the viewport
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0f, 10000.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0, 10000.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Should have received released event
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
- pickEvent = change->value().value<Qt3DRender::QPickEventPtr>();
- QVERIFY(pickEvent);
- QVERIFY(Qt3DRender::QPickEventPrivate::get(pickEvent.data())->m_entity.isNull());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 1);
- arbiter.events.clear();
// WHEN -> Releasing out of the viewport
+ mouseButtonPressedSpy.clear();
+ mouseMovedSpy.clear();
+ mouseButtonReleasedSpy.clear();
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0f, 10000.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(10000.0, 10000.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Should have received nothing
- QCOMPARE(arbiter.events.count(), 0);
+ QVERIFY(!backendPicker1->isPressed());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 0);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
}
void checkDispatchHoverEvent_data()
@@ -973,60 +1042,64 @@ private Q_SLOTS:
QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode);
QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode);
+ QSignalSpy mouseEntered(picker1, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited(picker1, &Qt3DRender::QObjectPicker::exited);
+
+ QVERIFY(mouseEntered.isValid());
+ QVERIFY(mouseExited.isValid());
+
// WHEN -> Hover on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::HoverMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::HoverMove, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Entered
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "entered");
-
- arbiter.events.clear();
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseEntered.count(), 1);
+ QCOMPARE(mouseExited.count(), 0);
// WHEN -> HoverMove Out
events.clear();
- events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(20.0f, 40.0f),
+ events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(20.0, 40.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN - Exited
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "exited");
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseEntered.count(), 1);
+ QCOMPARE(mouseExited.count(), 1);
- arbiter.events.clear();
+ mouseEntered.clear();
+ mouseExited.clear();
// WHEN -> HoverMove In + Pressed other
events.clear();
- events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(207.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QEvent::HoverMove, QPointF(207.0, 303.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
- events.push_back({nullptr, QMouseEvent(QEvent::MouseButtonPress, QPointF(0.0f, 0.0f),
+ events.push_back({nullptr, QMouseEvent(QEvent::MouseButtonPress, QPointF(0.0, 0.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN - Entered, Exited
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker1->isPressed());
- QCOMPARE(arbiter.events.count(), 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "entered");
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "exited");
-
- arbiter.events.clear();
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseEntered.count(), 1);
+ QCOMPARE(mouseExited.count(), 1);
}
void shouldDispatchMouseEventFromChildren_data()
@@ -1078,78 +1151,94 @@ private Q_SLOTS:
(pickResultMode == Qt3DRender::QPickingSettings::AllPicks) &&
(faceOrientationPickingMode == Qt3DRender::QPickingSettings::FrontAndBackFace);
+ QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0, 300.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
-
- arbiter.events.clear();
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
// WHEN -> Move on same object
+ mouseButtonPressedSpy.clear();
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(400.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(400.0, 300.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Moved
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 2 : 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "moved");
-
- arbiter.events.clear();
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 0);
+ QCOMPARE(mouseMovedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
// WHEN -> Release on object
+ mouseMovedSpy.clear();
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(400.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(400.0, 300.0),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Released + Clicked
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "clicked");
-
- arbiter.events.clear();
+ QVERIFY(!picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 0);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 1);
+ QCOMPARE(mouseClickedSpy.count(), 1);
// WHEN -> Release outside of object
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f),
+ mouseButtonPressedSpy.clear();
+ mouseMovedSpy.clear();
+ mouseButtonReleasedSpy.clear();
+
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0.0f, 0.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(0., 0.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Released
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), backAndFrontPicking ? 3 : 2);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "released");
-
- arbiter.events.clear();
+ QVERIFY(!picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 1);
+ QCOMPARE(mouseClickedSpy.count(), 1);
}
void checkPickerGrabbing_data()
@@ -1175,6 +1264,11 @@ private Q_SLOTS:
settings->setPickResultMode(pickResultMode);
settings->setFaceOrientationPickingMode(faceOrientationPickingMode);
+ const bool backAndFrontPicking =
+ (pickMethod == Qt3DRender::QPickingSettings::TrianglePicking) &&
+ (pickResultMode == Qt3DRender::QPickingSettings::AllPicks) &&
+ (faceOrientationPickingMode == Qt3DRender::QPickingSettings::FrontAndBackFace);
+
QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
TestArbiter arbiter1;
TestArbiter arbiter2;
@@ -1208,47 +1302,85 @@ private Q_SLOTS:
QCOMPARE(test->renderSettings()->pickResultMode(), pickResultMode);
QCOMPARE(test->renderSettings()->faceOrientationPickingMode(), faceOrientationPickingMode);
+ QSignalSpy mouseEntered1(picker1, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited1(picker1, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy1(picker1, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy1(picker1, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy1(picker1, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy1(picker1, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy1.isValid());
+ QVERIFY(mouseMovedSpy1.isValid());
+ QVERIFY(mouseButtonReleasedSpy1.isValid());
+ QVERIFY(mouseClickedSpy1.isValid());
+ QVERIFY(mouseEntered1.isValid());
+ QVERIFY(mouseExited1.isValid());
+
+ QSignalSpy mouseEntered2(picker2, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited2(picker2, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy2(picker2, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy2(picker2, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy2(picker2, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy2(picker2, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy2.isValid());
+ QVERIFY(mouseMovedSpy2.isValid());
+ QVERIFY(mouseButtonReleasedSpy2.isValid());
+ QVERIFY(mouseClickedSpy2.isValid());
+ QVERIFY(mouseEntered2.isValid());
+ QVERIFY(mouseExited2.isValid());
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
+ QVERIFY(picker1->isPressed());
- arbiter1.events.clear();
+ QCOMPARE(mouseButtonPressedSpy1.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
// WHEN -> Move on next object, show stay on previous picker unless all picks are requested
events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(280.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseMove, QPointF(280., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Moved over the second picker, is the first one still pressed
QVERIFY(!earlyReturn);
if (pickResultMode != Qt3DRender::QPickingSettings::AllPicks) {
QVERIFY(backendPicker1->isPressed());
- change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "moved");
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 1);
+ QCOMPARE(mouseMovedSpy1.count(), 1);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
} else {
- QVERIFY(arbiter2.events.size() > 1);
- change = arbiter2.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "moved");
- change = arbiter2.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "entered");
+ QVERIFY(!picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 0);
+ QCOMPARE(mouseMovedSpy2.count(), backAndFrontPicking ? 2 : 1);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 0);
+ QCOMPARE(mouseClickedSpy2.count(), 0);
+ QCOMPARE(mouseEntered2.count(), 1);
+ QCOMPARE(mouseExited2.count(), 0);
}
-
- arbiter1.events.clear();
- arbiter2.events.clear();
}
void checkParentNoPickerChildPicker()
@@ -1284,22 +1416,41 @@ private Q_SLOTS:
QVERIFY(backendPicker);
Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter);
+ QSignalSpy mouseEntered(picker, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited(picker, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+ QVERIFY(mouseEntered.isValid());
+ QVERIFY(mouseExited.isValid());
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(400., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
+ QCOMPARE(mouseEntered.count(), 0);
+ QCOMPARE(mouseExited.count(), 0);
}
void checkPickerAndViewports()
@@ -1335,38 +1486,63 @@ private Q_SLOTS:
QVERIFY(backendPicker);
Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter);
+ QSignalSpy mouseEntered(picker, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited(picker, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+ QVERIFY(mouseEntered.isValid());
+ QVERIFY(mouseExited.isValid());
+
// WHEN -> Pressed on object in vp1
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(280.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(280., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
+ QCOMPARE(mouseEntered.count(), 0);
+ QCOMPARE(mouseExited.count(), 0);
// WHEN reset -> Presset on object in vp2
backendPicker->cleanup();
backendPicker->setEnabled(true);
events.clear();
- arbiter.events.clear();
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(320., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Nothing happened
QVERIFY(!earlyReturn);
QVERIFY(!backendPicker->isPressed());
- QCOMPARE(arbiter.events.count(), 0);
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
+ QCOMPARE(mouseEntered.count(), 0);
+ QCOMPARE(mouseExited.count(), 0);
}
void checkMultipleRayDirections_data()
@@ -1383,8 +1559,8 @@ private Q_SLOTS:
const double angle = M_PI * 2. / (double)n * i;
const double x = std::sin(angle) * 10.;
const double z = std::cos(angle) * 10.;
- QVector3D pos(x, 0, z);
- QVector3D up(0, 1, 0);
+ QVector3D pos(x, 0.f, z);
+ QVector3D up(0.f, 1.f, 0.f);
QTest::newRow(QString::number(k++).toLatin1().data()) << m * pos << m * up;
}
}
@@ -1429,25 +1605,41 @@ private Q_SLOTS:
QVERIFY(backendPicker);
Qt3DCore::QBackendNodePrivate::get(backendPicker)->setArbiter(&arbiter);
+ QSignalSpy mouseEntered(picker, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited(picker, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy(picker, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy(picker, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy(picker, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy(picker, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy.isValid());
+ QVERIFY(mouseMovedSpy.isValid());
+ QVERIFY(mouseButtonReleasedSpy.isValid());
+ QVERIFY(mouseClickedSpy.isValid());
+ QVERIFY(mouseEntered.isValid());
+ QVERIFY(mouseExited.isValid());
+
// WHEN -> Pressed on object
Qt3DRender::Render::PickBoundingVolumeJob pickBVJob;
initializePickBoundingVolumeJob(&pickBVJob, test.data());
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(303.0f, 303.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(303., 303.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Pressed
QVERIFY(!earlyReturn);
QVERIFY(backendPicker->isPressed());
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
- Qt3DRender::QPickEventPtr pickEvent = change->value().value<Qt3DRender::QPickEventPtr>();
- QVERIFY(pickEvent);
-
- arbiter.events.clear();
+ QVERIFY(picker->isPressed());
+ QCOMPARE(mouseButtonPressedSpy.count(), 1);
+ QCOMPARE(mouseMovedSpy.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy.count(), 0);
+ QCOMPARE(mouseClickedSpy.count(), 0);
+ QCOMPARE(mouseEntered.count(), 0);
+ QCOMPARE(mouseExited.count(), 0);
}
void checkPriorityPicking()
@@ -1486,6 +1678,33 @@ private Q_SLOTS:
QVERIFY(backendPicker2);
Qt3DCore::QBackendNodePrivate::get(backendPicker2)->setArbiter(&arbiter2);
+ QSignalSpy mouseEntered1(picker1, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited1(picker1, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy1(picker1, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy1(picker1, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy1(picker1, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy1(picker1, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy1.isValid());
+ QVERIFY(mouseMovedSpy1.isValid());
+ QVERIFY(mouseButtonReleasedSpy1.isValid());
+ QVERIFY(mouseClickedSpy1.isValid());
+ QVERIFY(mouseEntered1.isValid());
+ QVERIFY(mouseExited1.isValid());
+
+ QSignalSpy mouseEntered2(picker2, &Qt3DRender::QObjectPicker::entered);
+ QSignalSpy mouseExited2(picker2, &Qt3DRender::QObjectPicker::exited);
+ QSignalSpy mouseButtonPressedSpy2(picker2, &Qt3DRender::QObjectPicker::pressed);
+ QSignalSpy mouseMovedSpy2(picker2, &Qt3DRender::QObjectPicker::moved);
+ QSignalSpy mouseButtonReleasedSpy2(picker2, &Qt3DRender::QObjectPicker::released);
+ QSignalSpy mouseClickedSpy2(picker2, &Qt3DRender::QObjectPicker::clicked);
+
+ QVERIFY(mouseButtonPressedSpy2.isValid());
+ QVERIFY(mouseMovedSpy2.isValid());
+ QVERIFY(mouseButtonReleasedSpy2.isValid());
+ QVERIFY(mouseClickedSpy2.isValid());
+ QVERIFY(mouseEntered2.isValid());
+ QVERIFY(mouseExited2.isValid());
// WHEN both have priority == 0, select closest
{
@@ -1494,31 +1713,62 @@ private Q_SLOTS:
// WHEN -> Pressed on object
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Select picker with highest priority
QVERIFY(!earlyReturn);
QVERIFY(backendPicker1->isPressed());
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter1.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
+ QVERIFY(picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 1);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
QVERIFY(!backendPicker2->isPressed());
- QVERIFY(arbiter2.events.isEmpty());
-
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300.0f, 300.0f),
+ QVERIFY(!picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 0);
+ QCOMPARE(mouseMovedSpy2.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 0);
+ QCOMPARE(mouseClickedSpy2.count(), 0);
+ QCOMPARE(mouseEntered2.count(), 0);
+ QCOMPARE(mouseExited2.count(), 0);
+
+ events.clear();
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
pickBVJob.runHelper();
- arbiter1.events.clear();
- arbiter2.events.clear();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
QVERIFY(!backendPicker1->isPressed());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 1);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 1);
+ QCOMPARE(mouseClickedSpy1.count(), 1);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
+
QVERIFY(!backendPicker2->isPressed());
+ QVERIFY(!picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 0);
+ QCOMPARE(mouseMovedSpy2.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 0);
+ QCOMPARE(mouseClickedSpy2.count(), 0);
+ QCOMPARE(mouseEntered2.count(), 0);
+ QCOMPARE(mouseExited2.count(), 0);
}
+ mouseButtonPressedSpy1.clear();
+ mouseButtonReleasedSpy1.clear();
+ mouseClickedSpy1.clear();
+
// WHEN furthest one has higher priority, select furthest one
{
backendPicker2->setPriority(1000);
@@ -1529,32 +1779,105 @@ private Q_SLOTS:
// WHEN -> Pressed on object
QList<QPair<QObject *, QMouseEvent>> events;
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300.0f, 300.0f),
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonPress, QPointF(300., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
bool earlyReturn = !pickBVJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
// THEN -> Select picker with highest priority
QVERIFY(!earlyReturn);
- QVERIFY(backendPicker2->isPressed());
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter2.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pressed");
-
QVERIFY(!backendPicker1->isPressed());
- QVERIFY(arbiter1.events.isEmpty());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 0);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
- events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300.0f, 300.0f),
+ QVERIFY(backendPicker2->isPressed());
+ QVERIFY(picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 1);
+ QCOMPARE(mouseMovedSpy2.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 0);
+ QCOMPARE(mouseClickedSpy2.count(), 0);
+ QCOMPARE(mouseEntered2.count(), 0);
+ QCOMPARE(mouseExited2.count(), 0);
+
+ events.clear();
+ events.push_back({nullptr, QMouseEvent(QMouseEvent::MouseButtonRelease, QPointF(300., 300.),
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)});
pickBVJob.setMouseEvents(events);
pickBVJob.runHelper();
- arbiter1.events.clear();
- arbiter2.events.clear();
+ Qt3DCore::QAspectJobPrivate::get(&pickBVJob)->postFrame(test->aspectManager());
QVERIFY(!backendPicker1->isPressed());
+ QVERIFY(!picker1->isPressed());
+ QCOMPARE(mouseButtonPressedSpy1.count(), 0);
+ QCOMPARE(mouseMovedSpy1.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy1.count(), 0);
+ QCOMPARE(mouseClickedSpy1.count(), 0);
+ QCOMPARE(mouseEntered1.count(), 0);
+ QCOMPARE(mouseExited1.count(), 0);
+
QVERIFY(!backendPicker2->isPressed());
+ QVERIFY(!picker2->isPressed());
+ QCOMPARE(mouseButtonPressedSpy2.count(), 1);
+ QCOMPARE(mouseMovedSpy2.count(), 0);
+ QCOMPARE(mouseButtonReleasedSpy2.count(), 1);
+ QCOMPARE(mouseClickedSpy2.count(), 1);
+ QCOMPARE(mouseEntered2.count(), 0);
+ QCOMPARE(mouseExited2.count(), 0);
}
}
+ void checkNoPickingFGPicking()
+ {
+ // GIVEN
+ QmlSceneReader sceneReader(QUrl("qrc:/testscene_nopicking.qml"));
+ QScopedPointer<Qt3DCore::QNode> root(qobject_cast<Qt3DCore::QNode *>(sceneReader.root()));
+ QVERIFY(root);
+ QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
+
+ // THEN
+ QVERIFY(test->frameGraphRoot() != nullptr);
+ Qt3DRender::QNoPicking *noPicking = root->findChild<Qt3DRender::QNoPicking *>();
+ QVERIFY(noPicking != nullptr);
+ Qt3DRender::QCamera *camera = root->findChild<Qt3DRender::QCamera *>();
+ QVERIFY(camera != nullptr);
+ QQuickWindow *window = root->findChild<QQuickWindow *>();
+ QVERIFY(camera != nullptr);
+ QCOMPARE(window->size(), QSize(600, 600));
+
+ // WHEN
+ Qt3DRender::Render::PickingUtils::ViewportCameraAreaGatherer gatherer;
+ QVector<Qt3DRender::Render::PickingUtils::ViewportCameraAreaDetails> results = gatherer.gather(test->frameGraphRoot());
+
+ // THEN
+ QCOMPARE(results.size(), 0);
+
+ // WHEN
+ Qt3DRender::Render::FrameGraphNode *backendFGNode = test->nodeManagers()->frameGraphManager()->lookupNode(noPicking->id());
+ QVERIFY(backendFGNode);
+ QCOMPARE(backendFGNode->nodeType(), Qt3DRender::Render::FrameGraphNode::NoPicking);
+ Qt3DRender::Render::NoPicking * backendNoPicking = static_cast<Qt3DRender::Render::NoPicking *>(backendFGNode);
+ backendNoPicking->setEnabled(false);
+
+ // THEN
+ QVERIFY(!backendNoPicking->isEnabled());
+
+ // WHEN
+ results = gatherer.gather(test->frameGraphRoot());
+
+ // THEN
+ QCOMPARE(results.size(), 1);
+ auto vca = results.first();
+ QCOMPARE(vca.area, QSize(600, 600));
+ QCOMPARE(vca.cameraId, camera->id());
+ QCOMPARE(vca.viewport, QRectF(0., 0., 1., 1.));
+ }
+
};
QTEST_MAIN(tst_PickBoundingVolumeJob)
diff --git a/tests/auto/render/picking/tst_picking.cpp b/tests/auto/render/picking/tst_picking.cpp
index 47027bf56..d0e6512d5 100644
--- a/tests/auto/render/picking/tst_picking.cpp
+++ b/tests/auto/render/picking/tst_picking.cpp
@@ -30,10 +30,12 @@
#include <Qt3DCore/qentity.h>
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/QPropertyUpdatedChange>
+#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DRender/private/qboundingvolumeprovider_p.h>
#include <Qt3DRender/private/pickboundingvolumejob_p.h>
#include <Qt3DRender/private/objectpicker_p.h>
#include <Qt3DRender/qobjectpicker.h>
+#include <Qt3DRender/private/qobjectpicker_p.h>
#include <Qt3DExtras/qspheremesh.h>
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/qbuffer.h>
@@ -139,21 +141,25 @@ private Q_SLOTS:
void testEventPressedAcceptPropagation()
{
// GIVEN
+ Qt3DCore::QScene scene;
PickableEntity root(QVector3D(), 5.0f);
PickableEntity child1(QVector3D(), 5.0f, &root);
PickableEntity child2(QVector3D(), 5.0f, &root);
PickableEntity child11(QVector3D(), 5.0f, &child1);
+ Qt3DCore::QNodePrivate::get(root.picker)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(child1.picker)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(child2.picker)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(child11.picker)->setScene(&scene);
QCoreApplication::processEvents();
+ auto dpicker = [](QObjectPicker *node) {
+ return static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node));
+ };
+
// WHEN
Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent());
- QVariant v;
- v.setValue<Qt3DRender::QPickEventPtr>(event);
- Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(child11.id()));
- e->setPropertyName("pressed");
- e->setValue(v);
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
// THEN
QCOMPARE(root.pressedCalled, 0);
@@ -164,7 +170,7 @@ private Q_SLOTS:
// WHEN
child11.pressedCalled = 0;
child11.acceptsEvents = false;
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
// THEN
QCOMPARE(root.pressedCalled, 0);
@@ -177,7 +183,7 @@ private Q_SLOTS:
child1.pressedCalled = 0;
child11.acceptsEvents = false;
child11.pressedCalled = 0;
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
// THEN
QCOMPARE(root.pressedCalled, 1);
@@ -189,23 +195,26 @@ private Q_SLOTS:
void testEventReleasedAcceptPropagation()
{
// GIVEN
+ Qt3DCore::QScene scene;
PickableEntity root(QVector3D(), 5.0f);
PickableEntity child1(QVector3D(), 5.0f, &root);
PickableEntity child2(QVector3D(), 5.0f, &root);
PickableEntity child11(QVector3D(), 5.0f, &child1);
+ Qt3DCore::QNodePrivate::get(root.picker)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(child1.picker)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(child2.picker)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(child11.picker)->setScene(&scene);
QCoreApplication::processEvents();
+ auto dpicker = [](QObjectPicker *node) {
+ return static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node));
+ };
+
// WHEN
Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent());
- QVariant v;
- v.setValue<Qt3DRender::QPickEventPtr>(event);
- Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(child11.id()));
- e->setPropertyName("pressed");
- e->setValue(v);
- child11.picker->sceneChangeEvent(e);
- e->setPropertyName("released");
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
+ dpicker(child11.picker)->releasedEvent(event.data());
// THEN
QCOMPARE(root.releasedCalled, 0);
@@ -217,10 +226,8 @@ private Q_SLOTS:
child11.releasedCalled = 0;
child11.pressedCalled = 0;
child11.acceptsEvents = false;
- e->setPropertyName("pressed");
- child11.picker->sceneChangeEvent(e);
- e->setPropertyName("released");
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->pressedEvent(event.data());
+ dpicker(child11.picker)->releasedEvent(event.data());
// THEN
QCOMPARE(child1.pressedCalled, 1);
@@ -235,21 +242,25 @@ private Q_SLOTS:
void testEventClickedAcceptPropagation()
{
// GIVEN
+ Qt3DCore::QScene scene;
PickableEntity root(QVector3D(), 5.0f);
PickableEntity child1(QVector3D(), 5.0f, &root);
PickableEntity child2(QVector3D(), 5.0f, &root);
PickableEntity child11(QVector3D(), 5.0f, &child1);
+ Qt3DCore::QNodePrivate::get(root.picker)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(child1.picker)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(child2.picker)->setScene(&scene);
+ Qt3DCore::QNodePrivate::get(child11.picker)->setScene(&scene);
QCoreApplication::processEvents();
+ auto dpicker = [](QObjectPicker *node) {
+ return static_cast<QObjectPickerPrivate *>(QObjectPickerPrivate::get(node));
+ };
+
// WHEN
Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent());
- QVariant v;
- v.setValue<Qt3DRender::QPickEventPtr>(event);
- Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(child11.id()));
- e->setPropertyName("clicked");
- e->setValue(v);
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->clickedEvent(event.data());
// THEN
QCOMPARE(root.clickedCalled, 0);
@@ -260,7 +271,7 @@ private Q_SLOTS:
// WHEN
child11.clickedCalled = 0;
child11.acceptsEvents = false;
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->clickedEvent(event.data());
// THEN
QCOMPARE(root.clickedCalled, 0);
@@ -273,7 +284,7 @@ private Q_SLOTS:
child1.clickedCalled = 0;
child11.acceptsEvents = false;
child11.clickedCalled = 0;
- child11.picker->sceneChangeEvent(e);
+ dpicker(child11.picker)->clickedEvent(event.data());
// THEN
QCOMPARE(root.clickedCalled, 1);
diff --git a/tests/auto/render/proximityfilter/tst_proximityfilter.cpp b/tests/auto/render/proximityfilter/tst_proximityfilter.cpp
index ac9cc610c..52537d457 100644
--- a/tests/auto/render/proximityfilter/tst_proximityfilter.cpp
+++ b/tests/auto/render/proximityfilter/tst_proximityfilter.cpp
@@ -31,7 +31,6 @@
#include <Qt3DRender/qproximityfilter.h>
#include <Qt3DRender/private/qproximityfilter_p.h>
#include <Qt3DRender/private/proximityfilter_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
@@ -56,6 +55,7 @@ private Q_SLOTS:
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QProximityFilter proximityFilter;
Qt3DCore::QEntity entity;
proximityFilter.setDistanceThreshold(1340.0f);
@@ -64,40 +64,45 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::ProximityFilter backendProximityFilter;
- simulateInitialization(&proximityFilter, &backendProximityFilter);
+ backendProximityFilter.setRenderer(&renderer);
+ simulateInitializationSync(&proximityFilter, &backendProximityFilter);
// THEN
QCOMPARE(backendProximityFilter.isEnabled(), true);
QCOMPARE(backendProximityFilter.peerId(), proximityFilter.id());
QCOMPARE(backendProximityFilter.distanceThreshold(), 1340.f);
QCOMPARE(backendProximityFilter.entityId(), entity.id());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
Qt3DRender::Render::ProximityFilter backendProximityFilter;
+ backendProximityFilter.setRenderer(&renderer);
proximityFilter.setEnabled(false);
- simulateInitialization(&proximityFilter, &backendProximityFilter);
+ simulateInitializationSync(&proximityFilter, &backendProximityFilter);
// THEN
QCOMPARE(backendProximityFilter.peerId(), proximityFilter.id());
QCOMPARE(backendProximityFilter.isEnabled(), false);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
}
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DRender::QProximityFilter proximityFilter;
Qt3DRender::Render::ProximityFilter backendProximityFilter;
TestRenderer renderer;
backendProximityFilter.setRenderer(&renderer);
+ simulateInitializationSync(&proximityFilter, &backendProximityFilter);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendProximityFilter.sceneChangeEvent(change);
+ proximityFilter.setEnabled(newValue);
+ backendProximityFilter.syncFromFrontEnd(&proximityFilter, false);
// THEN
QCOMPARE(backendProximityFilter.isEnabled(), newValue);
@@ -107,10 +112,9 @@ private Q_SLOTS:
{
// WHEN
const float newValue = 383.0f;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("distanceThreshold");
- change->setValue(QVariant::fromValue(newValue));
- backendProximityFilter.sceneChangeEvent(change);
+ proximityFilter.setDistanceThreshold(newValue);
+ backendProximityFilter.syncFromFrontEnd(&proximityFilter, false);
+
// THEN
QCOMPARE(backendProximityFilter.distanceThreshold(), newValue);
@@ -119,14 +123,12 @@ private Q_SLOTS:
}
{
// WHEN
- const Qt3DCore::QNodeId newValue = Qt3DCore::QNodeId::createId();
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("entity");
- change->setValue(QVariant::fromValue(newValue));
- backendProximityFilter.sceneChangeEvent(change);
+ Qt3DCore::QEntity e;
+ proximityFilter.setEntity(&e);
+ backendProximityFilter.syncFromFrontEnd(&proximityFilter, false);
// THEN
- QCOMPARE(backendProximityFilter.entityId(), newValue);
+ QCOMPARE(backendProximityFilter.entityId(), e.id());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
index dcd39c785..ad12ffad0 100644
--- a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
+++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp
@@ -117,14 +117,20 @@ private Q_SLOTS:
{
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
- Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity);
- Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity);
- Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity);
+ Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(50.0f, rootEntity);
+ Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(25.0f, rootEntity);
+ Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(75.0f, rootEntity);
+
+ Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity);
+ proximityFilter->setDistanceThreshold(200.0f);
+ proximityFilter->setEntity(targetEntity);
QTest::newRow("ShouldSelectAll") << rootEntity
- << Qt3DCore::QNodeIdVector()
+ << (Qt3DCore::QNodeIdVector() << proximityFilter->id())
<< (Qt3DCore::QNodeIdVector()
<< rootEntity->id()
+ << targetEntity->id()
<< childEntity1->id()
<< childEntity2->id()
<< childEntity3->id()
@@ -285,10 +291,6 @@ private Q_SLOTS:
// WHEN
Qt3DRender::Render::Entity *backendRoot = aspect->nodeManagers()->renderNodesManager()->getOrCreateResource(entitySubtree->id());
- Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob;
- updateEntitiesJob.setManager(aspect->nodeManagers());
- updateEntitiesJob.run();
-
Qt3DRender::Render::UpdateTreeEnabledJob updateTreeEnabledJob;
updateTreeEnabledJob.setRoot(backendRoot);
updateTreeEnabledJob.setManagers(aspect->nodeManagers());
diff --git a/tests/auto/render/qabstractlight/tst_qabstractlight.cpp b/tests/auto/render/qabstractlight/tst_qabstractlight.cpp
index bc67148d2..011ad1036 100644
--- a/tests/auto/render/qabstractlight/tst_qabstractlight.cpp
+++ b/tests/auto/render/qabstractlight/tst_qabstractlight.cpp
@@ -149,26 +149,13 @@ private Q_SLOTS:
light->setColor(Qt::red);
light->setIntensity(0.8f); // change from the default of 0.5f
- QCoreApplication::processEvents();
-
- QCOMPARE(arbiter.events.size(), 2 * 2); // Due to contained shader data
- for (int i = 0; i < 2; i++)
- arbiter.events.removeAt(i);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events[0].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "color");
- QCOMPARE(change->subjectId(), light->id());
- QCOMPARE(change->value().value<QColor>(), QColor(Qt::red));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- change = arbiter.events[1].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "intensity");
- QCOMPARE(change->subjectId(), light->id());
- QCOMPARE(change->value().value<float>(), 0.8f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 2);
+ QVERIFY(arbiter.dirtyNodes[0]->metaObject()->inherits(&Qt3DRender::QShaderData::staticMetaObject));
+ QCOMPARE(arbiter.dirtyNodes[1], light.data());
- light->setColor(Qt::red);
- QCoreApplication::processEvents();
+ arbiter.dirtyNodes.clear();
QCOMPARE(arbiter.events.size(), 0);
@@ -186,33 +173,13 @@ private Q_SLOTS:
pointLight->setConstantAttenuation(0.5f);
pointLight->setLinearAttenuation(0.0f); // No actual event triggered as 0.0f is default
pointLight->setQuadraticAttenuation(1.0f);
- QCoreApplication::processEvents();
-
- QCOMPARE(arbiter.events.size(), 4 * 2); // Due to contained shader data
- for (int i = 0; i < 4; i++)
- arbiter.events.removeAt(i);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events[0].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "color");
- QCOMPARE(change->subjectId(), pointLight->id());
- QCOMPARE(change->value().value<QColor>(), QColor(Qt::green));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- change = arbiter.events[1].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "intensity");
- QCOMPARE(change->subjectId(), pointLight->id());
- QCOMPARE(change->value().value<float>(), 0.8f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- change = arbiter.events[2].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "constantAttenuation");
- QCOMPARE(change->subjectId(), pointLight->id());
- QCOMPARE(change->value().value<float>(), 0.5f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- change = arbiter.events[3].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "quadraticAttenuation");
- QCOMPARE(change->subjectId(), pointLight->id());
- QCOMPARE(change->value().value<float>(), 1.0f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 2);
+ QVERIFY(arbiter.dirtyNodes[0]->metaObject()->inherits(&Qt3DRender::QShaderData::staticMetaObject));
+ QCOMPARE(arbiter.dirtyNodes[1], pointLight.data());
+
+ arbiter.dirtyNodes.clear();
}
void checkDirectionalLightPropertyUpdates()
@@ -224,28 +191,12 @@ private Q_SLOTS:
dirLight->setColor(Qt::blue);
dirLight->setIntensity(0.8f);
dirLight->setWorldDirection(QVector3D(0.5f, 0.0f, -1.0f));
- QCoreApplication::processEvents();
-
- QCOMPARE(arbiter.events.size(), 3 * 2); // Due to contained shader data
- for (int i = 0; i < 3; i++)
- arbiter.events.removeAt(i);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events[0].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "color");
- QCOMPARE(change->subjectId(), dirLight->id());
- QCOMPARE(change->value().value<QColor>(), QColor(Qt::blue));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- change = arbiter.events[1].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "intensity");
- QCOMPARE(change->subjectId(), dirLight->id());
- QCOMPARE(change->value().value<float>(), 0.8f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- change = arbiter.events[2].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "worldDirection");
- QCOMPARE(change->subjectId(), dirLight->id());
- QCOMPARE(change->value().value<QVector3D>(), QVector3D(0.5f, 0.0f, -1.0f));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- arbiter.events.clear();
+ QCOMPARE(arbiter.dirtyNodes.size(), 2);
+ QVERIFY(arbiter.dirtyNodes[0]->metaObject()->inherits(&Qt3DRender::QShaderData::staticMetaObject));
+ QCOMPARE(arbiter.dirtyNodes[1], dirLight.data());
+
+ arbiter.dirtyNodes.clear();
}
void checkSpotLightPropertyUpdates()
@@ -258,33 +209,12 @@ private Q_SLOTS:
spotLight->setIntensity(0.8f);
spotLight->setLocalDirection(QVector3D(0.5f, 0.0f, -1.0f));
spotLight->setCutOffAngle(0.75f);
- QCoreApplication::processEvents();
-
- QCOMPARE(arbiter.events.size(), 4 * 2); // Due to contained shader data
- for (int i = 0; i < 4; i++)
- arbiter.events.removeAt(i);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events[0].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "color");
- QCOMPARE(change->subjectId(), spotLight->id());
- QCOMPARE(change->value().value<QColor>(), QColor(Qt::lightGray));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- change = arbiter.events[1].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "intensity");
- QCOMPARE(change->subjectId(), spotLight->id());
- QCOMPARE(change->value().value<float>(), 0.8f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- change = arbiter.events[2].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "localDirection");
- QCOMPARE(change->subjectId(), spotLight->id());
- QCOMPARE(change->value().value<QVector3D>(), QVector3D(0.5f, 0.0f, -1.0f).normalized());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- change = arbiter.events[3].staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "cutOffAngle");
- QCOMPARE(change->subjectId(), spotLight->id());
- QCOMPARE(change->value().value<float>(), 0.75f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- arbiter.events.clear();
+ QCOMPARE(arbiter.dirtyNodes.size(), 2);
+ QVERIFY(arbiter.dirtyNodes[0]->metaObject()->inherits(&Qt3DRender::QShaderData::staticMetaObject));
+ QCOMPARE(arbiter.dirtyNodes[1], spotLight.data());
+
+ arbiter.dirtyNodes.clear();
}
};
diff --git a/tests/auto/render/qabstracttexture/tst_qabstracttexture.cpp b/tests/auto/render/qabstracttexture/tst_qabstracttexture.cpp
index 73c882619..a1973176e 100644
--- a/tests/auto/render/qabstracttexture/tst_qabstracttexture.cpp
+++ b/tests/auto/render/qabstracttexture/tst_qabstracttexture.cpp
@@ -37,6 +37,7 @@
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -464,25 +465,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setFormat(Qt3DRender::QAbstractTexture::RG8_UNorm);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "format");
- QCOMPARE(change->value().value<Qt3DRender::QAbstractTexture::TextureFormat>(), abstractTexture.format());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setFormat(Qt3DRender::QAbstractTexture::RG8_UNorm);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -497,25 +495,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setGenerateMipMaps(true);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "generateMipMaps");
- QCOMPARE(change->value().value<bool>(), abstractTexture.generateMipMaps());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setGenerateMipMaps(true);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -530,25 +525,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setWidth(1024);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "width");
- QCOMPARE(change->value().value<int>(), abstractTexture.width());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setWidth(1024);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -563,25 +555,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setHeight(256);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "height");
- QCOMPARE(change->value().value<int>(), abstractTexture.height());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setHeight(256);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -596,25 +585,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setDepth(512);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "depth");
- QCOMPARE(change->value().value<int>(), abstractTexture.depth());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setDepth(512);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -629,25 +615,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setMagnificationFilter(Qt3DRender::QAbstractTexture::NearestMipMapLinear);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "magnificationFilter");
- QCOMPARE(change->value().value<Qt3DRender::QAbstractTexture::Filter>(), abstractTexture.magnificationFilter());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setMagnificationFilter(Qt3DRender::QAbstractTexture::NearestMipMapLinear);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -662,25 +645,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setMinificationFilter(Qt3DRender::QAbstractTexture::NearestMipMapLinear);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "minificationFilter");
- QCOMPARE(change->value().value<Qt3DRender::QAbstractTexture::Filter>(), abstractTexture.minificationFilter());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setMinificationFilter(Qt3DRender::QAbstractTexture::NearestMipMapLinear);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -695,25 +675,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setMaximumAnisotropy(327.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "maximumAnisotropy");
- QCOMPARE(change->value().value<float>(), abstractTexture.maximumAnisotropy());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setMaximumAnisotropy(327.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -728,25 +705,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setComparisonFunction(Qt3DRender::QAbstractTexture::CompareAlways);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "comparisonFunction");
- QCOMPARE(change->value().value<Qt3DRender::QAbstractTexture::ComparisonFunction>(), abstractTexture.comparisonFunction());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setComparisonFunction(Qt3DRender::QAbstractTexture::CompareAlways);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -761,25 +735,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setComparisonMode(Qt3DRender::QAbstractTexture::CompareRefToTexture);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "comparisonMode");
- QCOMPARE(change->value().value<Qt3DRender::QAbstractTexture::ComparisonMode>(), abstractTexture.comparisonMode());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setComparisonMode(Qt3DRender::QAbstractTexture::CompareRefToTexture);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -794,25 +765,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setLayers(64);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "layers");
- QCOMPARE(change->value().value<int>(), abstractTexture.layers());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setLayers(64);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -827,25 +795,22 @@ private Q_SLOTS:
{
// WHEN
abstractTexture.setSamples(16);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "samples");
- QCOMPARE(change->value().value<int>(), abstractTexture.samples());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTexture.setSamples(16);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -864,13 +829,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.last().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
- QCOMPARE(change->propertyName(), "textureImage");
- QCOMPARE(change->addedNodeId(), image.id());
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
}
@@ -889,13 +852,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.last().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
- QCOMPARE(change->propertyName(), "textureImage");
- QCOMPARE(change->removedNodeId(), image.id());
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
}
@@ -1131,6 +1092,27 @@ private Q_SLOTS:
}
}
+ void checkTextureDataUpdate()
+ {
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ FakeTexture abstractTexture;
+ Qt3DRender::QTextureDataUpdate update;
+ arbiter.setArbiterOnNode(&abstractTexture);
+
+ // WHEN
+ abstractTexture.updateData(update);
+ QCoreApplication::processEvents();
+
+ // THEN (arbiter -> should not be stored in the initial changes but only send as a property change)
+ auto d = static_cast<Qt3DRender::QAbstractTexturePrivate*>(Qt3DRender::QAbstractTexturePrivate::get(&abstractTexture));
+ QCOMPARE(d->m_pendingDataUpdates.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTexture);
+ }
+ }
+
};
QTEST_MAIN(tst_QAbstractTexture)
diff --git a/tests/auto/render/qabstracttextureimage/tst_qabstracttextureimage.cpp b/tests/auto/render/qabstracttextureimage/tst_qabstracttextureimage.cpp
index 05029450a..6bd742dad 100644
--- a/tests/auto/render/qabstracttextureimage/tst_qabstracttextureimage.cpp
+++ b/tests/auto/render/qabstracttextureimage/tst_qabstracttextureimage.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/qabstracttextureimage_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -200,25 +199,20 @@ private Q_SLOTS:
{
// WHEN
abstractTextureImage.setMipLevel(9);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "mipLevel");
- QCOMPARE(change->value().value<int>(), abstractTextureImage.mipLevel());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTextureImage);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTextureImage.setMipLevel(9);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -233,25 +227,22 @@ private Q_SLOTS:
{
// WHEN
abstractTextureImage.setLayer(12);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "layer");
- QCOMPARE(change->value().value<int>(), abstractTextureImage.layer());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTextureImage);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTextureImage.setLayer(12);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -266,25 +257,22 @@ private Q_SLOTS:
{
// WHEN
abstractTextureImage.setFace(Qt3DRender::QAbstractTexture::CubeMapPositiveY);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "face");
- QCOMPARE(change->value().value<Qt3DRender::QAbstractTexture::CubeMapFace>(), abstractTextureImage.face());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &abstractTextureImage);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
abstractTextureImage.setFace(Qt3DRender::QAbstractTexture::CubeMapPositiveY);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qattribute/tst_qattribute.cpp b/tests/auto/render/qattribute/tst_qattribute.cpp
index 23532c435..588ce40db 100644
--- a/tests/auto/render/qattribute/tst_qattribute.cpp
+++ b/tests/auto/render/qattribute/tst_qattribute.cpp
@@ -85,7 +85,7 @@ private Q_SLOTS:
QTest::newRow("defaultConstructed") << defaultConstructed;
Qt3DRender::QAttribute *customVertex = new Qt3DRender::QAttribute();
- Qt3DRender::QBuffer *buffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer);
+ Qt3DRender::QBuffer *buffer = new Qt3DRender::QBuffer();
customVertex->setBuffer(buffer);
customVertex->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
customVertex->setCount(454);
@@ -98,7 +98,7 @@ private Q_SLOTS:
QTest::newRow("vertex") << customVertex;
Qt3DRender::QAttribute *customIndex = new Qt3DRender::QAttribute();
- Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer);
+ Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer();
customIndex->setBuffer(indexBuffer);
customIndex->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
customIndex->setCount(383);
@@ -111,7 +111,7 @@ private Q_SLOTS:
QTest::newRow("index") << customIndex;
Qt3DRender::QAttribute *customIndirect = new Qt3DRender::QAttribute();
- Qt3DRender::QBuffer *indirectBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::DrawIndirectBuffer);
+ Qt3DRender::QBuffer *indirectBuffer = new Qt3DRender::QBuffer();
customIndirect->setBuffer(indirectBuffer);
customIndirect->setAttributeType(Qt3DRender::QAttribute::DrawIndirectAttribute);
customIndirect->setCount(1);
@@ -160,134 +160,95 @@ private Q_SLOTS:
// WHEN
attribute->setVertexBaseType(Qt3DRender::QAttribute::Double);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "vertexBaseType");
- QCOMPARE(change->value().value<int>(), static_cast<int>(Qt3DRender::QAttribute::Double));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
attribute->setVertexSize(4);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "vertexSize");
- QCOMPARE(change->value().value<uint>(), 4U);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
attribute->setName(QStringLiteral("Duntov"));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "name");
- QCOMPARE(change->value().value<QString>(), QStringLiteral("Duntov"));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
attribute->setCount(883);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "count");
- QCOMPARE(change->value().value<uint>(), 883U);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
attribute->setByteStride(1340);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "byteStride");
- QCOMPARE(change->value().value<uint>(), 1340U);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
attribute->setByteOffset(1584);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "byteOffset");
- QCOMPARE(change->value().value<uint>(), 1584U);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
attribute->setDivisor(1450);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "divisor");
- QCOMPARE(change->value().value<uint>(), 1450U);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
attribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "attributeType");
- QCOMPARE(change->value().value<int>(), static_cast<int>(Qt3DRender::QAttribute::IndexAttribute));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
Qt3DRender::QBuffer buf;
attribute->setBuffer(&buf);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "buffer");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), buf.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
Qt3DRender::QBuffer buf2;
attribute->setBuffer(&buf2);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "buffer");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), buf2.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), attribute.data());
+ arbiter.dirtyNodes.clear();
}
void checkBufferBookkeeping()
@@ -309,7 +270,7 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::QAttribute someOtherAttribute;
- QScopedPointer<Qt3DRender::QBuffer> buf(new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, &someOtherAttribute));
+ QScopedPointer<Qt3DRender::QBuffer> buf(new Qt3DRender::QBuffer(&someOtherAttribute));
attribute->setBuffer(buf.data());
// THEN
diff --git a/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp b/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp
index f6c7e1a8a..a53650945 100644
--- a/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp
+++ b/tests/auto/render/qblitframebuffer/tst_qblitframebuffer.cpp
@@ -119,217 +119,169 @@ private Q_SLOTS:
// sourceRenderTarget
// WHEN
blitFramebuffer->setSource(sourceRenderTarget);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "source");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), sourceRenderTarget->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
blitFramebuffer->setSource(sourceRenderTarget);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
blitFramebuffer->setSource(nullptr);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "source");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), Qt3DCore::QNodeId());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// destinationRenderTarget
// WHEN
blitFramebuffer->setDestination(destinationRenderTarget);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "destination");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), destinationRenderTarget->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
blitFramebuffer->setDestination(destinationRenderTarget);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
blitFramebuffer->setDestination(nullptr);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "destination");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), Qt3DCore::QNodeId());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// sourceRect
// WHEN
blitFramebuffer->setSourceRect(QRect(0,0,1,1));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceRect");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<QRect>(), QRect(0,0,1,1)) ;
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
blitFramebuffer->setSourceRect(QRect(0,0,1,1));
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
blitFramebuffer->setSourceRect(QRect());
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceRect");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<QRect>(), QRect());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// destinationRect
blitFramebuffer->setDestinationRect(QRect(0,0,1,1));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "destinationRect");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<QRect>(), QRect(0,0,1,1)) ;
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
blitFramebuffer->setDestinationRect(QRect(0,0,1,1));
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
blitFramebuffer->setDestinationRect(QRect());
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "destinationRect");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<QRect>(), QRect());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// sourceAttachmentPoint
// WHEN
blitFramebuffer->setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceAttachmentPoint");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color1);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
blitFramebuffer->setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
blitFramebuffer->setSourceAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color0);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sourceAttachmentPoint");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color0);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// destinationAttachmentPoint
// WHEN
blitFramebuffer->setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "destinationAttachmentPoint");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color1);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
blitFramebuffer->setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color1);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
blitFramebuffer->setDestinationAttachmentPoint(Qt3DRender::QRenderTargetOutput::Color0);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "destinationAttachmentPoint");
- QCOMPARE(change->subjectId(), blitFramebuffer->id());
- QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), Qt3DRender::QRenderTargetOutput::Color0);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), blitFramebuffer.data());
+
+ arbiter.dirtyNodes.clear();
}
void checkSourceDestReset()
diff --git a/tests/auto/render/qbuffer/tst_qbuffer.cpp b/tests/auto/render/qbuffer/tst_qbuffer.cpp
index 21bedf744..94c0a49cb 100644
--- a/tests/auto/render/qbuffer/tst_qbuffer.cpp
+++ b/tests/auto/render/qbuffer/tst_qbuffer.cpp
@@ -130,27 +130,23 @@ private Q_SLOTS:
// WHEN
buffer->setUsage(Qt3DRender::QBuffer::DynamicCopy);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "usage");
- QCOMPARE(change->value().value<int>(), static_cast<int>(Qt3DRender::QBuffer::DynamicCopy));
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), buffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
buffer->setData(QByteArrayLiteral("Z28"));
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "data");
- QCOMPARE(change->value().value<QByteArray>(), QByteArrayLiteral("Z28"));
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), buffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
Qt3DRender::QBufferDataGeneratorPtr functor(new TestFunctor(355));
@@ -158,37 +154,28 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "dataGenerator");
- QCOMPARE(change->value().value<Qt3DRender::QBufferDataGeneratorPtr>(), functor);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), buffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
buffer->setSyncData(true);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "syncData");
- QCOMPARE(change->value().toBool(), true);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), buffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
buffer->updateData(1, QByteArrayLiteral("L1"));
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- QCOMPARE(buffer->data(), QByteArrayLiteral("ZL1"));
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "updateData");
- Qt3DRender::QBufferUpdate updateData = change->value().value<Qt3DRender::QBufferUpdate>();
- QCOMPARE(updateData.offset, 1);
- QCOMPARE(updateData.data, QByteArrayLiteral("L1"));
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), buffer.data());
}
};
diff --git a/tests/auto/render/qcamera/tst_qcamera.cpp b/tests/auto/render/qcamera/tst_qcamera.cpp
index fb2d3ea64..0dcbce63f 100644
--- a/tests/auto/render/qcamera/tst_qcamera.cpp
+++ b/tests/auto/render/qcamera/tst_qcamera.cpp
@@ -34,10 +34,8 @@
#include <qbackendnodetester.h>
#include <Qt3DCore/QEntity>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
-#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/qtransform.h>
@@ -56,6 +54,47 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+QVector<Qt3DCore::QNode *> getNodesForCreation(Qt3DCore::QNode *root)
+{
+ using namespace Qt3DCore;
+
+ QVector<QNode *> nodes;
+ Qt3DCore::QNodeVisitor visitor;
+ visitor.traverse(root, [&nodes](QNode *node) {
+ nodes.append(node);
+
+ // Store the metaobject of the node in the QNode so that we have it available
+ // to us during destruction in the QNode destructor. This allows us to send
+ // the QNodeId and the metaobject as typeinfo to the backend aspects so they
+ // in turn can find the correct QBackendNodeMapper object to handle the destruction
+ // of the corresponding backend nodes.
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(QNodePrivate::findStaticMetaObject(node->metaObject()));
+
+ // Mark this node as having been handled for creation so that it is picked up
+ d->m_hasBackendNode = true;
+ });
+
+ return nodes;
+}
+
+QVector<Qt3DCore::NodeTreeChange> nodeTreeChangesForNodes(const QVector<Qt3DCore::QNode *> nodes)
+{
+ QVector<Qt3DCore::NodeTreeChange> nodeTreeChanges;
+ nodeTreeChanges.reserve(nodes.size());
+
+ for (Qt3DCore::QNode *n : nodes) {
+ nodeTreeChanges.push_back({
+ n->id(),
+ Qt3DCore::QNodePrivate::get(n)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ n
+ });
+ }
+
+ return nodeTreeChanges;
+}
+
class TestAspect : public Qt3DRender::QRenderAspect
{
public:
@@ -65,20 +104,15 @@ public:
{
QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), creationChanges);
+ const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root);
+ d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), nodeTreeChangesForNodes(nodes));
Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
m_sceneRoot = rootEntity;
}
- ~TestAspect()
- {
- QRenderAspect::onUnregistered();
- }
+ ~TestAspect();
void onRegistered() { QRenderAspect::onRegistered(); }
void onUnregistered() { QRenderAspect::onUnregistered(); }
@@ -92,6 +126,11 @@ private:
Render::Entity *m_sceneRoot;
};
+TestAspect::~TestAspect()
+{
+ QRenderAspect::onUnregistered();
+}
+
} // namespace Qt3DRender
QT_END_NAMESPACE
@@ -100,10 +139,6 @@ namespace {
void runRequiredJobs(Qt3DRender::TestAspect *test)
{
- Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob;
- updateEntitiesJob.setManager(test->nodeManagers());
- updateEntitiesJob.run();
-
Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform;
updateWorldTransform.setRoot(test->sceneRoot());
updateWorldTransform.setManagers(test->nodeManagers());
diff --git a/tests/auto/render/qcameralens/tst_qcameralens.cpp b/tests/auto/render/qcameralens/tst_qcameralens.cpp
index adff66dc5..131c3a9d5 100644
--- a/tests/auto/render/qcameralens/tst_qcameralens.cpp
+++ b/tests/auto/render/qcameralens/tst_qcameralens.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/qcameralens_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -423,12 +422,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -438,6 +436,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -452,24 +451,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setNearPlane(5.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setNearPlane(5.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -484,24 +481,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setFarPlane(5.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setFarPlane(5.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -516,24 +511,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setFieldOfView(5.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setFieldOfView(5.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -548,24 +541,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setAspectRatio(9.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setAspectRatio(9.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -580,24 +571,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setLeft(0.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setLeft(0.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -612,24 +601,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setRight(24.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setRight(24.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -644,24 +631,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setBottom(-12.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setBottom(-12.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -676,24 +661,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setTop(12.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setTop(12.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -708,24 +691,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setExposure(2.0f);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "exposure");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setExposure(2.0f);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -743,25 +724,22 @@ private Q_SLOTS:
{
// WHEN
cameraLens.setProjectionMatrix(m);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "projectionMatrix");
- QCOMPARE(change->value().value<QMatrix4x4>(), m);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &cameraLens);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
cameraLens.setProjectionMatrix(m);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.events.size(), 0);
}
}
diff --git a/tests/auto/render/qcameraselector/tst_qcameraselector.cpp b/tests/auto/render/qcameraselector/tst_qcameraselector.cpp
index c11dde57f..650e531c2 100644
--- a/tests/auto/render/qcameraselector/tst_qcameraselector.cpp
+++ b/tests/auto/render/qcameraselector/tst_qcameraselector.cpp
@@ -92,49 +92,41 @@ private Q_SLOTS:
// WHEN
Qt3DCore::QEntity *camera = new Qt3DCore::QEntity();
cameraSelector->setCamera(camera);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "camera");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), camera->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), cameraSelector.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
cameraSelector->setCamera(camera);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
Qt3DCore::QEntity *camera2 = new Qt3DCore::QEntity();
cameraSelector->setCamera(camera2);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "camera");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), camera2->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), cameraSelector.data());
+
+ arbiter.dirtyNodes.clear();
// WHEN
cameraSelector->setCamera(nullptr);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "camera");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), Qt3DCore::QNodeId());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), cameraSelector.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkCameraBookkeeping()
diff --git a/tests/auto/render/qclearbuffers/tst_qclearbuffers.cpp b/tests/auto/render/qclearbuffers/tst_qclearbuffers.cpp
index ce1493e10..d2407229d 100644
--- a/tests/auto/render/qclearbuffers/tst_qclearbuffers.cpp
+++ b/tests/auto/render/qclearbuffers/tst_qclearbuffers.cpp
@@ -104,38 +104,30 @@ private Q_SLOTS:
// WHEN
clearBuffer->setBuffers(Qt3DRender::QClearBuffers::AllBuffers);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "buffers");
- QCOMPARE(change->subjectId(), clearBuffer->id());
- QCOMPARE(change->value().value<Qt3DRender::QClearBuffers::BufferType>(), Qt3DRender::QClearBuffers::AllBuffers);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), clearBuffer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
clearBuffer->setBuffers(Qt3DRender::QClearBuffers::AllBuffers);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
clearBuffer->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "buffers");
- QCOMPARE(change->subjectId(), clearBuffer->id());
- QCOMPARE(change->value().value<Qt3DRender::QClearBuffers::BufferType>(), Qt3DRender::QClearBuffers::ColorDepthBuffer);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), clearBuffer.data());
+
+ arbiter.dirtyNodes.clear();
}
};
diff --git a/tests/auto/render/qcomputecommand/tst_qcomputecommand.cpp b/tests/auto/render/qcomputecommand/tst_qcomputecommand.cpp
index cc07120a2..505229d5c 100644
--- a/tests/auto/render/qcomputecommand/tst_qcomputecommand.cpp
+++ b/tests/auto/render/qcomputecommand/tst_qcomputecommand.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/qcomputecommand_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -214,13 +213,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "workGroupX");
- QCOMPARE(change->value().value<int>(), computeCommand.workGroupX());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &computeCommand);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -229,7 +226,7 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -244,25 +241,22 @@ private Q_SLOTS:
{
// WHEN
computeCommand.setWorkGroupY(512);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "workGroupY");
- QCOMPARE(change->value().value<int>(), computeCommand.workGroupY());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &computeCommand);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
computeCommand.setWorkGroupY(512);
- QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -280,13 +274,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "workGroupZ");
- QCOMPARE(change->value().value<int>(), computeCommand.workGroupZ());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &computeCommand);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -296,6 +288,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -313,13 +306,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "runType");
- QCOMPARE(change->value().value<int>(), int(computeCommand.runType()));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &computeCommand);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -329,6 +320,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -349,23 +341,14 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 2);
- {
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "frameCount");
- QCOMPARE(change->value().value<int>(), 1);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
- {
- auto change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "enabled");
- QCOMPARE(change->value().value<bool>(), true);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &computeCommand);
+ QCOMPARE(computeCommand.isEnabled(), true);
computeCommand.setEnabled(false);
QCoreApplication::processEvents();
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -374,24 +357,15 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 2);
- {
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "frameCount");
- QCOMPARE(change->value().value<int>(), 2);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
- {
- auto change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "enabled");
- QCOMPARE(change->value().value<bool>(), true);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
-
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &computeCommand);
+ QCOMPARE(computeCommand.isEnabled(), true);
computeCommand.setEnabled(false);
QCoreApplication::processEvents();
arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -400,41 +374,16 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 5);
- {
- auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "workGroupX");
- QCOMPARE(change->value().value<int>(), 10);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
- {
- auto change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "workGroupY");
- QCOMPARE(change->value().value<int>(), 11);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
- {
- auto change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "workGroupZ");
- QCOMPARE(change->value().value<int>(), 12);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
- {
- auto change = arbiter.events.at(3).staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "frameCount");
- QCOMPARE(change->value().value<int>(), 1);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
- {
- auto change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "enabled");
- QCOMPARE(change->value().value<bool>(), true);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- }
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &computeCommand);
+ QCOMPARE(computeCommand.isEnabled(), true);
+ QCOMPARE(computeCommand.workGroupX(), 10);
+ QCOMPARE(computeCommand.workGroupY(), 11);
+ QCOMPARE(computeCommand.workGroupZ(), 12);
computeCommand.setEnabled(false);
- QCoreApplication::processEvents();
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
}
diff --git a/tests/auto/render/qdispatchcompute/tst_qdispatchcompute.cpp b/tests/auto/render/qdispatchcompute/tst_qdispatchcompute.cpp
index 6fa55f370..c4bed3a83 100644
--- a/tests/auto/render/qdispatchcompute/tst_qdispatchcompute.cpp
+++ b/tests/auto/render/qdispatchcompute/tst_qdispatchcompute.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/qdispatchcompute_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -189,13 +188,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "workGroupX");
- QCOMPARE(change->value().value<int>(), dispatchCompute.workGroupX());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &dispatchCompute);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -205,6 +202,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -222,13 +220,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "workGroupY");
- QCOMPARE(change->value().value<int>(), dispatchCompute.workGroupY());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &dispatchCompute);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -238,6 +234,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -255,13 +252,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "workGroupZ");
- QCOMPARE(change->value().value<int>(), dispatchCompute.workGroupZ());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &dispatchCompute);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -271,6 +266,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qeffect/tst_qeffect.cpp b/tests/auto/render/qeffect/tst_qeffect.cpp
index 7449fee2c..cc4889b8f 100644
--- a/tests/auto/render/qeffect/tst_qeffect.cpp
+++ b/tests/auto/render/qeffect/tst_qeffect.cpp
@@ -34,9 +34,6 @@
#include <Qt3DRender/private/qeffect_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -217,13 +214,8 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->addedNodeId(), parameter.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QVERIFY(effect.parameters().contains(&parameter));
}
{
@@ -232,13 +224,8 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->removedNodeId(), parameter.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QVERIFY(!effect.parameters().contains(&parameter));
}
}
@@ -257,13 +244,10 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "technique");
- QCOMPARE(change->addedNodeId(), technique.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &effect);
+ arbiter.dirtyNodes.clear();
}
{
@@ -272,13 +256,10 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->propertyName(), "technique");
- QCOMPARE(change->removedNodeId(), technique.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &effect);
+ arbiter.dirtyNodes.clear();
}
}
diff --git a/tests/auto/render/qfilterkey/tst_qfilterkey.cpp b/tests/auto/render/qfilterkey/tst_qfilterkey.cpp
index 8c8381323..f4c31c89e 100644
--- a/tests/auto/render/qfilterkey/tst_qfilterkey.cpp
+++ b/tests/auto/render/qfilterkey/tst_qfilterkey.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/qfilterkey_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -166,13 +165,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "value");
- QCOMPARE(change->value().value<QVariant>(), filterKey.value());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &filterKey);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -182,6 +179,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -199,13 +197,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "name");
- QCOMPARE(change->value().value<QString>(), filterKey.name());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &filterKey);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -215,6 +211,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp b/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp
index 1e19d8609..24febdac4 100644
--- a/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp
+++ b/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp
@@ -181,14 +181,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "enabled");
- QCOMPARE(change->subjectId(), frameGraphNode->id());
- QCOMPARE(change->value().toBool(), false);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), frameGraphNode.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
frameGraphNode->setEnabled(false);
@@ -196,20 +193,18 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
frameGraphNode->setEnabled(true);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "enabled");
- QCOMPARE(change->subjectId(), frameGraphNode->id());
- QCOMPARE(change->value().toBool(), true);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), frameGraphNode.data());
+
+ arbiter.dirtyNodes.clear();
}
void checkParentFrameNodeRetrieval()
diff --git a/tests/auto/render/qgeometry/tst_qgeometry.cpp b/tests/auto/render/qgeometry/tst_qgeometry.cpp
index 55b7e752c..017314ecf 100644
--- a/tests/auto/render/qgeometry/tst_qgeometry.cpp
+++ b/tests/auto/render/qgeometry/tst_qgeometry.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include <QtTest/QTest>
+#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
@@ -36,9 +37,6 @@
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/qbuffer.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
#include <QSignalSpy>
#include "testpostmanarbiter.h"
@@ -130,13 +128,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeAddedChangePtr nodeAddedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(nodeAddedChange->propertyName(), "attribute");
- QCOMPARE(nodeAddedChange->addedNodeId(), attr.id());
- QCOMPARE(nodeAddedChange->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometry.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
geometry->addAttribute(&attr);
@@ -144,17 +140,16 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
geometry->removeAttribute(&attr);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeRemovedChangePtr nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "attribute");
- QCOMPARE(nodeRemovedChange->removedNodeId(), attr.id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometry.data());
arbiter.events.clear();
}
diff --git a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp
index 221d0f880..28574d3c5 100644
--- a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp
+++ b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp
@@ -38,10 +38,6 @@
#include <Qt3DRender/qbuffer.h>
#include <Qt3DRender/private/qgeometryrenderer_p.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
-
#include "testpostmanarbiter.h"
class TestFactory : public Qt3DRender::QGeometryFactory
@@ -162,117 +158,99 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "instanceCount");
- QCOMPARE(change->value().value<int>(), 256);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
geometryRenderer->setVertexCount(1340);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "vertexCount");
- QCOMPARE(change->value().value<int>(), 1340);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
geometryRenderer->setIndexOffset(883);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "indexOffset");
- QCOMPARE(change->value().value<int>(), 883);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
geometryRenderer->setFirstInstance(1200);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "firstInstance");
- QCOMPARE(change->value().value<int>(), 1200);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
geometryRenderer->setIndexBufferByteOffset(91);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "indexBufferByteOffset");
- QCOMPARE(change->value().value<int>(), 91);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
geometryRenderer->setRestartIndexValue(65535);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "restartIndexValue");
- QCOMPARE(change->value().value<int>(), 65535);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
geometryRenderer->setVerticesPerPatch(2);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "verticesPerPatch");
- QCOMPARE(change->value().toInt(), 2);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
geometryRenderer->setPrimitiveRestartEnabled(true);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "primitiveRestartEnabled");
- QCOMPARE(change->value().value<bool>(), true);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Patches);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "primitiveType");
- QCOMPARE(change->value().value<int>(), static_cast<int>(Qt3DRender::QGeometryRenderer::Patches));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
Qt3DRender::QGeometryFactoryPtr factory(new TestFactory(555));
@@ -280,13 +258,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "geometryFactory");
- QCOMPARE(change->value().value<Qt3DRender::QGeometryFactoryPtr>(), factory);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
Qt3DRender::QGeometry geom;
@@ -294,13 +270,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr nodeAddedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(nodeAddedChange->propertyName(), "geometry");
- QCOMPARE(nodeAddedChange->value().value<Qt3DCore::QNodeId>(), geom.id());
- QCOMPARE(nodeAddedChange->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
Qt3DRender::QGeometry geom2;
@@ -308,13 +282,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "geometry");
- QCOMPARE(nodeRemovedChange->value().value<Qt3DCore::QNodeId>(), geom2.id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), geometryRenderer.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkGeometryBookkeeping()
diff --git a/tests/auto/render/qlayerfilter/tst_qlayerfilter.cpp b/tests/auto/render/qlayerfilter/tst_qlayerfilter.cpp
index c7686bae2..648a1d104 100644
--- a/tests/auto/render/qlayerfilter/tst_qlayerfilter.cpp
+++ b/tests/auto/render/qlayerfilter/tst_qlayerfilter.cpp
@@ -30,8 +30,6 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/qlayer.h>
#include <Qt3DRender/qlayerfilter.h>
@@ -119,14 +117,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto addChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(addChange->propertyName(), "layer");
- QCOMPARE(addChange->subjectId(), layerFilter->id());
- QCOMPARE(addChange->addedNodeId(), layerFilter->layers().at(0)->id());
- QCOMPARE(addChange->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(layerFilter.data()));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
layer = new Qt3DRender::QLayer(layerFilter.data());
@@ -135,14 +130,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- addChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(addChange->propertyName(), "layer");
- QCOMPARE(addChange->subjectId(), layerFilter->id());
- QCOMPARE(addChange->addedNodeId(), layerFilter->layers().at(1)->id());
- QCOMPARE(addChange->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(layerFilter.data()));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
layer = layerFilter->layers().at(0);
@@ -150,14 +142,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto removeChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(removeChange->propertyName(), "layer");
- QCOMPARE(removeChange->subjectId(), layerFilter->id());
- QCOMPARE(removeChange->removedNodeId(), layer->id());
- QCOMPARE(removeChange->type(), Qt3DCore::PropertyValueRemoved);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(layerFilter.data()));
+
+ arbiter.dirtyNodes.clear();
}
void checkLayerBookkeeping()
diff --git a/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp b/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp
index ba357c8c9..7d4e5d45d 100644
--- a/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp
+++ b/tests/auto/render/qlevelofdetail/tst_qlevelofdetail.cpp
@@ -93,12 +93,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "thresholdType");
- QCOMPARE(change->value().value<int>(), static_cast<int>(Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold));
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), lod.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -108,12 +107,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "thresholds");
- QCOMPARE(change->value().value<decltype(thresholds)>(), thresholds);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), lod.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
}
};
diff --git a/tests/auto/render/qmaterial/tst_qmaterial.cpp b/tests/auto/render/qmaterial/tst_qmaterial.cpp
index dc6fe7789..994b11d43 100644
--- a/tests/auto/render/qmaterial/tst_qmaterial.cpp
+++ b/tests/auto/render/qmaterial/tst_qmaterial.cpp
@@ -27,9 +27,6 @@
****************************************************************************/
#include <QtTest/QTest>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DRender/private/qrenderstate_p.h>
@@ -253,37 +250,26 @@ private Q_SLOTS:
// WHEN
Qt3DRender::QEffect effect;
material->setEffect(&effect);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "effect");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), effect.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), material.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// GIVEN
TestArbiter arbiter2;
QScopedPointer<TestMaterial> material2(new TestMaterial());
arbiter2.setArbiterOnNode(material2.data());
- QCoreApplication::processEvents();
- // Clear events trigger by child generation of TestMnterial
- arbiter2.events.clear();
-
// WHEN
material2->setEffect(&effect);
- QCoreApplication::processEvents();
// THEN
- qDebug() << Q_FUNC_INFO << arbiter2.events.size();
- QCOMPARE(arbiter2.events.size(), 1);
- change = arbiter2.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "effect");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), effect.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter2.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter2.dirtyNodes.front(), material2.data());
+
+ arbiter2.dirtyNodes.clear();
}
void checkDynamicParametersAddedUpdates()
@@ -306,13 +292,9 @@ private Q_SLOTS:
QCOMPARE(param->parent(), material);
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeAddedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->addedNodeId(), param->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(material->parameters().contains(param));
// WHEN (add parameter to effect)
param = new Qt3DRender::QParameter("testParamEffect", QVariant::fromValue(383.0f));
@@ -320,13 +302,9 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->addedNodeId(), param->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 2);
+ QVERIFY(material->effect()->parameters().contains(param));
// WHEN (add parameter to technique)
param = new Qt3DRender::QParameter("testParamTechnique", QVariant::fromValue(383.0f));
@@ -334,13 +312,10 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->addedNodeId(), param->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 3);
+ QVERIFY(material->m_technique->parameters().contains(param));
- arbiter.events.clear();
// WHEN (add parameter to renderpass)
param = new Qt3DRender::QParameter("testParamRenderPass", QVariant::fromValue(383.0f));
@@ -348,13 +323,9 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->addedNodeId(), param->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 4);
+ QVERIFY(material->m_renderPass->parameters().contains(param));
}
void checkShaderProgramUpdates()
@@ -364,93 +335,64 @@ private Q_SLOTS:
TestMaterial *material = new TestMaterial();
arbiter.setArbiterOnNode(material);
- QCoreApplication::processEvents();
- // Clear events trigger by child generation of TestMnterial
- arbiter.events.clear();
-
// WHEN
const QByteArray vertexCode = QByteArrayLiteral("new vertex shader code");
material->m_shaderProgram->setVertexShaderCode(vertexCode);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "vertexShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), vertexCode);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), material->m_shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
const QByteArray fragmentCode = QByteArrayLiteral("new fragment shader code");
material->m_shaderProgram->setFragmentShaderCode(fragmentCode);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "fragmentShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), fragmentCode);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), material->m_shaderProgram);
+ arbiter.dirtyNodes.clear();
// WHEN
const QByteArray geometryCode = QByteArrayLiteral("new geometry shader code");
material->m_shaderProgram->setGeometryShaderCode(geometryCode);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "geometryShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), geometryCode);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), material->m_shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
const QByteArray computeCode = QByteArrayLiteral("new compute shader code");
material->m_shaderProgram->setComputeShaderCode(computeCode);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "computeShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), computeCode);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), material->m_shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
const QByteArray tesselControlCode = QByteArrayLiteral("new tessellation control shader code");
material->m_shaderProgram->setTessellationControlShaderCode(tesselControlCode);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "tessellationControlShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), tesselControlCode);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), material->m_shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
const QByteArray tesselEvalCode = QByteArrayLiteral("new tessellation eval shader code");
material->m_shaderProgram->setTessellationEvaluationShaderCode(tesselEvalCode);
- QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "tessellationEvaluationShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), tesselEvalCode);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), material->m_shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkEffectBookkeeping()
diff --git a/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp b/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp
index 25ee10cad..41fdd8428 100644
--- a/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp
+++ b/tests/auto/render/qmemorybarrier/tst_qmemorybarrier.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/qmemorybarrier_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -148,13 +147,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "waitOperations");
- QCOMPARE(change->value().value<Qt3DRender::QMemoryBarrier::Operations>(), memoryBarrier.waitOperations());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &memoryBarrier);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -164,6 +161,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qmesh/tst_qmesh.cpp b/tests/auto/render/qmesh/tst_qmesh.cpp
index fbc566395..0df96dd24 100644
--- a/tests/auto/render/qmesh/tst_qmesh.cpp
+++ b/tests/auto/render/qmesh/tst_qmesh.cpp
@@ -186,18 +186,10 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "geometryFactory");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- Qt3DRender::QGeometryFactoryPtr factory = change->value().value<Qt3DRender::QGeometryFactoryPtr>();
- QSharedPointer<Qt3DRender::MeshLoaderFunctor> meshFunctor = qSharedPointerCast<Qt3DRender::MeshLoaderFunctor>(factory);
- QVERIFY(meshFunctor != nullptr);
- QCOMPARE(meshFunctor->mesh(), mesh.id());
- QCOMPARE(meshFunctor->sourcePath(), mesh.source());
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mesh);
+
+ arbiter.dirtyNodes.clear();
}
{
@@ -206,7 +198,7 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -231,18 +223,10 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "geometryFactory");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- Qt3DRender::QGeometryFactoryPtr factory = change->value().value<Qt3DRender::QGeometryFactoryPtr>();
- QSharedPointer<Qt3DRender::MeshLoaderFunctor> meshFunctor = qSharedPointerCast<Qt3DRender::MeshLoaderFunctor>(factory);
- QVERIFY(meshFunctor != nullptr);
- QCOMPARE(meshFunctor->mesh(), mesh.id());
- QCOMPARE(meshFunctor->meshName(), mesh.meshName());
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &mesh);
+
+ arbiter.dirtyNodes.clear();
}
{
@@ -251,33 +235,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
- void checkStatusUpdate()
- {
- // GIVEN
- qRegisterMetaType<Qt3DRender::QMesh::Status>("Status");
- MyQMesh mesh;
- QSignalSpy spy(&mesh, SIGNAL(statusChanged(Status)));
-
- // THEN
- QCOMPARE(mesh.status(), Qt3DRender::QMesh::None);
-
- // WHEN
- const Qt3DRender::QMesh::Status newStatus = Qt3DRender::QMesh::Error;
- Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(mesh.id()));
- e->setPropertyName("status");
- e->setValue(QVariant::fromValue(newStatus));
- mesh.sceneChangeEvent(e);
-
- // THEN
- QCOMPARE(mesh.status(), newStatus);
- QCOMPARE(spy.count(), 1);
- }
-
void checkGeometryFactoryIsAccessibleEvenWithNoScene() // QTBUG-65506
{
// GIVEN
diff --git a/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp b/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp
index bd486774c..5977829a6 100644
--- a/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp
+++ b/tests/auto/render/qobjectpicker/tst_qobjectpicker.cpp
@@ -156,14 +156,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- QCOMPARE(picker.priority(), 883);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "priority");
- QCOMPARE(change->value().value<int>(), picker.priority());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &picker);
+
+ arbiter.dirtyNodes.clear();
}
{
@@ -173,6 +170,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
{
@@ -182,14 +180,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- QCOMPARE(picker.isDragEnabled(), true);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "dragEnabled");
- QCOMPARE(change->value().value<bool>(), picker.isDragEnabled());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &picker);
+
+ arbiter.dirtyNodes.clear();
}
{
@@ -199,6 +194,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
{
@@ -208,14 +204,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- QCOMPARE(picker.isHoverEnabled(), true);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "hoverEnabled");
- QCOMPARE(change->value().value<bool>(), picker.isHoverEnabled());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &picker);
+
+ arbiter.dirtyNodes.clear();
}
{
@@ -225,6 +218,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
}
@@ -240,102 +234,25 @@ private Q_SLOTS:
QTest::newRow("objectPicker_all_true") << objectPicker;
}
- // TODO: Avoid cloning here
-// void checkCloning()
-// {
-// // GIVEN
-// QFETCH(Qt3DRender::QObjectPicker *, objectPicker);
-
-// // WHEN
-// Qt3DRender::QObjectPicker *clone = static_cast<Qt3DRender::QObjectPicker *>(QNode::clone(objectPicker));
-// QCoreApplication::processEvents();
-
-// // THEN
-// QVERIFY(clone != nullptr);
-// QCOMPARE(objectPicker->id(), clone->id());
-// QCOMPARE(objectPicker->isHoverEnabled(), clone->isHoverEnabled());
-// QCOMPARE(objectPicker->isPressed(), clone->isPressed());
-// QCOMPARE(objectPicker->containsMouse(), clone->containsMouse());
-// }
-
void checkPropertyUpdates()
{
// GIVEN
TestArbiter arbiter;
+ Qt3DCore::QScene scene;
QScopedPointer<Qt3DRender::QObjectPicker> objectPicker(new Qt3DRender::QObjectPicker());
arbiter.setArbiterOnNode(objectPicker.data());
+ Qt3DCore::QNodePrivate::get(objectPicker.data())->setScene(&scene);
// WHEN
objectPicker->setHoverEnabled(true);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "hoverEnabled");
- QCOMPARE(change->value().toBool(), true);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
- }
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), objectPicker.data());
- void checkBackendUpdates_data()
- {
- QTest::addColumn<QByteArray>("signalPrototype");
- QTest::addColumn<QByteArray>("propertyName");
- QTest::addColumn<bool>("requiresEvent");
-
- QTest::newRow("clicked")
- << QByteArray(SIGNAL(clicked(Qt3DRender::QPickEvent *)))
- << QByteArrayLiteral("clicked")
- << true;
-
- QTest::newRow("pressed")
- << QByteArray(SIGNAL(pressed(Qt3DRender::QPickEvent *)))
- << QByteArrayLiteral("pressed")
- << true;
-
- QTest::newRow("released")
- << QByteArray(SIGNAL(released(Qt3DRender::QPickEvent *)))
- << QByteArrayLiteral("released")
- << true;
-
- QTest::newRow("entered")
- << QByteArray(SIGNAL(entered()))
- << QByteArrayLiteral("entered")
- << false;
-
- QTest::newRow("exited")
- << QByteArray(SIGNAL(exited()))
- << QByteArrayLiteral("exited")
- << false;
- }
-
- void checkBackendUpdates()
- {
- // GIVEN
- QFETCH(QByteArray, signalPrototype);
- QFETCH(QByteArray, propertyName);
- QFETCH(bool, requiresEvent);
- QScopedPointer<MyObjectPicker> objectPicker(new MyObjectPicker());
- QSignalSpy spy(objectPicker.data(), signalPrototype.constData());
- Qt3DRender::QPickEventPtr event(new Qt3DRender::QPickEvent());
-
- // WHEN
- // Create Backend Change and distribute it to frontend node
- Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(objectPicker->id()));
- e->setPropertyName(propertyName.constData());
- if (requiresEvent)
- {
- QVariant v;
- v.setValue<Qt3DRender::QPickEventPtr>(event);
- e->setValue(v);
- }
- objectPicker->sceneChangeEvent(e);
-
- // THEN
- // Check that the QObjectPicker triggers the expected signal
- QCOMPARE(spy.count(), 1);
+ arbiter.dirtyNodes.clear();
}
};
diff --git a/tests/auto/render/qparameter/tst_qparameter.cpp b/tests/auto/render/qparameter/tst_qparameter.cpp
index d5957db27..3df09cff4 100644
--- a/tests/auto/render/qparameter/tst_qparameter.cpp
+++ b/tests/auto/render/qparameter/tst_qparameter.cpp
@@ -31,7 +31,6 @@
#include <Qt3DRender/private/qparameter_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/qentity.h>
@@ -166,13 +165,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "name");
- QCOMPARE(change->value().value<QString>(), parameter.name());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &parameter);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -182,6 +179,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -199,13 +197,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "value");
- QCOMPARE(change->value().value<QVariant>(), parameter.value());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &parameter);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -215,6 +211,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
// WHEN -> QNode -> QNodeId
@@ -227,13 +224,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "value");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(),testEntity.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &parameter);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -243,6 +238,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp b/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp
index 890d6ee3e..10a532454 100644
--- a/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp
+++ b/tests/auto/render/qproximityfilter/tst_qproximityfilter.cpp
@@ -31,7 +31,6 @@
#include <Qt3DRender/private/qproximityfilter_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include <Qt3DCore/qentity.h>
@@ -176,13 +175,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "entity");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), proximityFilter.entity()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &proximityFilter);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -192,6 +189,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -209,13 +207,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "distanceThreshold");
- QCOMPARE(change->value().value<float>(), proximityFilter.distanceThreshold());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &proximityFilter);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -225,6 +221,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qray3d/tst_qray3d.cpp b/tests/auto/render/qray3d/tst_qray3d.cpp
index 008b89aca..ef0702a0a 100644
--- a/tests/auto/render/qray3d/tst_qray3d.cpp
+++ b/tests/auto/render/qray3d/tst_qray3d.cpp
@@ -506,7 +506,7 @@ void tst_QRay3D::properties()
QCOMPARE(r.direction(), Vector3D(4, 5, 6).normalized());
obj.setProperty("ray",
- qVariantFromValue
+ QVariant::fromValue
(Qt3DRender::RayCasting::QRay3D(Vector3D(-1, -2, -3), Vector3D(-4, -5, -6))));
r = qvariant_cast<Qt3DRender::RayCasting::QRay3D>(obj.property("ray"));
diff --git a/tests/auto/render/qraycaster/tst_qraycaster.cpp b/tests/auto/render/qraycaster/tst_qraycaster.cpp
index 43b317f00..720c372de 100644
--- a/tests/auto/render/qraycaster/tst_qraycaster.cpp
+++ b/tests/auto/render/qraycaster/tst_qraycaster.cpp
@@ -30,6 +30,7 @@
#include <QtTest/QSignalSpy>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/QRayCaster>
@@ -111,13 +112,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "origin");
- QCOMPARE(change->value().value<QVector3D>(), QVector3D(1., 1., 1.));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), rayCaster.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
auto layer = new Qt3DRender::QLayer(rayCaster.data());
diff --git a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp
index 2fab1e837..9ed7651fc 100644
--- a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp
+++ b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QTest>
#include <QtTest/QSignalSpy>
+#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DRender/QRenderCapture>
@@ -72,17 +73,11 @@ private Q_SLOTS:
QScopedPointer<Qt3DRender::QRenderCaptureReply> reply(renderCapture->requestCapture(QRect(10, 15, 20, 50)));
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "renderCaptureRequest");
- QCOMPARE(change->subjectId(),renderCapture->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QVERIFY(change->value().canConvert<Qt3DRender::QRenderCaptureRequest>());
- const Qt3DRender::QRenderCaptureRequest request = change->value().value<Qt3DRender::QRenderCaptureRequest>();
- QCOMPARE(request.captureId, 1);
- QCOMPARE(request.rect, QRect(10, 15, 20, 50));
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), renderCapture.data());
+
+ arbiter.dirtyNodes.clear();
}
void checkRenderCaptureReply()
diff --git a/tests/auto/render/qrenderpass/tst_qrenderpass.cpp b/tests/auto/render/qrenderpass/tst_qrenderpass.cpp
index bcc8e9313..81f949064 100644
--- a/tests/auto/render/qrenderpass/tst_qrenderpass.cpp
+++ b/tests/auto/render/qrenderpass/tst_qrenderpass.cpp
@@ -36,7 +36,6 @@
#include <Qt3DRender/private/qrenderpass_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
@@ -305,13 +304,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "shaderProgram");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), renderPass.shaderProgram()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -321,6 +318,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -339,11 +337,9 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "filterKeys");
- QCOMPARE(change->addedNodeId(), filterKey.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
arbiter.events.clear();
}
@@ -354,11 +350,9 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->propertyName(), "filterKeys");
- QCOMPARE(change->removedNodeId(), filterKey.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
arbiter.events.clear();
}
@@ -379,11 +373,9 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "renderState");
- QCOMPARE(change->addedNodeId(), renderState.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
arbiter.events.clear();
}
@@ -394,11 +386,9 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->propertyName(), "renderState");
- QCOMPARE(change->removedNodeId(), renderState.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
arbiter.events.clear();
}
@@ -419,11 +409,9 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->addedNodeId(), parameter.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
arbiter.events.clear();
}
@@ -434,11 +422,9 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->removedNodeId(), parameter.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderPass);
arbiter.events.clear();
}
diff --git a/tests/auto/render/qrenderpassfilter/tst_qrenderpassfilter.cpp b/tests/auto/render/qrenderpassfilter/tst_qrenderpassfilter.cpp
index 23544c0c6..d12f04e33 100644
--- a/tests/auto/render/qrenderpassfilter/tst_qrenderpassfilter.cpp
+++ b/tests/auto/render/qrenderpassfilter/tst_qrenderpassfilter.cpp
@@ -37,10 +37,6 @@
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qfilterkey.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
-
#include "testpostmanarbiter.h"
class tst_QRenderPassFilter: public QObject
@@ -154,14 +150,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeAddedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->subjectId(),renderPassFilter->id());
- QCOMPARE(change->addedNodeId(), param1->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(renderPassFilter.data()));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
renderPassFilter->addParameter(param1);
@@ -169,20 +162,18 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
renderPassFilter->removeParameter(param1);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeRemovedChangePtr nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "parameter");
- QCOMPARE(nodeRemovedChange->subjectId(), renderPassFilter->id());
- QCOMPARE(nodeRemovedChange->removedNodeId(), param1->id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(renderPassFilter.data()));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
Qt3DRender::QFilterKey *filterKey1 = new Qt3DRender::QFilterKey();
@@ -190,14 +181,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "match");
- QCOMPARE(change->subjectId(),renderPassFilter->id());
- QCOMPARE(change->addedNodeId(), filterKey1->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(renderPassFilter.data()));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
renderPassFilter->addMatch(filterKey1);
@@ -205,20 +193,18 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
renderPassFilter->removeMatch(filterKey1);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "match");
- QCOMPARE(nodeRemovedChange->subjectId(), renderPassFilter->id());
- QCOMPARE(nodeRemovedChange->removedNodeId(), filterKey1->id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(renderPassFilter.data()));
+
+ arbiter.dirtyNodes.clear();
}
void checkParameterBookkeeping()
diff --git a/tests/auto/render/qrendersettings/tst_qrendersettings.cpp b/tests/auto/render/qrendersettings/tst_qrendersettings.cpp
index 6f182cbeb..b58ab0947 100644
--- a/tests/auto/render/qrendersettings/tst_qrendersettings.cpp
+++ b/tests/auto/render/qrendersettings/tst_qrendersettings.cpp
@@ -33,7 +33,6 @@
#include <Qt3DRender/private/qrendersettings_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -253,13 +252,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "renderPolicy");
- QCOMPARE(change->value().value<Qt3DRender::QRenderSettings::RenderPolicy>(), renderSettings.renderPolicy());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderSettings);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -269,6 +266,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -287,13 +285,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "activeFrameGraph");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), viewport.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderSettings);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -303,6 +299,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -322,13 +319,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pickMethod");
- QCOMPARE(change->value().value<Qt3DRender::QPickingSettings::PickMethod>(), pickingSettings->pickMethod());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderSettings);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -338,6 +333,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -357,13 +353,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pickResultMode");
- QCOMPARE(change->value().value<Qt3DRender::QPickingSettings::PickResultMode>(), pickingSettings->pickResultMode());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderSettings);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -373,6 +367,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -392,13 +387,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "faceOrientationPickingMode");
- QCOMPARE(change->value().value<Qt3DRender::QPickingSettings::FaceOrientationPickingMode>(), pickingSettings->faceOrientationPickingMode());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderSettings);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -408,6 +401,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -427,13 +421,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "pickWorldSpaceTolerance");
- QCOMPARE(change->value().toFloat(), pickingSettings->worldSpaceTolerance());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderSettings);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -443,6 +435,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qrenderstate/tst_qrenderstate.cpp b/tests/auto/render/qrenderstate/tst_qrenderstate.cpp
index dc2a9b242..fb212bc8f 100644
--- a/tests/auto/render/qrenderstate/tst_qrenderstate.cpp
+++ b/tests/auto/render/qrenderstate/tst_qrenderstate.cpp
@@ -41,6 +41,7 @@
#include <Qt3DRender/QBlendEquationArguments>
#include <Qt3DRender/QColorMask>
#include <Qt3DRender/QCullFace>
+#include <Qt3DRender/QDepthRange>
#include <Qt3DRender/QDepthTest>
#include <Qt3DRender/QDithering>
#include <Qt3DRender/QFrontFace>
@@ -74,8 +75,8 @@ private:
RenderStateNode* createBackendNode(QRenderState *frontend)
{
RenderStateNode *backend = m_renderStateManager.getOrCreateResource(frontend->id());
- simulateInitialization(frontend, backend);
backend->setRenderer(&m_renderer);
+ simulateInitializationSync(frontend, backend);
return backend;
}
@@ -169,6 +170,9 @@ private Q_SLOTS:
addTestCase<QStencilMask>(StencilWriteStateMask, "frontOutputMask", &QStencilMask::setFrontOutputMask, 0x12, 0x34);
addTestCase<QStencilMask>(StencilWriteStateMask, "backOutputMask", &QStencilMask::setBackOutputMask, 0x12, 0x34);
+
+ addTestCase<QDepthRange>(DepthRangeMask, "nearValue", &QDepthRange::setNearValue, 0.1, 0.2);
+ addTestCase<QDepthRange>(DepthRangeMask, "farValue", &QDepthRange::setFarValue, 0.5, 0.6);
}
void checkPropertyUpdates()
@@ -183,6 +187,7 @@ private Q_SLOTS:
// THEN
RenderStateNode *backend1 = createBackendNode(frontend1);
RenderStateNode *backend2 = createBackendNode(frontend2);
+
QVERIFY(backend1->type() == mask);
QVERIFY(backend2->type() == mask);
QVERIFY(backend1->impl() != backend2->impl());
@@ -196,18 +201,17 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<QPropertyUpdatedChange>();
- QVERIFY(change->propertyName() == propertyName);
- QCOMPARE(change->subjectId(), frontend1->id());
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), frontend1);
// WHEN
- backend1->sceneChangeEvent(change.staticCast<QSceneChange>());
+ backend1->syncFromFrontEnd(frontend1, false);
// THEN
QVERIFY(backend1->impl() == backend2->impl());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkStencilUpdates_data()
@@ -281,12 +285,12 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<QPropertyUpdatedChange>();
- QCOMPARE(change->subjectId(), frontend1->id());
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), frontend1);
// WHEN
- backend1->sceneChangeEvent(change.staticCast<QSceneChange>());
+ backend1->syncFromFrontEnd(frontend1, false);
// THEN
QVERIFY(backend1->impl() == backend2->impl());
diff --git a/tests/auto/render/qrenderstateset/tst_qrenderstateset.cpp b/tests/auto/render/qrenderstateset/tst_qrenderstateset.cpp
index 6b200d19d..39f0c3c72 100644
--- a/tests/auto/render/qrenderstateset/tst_qrenderstateset.cpp
+++ b/tests/auto/render/qrenderstateset/tst_qrenderstateset.cpp
@@ -37,10 +37,6 @@
#include <Qt3DRender/qrenderstate.h>
#include <Qt3DRender/private/qrenderstateset_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
-
#include "testpostmanarbiter.h"
class MyStateSet;
@@ -140,14 +136,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeAddedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "renderState");
- QCOMPARE(change->subjectId(), stateSet->id());
- QCOMPARE(change->addedNodeId(), state1->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(stateSet.data()));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
stateSet->addRenderState(state1);
@@ -155,20 +148,17 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
-
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
stateSet->removeRenderState(state1);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeRemovedChangePtr nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "renderState");
- QCOMPARE(nodeRemovedChange->subjectId(), stateSet->id());
- QCOMPARE(nodeRemovedChange->removedNodeId(), state1->id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(stateSet.data()));
+
+ arbiter.dirtyNodes.clear();
}
void checkRenderStateBookkeeping()
diff --git a/tests/auto/render/qrendersurfaceselector/tst_qrendersurfaceselector.cpp b/tests/auto/render/qrendersurfaceselector/tst_qrendersurfaceselector.cpp
index 982a58b2b..a30617781 100644
--- a/tests/auto/render/qrendersurfaceselector/tst_qrendersurfaceselector.cpp
+++ b/tests/auto/render/qrendersurfaceselector/tst_qrendersurfaceselector.cpp
@@ -33,7 +33,6 @@
#include <Qt3DRender/qrendersurfaceselector.h>
#include <Qt3DRender/private/qrendersurfaceselector_p.h>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -261,13 +260,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "surface");
- QCOMPARE(change->value().value<QObject *>(), renderSurfaceSelector.surface());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderSurfaceSelector);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -277,6 +274,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
// Prevents crashes with temporary window being destroyed
@@ -296,13 +294,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "externalRenderTargetSize");
- QCOMPARE(change->value().value<QSize>(), renderSurfaceSelector.externalRenderTargetSize());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderSurfaceSelector);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -312,6 +308,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -329,13 +326,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "surfacePixelRatio");
- QCOMPARE(change->value().value<float>(), renderSurfaceSelector.surfacePixelRatio());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderSurfaceSelector);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -345,6 +340,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qrendertarget/tst_qrendertarget.cpp b/tests/auto/render/qrendertarget/tst_qrendertarget.cpp
index 03a9e5f94..ad9d5f329 100644
--- a/tests/auto/render/qrendertarget/tst_qrendertarget.cpp
+++ b/tests/auto/render/qrendertarget/tst_qrendertarget.cpp
@@ -32,8 +32,6 @@
#include <Qt3DRender/private/qrendertarget_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -167,13 +165,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "output");
- QCOMPARE(change->addedNodeId(), renderTargetOutput.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderTarget);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -182,13 +178,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->propertyName(), "output");
- QCOMPARE(change->removedNodeId(), renderTargetOutput.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderTarget);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
}
};
diff --git a/tests/auto/render/qrendertargetoutput/tst_qrendertargetoutput.cpp b/tests/auto/render/qrendertargetoutput/tst_qrendertargetoutput.cpp
index c847095dc..55733f0f3 100644
--- a/tests/auto/render/qrendertargetoutput/tst_qrendertargetoutput.cpp
+++ b/tests/auto/render/qrendertargetoutput/tst_qrendertargetoutput.cpp
@@ -34,7 +34,6 @@
#include <Qt3DRender/qabstracttexture.h>
#include <Qt3DRender/qtexture.h>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -247,13 +246,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "attachmentPoint");
- QCOMPARE(change->value().value<Qt3DRender::QRenderTargetOutput::AttachmentPoint>(), renderTargetOutput.attachmentPoint());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderTargetOutput);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -263,6 +260,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -281,13 +279,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "texture");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), renderTargetOutput.texture()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderTargetOutput);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -297,6 +293,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -314,13 +311,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "mipLevel");
- QCOMPARE(change->value().value<int>(), renderTargetOutput.mipLevel());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderTargetOutput);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -330,6 +325,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -347,13 +343,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "layer");
- QCOMPARE(change->value().value<int>(), renderTargetOutput.layer());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderTargetOutput);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -363,6 +357,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -380,13 +375,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "face");
- QCOMPARE(change->value().value<Qt3DRender::QAbstractTexture::CubeMapFace>(), renderTargetOutput.face());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &renderTargetOutput);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -396,6 +389,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qrendertargetselector/tst_qrendertargetselector.cpp b/tests/auto/render/qrendertargetselector/tst_qrendertargetselector.cpp
index 6b53ab733..7bacc3b6d 100644
--- a/tests/auto/render/qrendertargetselector/tst_qrendertargetselector.cpp
+++ b/tests/auto/render/qrendertargetselector/tst_qrendertargetselector.cpp
@@ -117,14 +117,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "target");
- QCOMPARE(change->subjectId(), renderTargetSelector->id());
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), target->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), renderTargetSelector.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
renderTargetSelector->setTarget(target);
@@ -132,20 +129,18 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
renderTargetSelector->setTarget(nullptr);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "target");
- QCOMPARE(change->subjectId(), renderTargetSelector->id());
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), Qt3DCore::QNodeId());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), renderTargetSelector.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
QVector<Qt3DRender::QRenderTargetOutput::AttachmentPoint> outputs;
@@ -154,14 +149,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "outputs");
- QCOMPARE(change->subjectId(), renderTargetSelector->id());
- QCOMPARE(change->value().value<QVector<Qt3DRender::QRenderTargetOutput::AttachmentPoint> >(), outputs);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), renderTargetSelector.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
renderTargetSelector->setOutputs(outputs);
@@ -169,21 +161,18 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
renderTargetSelector->setOutputs(QVector<Qt3DRender::QRenderTargetOutput::AttachmentPoint>());
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "outputs");
- QCOMPARE(change->subjectId(), renderTargetSelector->id());
- QCOMPARE(change->value().value<QVector<Qt3DRender::QRenderTargetOutput::AttachmentPoint> >(), QVector<Qt3DRender::QRenderTargetOutput::AttachmentPoint>());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), renderTargetSelector.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkRenderTargetBookkeeping()
diff --git a/tests/auto/render/qscene2d/tst_qscene2d.cpp b/tests/auto/render/qscene2d/tst_qscene2d.cpp
index 846207456..583da6eaf 100644
--- a/tests/auto/render/qscene2d/tst_qscene2d.cpp
+++ b/tests/auto/render/qscene2d/tst_qscene2d.cpp
@@ -32,7 +32,6 @@
#include <private/qscene2d_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -222,13 +221,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "output");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), scene2d.output()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &scene2d);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -238,6 +235,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -255,14 +253,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "renderPolicy");
- QCOMPARE(change->value().value<Qt3DRender::Quick::QScene2D::RenderPolicy>(),
- scene2d.renderPolicy());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &scene2d);
+
+ arbiter.dirtyNodes.clear();
}
{
@@ -272,6 +267,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -289,13 +285,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "mouseEnabled");
- QCOMPARE(change->value().toBool(), scene2d.isMouseEnabled());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &scene2d);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -305,6 +299,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qsceneloader/tst_qsceneloader.cpp b/tests/auto/render/qsceneloader/tst_qsceneloader.cpp
index d5d3feec8..79ca6a291 100644
--- a/tests/auto/render/qsceneloader/tst_qsceneloader.cpp
+++ b/tests/auto/render/qsceneloader/tst_qsceneloader.cpp
@@ -31,7 +31,6 @@
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
#include <Qt3DCore/qtransform.h>
#include <Qt3DRender/qsceneloader.h>
@@ -130,64 +129,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "source");
- QCOMPARE(change->value().value<QUrl>(), sourceUrl);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), sceneLoader.data());
- arbiter.events.clear();
- }
-
- void checkStatusPropertyUpdate()
- {
- // GIVEN
- qRegisterMetaType<Qt3DRender::QSceneLoader::Status>("Status");
- TestArbiter arbiter;
- QScopedPointer<Qt3DRender::QSceneLoader> sceneLoader(new Qt3DRender::QSceneLoader());
- arbiter.setArbiterOnNode(sceneLoader.data());
- QSignalSpy spy(sceneLoader.data(), SIGNAL(statusChanged(Status)));
-
-
- // WHEN
- const Qt3DRender::QSceneLoader::Status newStatus = Qt3DRender::QSceneLoader::Ready;
- sceneLoader->setStatus(newStatus);
-
- // THEN
- QVERIFY(arbiter.events.empty());
- QCOMPARE(spy.count(), 1);
-
- spy.clear();
- }
-
- void checkPropertyChanges()
- {
- // GIVEN
- Qt3DCore::QScene scene;
- Qt3DCore::QEntity rootEntity;
- QScopedPointer<Qt3DRender::QSceneLoader> sceneLoader(new Qt3DRender::QSceneLoader());
- Qt3DCore::QNodePrivate::get(&rootEntity)->setScene(&scene);
- Qt3DCore::QNodePrivate::get(sceneLoader.data())->setScene(&scene);
- rootEntity.addComponent(sceneLoader.data());
-
- // WHEN
- Qt3DCore::QEntity backendCreatedSubtree;
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("scene");
- valueChange->setValue(QVariant::fromValue(&backendCreatedSubtree));
- sceneLoader->sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(static_cast<Qt3DRender::QSceneLoaderPrivate *>(Qt3DCore::QNodePrivate::get(sceneLoader.data()))->m_subTreeRoot, &backendCreatedSubtree);
-
- // WHEN
- const Qt3DRender::QSceneLoader::Status newStatus = Qt3DRender::QSceneLoader::Ready;
- valueChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- valueChange->setPropertyName("status");
- valueChange->setValue(QVariant::fromValue(newStatus));
- sceneLoader->sceneChangeEvent(valueChange);
-
- // THEN
- QCOMPARE(sceneLoader->status(), newStatus);
+ arbiter.dirtyNodes.clear();
}
void checkEntities()
diff --git a/tests/auto/render/qscreenraycaster/tst_qscreenraycaster.cpp b/tests/auto/render/qscreenraycaster/tst_qscreenraycaster.cpp
index fd67da175..2fe515436 100644
--- a/tests/auto/render/qscreenraycaster/tst_qscreenraycaster.cpp
+++ b/tests/auto/render/qscreenraycaster/tst_qscreenraycaster.cpp
@@ -30,8 +30,6 @@
#include <QtTest/QSignalSpy>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/QScreenRayCaster>
#include "testpostmanarbiter.h"
@@ -105,13 +103,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.last().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "position");
- QCOMPARE(change->value().value<QPoint>(), QPoint(200, 200));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), rayCaster.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
void checkBackendUpdates_data()
diff --git a/tests/auto/render/texturedatamanager/texturedatamanager.pro b/tests/auto/render/qshaderimage/qshaderimage.pro
index cb6f2ee64..1990b9732 100644
--- a/tests/auto/render/texturedatamanager/texturedatamanager.pro
+++ b/tests/auto/render/qshaderimage/qshaderimage.pro
@@ -1,12 +1,12 @@
TEMPLATE = app
-TARGET = tst_texturedatamanager
+TARGET = tst_qshaderimage
QT += 3dcore 3dcore-private 3drender 3drender-private testlib
CONFIG += testcase
-SOURCES += tst_texturedatamanager.cpp
+SOURCES += tst_qshaderimage.cpp
include(../../core/common/common.pri)
include(../commons/commons.pri)
diff --git a/tests/auto/render/qshaderimage/tst_qshaderimage.cpp b/tests/auto/render/qshaderimage/tst_qshaderimage.cpp
new file mode 100644
index 000000000..436d81192
--- /dev/null
+++ b/tests/auto/render/qshaderimage/tst_qshaderimage.cpp
@@ -0,0 +1,488 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <Qt3DRender/qshaderimage.h>
+#include <Qt3DRender/qtexture.h>
+#include <Qt3DRender/private/qshaderimage_p.h>
+#include <QObject>
+#include <QSignalSpy>
+#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/qnodecreatedchange.h>
+#include "testpostmanarbiter.h"
+
+class tst_QShaderImage : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ qRegisterMetaType<Qt3DRender::QAbstractTexture*>("Qt3DRender::QAbstractTexture*");
+
+ }
+
+ void checkDefaultConstruction()
+ {
+ // GIVEN
+ Qt3DRender::QShaderImage shaderImage;
+
+ // THEN
+ QVERIFY(shaderImage.texture() == nullptr);
+ QCOMPARE(shaderImage.layered(), false);
+ QCOMPARE(shaderImage.mipLevel(), 0);
+ QCOMPARE(shaderImage.layer(), 0);
+ QCOMPARE(shaderImage.access(), Qt3DRender::QShaderImage::ReadWrite);
+ QCOMPARE(shaderImage.format(), Qt3DRender::QShaderImage::Automatic);
+ }
+
+ void checkPropertyChanges()
+ {
+ // GIVEN
+ Qt3DRender::QShaderImage shaderImage;
+
+ {
+ // WHEN
+ QSignalSpy spy(&shaderImage, SIGNAL(textureChanged(Qt3DRender::QAbstractTexture *)));
+ Qt3DRender::QTexture2D newValue;
+ shaderImage.setTexture(&newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(shaderImage.texture(), &newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ shaderImage.setTexture(&newValue);
+
+ // THEN
+ QCOMPARE(shaderImage.texture(), &newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&shaderImage, SIGNAL(layeredChanged(bool)));
+ const bool newValue = true;
+ shaderImage.setLayered(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(shaderImage.layered(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ shaderImage.setLayered(newValue);
+
+ // THEN
+ QCOMPARE(shaderImage.layered(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&shaderImage, SIGNAL(mipLevelChanged(int)));
+ const int newValue = 12;
+ shaderImage.setMipLevel(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(shaderImage.mipLevel(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ shaderImage.setMipLevel(newValue);
+
+ // THEN
+ QCOMPARE(shaderImage.mipLevel(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&shaderImage, SIGNAL(layerChanged(int)));
+ const int newValue = 2;
+ shaderImage.setLayer(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(shaderImage.layer(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ shaderImage.setLayer(newValue);
+
+ // THEN
+ QCOMPARE(shaderImage.layer(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&shaderImage, SIGNAL(accessChanged(Access)));
+ const Qt3DRender::QShaderImage::Access newValue = Qt3DRender::QShaderImage::ReadOnly;
+ shaderImage.setAccess(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(shaderImage.access(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ shaderImage.setAccess(newValue);
+
+ // THEN
+ QCOMPARE(shaderImage.access(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ {
+ // WHEN
+ QSignalSpy spy(&shaderImage, SIGNAL(formatChanged(ImageFormat)));
+ const Qt3DRender::QShaderImage::ImageFormat newValue = Qt3DRender::QShaderImage::RG8U;
+ shaderImage.setFormat(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(shaderImage.format(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ shaderImage.setFormat(newValue);
+
+ // THEN
+ QCOMPARE(shaderImage.format(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+ }
+
+ void checkCreationData()
+ {
+ // GIVEN
+ Qt3DRender::QShaderImage shaderImage;
+ Qt3DRender::QTexture2D t;
+
+ shaderImage.setTexture(&t);
+ shaderImage.setLayered(true);
+ shaderImage.setMipLevel(883);
+ shaderImage.setLayer(1584);
+ shaderImage.setAccess(Qt3DRender::QShaderImage::WriteOnly);
+ shaderImage.setFormat(Qt3DRender::QShaderImage::R32F);
+
+ // WHEN
+ QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&shaderImage);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ // ShaderImage + Texture creation
+ QCOMPARE(creationChanges.size(), 2);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderImageData>>(creationChanges.first());
+ const Qt3DRender::QShaderImageData cloneData = creationChangeData->data;
+
+ QCOMPARE(shaderImage.texture()->id(), cloneData.textureId);
+ QCOMPARE(shaderImage.layered(), cloneData.layered);
+ QCOMPARE(shaderImage.mipLevel(), cloneData.mipLevel);
+ QCOMPARE(shaderImage.layer(), cloneData.layer);
+ QCOMPARE(shaderImage.access(), cloneData.access);
+ QCOMPARE(shaderImage.format(), cloneData.format);
+ QCOMPARE(shaderImage.id(), creationChangeData->subjectId());
+ QCOMPARE(shaderImage.isEnabled(), true);
+ QCOMPARE(shaderImage.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(shaderImage.metaObject(), creationChangeData->metaObject());
+ }
+
+ // WHEN
+ shaderImage.setEnabled(false);
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&shaderImage);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ // ShaderImage + Texture creation
+ QCOMPARE(creationChanges.size(), 2);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QShaderImageData>>(creationChanges.first());
+ const Qt3DRender::QShaderImageData cloneData = creationChangeData->data;
+
+ QCOMPARE(shaderImage.texture()->id(), cloneData.textureId);
+ QCOMPARE(shaderImage.layered(), cloneData.layered);
+ QCOMPARE(shaderImage.mipLevel(), cloneData.mipLevel);
+ QCOMPARE(shaderImage.layer(), cloneData.layer);
+ QCOMPARE(shaderImage.access(), cloneData.access);
+ QCOMPARE(shaderImage.format(), cloneData.format);
+ QCOMPARE(shaderImage.id(), creationChangeData->subjectId());
+ QCOMPARE(shaderImage.isEnabled(), false);
+ QCOMPARE(shaderImage.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(shaderImage.metaObject(), creationChangeData->metaObject());
+ }
+ }
+
+ void checkTextureUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QShaderImage shaderImage;
+ arbiter.setArbiterOnNode(&shaderImage);
+ Qt3DRender::QTexture2D t;
+
+ {
+ // WHEN
+ shaderImage.setTexture(&t);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderImage);
+
+ arbiter.dirtyNodes.clear();
+ }
+
+ {
+ // WHEN
+ shaderImage.setTexture(&t);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
+ }
+
+ }
+
+ void checkLayeredUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QShaderImage shaderImage;
+ arbiter.setArbiterOnNode(&shaderImage);
+
+ {
+ // WHEN
+ shaderImage.setLayered(true);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderImage);
+
+ arbiter.dirtyNodes.clear();
+ }
+
+ {
+ // WHEN
+ shaderImage.setLayered(true);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
+ }
+
+ }
+
+ void checkMipLevelUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QShaderImage shaderImage;
+ arbiter.setArbiterOnNode(&shaderImage);
+
+ {
+ // WHEN
+ shaderImage.setMipLevel(5);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderImage);
+
+ arbiter.dirtyNodes.clear();
+ }
+
+ {
+ // WHEN
+ shaderImage.setMipLevel(5);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
+ }
+
+ }
+
+ void checkLayerUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QShaderImage shaderImage;
+ arbiter.setArbiterOnNode(&shaderImage);
+
+ {
+ // WHEN
+ shaderImage.setLayer(8);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderImage);
+
+ arbiter.dirtyNodes.clear();
+ }
+
+ {
+ // WHEN
+ shaderImage.setLayer(8);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
+ }
+
+ }
+
+ void checkAccessUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QShaderImage shaderImage;
+ arbiter.setArbiterOnNode(&shaderImage);
+
+ {
+ // WHEN
+ shaderImage.setAccess(Qt3DRender::QShaderImage::WriteOnly);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderImage);
+
+ arbiter.dirtyNodes.clear();
+ }
+
+ {
+ // WHEN
+ shaderImage.setAccess(Qt3DRender::QShaderImage::WriteOnly);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
+ }
+
+ }
+
+ void checkFormatUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QShaderImage shaderImage;
+ arbiter.setArbiterOnNode(&shaderImage);
+
+ {
+ // WHEN
+ shaderImage.setFormat(Qt3DRender::QShaderImage::RG16F);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderImage);
+
+ arbiter.dirtyNodes.clear();
+ }
+
+ {
+ // WHEN
+ shaderImage.setFormat(Qt3DRender::QShaderImage::RG16F);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
+ }
+
+ }
+
+ void checkTextureBookeeping()
+ {
+ // GIVEN
+ Qt3DRender::QShaderImage shaderImage;
+ QSignalSpy spy(&shaderImage, SIGNAL(textureChanged(Qt3DRender::QAbstractTexture *)));
+
+ {
+ // WHEN
+ Qt3DRender::QTexture2D tex;
+ shaderImage.setTexture(&tex);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(shaderImage.texture(), &tex);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ }
+ // THEN
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(shaderImage.texture() == nullptr);
+ }
+
+};
+
+QTEST_MAIN(tst_QShaderImage)
+
+#include "tst_qshaderimage.moc"
diff --git a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
index 3fcc49067..a261d0860 100644
--- a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
+++ b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
@@ -261,13 +261,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "vertexShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), shaderProgram.vertexShaderCode());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -277,6 +275,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -294,13 +293,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "tessellationControlShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), shaderProgram.tessellationControlShaderCode());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -310,6 +307,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -327,13 +325,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "tessellationEvaluationShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), shaderProgram.tessellationEvaluationShaderCode());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -343,6 +339,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -360,13 +357,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "geometryShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), shaderProgram.geometryShaderCode());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -376,6 +371,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -393,13 +389,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "fragmentShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), shaderProgram.fragmentShaderCode());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -409,6 +403,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -426,13 +421,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "computeShaderCode");
- QCOMPARE(change->value().value<QByteArray>(), shaderProgram.computeShaderCode());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &shaderProgram);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -442,6 +435,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -476,6 +470,9 @@ private Q_SLOTS:
QCOMPARE(spy.count(), 0);
QCOMPARE(arbiter.events.size(), 0);
QCOMPARE(log(), logValue);
+
+ // Cleanup
+ Qt3DCore::QNodePrivate::get(this)->setArbiter(nullptr);
}
void checkStatusPropertyUpdate()
@@ -509,6 +506,9 @@ private Q_SLOTS:
QCOMPARE(spy.count(), 0);
QCOMPARE(arbiter.events.size(), 0);
QCOMPARE(status(), newStatus);
+
+ // Cleanup
+ Qt3DCore::QNodePrivate::get(this)->setArbiter(nullptr);
}
void checkIncludes()
diff --git a/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp b/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp
index 021a3d6c1..851316e60 100644
--- a/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp
+++ b/tests/auto/render/qshaderprogrambuilder/tst_qshaderprogrambuilder.cpp
@@ -351,13 +351,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "shaderProgram");
- QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), builder.shaderProgram()->id());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &builder);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -367,6 +365,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -384,13 +383,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "enabledLayers");
- QCOMPARE(change->value().toStringList(), layers);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &builder);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -400,6 +397,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -416,13 +414,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "vertexShaderGraph");
- QCOMPARE(change->value().value<QUrl>(), builder.vertexShaderGraph());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &builder);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -432,6 +428,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -449,13 +446,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "tessellationControlShaderGraph");
- QCOMPARE(change->value().value<QUrl>(), builder.tessellationControlShaderGraph());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &builder);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -465,6 +460,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -482,13 +478,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "tessellationEvaluationShaderGraph");
- QCOMPARE(change->value().value<QUrl>(), builder.tessellationEvaluationShaderGraph());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &builder);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -498,6 +492,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -515,13 +510,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "geometryShaderGraph");
- QCOMPARE(change->value().value<QUrl>(), builder.geometryShaderGraph());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &builder);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -531,6 +524,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -548,13 +542,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "fragmentShaderGraph");
- QCOMPARE(change->value().value<QUrl>(), builder.fragmentShaderGraph());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &builder);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -564,6 +556,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -581,13 +574,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "computeShaderGraph");
- QCOMPARE(change->value().value<QUrl>(), builder.computeShaderGraph());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &builder);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -597,18 +588,17 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
void checkGeneratedCodePropertyUpdates()
{
+ Qt3DRender::QShaderProgramBuilderPrivate *dBuilder = static_cast<decltype(dBuilder)>(Qt3DCore::QNodePrivate::get(this));
{
// WHEN
QSignalSpy spy(this, SIGNAL(vertexShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::Vertex), QByteArrayLiteral("vertex"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("vertex"), Qt3DRender::QShaderProgram::Vertex);
// THEN
QVERIFY(spy.isValid());
@@ -618,10 +608,7 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(fragmentShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::Fragment), QByteArrayLiteral("fragment"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("fragment"), Qt3DRender::QShaderProgram::Fragment);
// THEN
QVERIFY(spy.isValid());
@@ -631,10 +618,7 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(geometryShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::Geometry), QByteArrayLiteral("geometry"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("geometry"), Qt3DRender::QShaderProgram::Geometry);
// THEN
QVERIFY(spy.isValid());
@@ -644,10 +628,8 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(computeShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::Compute), QByteArrayLiteral("compute"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("compute"), Qt3DRender::QShaderProgram::Compute);
+
// THEN
QVERIFY(spy.isValid());
@@ -657,10 +639,7 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(tessellationControlShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::TessellationControl), QByteArrayLiteral("control"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("control"), Qt3DRender::QShaderProgram::TessellationControl);
// THEN
QVERIFY(spy.isValid());
@@ -670,10 +649,7 @@ private Q_SLOTS:
{
// WHEN
QSignalSpy spy(this, SIGNAL(tessellationEvaluationShaderCodeChanged(QByteArray)));
- Qt3DCore::QPropertyUpdatedChangePtr valueChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- valueChange->setPropertyName("generatedShaderCode");
- valueChange->setValue(QVariant::fromValue(QPair<int, QByteArray>(int(Qt3DRender::QShaderProgram::TessellationEvaluation), QByteArrayLiteral("eval"))));
- sceneChangeEvent(valueChange);
+ dBuilder->setShaderCode(QByteArrayLiteral("eval"), Qt3DRender::QShaderProgram::TessellationEvaluation);
// THEN
QVERIFY(spy.isValid());
diff --git a/tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp b/tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp
index 1a1db60e4..4011eeea6 100644
--- a/tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp
+++ b/tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/qtexture_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -144,13 +143,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- const auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "textureId");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->value().toInt(), 1584);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &glTexture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -160,6 +157,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qsortpolicy/tst_qsortpolicy.cpp b/tests/auto/render/qsortpolicy/tst_qsortpolicy.cpp
index 477acc058..66c625cfc 100644
--- a/tests/auto/render/qsortpolicy/tst_qsortpolicy.cpp
+++ b/tests/auto/render/qsortpolicy/tst_qsortpolicy.cpp
@@ -117,13 +117,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "sortTypes");
- QCOMPARE(change->value().value<QVector<int>>(), sortTypesInt);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), sortPolicy.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
};
diff --git a/tests/auto/render/qtechnique/tst_qtechnique.cpp b/tests/auto/render/qtechnique/tst_qtechnique.cpp
index 1026dddc0..40d763ad4 100644
--- a/tests/auto/render/qtechnique/tst_qtechnique.cpp
+++ b/tests/auto/render/qtechnique/tst_qtechnique.cpp
@@ -37,9 +37,6 @@
#include <Qt3DRender/private/qtechnique_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -329,28 +326,21 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "pass");
- QCOMPARE(change->addedNodeId(), pass.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
-
{
// WHEN
technique.removeRenderPass(&pass);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->propertyName(), "pass");
- QCOMPARE(change->removedNodeId(), pass.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
}
}
@@ -368,13 +358,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->addedNodeId(), parameter.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -383,13 +371,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->propertyName(), "parameter");
- QCOMPARE(change->removedNodeId(), parameter.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
}
@@ -407,13 +393,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(change->propertyName(), "filterKeys");
- QCOMPARE(change->addedNodeId(), filterKey.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -422,13 +406,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(change->propertyName(), "filterKeys");
- QCOMPARE(change->removedNodeId(), filterKey.id());
- QCOMPARE(change->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
}
@@ -445,14 +427,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "graphicsApiFilterData");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- Qt3DRender::GraphicsApiFilterData data = change->value().value<Qt3DRender::GraphicsApiFilterData>();
- QCOMPARE(data.m_major, 4);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
+
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
@@ -460,14 +439,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "graphicsApiFilterData");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- Qt3DRender::GraphicsApiFilterData data = change->value().value<Qt3DRender::GraphicsApiFilterData>();
- QCOMPARE(data.m_minor, 5);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
+
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
@@ -475,14 +451,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "graphicsApiFilterData");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- Qt3DRender::GraphicsApiFilterData data = change->value().value<Qt3DRender::GraphicsApiFilterData>();
- QCOMPARE(data.m_vendor, QStringLiteral("AMD"));
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
+
+ arbiter.dirtyNodes.clear();
}
{
// WHEN
@@ -490,14 +463,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "graphicsApiFilterData");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- Qt3DRender::GraphicsApiFilterData data = change->value().value<Qt3DRender::GraphicsApiFilterData>();
- QCOMPARE(data.m_profile, Qt3DRender::QGraphicsApiFilter::CompatibilityProfile);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QVERIFY(arbiter.dirtyNodes.contains(&technique));
+
+ arbiter.dirtyNodes.clear();
}
}
};
diff --git a/tests/auto/render/qtechniquefilter/tst_qtechniquefilter.cpp b/tests/auto/render/qtechniquefilter/tst_qtechniquefilter.cpp
index 4f6daae8c..37f0ba9a7 100644
--- a/tests/auto/render/qtechniquefilter/tst_qtechniquefilter.cpp
+++ b/tests/auto/render/qtechniquefilter/tst_qtechniquefilter.cpp
@@ -37,10 +37,6 @@
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qfilterkey.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
-
#include "testpostmanarbiter.h"
class tst_QTechniqueFilter: public QObject
@@ -159,14 +155,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeAddedChangePtr nodeAddedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(nodeAddedChange->propertyName(), "parameter");
- QCOMPARE(nodeAddedChange->subjectId(),techniqueFilter->id());
- QCOMPARE(nodeAddedChange->addedNodeId(), param1->id());
- QCOMPARE(nodeAddedChange->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), techniqueFilter.data());
+ arbiter.dirtyNodes.clear();
- arbiter.events.clear();
// WHEN
techniqueFilter->addParameter(param1);
@@ -174,20 +167,17 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
techniqueFilter->removeParameter(param1);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyNodeRemovedChangePtr nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "parameter");
- QCOMPARE(nodeRemovedChange->subjectId(), techniqueFilter->id());
- QCOMPARE(nodeRemovedChange->removedNodeId(), param1->id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), techniqueFilter.data());
+ arbiter.dirtyNodes.clear();
// WHEN
Qt3DRender::QFilterKey *filterKey1 = new Qt3DRender::QFilterKey();
@@ -195,14 +185,10 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- nodeAddedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(nodeAddedChange->propertyName(), "matchAll");
- QCOMPARE(nodeAddedChange->subjectId(),techniqueFilter->id());
- QCOMPARE(nodeAddedChange->addedNodeId(), filterKey1->id());
- QCOMPARE(nodeAddedChange->type(), Qt3DCore::PropertyValueAdded);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), techniqueFilter.data());
+ arbiter.dirtyNodes.clear();
// WHEN
techniqueFilter->addMatch(filterKey1);
@@ -210,20 +196,17 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
techniqueFilter->removeMatch(filterKey1);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- nodeRemovedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(nodeRemovedChange->propertyName(), "matchAll");
- QCOMPARE(nodeRemovedChange->subjectId(), techniqueFilter->id());
- QCOMPARE(nodeRemovedChange->removedNodeId(), filterKey1->id());
- QCOMPARE(nodeRemovedChange->type(), Qt3DCore::PropertyValueRemoved);
-
- arbiter.events.clear();
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), techniqueFilter.data());
+ arbiter.dirtyNodes.clear();
}
void checkParameterBookkeeping()
diff --git a/tests/auto/render/qtexturedataupdate/qtexturedataupdate.pro b/tests/auto/render/qtexturedataupdate/qtexturedataupdate.pro
new file mode 100644
index 000000000..89a076523
--- /dev/null
+++ b/tests/auto/render/qtexturedataupdate/qtexturedataupdate.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+
+TARGET = tst_qtexturedataupdate
+
+QT += 3dcore 3dcore-private 3drender 3drender-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_qtexturedataupdate.cpp
+
diff --git a/tests/auto/render/qtexturedataupdate/tst_qtexturedataupdate.cpp b/tests/auto/render/qtexturedataupdate/tst_qtexturedataupdate.cpp
new file mode 100644
index 000000000..3a8432d2e
--- /dev/null
+++ b/tests/auto/render/qtexturedataupdate/tst_qtexturedataupdate.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <Qt3DRender/qtexturedataupdate.h>
+#include <Qt3DRender/qabstracttexture.h>
+#include <Qt3DRender/qtextureimagedata.h>
+
+class tst_QTextureDataUpdate : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void checkDefaultConstruction()
+ {
+ // GIVEN
+ Qt3DRender::QTextureDataUpdate textureUpdate;
+
+ // THEN
+ QCOMPARE(textureUpdate.x(), 0);
+ QCOMPARE(textureUpdate.y(), 0);
+ QCOMPARE(textureUpdate.z(), 0);
+ QCOMPARE(textureUpdate.layer(), 0);
+ QCOMPARE(textureUpdate.mipLevel(), 0);
+ QCOMPARE(textureUpdate.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX);
+ QVERIFY(textureUpdate.data().isNull());
+ }
+
+ void checkSettersAndGetters()
+ {
+ // GIVEN
+ Qt3DRender::QTextureDataUpdate textureUpdate;
+
+ // WHEN
+ textureUpdate.setX(883);
+
+ // THEN
+ QCOMPARE(textureUpdate.x(), 883);
+
+ // WHEN
+ textureUpdate.setY(1340);
+ // THEN
+ QCOMPARE(textureUpdate.y(), 1340);
+
+ // WHEN
+ textureUpdate.setZ(1584);
+
+ // THEN
+ QCOMPARE(textureUpdate.z(), 1584);
+
+ // WHEN
+ textureUpdate.setLayer(454);
+
+ // THEN
+ QCOMPARE(textureUpdate.layer(), 454);
+
+ // WHEN
+ textureUpdate.setMipLevel(350);
+ // THEN
+ QCOMPARE(textureUpdate.mipLevel(), 350);
+
+ // WHEN
+ textureUpdate.setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeZ);
+
+ // THEN
+ QCOMPARE(textureUpdate.face(), Qt3DRender::QAbstractTexture::CubeMapNegativeZ);
+
+ // WHEN
+ Qt3DRender::QTextureImageDataPtr imgData = Qt3DRender::QTextureImageDataPtr::create();
+ textureUpdate.setData(imgData);
+
+ // THEN
+ QCOMPARE(textureUpdate.data(), imgData);
+ }
+
+ void checkCopyConstruction()
+ {
+ // GIVEN
+ Qt3DRender::QTextureDataUpdate textureUpdate;
+ textureUpdate.setX(883);
+ textureUpdate.setY(1340);
+ textureUpdate.setZ(1584);
+ textureUpdate.setLayer(454);
+ textureUpdate.setMipLevel(350);
+ textureUpdate.setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeZ);
+ Qt3DRender::QTextureImageDataPtr imgData = Qt3DRender::QTextureImageDataPtr::create();
+ textureUpdate.setData(imgData);
+
+ // WHEN
+ Qt3DRender::QTextureDataUpdate textureUpdateCpy(textureUpdate);
+
+ // THEN
+ QCOMPARE(textureUpdateCpy.x(), 883);
+ QCOMPARE(textureUpdateCpy.y(), 1340);
+ QCOMPARE(textureUpdateCpy.z(), 1584);
+ QCOMPARE(textureUpdateCpy.layer(), 454);
+ QCOMPARE(textureUpdateCpy.mipLevel(), 350);
+ QCOMPARE(textureUpdateCpy.face(), Qt3DRender::QAbstractTexture::CubeMapNegativeZ);
+ QCOMPARE(textureUpdateCpy.data(), imgData);
+ }
+
+ void checkAssigment()
+ {
+ // GIVEN
+ Qt3DRender::QTextureDataUpdate textureUpdate;
+ Qt3DRender::QTextureDataUpdate textureUpdateAssign;
+ textureUpdate.setX(883);
+ textureUpdate.setY(1340);
+ textureUpdate.setZ(1584);
+ textureUpdate.setLayer(454);
+ textureUpdate.setMipLevel(350);
+ textureUpdate.setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeZ);
+ Qt3DRender::QTextureImageDataPtr imgData = Qt3DRender::QTextureImageDataPtr::create();
+ textureUpdate.setData(imgData);
+
+ // WHEN
+ textureUpdateAssign = textureUpdate;
+
+ // THEN
+ QCOMPARE(textureUpdateAssign.x(), 883);
+ QCOMPARE(textureUpdateAssign.y(), 1340);
+ QCOMPARE(textureUpdateAssign.z(), 1584);
+ QCOMPARE(textureUpdateAssign.layer(), 454);
+ QCOMPARE(textureUpdateAssign.mipLevel(), 350);
+ QCOMPARE(textureUpdateAssign.face(), Qt3DRender::QAbstractTexture::CubeMapNegativeZ);
+ QCOMPARE(textureUpdateAssign.data(), imgData);
+
+ QCOMPARE(textureUpdateAssign.x(), textureUpdate.x());
+ QCOMPARE(textureUpdateAssign.y(), textureUpdate.y());
+ QCOMPARE(textureUpdateAssign.z(), textureUpdate.z());
+ QCOMPARE(textureUpdateAssign.layer(), textureUpdate.layer());
+ QCOMPARE(textureUpdateAssign.mipLevel(), textureUpdate.mipLevel());
+ QCOMPARE(textureUpdateAssign.face(), textureUpdate.face());
+ QCOMPARE(textureUpdateAssign.data(), textureUpdate.data());
+ }
+
+ void checkConversionToVariant()
+ {
+ // GIVEN
+ Qt3DRender::QTextureDataUpdate textureUpdate;
+ textureUpdate.setX(883);
+ textureUpdate.setY(1340);
+ textureUpdate.setZ(1584);
+ textureUpdate.setLayer(454);
+ textureUpdate.setMipLevel(350);
+ textureUpdate.setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeZ);
+ Qt3DRender::QTextureImageDataPtr imgData = Qt3DRender::QTextureImageDataPtr::create();
+ textureUpdate.setData(imgData);
+
+ // WHEN
+ const QVariant v = QVariant::fromValue(textureUpdate);
+ const Qt3DRender::QTextureDataUpdate out = v.value<Qt3DRender::QTextureDataUpdate>();
+
+ // THEN
+ QCOMPARE(out.x(), 883);
+ QCOMPARE(out.y(), 1340);
+ QCOMPARE(out.z(), 1584);
+ QCOMPARE(out.layer(), 454);
+ QCOMPARE(out.mipLevel(), 350);
+ QCOMPARE(out.face(), Qt3DRender::QAbstractTexture::CubeMapNegativeZ);
+ QCOMPARE(out.data(), imgData);
+ }
+
+ void checkComparison()
+ {
+ // GIVEN
+ Qt3DRender::QTextureDataUpdate textureUpdate1;
+ Qt3DRender::QTextureDataUpdate textureUpdate2;
+
+ // THEN
+ QVERIFY(textureUpdate1 == textureUpdate2);
+ QVERIFY(!(textureUpdate1 != textureUpdate2));
+
+ // WHEN
+ textureUpdate1.setX(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 != textureUpdate2);
+
+ // WHEN
+ textureUpdate2.setX(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 == textureUpdate2);
+
+ // WHEN
+ textureUpdate1.setY(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 != textureUpdate2);
+
+ // WHEN
+ textureUpdate2.setY(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 == textureUpdate2);
+
+ // WHEN
+ textureUpdate1.setZ(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 != textureUpdate2);
+
+ // WHEN
+ textureUpdate2.setZ(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 == textureUpdate2);
+
+ // WHEN
+ textureUpdate1.setLayer(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 != textureUpdate2);
+
+ // WHEN
+ textureUpdate2.setLayer(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 == textureUpdate2);
+
+ // WHEN
+ textureUpdate1.setMipLevel(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 != textureUpdate2);
+
+ // WHEN
+ textureUpdate2.setMipLevel(883);
+
+ // THEN
+ QVERIFY(textureUpdate1 == textureUpdate2);
+
+ // WHEN
+ textureUpdate1.setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeX);
+
+ // THEN
+ QVERIFY(textureUpdate1 != textureUpdate2);
+
+ // WHEN
+ textureUpdate2.setFace(Qt3DRender::QAbstractTexture::CubeMapNegativeX);
+
+ // THEN
+ QVERIFY(textureUpdate1 == textureUpdate2);
+
+ // WHEN
+ Qt3DRender::QTextureImageDataPtr imgData = Qt3DRender::QTextureImageDataPtr::create();
+ textureUpdate1.setData(imgData);
+
+ // THEN
+ QVERIFY(textureUpdate1 != textureUpdate2);
+
+ // WHEN
+ textureUpdate2.setData(imgData);
+
+ // THEN
+ QVERIFY(textureUpdate1 == textureUpdate2);
+ }
+};
+
+QTEST_APPLESS_MAIN(tst_QTextureDataUpdate)
+
+#include "tst_qtexturedataupdate.moc"
diff --git a/tests/auto/render/qtextureimage/tst_qtextureimage.cpp b/tests/auto/render/qtextureimage/tst_qtextureimage.cpp
index 224784011..4996c877d 100644
--- a/tests/auto/render/qtextureimage/tst_qtextureimage.cpp
+++ b/tests/auto/render/qtextureimage/tst_qtextureimage.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/qtextureimage_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -174,14 +173,8 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "dataGenerator");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- const auto generator = qSharedPointerCast<Qt3DRender::QImageTextureDataFunctor>(change->value().value<Qt3DRender::QTextureImageDataGeneratorPtr>());
- QVERIFY(generator);
- QCOMPARE(generator->url(), textureImage.source());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &textureImage);
arbiter.events.clear();
}
@@ -210,14 +203,8 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "dataGenerator");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
-
- const auto generator = qSharedPointerCast<Qt3DRender::QImageTextureDataFunctor>(change->value().value<Qt3DRender::QTextureImageDataGeneratorPtr>());
- QVERIFY(generator);
- QCOMPARE(generator->isMirrored(), textureImage.isMirrored());
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &textureImage);
arbiter.events.clear();
}
diff --git a/tests/auto/render/qtextureloader/tst_qtextureloader.cpp b/tests/auto/render/qtextureloader/tst_qtextureloader.cpp
index 56ad55adf..dd92894da 100644
--- a/tests/auto/render/qtextureloader/tst_qtextureloader.cpp
+++ b/tests/auto/render/qtextureloader/tst_qtextureloader.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/private/qtexture_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -168,16 +167,14 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- const auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "generator");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &textureLoader);
- const auto generator = qSharedPointerCast<Qt3DRender::QTextureFromSourceGenerator>(change->value().value<Qt3DRender::QTextureGeneratorPtr>());
+ Qt3DRender::QAbstractTexturePrivate *d = dynamic_cast<Qt3DRender::QAbstractTexturePrivate *>(Qt3DRender::QAbstractTexturePrivate::get(&textureLoader));
+ const auto generator = qSharedPointerCast<Qt3DRender::QTextureFromSourceGenerator>(d->dataFunctor());
QVERIFY(generator);
QCOMPARE(generator->url(), QUrl(QStringLiteral("Gary")));
-
arbiter.events.clear();
}
@@ -205,16 +202,15 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- const auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "generator");
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &textureLoader);
- const auto generator = qSharedPointerCast<Qt3DRender::QTextureFromSourceGenerator>(change->value().value<Qt3DRender::QTextureGeneratorPtr>());
+ Qt3DRender::QAbstractTexturePrivate *d = dynamic_cast<Qt3DRender::QAbstractTexturePrivate *>(Qt3DRender::QAbstractTexturePrivate::get(&textureLoader));
+ const auto generator = qSharedPointerCast<Qt3DRender::QTextureFromSourceGenerator>(d->dataFunctor());
QVERIFY(generator);
QCOMPARE(generator->isMirrored(), false);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -223,7 +219,7 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
diff --git a/tests/auto/render/qviewport/tst_qviewport.cpp b/tests/auto/render/qviewport/tst_qviewport.cpp
index 93a2735f2..ab3dda08f 100644
--- a/tests/auto/render/qviewport/tst_qviewport.cpp
+++ b/tests/auto/render/qviewport/tst_qviewport.cpp
@@ -97,37 +97,32 @@ private Q_SLOTS:
{
// WHEN
- viewport->setNormalizedRect(QRectF(0.5f, 0.5f, 1.0f, 1.0f));
+ viewport->setNormalizedRect(QRectF(0.5, 0.5, 1.0, 1.0));
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "normalizedRect");
- QCOMPARE(change->subjectId(), viewport->id());
- QCOMPARE(change->value().value<QRectF>(), QRectF(0.5f, 0.5f, 1.0f, 1.0f));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), viewport.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
- viewport->setNormalizedRect(QRectF(0.5f, 0.5f, 1.0f, 1.0f));
+ viewport->setNormalizedRect(QRectF(0.5, 0.5, 1.0, 1.0));
QCoreApplication::processEvents();
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
- viewport->setNormalizedRect(QRectF(0.0f, 0.0f, 1.0f, 1.0f));
+ viewport->setNormalizedRect(QRectF(0.0, 0.0, 1.0, 1.0));
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "normalizedRect");
- QCOMPARE(change->subjectId(), viewport->id());
- QCOMPARE(change->value().value<QRectF>(), QRectF(0.0f, 0.0f, 1.0f, 1.0f));
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), viewport.data());
}
arbiter.events.clear();
@@ -138,14 +133,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "gamma");
- QCOMPARE(change->subjectId(), viewport->id());
- QCOMPARE(change->value().toFloat(), 1.8f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), viewport.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
viewport->setGamma(1.8f);
@@ -153,18 +145,16 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
viewport->setGamma(2.0f);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "gamma");
- QCOMPARE(change->subjectId(), viewport->id());
- QCOMPARE(change->value().toFloat(), 2.0f);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), viewport.data());
}
}
};
diff --git a/tests/auto/render/qwaitfence/tst_qwaitfence.cpp b/tests/auto/render/qwaitfence/tst_qwaitfence.cpp
index ab3ae9b4d..801abfcc6 100644
--- a/tests/auto/render/qwaitfence/tst_qwaitfence.cpp
+++ b/tests/auto/render/qwaitfence/tst_qwaitfence.cpp
@@ -43,7 +43,6 @@
#include <Qt3DRender/private/qwaitfence_p.h>
#include <QObject>
#include <QSignalSpy>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/qnodecreatedchange.h>
#include "testpostmanarbiter.h"
@@ -228,13 +227,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "handleType");
- QCOMPARE(change->value().value<Qt3DRender::QWaitFence::HandleType>(), waitFence.handleType());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &waitFence);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -244,6 +241,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -260,13 +258,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "handle");
- QCOMPARE(change->value().value<QVariant>(), waitFence.handle());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &waitFence);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -276,6 +272,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
@@ -292,13 +289,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "waitOnCPU");
- QCOMPARE(change->value().value<bool>(), waitFence.waitOnCPU());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &waitFence);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -308,6 +303,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.events.size(), 0);
}
}
@@ -324,13 +320,11 @@ private Q_SLOTS:
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "timeout");
- QCOMPARE(change->value().value<quint64>(), waitFence.timeout());
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &waitFence);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
{
@@ -340,6 +334,7 @@ private Q_SLOTS:
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
}
}
};
diff --git a/tests/auto/render/raycaster/tst_raycaster.cpp b/tests/auto/render/raycaster/tst_raycaster.cpp
index 4d30c6d45..57a1bcf47 100644
--- a/tests/auto/render/raycaster/tst_raycaster.cpp
+++ b/tests/auto/render/raycaster/tst_raycaster.cpp
@@ -32,7 +32,6 @@
#include <Qt3DRender/qpickevent.h>
#include <Qt3DRender/qraycaster.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "testpostmanarbiter.h"
#include "testrenderer.h"
@@ -44,6 +43,7 @@ private Q_SLOTS:
void checkPeerPropertyMirroring()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::RayCaster rayCaster;
Qt3DRender::QRayCaster caster;
caster.setRunMode(Qt3DRender::QRayCaster::Continuous);
@@ -52,7 +52,8 @@ private Q_SLOTS:
caster.setLength(42.f);
// WHEN
- simulateInitialization(&caster, &rayCaster);
+ rayCaster.setRenderer(&renderer);
+ simulateInitializationSync(&caster, &rayCaster);
// THEN
QVERIFY(!rayCaster.peerId().isNull());
@@ -65,6 +66,7 @@ private Q_SLOTS:
void checkInitialAndCleanedUpState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::RayCaster rayCaster;
// THEN
@@ -76,7 +78,8 @@ private Q_SLOTS:
caster.setRunMode(Qt3DRender::QRayCaster::Continuous);
// WHEN
- simulateInitialization(&caster, &rayCaster);
+ rayCaster.setRenderer(&renderer);
+ simulateInitializationSync(&caster, &rayCaster);
rayCaster.cleanup();
// THEN
@@ -88,40 +91,20 @@ private Q_SLOTS:
// GIVEN
TestRenderer renderer;
{
+ Qt3DRender::QRayCaster caster;
Qt3DRender::Render::RayCaster rayCaster;
rayCaster.setRenderer(&renderer);
+ simulateInitializationSync(&caster, &rayCaster);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(Qt3DRender::QRayCaster::Continuous);
- updateChange->setPropertyName("runMode");
- rayCaster.sceneChangeEvent(updateChange);
+ caster.setRunMode(Qt3DRender::QRayCaster::Continuous);
+ rayCaster.syncFromFrontEnd(&caster, false);
// THEN
QCOMPARE(rayCaster.runMode(), Qt3DRender::QRayCaster::Continuous);
QVERIFY(renderer.dirtyBits() != 0);
}
}
-
- void checkBackendPropertyNotifications()
- {
- // GIVEN
- TestArbiter arbiter;
- Qt3DRender::Render::RayCaster rayCaster;
- Qt3DCore::QBackendNodePrivate::get(&rayCaster)->setArbiter(&arbiter);
- Qt3DRender::QAbstractRayCaster::Hits hits;
-
- // WHEN
- rayCaster.dispatchHits(hits);
-
- // THEN
- QCOMPARE(arbiter.events.count(), 2);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "hits");
- QVERIFY(!rayCaster.isEnabled());
-
- arbiter.events.clear();
- }
};
diff --git a/tests/auto/render/raycasting/tst_raycasting.cpp b/tests/auto/render/raycasting/tst_raycasting.cpp
index d14bcddcb..9178b9d6f 100644
--- a/tests/auto/render/raycasting/tst_raycasting.cpp
+++ b/tests/auto/render/raycasting/tst_raycasting.cpp
@@ -182,13 +182,13 @@ void tst_RayCasting::shouldReturnAllResults()
&provider));
// WHEN
- QVector<QCollisionQueryResult> results = service.fetchAllResults();
+ const QVector<QCollisionQueryResult> results = service.fetchAllResults();
// THEN
bool expectedHandlesFound = true;
- Q_FOREACH (QQueryHandle expected, handles) {
+ for (QQueryHandle expected : qAsConst(handles)) {
bool found = false;
- Q_FOREACH (QCollisionQueryResult result, results) {
+ for (QCollisionQueryResult result : results) {
if (result.handle() == expected)
found = true;
}
diff --git a/tests/auto/render/raycastingjob/testscene_screenraycasting.qml b/tests/auto/render/raycastingjob/testscene_screenraycasting.qml
index 4ad696d49..47221aec8 100644
--- a/tests/auto/render/raycastingjob/testscene_screenraycasting.qml
+++ b/tests/auto/render/raycastingjob/testscene_screenraycasting.qml
@@ -48,11 +48,12 @@
**
****************************************************************************/
-import Qt3D.Core 2.0
-import Qt3D.Render 2.11
-import Qt3D.Extras 2.0
-import QtQuick.Window 2.0
-import Qt3D.Input 2.0
+import QtQml 2.14
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Input 2.14
+import Qt3D.Extras 2.14
+import QtQuick.Window 2.14
Entity {
id: sceneRoot
diff --git a/tests/auto/render/raycastingjob/testscene_worldraycasting.qml b/tests/auto/render/raycastingjob/testscene_worldraycasting.qml
index 159c8b515..cdb6b9234 100644
--- a/tests/auto/render/raycastingjob/testscene_worldraycasting.qml
+++ b/tests/auto/render/raycastingjob/testscene_worldraycasting.qml
@@ -48,10 +48,11 @@
**
****************************************************************************/
-import Qt3D.Core 2.0
-import Qt3D.Render 2.11
-import Qt3D.Extras 2.0
-import QtQuick.Window 2.0
+import QtQml 2.14
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Extras 2.14
+import QtQuick.Window 2.14
Entity {
id: sceneRoot
diff --git a/tests/auto/render/raycastingjob/testscene_worldraycastingalllayers.qml b/tests/auto/render/raycastingjob/testscene_worldraycastingalllayers.qml
index c88ffab36..efcc31e8f 100644
--- a/tests/auto/render/raycastingjob/testscene_worldraycastingalllayers.qml
+++ b/tests/auto/render/raycastingjob/testscene_worldraycastingalllayers.qml
@@ -48,10 +48,11 @@
**
****************************************************************************/
-import Qt3D.Core 2.0
-import Qt3D.Render 2.11
-import Qt3D.Extras 2.0
-import QtQuick.Window 2.0
+import QtQml 2.14
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Extras 2.14
+import QtQuick.Window 2.14
Entity {
id: sceneRoot
diff --git a/tests/auto/render/raycastingjob/testscene_worldraycastinglayer.qml b/tests/auto/render/raycastingjob/testscene_worldraycastinglayer.qml
index f561dcf49..5c6170ae6 100644
--- a/tests/auto/render/raycastingjob/testscene_worldraycastinglayer.qml
+++ b/tests/auto/render/raycastingjob/testscene_worldraycastinglayer.qml
@@ -48,10 +48,11 @@
**
****************************************************************************/
-import Qt3D.Core 2.0
-import Qt3D.Render 2.11
-import Qt3D.Extras 2.0
-import QtQuick.Window 2.0
+import QtQml 2.14
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Extras 2.14
+import QtQuick.Window 2.14
Entity {
id: sceneRoot
diff --git a/tests/auto/render/raycastingjob/testscene_worldraycastingparentlayer.qml b/tests/auto/render/raycastingjob/testscene_worldraycastingparentlayer.qml
index 5322030b7..99ca26d6f 100644
--- a/tests/auto/render/raycastingjob/testscene_worldraycastingparentlayer.qml
+++ b/tests/auto/render/raycastingjob/testscene_worldraycastingparentlayer.qml
@@ -48,10 +48,11 @@
**
****************************************************************************/
-import Qt3D.Core 2.0
-import Qt3D.Render 2.11
-import Qt3D.Extras 2.0
-import QtQuick.Window 2.0
+import QtQml 2.14
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Extras 2.14
+import QtQuick.Window 2.14
Entity {
id: sceneRoot
diff --git a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp
index 9477947ac..eaf85f5b6 100644
--- a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp
+++ b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp
@@ -34,6 +34,10 @@
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qaspectmanager_p.h>
+#include <Qt3DCore/private/qscene_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
#include <QtQuick/qquickwindow.h>
#include <Qt3DRender/QCamera>
@@ -51,7 +55,6 @@
#include <Qt3DRender/private/updateworldtransformjob_p.h>
#include <Qt3DRender/private/expandboundingvolumejob_p.h>
#include <Qt3DRender/private/calcboundingvolumejob_p.h>
-#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
#include <Qt3DRender/private/calcgeometrytrianglevolumes_p.h>
#include <Qt3DRender/private/loadbufferjob_p.h>
#include <Qt3DRender/private/buffermanager_p.h>
@@ -63,6 +66,47 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+QVector<Qt3DCore::QNode *> getNodesForCreation(Qt3DCore::QNode *root)
+{
+ using namespace Qt3DCore;
+
+ QVector<QNode *> nodes;
+ Qt3DCore::QNodeVisitor visitor;
+ visitor.traverse(root, [&nodes](QNode *node) {
+ nodes.append(node);
+
+ // Store the metaobject of the node in the QNode so that we have it available
+ // to us during destruction in the QNode destructor. This allows us to send
+ // the QNodeId and the metaobject as typeinfo to the backend aspects so they
+ // in turn can find the correct QBackendNodeMapper object to handle the destruction
+ // of the corresponding backend nodes.
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(QNodePrivate::findStaticMetaObject(node->metaObject()));
+
+ // Mark this node as having been handled for creation so that it is picked up
+ d->m_hasBackendNode = true;
+ });
+
+ return nodes;
+}
+
+QVector<Qt3DCore::NodeTreeChange> nodeTreeChangesForNodes(const QVector<Qt3DCore::QNode *> nodes)
+{
+ QVector<Qt3DCore::NodeTreeChange> nodeTreeChanges;
+ nodeTreeChanges.reserve(nodes.size());
+
+ for (Qt3DCore::QNode *n : nodes) {
+ nodeTreeChanges.push_back({
+ n->id(),
+ Qt3DCore::QNodePrivate::get(n)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ n
+ });
+ }
+
+ return nodeTreeChanges;
+}
+
class TestAspect : public Qt3DRender::QRenderAspect
{
public:
@@ -70,12 +114,18 @@ public:
: Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous)
, m_sceneRoot(nullptr)
{
- QRenderAspect::onRegistered();
-
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), creationChanges);
+ m_engine = new Qt3DCore::QAspectEngine(this);
+ m_engine->registerAspect(this);
+ Q_ASSERT(d_func()->m_aspectManager);
+
+ // do what QAspectEngine::setRootEntity does since we don't want to enter the simulation loop
+ Qt3DCore::QEntityPtr proot(qobject_cast<Qt3DCore::QEntity *>(root), [](Qt3DCore::QEntity *) { });
+ Qt3DCore::QAspectEnginePrivate *aed = Qt3DCore::QAspectEnginePrivate::get(m_engine);
+ aed->m_root = proot;
+ aed->initialize();
+ aed->initNodeTree(root);
+ const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root);
+ aed->m_aspectManager->setRootEntity(proot.data(), nodes);
Render::Entity *rootEntity = nodeManagers()->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
@@ -84,7 +134,17 @@ public:
~TestAspect()
{
- QRenderAspect::onUnregistered();
+ using namespace Qt3DCore;
+ QNodeVisitor visitor;
+ visitor.traverse(m_engine->rootEntity().data(), [](QNode *node) {
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_scene = nullptr;
+ d->m_changeArbiter = nullptr;
+ });
+
+ m_engine->unregisterAspect(this);
+ delete m_engine;
+ m_engine = nullptr;
}
void onRegistered() { QRenderAspect::onRegistered(); }
@@ -94,8 +154,10 @@ public:
Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const { return d_func()->m_renderer->frameGraphRoot(); }
Qt3DRender::Render::RenderSettings *renderSettings() const { return d_func()->m_renderer->settings(); }
Qt3DRender::Render::Entity *sceneRoot() const { return m_sceneRoot; }
-
+ Qt3DCore::QAspectManager *aspectManager() const { return d_func()->m_aspectManager; }
+ Qt3DCore::QChangeArbiter *arbiter() const { return d_func()->m_arbiter; }
private:
+ Qt3DCore::QAspectEngine *m_engine;
Render::Entity *m_sceneRoot;
};
@@ -107,9 +169,9 @@ namespace {
void runRequiredJobs(Qt3DRender::TestAspect *test)
{
- Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob;
- updateEntitiesJob.setManager(test->nodeManagers());
- updateEntitiesJob.run();
+ QCoreApplication::processEvents();
+ const auto dn = test->arbiter()->takeDirtyFrontEndNodes();
+ Qt3DCore::QAbstractAspectPrivate::get(test)->syncDirtyFrontEndNodes(dn);
Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform;
updateWorldTransform.setRoot(test->sceneRoot());
@@ -198,6 +260,7 @@ private Q_SLOTS:
QmlSceneReader sceneReader(source);
QScopedPointer<Qt3DCore::QEntity> root(qobject_cast<Qt3DCore::QEntity *>(sceneReader.root()));
QVERIFY(root);
+ QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
Qt3DCore::QComponentVector rootComponents = root->components();
Qt3DRender::QRayCaster *rayCaster = nullptr;
@@ -210,33 +273,31 @@ private Q_SLOTS:
rayCaster->trigger(rayOrigin, rayDirection, rayLength);
- QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
- TestArbiter arbiter;
-
// Runs Required jobs
runRequiredJobs(test.data());
Qt3DRender::Render::RayCaster *backendRayCaster = test->nodeManagers()->rayCasterManager()->lookupResource(rayCaster->id());
QVERIFY(backendRayCaster);
- Qt3DCore::QBackendNodePrivate::get(backendRayCaster)->setArbiter(&arbiter);
+ Qt3DCore::QBackendNodePrivate::get(backendRayCaster)->setArbiter(test->arbiter());
// WHEN
Qt3DRender::Render::RayCastingJob rayCastingJob;
initializeJob(&rayCastingJob, test.data());
bool earlyReturn = !rayCastingJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&rayCastingJob)->postFrame(test->aspectManager());
+ QCoreApplication::processEvents();
// THEN
QVERIFY(!earlyReturn);
QVERIFY(!backendRayCaster->isEnabled());
- QCOMPARE(arbiter.events.count(), 2); // hits & disable
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "hits");
- Qt3DRender::QRayCaster::Hits hits = change->value().value<Qt3DRender::QRayCaster::Hits>();
- QCOMPARE(hits.size(), numIntersections);
+ QVERIFY(!rayCaster->isEnabled());
+ auto dirtyNodes = test->arbiter()->takeDirtyFrontEndNodes();
+ QCOMPARE(dirtyNodes.count(), 1); // hits & disable
+ QCOMPARE(rayCaster->hits().size(), numIntersections);
if (numIntersections)
- QVERIFY(hits.first().entityId());
+ QVERIFY(rayCaster->hits().first().entityId());
}
void screenSpaceRayCaster_data()
@@ -259,6 +320,7 @@ private Q_SLOTS:
QmlSceneReader sceneReader(source);
QScopedPointer<Qt3DCore::QEntity> root(qobject_cast<Qt3DCore::QEntity *>(sceneReader.root()));
QVERIFY(root);
+ QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
Qt3DCore::QComponentVector rootComponents = root->components();
Qt3DRender::QScreenRayCaster *rayCaster = nullptr;
@@ -271,33 +333,31 @@ private Q_SLOTS:
rayCaster->trigger(rayPosition);
- QScopedPointer<Qt3DRender::TestAspect> test(new Qt3DRender::TestAspect(root.data()));
- TestArbiter arbiter;
-
// Runs Required jobs
runRequiredJobs(test.data());
Qt3DRender::Render::RayCaster *backendRayCaster = test->nodeManagers()->rayCasterManager()->lookupResource(rayCaster->id());
QVERIFY(backendRayCaster);
- Qt3DCore::QBackendNodePrivate::get(backendRayCaster)->setArbiter(&arbiter);
+ Qt3DCore::QBackendNodePrivate::get(backendRayCaster)->setArbiter(test->arbiter());
// WHEN
Qt3DRender::Render::RayCastingJob rayCastingJob;
initializeJob(&rayCastingJob, test.data());
bool earlyReturn = !rayCastingJob.runHelper();
+ Qt3DCore::QAspectJobPrivate::get(&rayCastingJob)->postFrame(test->aspectManager());
+ QCoreApplication::processEvents();
// THEN
QVERIFY(!earlyReturn);
QVERIFY(!backendRayCaster->isEnabled());
- QCOMPARE(arbiter.events.count(), 2); // hits & disable
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "hits");
- Qt3DRender::QScreenRayCaster::Hits hits = change->value().value<Qt3DRender::QScreenRayCaster::Hits>();
- QCOMPARE(hits.size(), numIntersections);
+ QVERIFY(!rayCaster->isEnabled());
+ auto dirtyNodes = test->arbiter()->takeDirtyFrontEndNodes();
+ QCOMPARE(dirtyNodes.count(), 1); // hits & disable
+ QCOMPARE(rayCaster->hits().size(), numIntersections);
if (numIntersections)
- QVERIFY(hits.first().entityId());
+ QVERIFY(rayCaster->hits().first().entityId());
}
};
diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro
index edf6fa101..180ff7ac1 100644
--- a/tests/auto/render/render.pro
+++ b/tests/auto/render/render.pro
@@ -41,6 +41,7 @@ qtConfig(private_tests) {
# qboundingvolumedebug \
# boundingvolumedebug \
ddstextures \
+ ktxtextures \
shadercache \
layerfiltering \
filterentitybycomponent \
@@ -64,7 +65,6 @@ qtConfig(private_tests) {
qabstracttexture \
qabstracttextureimage \
qrendersettings \
- texturedatamanager \
rendertarget \
transform \
computecommand \
@@ -103,7 +103,10 @@ qtConfig(private_tests) {
qsetfence \
qwaitfence \
setfence \
- waitfence
+ waitfence \
+ qtexturedataupdate \
+ qshaderimage \
+ shaderimage
QT_FOR_CONFIG = 3dcore-private
# TO DO: These could be restored to be executed in all cases
@@ -134,7 +137,8 @@ qtConfig(qt3d-opengl-renderer):qtConfig(private_tests) {
renderviews \
renderqueue \
renderviewbuilder \
- sendrendercapturejob
+ sendrendercapturejob \
+ gltexture
qtConfig(qt3d-extras) {
SUBDIRS += \
diff --git a/tests/auto/render/rendercapture/tst_rendercapture.cpp b/tests/auto/render/rendercapture/tst_rendercapture.cpp
index 799a7ccff..3ad3668c9 100644
--- a/tests/auto/render/rendercapture/tst_rendercapture.cpp
+++ b/tests/auto/render/rendercapture/tst_rendercapture.cpp
@@ -31,7 +31,6 @@
#include <Qt3DRender/private/rendercapture_p.h>
#include <Qt3DRender/qrendercapture.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "testpostmanarbiter.h"
#include "testrenderer.h"
@@ -43,48 +42,51 @@ private Q_SLOTS:
void checkInitialState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QRenderCapture frontend;
Qt3DRender::Render::RenderCapture backend;
// WHEN
- simulateInitialization(&frontend, &backend);
+ backend.setRenderer(&renderer);
+ simulateInitializationSync(&frontend, &backend);
// THEN
QVERIFY(!backend.peerId().isNull());
QCOMPARE(backend.wasCaptureRequested(), false);
QCOMPARE(backend.isEnabled(), true);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
void checkEnabledPropertyChange()
{
// GIVEN
+ Qt3DRender::QRenderCapture frontend;
Qt3DRender::Render::RenderCapture renderCapture;
TestRenderer renderer;
renderCapture.setRenderer(&renderer);
+ simulateInitializationSync(&frontend, &renderCapture);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(renderCapture.peerId()));
- change->setPropertyName(QByteArrayLiteral("enabled"));
- change->setValue(QVariant::fromValue(true));
- sceneChangeEvent(&renderCapture, change);
+ frontend.setEnabled(false);
+ renderCapture.syncFromFrontEnd(&frontend, false);
// THEN
- QCOMPARE(renderCapture.isEnabled(), true);
+ QCOMPARE(renderCapture.isEnabled(), false);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
void checkReceiveRenderCaptureRequest()
{
// GIVEN
+ Qt3DRender::QRenderCapture frontend;
Qt3DRender::Render::RenderCapture renderCapture;
TestRenderer renderer;
renderCapture.setRenderer(&renderer);
- renderCapture.setEnabled(true);
+ simulateInitializationSync(&frontend, &renderCapture);
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr change(new Qt3DCore::QPropertyUpdatedChange(renderCapture.peerId()));
- change->setPropertyName(QByteArrayLiteral("renderCaptureRequest"));
- change->setValue(QVariant::fromValue(32));
- sceneChangeEvent(&renderCapture, change);
+ frontend.requestCapture();
+ renderCapture.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(renderCapture.wasCaptureRequested(), true);
diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp
index 2fc76c792..a343d6e57 100644
--- a/tests/auto/render/renderer/tst_renderer.cpp
+++ b/tests/auto/render/renderer/tst_renderer.cpp
@@ -36,6 +36,7 @@
#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <Qt3DRender/private/offscreensurfacehelper_p.h>
#include <Qt3DRender/private/renderqueue_p.h>
+#include <Qt3DRender/private/job_common_p.h>
class tst_Renderer : public QObject
{
@@ -87,7 +88,7 @@ private Q_SLOTS:
1); // SendRenderCaptureJob
// WHEN
- renderer.m_sendBufferCaptureJob->addRequest({nullptr, {}});
+ renderer.m_sendBufferCaptureJob->addRequest({Qt3DCore::QNodeId(), {}});
jobs = renderer.preRenderingJobs();
// THEN
@@ -159,27 +160,94 @@ private Q_SLOTS:
const int layerCacheJobCount = 2;
// filterEntityByLayerJob,
// syncFilterEntityByLayerJob
- const int singleRenderViewJobCount = 8 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount();
+
+ const int singleRenderViewCommandRebuildJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount();
+
+ const int singleRenderViewJobCount = 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount();
// RenderViewBuilder renderViewJob,
// syncRenderViewInitializationJob,
// syncFrustumCullingJob,
// filterProximityJob,
// setClearDrawBufferIndexJob,
// frustumCullingJob,
- // syncRenderCommandBuldingJob,
- // syncRenderViewCommandBuilderJob
+ // syncRenderCommandUpdateJob,
+ // syncRenderViewCommandPostUpdateJob
// n * (RenderViewCommandBuildJobs)
- // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt)
+ // WHEN
QVector<Qt3DCore::QAspectJobPtr> jobs = renderer.renderBinJobs();
+ // THEN -> AllDirty
+ // (Renderer is not initialized so FilterCompatibleTechniqueJob
+ // and ShaderGathererJob are not added here)
+ QCOMPARE(jobs.size(),
+ 1 + // EntityEnabledDirty
+ 1 + // WorldTransformJob
+ 1 + // UpdateWorldBoundingVolume
+ 1 + // UpdateShaderDataTransform
+ 1 + // ExpandBoundingVolumeJob
+ 1 + // CalculateBoundingVolumeJob
+ 1 + // UpdateMeshTriangleListJob
+ 1 + // updateSkinningPaletteJob
+ 1 + // SyncLoadingJobs
+ 1 + // updateLevelOfDetailJob
+ 1 + // cleanupJob
+ 1 + // sendDisablesToFrontend
+ 1 + // VAOGatherer
+ 1 + // BufferGathererJob
+ 1 + // TexturesGathererJob
+ 1 + // UpdateEntityLayersJob
+ 1 + // LightGathererJob
+ 1 + // CacheLightJob
+ 1 + // RenderableEntityFilterJob
+ 1 + // CacheRenderableEntitiesJob
+ 1 + // ComputableEntityFilterJob
+ 1 + // CacheComputableEntitiesJob
+ singleRenderViewJobCount +
+ singleRenderViewCommandRebuildJobCount +
+ layerCacheJobCount +
+ renderViewBuilderMaterialCacheJobCount);
+
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderQueue->reset();
+
+ // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (Nothing in cache)
+ renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr);
+ jobs = renderer.renderBinJobs();
+
+ // THEN (level
+ QCOMPARE(jobs.size(),
+ 1 + // updateLevelOfDetailJob
+ 1 + // cleanupJob
+ 1 + // VAOGatherer
+ 1 + // updateSkinningPaletteJob
+ 1 + // SyncLoadingJobs
+ 1 + // sendDisablesToFrontend
+ singleRenderViewJobCount +
+ singleRenderViewCommandRebuildJobCount +
+ renderViewBuilderMaterialCacheJobCount +
+ layerCacheJobCount);
+
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderQueue->reset();
+
+ // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (RV leaf in cache)
+ renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr);
+ renderer.cache()->leafNodeCache[renderer.m_frameGraphLeaves.first()] = {};
+ jobs = renderer.renderBinJobs();
+
// THEN (level
QCOMPARE(jobs.size(),
1 + // updateLevelOfDetailJob
1 + // cleanupJob
1 + // VAOGatherer
1 + // updateSkinningPaletteJob
- singleRenderViewJobCount); // Only valid for the first call to renderBinJobs(), since subsequent calls won't have the renderqueue reset
+ 1 + // SyncLoadingJobs
+ 1 + // sendDisablesToFrontend
+ singleRenderViewJobCount +
+ singleRenderViewCommandRebuildJobCount +
+ renderViewBuilderMaterialCacheJobCount +
+ layerCacheJobCount);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
renderQueue->reset();
@@ -194,6 +262,8 @@ private Q_SLOTS:
1 + // cleanupJob
1 + // VAOGatherer
1 + // updateSkinningPaletteJob
+ 1 + // SyncLoadingJobs
+ 1 + // sendDisablesToFrontend
1 + // EntityEnabledDirty
singleRenderViewJobCount +
layerCacheJobCount);
@@ -214,6 +284,8 @@ private Q_SLOTS:
1 + // UpdateWorldBoundingVolume
1 + // UpdateShaderDataTransform
1 + // updateSkinningPaletteJob
+ 1 + // SyncLoadingJobs
+ 1 + // sendDisablesToFrontend
1 + // ExpandBoundingVolumeJob
singleRenderViewJobCount);
@@ -230,7 +302,10 @@ private Q_SLOTS:
1 + // cleanupJob
1 + // VAOGatherer
1 + // updateSkinningPaletteJob
+ 1 + // SyncLoadingJobs
+ 1 + // sendDisablesToFrontend
singleRenderViewJobCount +
+ singleRenderViewCommandRebuildJobCount +
renderViewBuilderMaterialCacheJobCount);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
@@ -248,9 +323,12 @@ private Q_SLOTS:
1 + // CalculateBoundingVolumeJob
1 + // UpdateMeshTriangleListJob
1 + // updateSkinningPaletteJob
+ 1 + // SyncLoadingJobs
1 + // ExpandBoundingVolumeJob
1 + // RenderableEntityFilterPtr
1 + // SyncRenderableEntities
+ 1 + // sendDisablesToFrontend
+ singleRenderViewCommandRebuildJobCount +
singleRenderViewJobCount);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
@@ -266,9 +344,11 @@ private Q_SLOTS:
1 + // cleanupJob
1 + // VAOGatherer
1 + // updateSkinningPaletteJob
+ 1 + // SyncLoadingJobs
1 + // CalculateBoundingVolumeJob
1 + // UpdateMeshTriangleListJob
1 + // BufferGathererJob
+ 1 + // sendDisablesToFrontend
singleRenderViewJobCount);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
@@ -286,86 +366,12 @@ private Q_SLOTS:
1 + // TexturesGathererJob
1 + // updateSkinningPaletteJob
1 + // SyncTexturesGathererJob
+ 1 + // sendDisablesToFrontend
singleRenderViewJobCount);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
renderQueue->reset();
- // WHEN
- renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr);
- jobs = renderer.renderBinJobs();
-
- QCOMPARE(jobs.size(),
- 1 + // updateLevelOfDetailJob
- 1 + // cleanupJob
- 1 + // VAOGatherer
- 1 + // updateSkinningPaletteJob
- singleRenderViewJobCount +
- layerCacheJobCount +
- renderViewBuilderMaterialCacheJobCount);
-
- renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderQueue->reset();
-
- // WHEN
- renderer.markDirty(Qt3DRender::Render::AbstractRenderer::EntityHierarchyDirty, nullptr);
- jobs = renderer.renderBinJobs();
-
- // THEN
- QCOMPARE(jobs.size(),
- 1 + // EntityEnabledDirty
- 1 + // EntityHierarchyJob
- 1 + // WorldTransformJob
- 1 + // UpdateWorldBoundingVolume
- 1 + // UpdateShaderDataTransform
- 1 + // ExpandBoundingVolumeJob
- 1 + // UpdateEntityLayersJob
- 1 + // updateLevelOfDetailJob
- 1 + // updateSkinningPaletteJob
- 1 + // cleanupJob
- 1 + // sendBufferCaptureJob
- singleRenderViewJobCount +
- layerCacheJobCount);
-
- renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderQueue->reset();
-
- // WHEN
- renderer.markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr);
- jobs = renderer.renderBinJobs();
-
- // THEN (Renderer is not initialized so FilterCompatibleTechniqueJob
- // and ShaderGathererJob are not added here)
- QCOMPARE(jobs.size(),
- 1 + // EntityEnabledDirty
- 1 + // EntityHierarchyDirty
- 1 + // WorldTransformJob
- 1 + // UpdateWorldBoundingVolume
- 1 + // UpdateShaderDataTransform
- 1 + // ExpandBoundingVolumeJob
- 1 + // CalculateBoundingVolumeJob
- 1 + // UpdateMeshTriangleListJob
- 1 + // updateSkinningPaletteJob
- 1 + // updateLevelOfDetailJob
- 1 + // cleanupJob
- 1 + // VAOGatherer
- 1 + // BufferGathererJob
- 1 + // TexturesGathererJob
- 1 + // SyncTextureLoadingJob
- 1 + // UpdateEntityLayersJob
- 1 + // RenderableEntityFilterPtr
- 1 + // SyncRenderableEntities
- 1 + // ComputableEntityFilterPtr
- 1 + // SyncComputableEntities
- 1 + // LightGathererPtr
- 1 + // SyncLightsGatherer
- singleRenderViewJobCount +
- layerCacheJobCount +
- renderViewBuilderMaterialCacheJobCount);
-
- renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderQueue->reset();
-
// Properly shutdown command thread
renderer.shutdown();
}
diff --git a/tests/auto/render/renderpass/tst_renderpass.cpp b/tests/auto/render/renderpass/tst_renderpass.cpp
index a4a2762ba..39ff1c06e 100644
--- a/tests/auto/render/renderpass/tst_renderpass.cpp
+++ b/tests/auto/render/renderpass/tst_renderpass.cpp
@@ -30,10 +30,6 @@
#include <qbackendnodetester.h>
#include <Qt3DRender/private/renderpass_p.h>
-#include <Qt3DCore/QPropertyUpdatedChange>
-#include <Qt3DCore/QPropertyNodeAddedChange>
-#include <Qt3DCore/QPropertyNodeRemovedChange>
-
#include <Qt3DRender/QFilterKey>
#include <Qt3DRender/QRenderPass>
#include <Qt3DRender/QShaderProgram>
@@ -70,6 +66,7 @@ using namespace Qt3DRender::Render;
class tst_RenderRenderPass : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
+
public:
tst_RenderRenderPass()
: m_renderStateManager(new RenderStateManager())
@@ -96,6 +93,8 @@ private slots:
{
// GIVEN
RenderPass backend;
+ TestRenderer renderer;
+ backend.setRenderer(&renderer);
// WHEN
backend.setEnabled(true);
@@ -112,7 +111,7 @@ private slots:
frontend.addRenderState(&state);
frontend.setShaderProgram(&program);
- simulateInitialization(&frontend, &backend);
+ simulateInitializationSync(&frontend, &backend);
}
backend.cleanup();
@@ -141,12 +140,15 @@ private slots:
frontend.addRenderState(frontendState);
RenderPass backend;
+ TestRenderer renderer;
+ backend.setRenderer(&renderer);
RenderStateNode *backendState = m_renderStateManager->getOrCreateResource(frontendState->id());
- simulateInitialization(frontendState, backendState);
+ backendState->setRenderer(&renderer);
+ simulateInitializationSync(frontendState, backendState);
// WHEN
- simulateInitialization(&frontend, &backend);
+ simulateInitializationSync(&frontend, &backend);
// THEN
QCOMPARE(backend.shaderProgram(), frontend.shaderProgram()->id());
@@ -165,25 +167,26 @@ private slots:
void shouldHandleShaderPropertyChangeEvents()
{
// GIVEN
- QScopedPointer<QShaderProgram> shader(new QShaderProgram);
+ QShaderProgram *shader = new QShaderProgram;
RenderPass backend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ QRenderPass frontend;
+ simulateInitializationSync(&frontend, &backend);
+
// WHEN
- const auto addChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), shader.data());
- addChange->setPropertyName("shaderProgram");
- backend.sceneChangeEvent(addChange);
+ frontend.setShaderProgram(shader);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.shaderProgram(), shader->id());
QVERIFY(renderer.dirtyBits() != 0);
// WHEN
- const auto removeChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), shader.data());
- removeChange->setPropertyName("shaderProgram");
- backend.sceneChangeEvent(removeChange);
+ frontend.setShaderProgram(nullptr);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(backend.shaderProgram().isNull());
@@ -192,16 +195,18 @@ private slots:
void shouldHandleAnnotationsPropertyChangeEvents()
{
// GIVEN
- QScopedPointer<QFilterKey> annotation(new QFilterKey);
+ QFilterKey *annotation = new QFilterKey;
RenderPass backend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ QRenderPass frontend;
+ simulateInitializationSync(&frontend, &backend);
+
// WHEN
- const auto addChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), annotation.data());
- addChange->setPropertyName("filterKeys");
- backend.sceneChangeEvent(addChange);
+ frontend.addFilterKey(annotation);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.filterKeys().size(), 1);
@@ -209,9 +214,8 @@ private slots:
QVERIFY(renderer.dirtyBits() != 0);
// WHEN
- const auto removeChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), annotation.data());
- removeChange->setPropertyName("filterKeys");
- backend.sceneChangeEvent(removeChange);
+ frontend.removeFilterKey(annotation);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(backend.filterKeys().isEmpty());
@@ -220,16 +224,18 @@ private slots:
void shouldHandleParametersPropertyChangeEvents()
{
// GIVEN
- QScopedPointer<QParameter> parameter(new QParameter);
+ QParameter *parameter = new QParameter;
RenderPass backend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ QRenderPass frontend;
+ simulateInitializationSync(&frontend, &backend);
+
// WHEN
- const auto addChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), parameter.data());
- addChange->setPropertyName("parameter");
- backend.sceneChangeEvent(addChange);
+ frontend.addParameter(parameter);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.parameters().size(), 1);
@@ -237,9 +243,8 @@ private slots:
QVERIFY(renderer.dirtyBits() != 0);
// WHEN
- const auto removeChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), parameter.data());
- removeChange->setPropertyName("parameter");
- backend.sceneChangeEvent(removeChange);
+ frontend.removeParameter(parameter);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(backend.parameters().isEmpty());
@@ -254,12 +259,15 @@ private slots:
backend.setRenderer(&renderer);
RenderStateNode *backendState = m_renderStateManager->getOrCreateResource(frontendState->id());
- simulateInitialization(frontendState, backendState);
+ backendState->setRenderer(&renderer);
+ simulateInitializationSync(frontendState, backendState);
+
+ QRenderPass frontend;
+ simulateInitializationSync(&frontend, &backend);
// WHEN
- const auto addChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), frontendState);
- addChange->setPropertyName("renderState");
- backend.sceneChangeEvent(addChange);
+ frontend.addRenderState(frontendState);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.renderStates().size(), 1);
@@ -267,32 +275,13 @@ private slots:
QVERIFY(renderer.dirtyBits() != 0);
// WHEN
- const auto removeChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), frontendState);
- removeChange->setPropertyName("renderState");
- backend.sceneChangeEvent(removeChange);
+ frontend.removeRenderState(frontendState);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(backend.renderStates().isEmpty());
}
- void shouldHandleShaderProgramPropertyChangeEvents()
- {
- // GIVEN
- RenderPass backend;
- TestRenderer renderer;
- backend.setRenderer(&renderer);
-
- // WHEN
- Qt3DCore::QNodeId shaderId = Qt3DCore::QNodeId::createId();
- const auto shaderChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- shaderChange->setPropertyName("shaderProgram");
- shaderChange->setValue(QVariant::fromValue(shaderId));
- backend.sceneChangeEvent(shaderChange);
-
- // THEN
- QCOMPARE(backend.shaderProgram(), shaderId);
- }
-
private:
RenderStateManager *m_renderStateManager;
};
diff --git a/tests/auto/render/rendertarget/tst_rendertarget.cpp b/tests/auto/render/rendertarget/tst_rendertarget.cpp
index a5d8cad77..31eee6ec5 100644
--- a/tests/auto/render/rendertarget/tst_rendertarget.cpp
+++ b/tests/auto/render/rendertarget/tst_rendertarget.cpp
@@ -32,9 +32,6 @@
#include <Qt3DRender/qrendertargetoutput.h>
#include <Qt3DRender/private/qrendertarget_p.h>
#include <Qt3DRender/private/rendertarget_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
@@ -75,6 +72,7 @@ private Q_SLOTS:
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QRenderTarget renderTarget;
Qt3DRender::QRenderTargetOutput renderTargetOuput;
renderTarget.addOutput(&renderTargetOuput);
@@ -82,8 +80,8 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::RenderTarget backendRenderTarget;
- simulateInitialization(&renderTarget, &backendRenderTarget);
-
+ backendRenderTarget.setRenderer(&renderer);
+ simulateInitializationSync(&renderTarget, &backendRenderTarget);
// THEN
QCOMPARE(backendRenderTarget.isEnabled(), true);
QCOMPARE(backendRenderTarget.peerId(), renderTarget.id());
@@ -93,7 +91,8 @@ private Q_SLOTS:
// WHEN
Qt3DRender::Render::RenderTarget backendRenderTarget;
renderTarget.setEnabled(false);
- simulateInitialization(&renderTarget, &backendRenderTarget);
+ backendRenderTarget.setRenderer(&renderer);
+ simulateInitializationSync(&renderTarget, &backendRenderTarget);
// THEN
QCOMPARE(backendRenderTarget.peerId(), renderTarget.id());
@@ -168,17 +167,17 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DRender::QRenderTarget renderTarget;
Qt3DRender::Render::RenderTarget backendRenderTarget;
TestRenderer renderer;
backendRenderTarget.setRenderer(&renderer);
+ simulateInitializationSync(&renderTarget, &backendRenderTarget);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendRenderTarget.sceneChangeEvent(change);
+ renderTarget.setEnabled(newValue);
+ backendRenderTarget.syncFromFrontEnd(&renderTarget, false);
// THEN
QCOMPARE(backendRenderTarget.isEnabled(), newValue);
@@ -186,21 +185,23 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::QRenderTargetOutput targetOutput;
- const auto addChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &targetOutput);
- addChange->setPropertyName("output");
- backendRenderTarget.sceneChangeEvent(addChange);
+ renderTarget.addOutput(&targetOutput);
+ backendRenderTarget.syncFromFrontEnd(&renderTarget, false);
// THEN
QCOMPARE(backendRenderTarget.renderOutputs().size(), 1);
QCOMPARE(backendRenderTarget.renderOutputs().first(), targetOutput.id());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
// WHEN
- const auto removeChange = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &targetOutput);
- removeChange->setPropertyName("output");
- backendRenderTarget.sceneChangeEvent(removeChange);
+ renderTarget.removeOutput(&targetOutput);
+ backendRenderTarget.syncFromFrontEnd(&renderTarget, false);
// THEN
QCOMPARE(backendRenderTarget.renderOutputs().size(), 0);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
}
diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
index 27671bb68..6024084bd 100644
--- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
+++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
@@ -27,9 +27,9 @@
****************************************************************************/
#include <QtTest/QTest>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <Qt3DRender/private/qrenderaspect_p.h>
@@ -52,6 +52,7 @@
#include <Qt3DRender/private/qrenderaspect_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
QT_BEGIN_NAMESPACE
@@ -67,11 +68,22 @@ public:
Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data();
QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- for (const Qt3DCore::QNodeCreatedChangeBasePtr change : creationChanges)
- d_func()->createBackendNode(change);
+ QVector<Qt3DCore::QNode *> nodes;
+ Qt3DCore::QNodeVisitor v;
+ v.traverse(root, [&nodes](Qt3DCore::QNode *node) {
+ Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject()));
+ d->m_hasBackendNode = true;
+ nodes << node;
+ });
+
+ for (const auto node: nodes)
+ d_func()->createBackendNode({
+ node->id(),
+ Qt3DCore::QNodePrivate::get(node)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ node
+ });
}
~TestAspect()
@@ -213,29 +225,29 @@ private Q_SLOTS:
QCOMPARE(renderViewBuilder.materialGathererCacheNeedsToBeRebuilt(), false);
QVERIFY(!renderViewBuilder.renderViewJob().isNull());
QVERIFY(!renderViewBuilder.frustumCullingJob().isNull());
- QVERIFY(!renderViewBuilder.syncFrustumCullingJob().isNull());
+ QVERIFY(!renderViewBuilder.syncPreFrustumCullingJob().isNull());
QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull());
QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull());
QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull());
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob().isNull());
- QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob().isNull());
- QVERIFY(renderViewBuilder.syncRenderViewInitializationJob().isNull());
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull());
+ QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull());
+ QVERIFY(renderViewBuilder.syncRenderViewPostInitializationJob().isNull());
- QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), 0);
+ QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), 0);
QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0);
// WHEN
renderViewBuilder.prepareJobs();
// THEN
- QVERIFY(!renderViewBuilder.syncRenderCommandBuildingJob().isNull());
- QVERIFY(!renderViewBuilder.syncRenderViewCommandBuildersJob().isNull());
- QVERIFY(!renderViewBuilder.syncRenderViewInitializationJob().isNull());
+ QVERIFY(!renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull());
+ QVERIFY(!renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull());
+ QVERIFY(!renderViewBuilder.syncRenderViewPostInitializationJob().isNull());
QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull());
QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull());
- QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
+ QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0);
QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
}
@@ -269,39 +281,6 @@ private Q_SLOTS:
// mark jobs dirty and recheck
QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 9 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
}
-
- {
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setLightGathererCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
-
- // THEN
- QCOMPARE(renderViewBuilder.lightGathererCacheNeedsToBeRebuilt(), true);
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- }
-
- {
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
-
- // THEN
- QCOMPARE(renderViewBuilder.renderableCacheNeedsToBeRebuilt(), true);
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- }
-
- {
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setComputableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
-
- // THEN
- QCOMPARE(renderViewBuilder.computableCacheNeedsToBeRebuilt(), true);
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- }
}
void checkCheckJobDependencies()
@@ -327,49 +306,53 @@ private Q_SLOTS:
// Step 2
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1);
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data());
+ QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(),
+ renderViewBuilder.renderViewJob().data());
// Step 3
QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull());
QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull());
QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1);
- QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data());
+ QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(),
+ renderViewBuilder.syncRenderViewPostInitializationJob().data());
- QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3);
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
+ QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3);
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
// Step 4
QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob()));
+ QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob()));
QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
- QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6);
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
+ QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7);
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->cacheLightJob()));
// Step 5
- for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
+ for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) {
QCOMPARE(renderViewBuilderJob->dependencies().size(), 1);
- QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data());
+ QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(),
+ renderViewBuilder.syncRenderViewPreCommandUpdateJob().data());
}
// Step 6
- QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size());
- for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
- QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob));
+ QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size());
+ for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) {
+ QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob));
}
}
{
@@ -385,62 +368,63 @@ private Q_SLOTS:
QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update
// Step 2
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1);
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data());
+ QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(),
+ renderViewBuilder.renderViewJob().data());
// Step 3
QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 3);
QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateEntityLayersJob()));
- QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob()));
QCOMPARE(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().size(), 1);
QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob()));
QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1);
- QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data());
+ QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(),
+ renderViewBuilder.syncRenderViewPostInitializationJob().data());
- QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3);
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
+ QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3);
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
+ QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) {
QCOMPARE(materialGatherer->dependencies().size(), 3);
- QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob()));
}
// Step 4
QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob()));
+ QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob()));
QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
- QCOMPARE(renderViewBuilder.syncMaterialGathererJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size());
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncMaterialGathererJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
// Step 5
- for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
+ for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) {
QCOMPARE(renderViewBuilderJob->dependencies().size(), 1);
- QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data());
+ QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(),
+ renderViewBuilder.syncRenderViewPreCommandUpdateJob().data());
}
// Step 6
- QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size());
- for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
- QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob));
+ QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size());
+ for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) {
+ QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob));
}
}
}
@@ -472,21 +456,18 @@ private Q_SLOTS:
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport);
Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
// WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setLightGathererCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
- renderViewBuilder.buildJobHierachy();
- renderViewBuilder.lightGathererJob()->run();
+ renderer->lightGathererJob()->run();
// THEN
- QCOMPARE(renderViewBuilder.lightGathererJob()->lights().size(), 2);
- QVERIFY(renderViewBuilder.lightGathererJob()->takeEnvironmentLight() != nullptr);
+ QCOMPARE(renderer->lightGathererJob()->lights().size(), 2);
+ QVERIFY(renderer->lightGathererJob()->takeEnvironmentLight() != nullptr);
}
void checkRenderableEntitiesFilteringExecution()
@@ -495,20 +476,17 @@ private Q_SLOTS:
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport);
Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
// WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
- renderViewBuilder.buildJobHierachy();
- renderViewBuilder.renderableEntityFilterJob()->run();
+ renderer->renderableEntityFilterJob()->run();
// THEN
- QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->filteredEntities().size(), 1);
+ QCOMPARE(renderer->renderableEntityFilterJob()->filteredEntities().size(), 1);
}
void checkComputableEntitiesFilteringExecution()
@@ -517,20 +495,17 @@ private Q_SLOTS:
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport);
Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
// WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setComputableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
- renderViewBuilder.buildJobHierachy();
- renderViewBuilder.computableEntityFilterJob()->run();
+ renderer->computableEntityFilterJob()->run();
// THEN
- QCOMPARE(renderViewBuilder.computableEntityFilterJob()->filteredEntities().size(), 1);
+ QCOMPARE(renderer->computableEntityFilterJob()->filteredEntities().size(), 1);
}
void checkSyncRenderViewInitializationExecution()
@@ -566,7 +541,7 @@ private Q_SLOTS:
// WHEN
renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.syncRenderViewInitializationJob()->run();
+ renderViewBuilder.syncRenderViewPostInitializationJob()->run();
// THEN
QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true);
@@ -593,7 +568,7 @@ private Q_SLOTS:
// WHEN
renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.syncRenderViewInitializationJob()->run();
+ renderViewBuilder.syncRenderViewPostInitializationJob()->run();
// THEN
QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true);
@@ -632,7 +607,7 @@ private Q_SLOTS:
// WHEN
renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.syncFrustumCullingJob()->run();
+ renderViewBuilder.syncPreFrustumCullingJob()->run();
// THEN
QCOMPARE(convertToQMatrix4x4(renderViewBuilder.frustumCullingJob()->viewProjection()), camera->projectionMatrix() * camera->viewMatrix());
@@ -647,24 +622,28 @@ private Q_SLOTS:
Qt3DRender::QLayer *layer = new Qt3DRender::QLayer();
layerFilter->addLayer(layer);
Qt3DRender::TestAspect testAspect(buildEntityFilterTestScene(viewport, layer));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(layerFilter->id());
QVERIFY(leafNode != nullptr);
// WHEN
+ renderer->markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr);
+
Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true);
- renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true);
renderViewBuilder.prepareJobs();
renderViewBuilder.buildJobHierachy();
+ renderer->renderableEntityFilterJob()->run();
+ renderer->cacheRenderableEntitiesJob()->run();
+
renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.renderableEntityFilterJob()->run();
- renderViewBuilder.syncRenderViewInitializationJob()->run();
+ renderViewBuilder.syncRenderViewPostInitializationJob()->run();
renderViewBuilder.filterEntityByLayerJob()->run();
- QVector<Qt3DRender::Render::Entity *> renderableEntity = renderViewBuilder.renderableEntityFilterJob()->filteredEntities();
+ QVector<Qt3DRender::Render::Entity *> renderableEntity = renderer->renderableEntityFilterJob()->filteredEntities();
QVector<Qt3DRender::Render::Entity *> filteredEntity = renderViewBuilder.filterEntityByLayerJob()->filteredEntities();
// THEN
diff --git a/tests/auto/render/renderviews/renderviews.pro b/tests/auto/render/renderviews/renderviews.pro
index 12ddb9eb9..046c00696 100644
--- a/tests/auto/render/renderviews/renderviews.pro
+++ b/tests/auto/render/renderviews/renderviews.pro
@@ -9,3 +9,4 @@ CONFIG += testcase
SOURCES += tst_renderviews.cpp
include(../../core/common/common.pri)
+include(../commons/commons.pri)
diff --git a/tests/auto/render/renderviews/tst_renderviews.cpp b/tests/auto/render/renderviews/tst_renderviews.cpp
index 3039eaa02..1558b68c9 100644
--- a/tests/auto/render/renderviews/tst_renderviews.cpp
+++ b/tests/auto/render/renderviews/tst_renderviews.cpp
@@ -35,6 +35,7 @@
#include <private/renderviewjobutils_p.h>
#include <private/rendercommand_p.h>
#include <testpostmanarbiter.h>
+#include <testrenderer.h>
QT_BEGIN_NAMESPACE
@@ -50,16 +51,11 @@ void compareShaderParameterPacks(const ShaderParameterPack &t1,
const PackUniformHash hash1 = t1.uniforms();
const PackUniformHash hash2 = t2.uniforms();
- QCOMPARE(hash1.size(), hash2.size());
+ QCOMPARE(hash1.keys.size(), hash2.keys.size());
- auto it = hash1.constBegin();
- const auto end = hash1.constEnd();
-
- while (it != end) {
- const auto h2It = hash2.find(it.key());
- QVERIFY(h2It != hash2.cend());
- QCOMPARE(it.value(), h2It.value());
- ++it;
+ for (int i = 0, m = hash1.keys.size(); i < m; ++i) {
+ const int key = hash1.keys.at(i);
+ QCOMPARE(hash1.value(key), hash2.value(key));
}
}
@@ -104,6 +100,7 @@ private Q_SLOTS:
void checkSetRenderViewConfig()
{
+ TestRenderer renderer;
{
// GIVEN
const QMemoryBarrier::Operations barriers(QMemoryBarrier::AtomicCounter|QMemoryBarrier::ShaderStorage);
@@ -113,10 +110,11 @@ private Q_SLOTS:
RenderView renderView;
// setRenderViewConfigFromFrameGraphLeafNode assumes node has a manager
backendBarrier.setFrameGraphManager(&frameGraphManager);
+ backendBarrier.setRenderer(&renderer);
// WHEN
frontendBarrier.setWaitOperations(barriers);
- simulateInitialization(&frontendBarrier, &backendBarrier);
+ simulateInitializationSync(&frontendBarrier, &backendBarrier);
// THEN
QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None);
@@ -135,14 +133,14 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::BackToFront);
for (int i = 0; i < 200; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_depth = float(i);
+ RenderCommand c;
+ c.m_depth = float(i);
rawCommands.push_back(c);
}
@@ -152,10 +150,10 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
for (int j = 1; j < sortedCommands.size(); ++j)
- QVERIFY(sortedCommands.at(j - 1)->m_depth > sortedCommands.at(j)->m_depth);
+ QVERIFY(sortedCommands.at(j - 1).m_depth > sortedCommands.at(j).m_depth);
// RenderCommands are deleted by RenderView dtor
}
@@ -164,7 +162,7 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::Material);
@@ -178,8 +176,8 @@ private Q_SLOTS:
};
for (int i = 0; i < 20; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_shaderDna = dnas[i % 5];
+ RenderCommand c;
+ c.m_shaderDna = dnas[i % 5];
rawCommands.push_back(c);
}
@@ -189,18 +187,18 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
ProgramDNA targetDNA;
for (int j = 0; j < sortedCommands.size(); ++j) {
if (j % 4 == 0) {
- targetDNA = sortedCommands.at(j)->m_shaderDna;
+ targetDNA = sortedCommands.at(j).m_shaderDna;
if (j > 0)
- QVERIFY(targetDNA != sortedCommands.at(j - 1)->m_shaderDna);
+ QVERIFY(targetDNA != sortedCommands.at(j - 1).m_shaderDna);
}
- QCOMPARE(targetDNA, sortedCommands.at(j)->m_shaderDna);
+ QCOMPARE(targetDNA, sortedCommands.at(j).m_shaderDna);
}
// RenderCommands are deleted by RenderView dtor
@@ -244,12 +242,12 @@ private Q_SLOTS:
QFETCH(QVector<ShaderParameterPack>, expectedMinimizedParameters);
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
for (int i = 0, m = programDNAs.size(); i < m; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_shaderDna = programDNAs.at(i);
- c->m_parameterPack = rawParameters.at(i);
+ RenderCommand c;
+ c.m_shaderDna = programDNAs.at(i);
+ c.m_parameterPack = rawParameters.at(i);
rawCommands.push_back(c);
}
@@ -258,13 +256,13 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands, sortedCommands);
for (int i = 0, m = programDNAs.size(); i < m; ++i) {
- const RenderCommand *c = sortedCommands.at(i);
- QCOMPARE(c->m_shaderDna, programDNAs.at(i));
- compareShaderParameterPacks(c->m_parameterPack, expectedMinimizedParameters.at(i));
+ const RenderCommand c = sortedCommands.at(i);
+ QCOMPARE(c.m_shaderDna, programDNAs.at(i));
+ compareShaderParameterPacks(c.m_parameterPack, expectedMinimizedParameters.at(i));
}
}
@@ -273,14 +271,14 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::FrontToBack);
for (int i = 0; i < 200; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_depth = float(i);
+ RenderCommand c;
+ c.m_depth = float(i);
rawCommands.push_back(c);
}
@@ -290,10 +288,10 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
for (int j = 1; j < sortedCommands.size(); ++j)
- QVERIFY(sortedCommands.at(j - 1)->m_depth < sortedCommands.at(j)->m_depth);
+ QVERIFY(sortedCommands.at(j - 1).m_depth < sortedCommands.at(j).m_depth);
// RenderCommands are deleted by RenderView dtor
}
@@ -302,14 +300,14 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::StateChangeCost);
for (int i = 0; i < 200; ++i) {
- RenderCommand *c = new RenderCommand();
- c->m_changeCost = i;
+ RenderCommand c;
+ c.m_changeCost = i;
rawCommands.push_back(c);
}
@@ -319,10 +317,10 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
for (int j = 1; j < sortedCommands.size(); ++j)
- QVERIFY(sortedCommands.at(j - 1)->m_changeCost > sortedCommands.at(j)->m_changeCost);
+ QVERIFY(sortedCommands.at(j - 1).m_changeCost > sortedCommands.at(j).m_changeCost);
// RenderCommands are deleted by RenderView dtor
}
@@ -331,7 +329,7 @@ private Q_SLOTS:
{
// GIVEN
RenderView renderView;
- QVector<RenderCommand *> rawCommands;
+ QVector<RenderCommand> rawCommands;
QVector<QSortPolicy::SortType> sortTypes;
sortTypes.push_back(QSortPolicy::StateChangeCost);
@@ -357,24 +355,24 @@ private Q_SLOTS:
};
auto buildRC = [] (ProgramDNA dna, float depth, int changeCost) {
- RenderCommand *c = new RenderCommand();
- c->m_shaderDna = dna;
- c->m_depth = depth;
- c->m_changeCost = changeCost;
+ RenderCommand c;
+ c.m_shaderDna = dna;
+ c.m_depth = depth;
+ c.m_changeCost = changeCost;
return c;
};
- RenderCommand *c5 = buildRC(dna[3], depth[1], stateChangeCost[1]);
- RenderCommand *c3 = buildRC(dna[3], depth[0], stateChangeCost[1]);
- RenderCommand *c4 = buildRC(dna[2], depth[1], stateChangeCost[1]);
- RenderCommand *c8 = buildRC(dna[1], depth[1], stateChangeCost[1]);
- RenderCommand *c0 = buildRC(dna[0], depth[2], stateChangeCost[1]);
+ RenderCommand c5 = buildRC(dna[3], depth[1], stateChangeCost[1]);
+ RenderCommand c3 = buildRC(dna[3], depth[0], stateChangeCost[1]);
+ RenderCommand c4 = buildRC(dna[2], depth[1], stateChangeCost[1]);
+ RenderCommand c8 = buildRC(dna[1], depth[1], stateChangeCost[1]);
+ RenderCommand c0 = buildRC(dna[0], depth[2], stateChangeCost[1]);
- RenderCommand *c2 = buildRC(dna[2], depth[2], stateChangeCost[0]);
- RenderCommand *c9 = buildRC(dna[2], depth[0], stateChangeCost[0]);
- RenderCommand *c1 = buildRC(dna[1], depth[0], stateChangeCost[0]);
- RenderCommand *c7 = buildRC(dna[0], depth[2], stateChangeCost[0]);
- RenderCommand *c6 = buildRC(dna[0], depth[1], stateChangeCost[0]);
+ RenderCommand c2 = buildRC(dna[2], depth[2], stateChangeCost[0]);
+ RenderCommand c9 = buildRC(dna[2], depth[0], stateChangeCost[0]);
+ RenderCommand c1 = buildRC(dna[1], depth[0], stateChangeCost[0]);
+ RenderCommand c7 = buildRC(dna[0], depth[2], stateChangeCost[0]);
+ RenderCommand c6 = buildRC(dna[0], depth[1], stateChangeCost[0]);
rawCommands << c0 << c1 << c2 << c3 << c4 << c5 << c6 << c7 << c8 << c9;
@@ -384,12 +382,9 @@ private Q_SLOTS:
renderView.sort();
// THEN
- const QVector<RenderCommand *> sortedCommands = renderView.commands();
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
QCOMPARE(rawCommands.size(), sortedCommands.size());
- for (RenderCommand *rc : sortedCommands)
- qDebug() << rc->m_changeCost << rc->m_shaderDna << rc->m_depth;
-
// Ordered by higher state, higher shaderDNA and higher depth
QCOMPARE(c0, sortedCommands.at(4));
QCOMPARE(c3, sortedCommands.at(1));
@@ -406,6 +401,84 @@ private Q_SLOTS:
// RenderCommands are deleted by RenderView dtor
}
+ void checkRenderCommandTextureSorting()
+ {
+ // GIVEN
+ RenderView renderView;
+ QVector<QSortPolicy::SortType> sortTypes;
+
+ sortTypes.push_back(QSortPolicy::Texture);
+
+
+ Qt3DCore::QNodeId tex1 = Qt3DCore::QNodeId::createId();
+ Qt3DCore::QNodeId tex2 = Qt3DCore::QNodeId::createId();
+ Qt3DCore::QNodeId tex3 = Qt3DCore::QNodeId::createId();
+ Qt3DCore::QNodeId tex4 = Qt3DCore::QNodeId::createId();
+
+ RenderCommand a;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(0, 0, tex1);
+ pack.setTexture(1, 0, tex3);
+ pack.setTexture(2, 0, tex4);
+ pack.setTexture(3, 0, tex2);
+ a.m_parameterPack = pack;
+ }
+ RenderCommand b;
+ RenderCommand c;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(0, 0, tex1);
+ pack.setTexture(3, 0, tex2);
+ c.m_parameterPack = pack;
+ }
+ RenderCommand d;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(1, 0, tex3);
+ pack.setTexture(2, 0, tex4);
+ d.m_parameterPack = pack;
+ }
+ RenderCommand e;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(3, 0, tex2);
+ e.m_parameterPack = pack;
+ }
+ RenderCommand f;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(3, 0, tex2);
+ f.m_parameterPack = pack;
+ }
+ RenderCommand g;
+ {
+ ShaderParameterPack pack;
+ pack.setTexture(0, 0, tex1);
+ pack.setTexture(1, 0, tex3);
+ pack.setTexture(2, 0, tex4);
+ pack.setTexture(3, 0, tex2);
+ g.m_parameterPack = pack;
+ }
+
+ // WHEN
+ QVector<RenderCommand> rawCommands = {a, b, c, d, e, f, g};
+ renderView.addSortType(sortTypes);
+ renderView.setCommands(rawCommands);
+ renderView.sort();
+
+ // THEN
+ const QVector<RenderCommand> sortedCommands = renderView.commands();
+ QCOMPARE(rawCommands.size(), sortedCommands.size());
+ QCOMPARE(sortedCommands.at(0), a);
+ QCOMPARE(sortedCommands.at(1), g);
+ QCOMPARE(sortedCommands.at(2), d);
+ QCOMPARE(sortedCommands.at(3), c);
+ QCOMPARE(sortedCommands.at(4), e);
+ QCOMPARE(sortedCommands.at(5), f);
+ QCOMPARE(sortedCommands.at(6), b);
+ // RenderCommands are deleted by RenderView dtor
+ }
private:
};
diff --git a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp
index 247c5e0a3..6d349f994 100644
--- a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp
+++ b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp
@@ -34,7 +34,7 @@
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/stringtoint_p.h>
#include <Qt3DRender/qshaderdata.h>
-
+#include "testrenderer.h"
#include "testpostmanarbiter.h"
class tst_RenderViewUtils : public Qt3DCore::QBackendNodeTester
@@ -54,20 +54,22 @@ private Q_SLOTS:
void shouldNotifyDynamicPropertyChanges();
private:
- void initBackendShaderData(Qt3DRender::QShaderData *frontend,
+ void initBackendShaderData(Qt3DRender::Render::AbstractRenderer *renderer,
+ Qt3DRender::QShaderData *frontend,
Qt3DRender::Render::ShaderDataManager *manager)
{
// Create children first
- Q_FOREACH (QObject *c, frontend->children()) {
+ for (QObject *c : frontend->children()) {
Qt3DRender::QShaderData *cShaderData = qobject_cast<Qt3DRender::QShaderData *>(c);
if (cShaderData)
- initBackendShaderData(cShaderData, manager);
+ initBackendShaderData(renderer, cShaderData, manager);
}
// Create backend element for frontend one
Qt3DRender::Render::ShaderData *backend = manager->getOrCreateResource(frontend->id());
// Init the backend element
- simulateInitialization(frontend, backend);
+ backend->setRenderer(renderer);
+ simulateInitializationSync(frontend, backend);
}
void initBackendTexture(Qt3DRender::QAbstractTexture *frontend,
@@ -345,13 +347,14 @@ private:
void tst_RenderViewUtils::topLevelScalarValueNoUniforms()
{
// GIVEN
+ TestRenderer renderer;
QScopedPointer<ScalarShaderData> shaderData(new ScalarShaderData());
QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager());
QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager());
// WHEN
shaderData->setScalar(883.0f);
- initBackendShaderData(shaderData.data(), manager.data());
+ initBackendShaderData(&renderer, shaderData.data(), manager.data());
// THEN
Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id());
@@ -373,13 +376,14 @@ void tst_RenderViewUtils::topLevelScalarValueNoUniforms()
void tst_RenderViewUtils::topLevelScalarValue()
{
// GIVEN
+ TestRenderer renderer;
QScopedPointer<ScalarShaderData> shaderData(new ScalarShaderData());
QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager());
QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager());
// WHEN
shaderData->setScalar(883.0f);
- initBackendShaderData(shaderData.data(), manager.data());
+ initBackendShaderData(&renderer, shaderData.data(), manager.data());
// THEN
Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id());
@@ -413,6 +417,7 @@ void tst_RenderViewUtils::topLevelScalarValue()
void tst_RenderViewUtils::topLevelTextureValueNoUniforms()
{
// GIVEN
+ TestRenderer renderer;
QScopedPointer<TextureShaderData> shaderData(new TextureShaderData);
QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager);
QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D);
@@ -420,7 +425,7 @@ void tst_RenderViewUtils::topLevelTextureValueNoUniforms()
// WHEN
shaderData->setTexture(texture.data());
- initBackendShaderData(shaderData.data(), manager.data());
+ initBackendShaderData(&renderer, shaderData.data(), manager.data());
// THEN
Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id());
@@ -442,6 +447,7 @@ void tst_RenderViewUtils::topLevelTextureValueNoUniforms()
void tst_RenderViewUtils::topLevelTextureValue()
{
// GIVEN
+ TestRenderer renderer;
QScopedPointer<TextureShaderData> shaderData(new TextureShaderData);
QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager);
QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D);
@@ -450,7 +456,7 @@ void tst_RenderViewUtils::topLevelTextureValue()
// WHEN
initBackendTexture(texture.data(), textureManager.data());
shaderData->setTexture(texture.data());
- initBackendShaderData(shaderData.data(), manager.data());
+ initBackendShaderData(&renderer, shaderData.data(), manager.data());
// THEN
Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id());
@@ -484,6 +490,7 @@ void tst_RenderViewUtils::topLevelTextureValue()
void tst_RenderViewUtils::topLevelArrayValue()
{
// GIVEN
+ TestRenderer renderer;
QScopedPointer<ArrayShaderData> shaderData(new ArrayShaderData());
QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager());
QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager());
@@ -491,7 +498,7 @@ void tst_RenderViewUtils::topLevelArrayValue()
// WHEN
QVariantList arrayValues = QVariantList() << 454 << 350 << 383 << 427 << 552;
shaderData->setArray(arrayValues);
- initBackendShaderData(shaderData.data(), manager.data());
+ initBackendShaderData(&renderer, shaderData.data(), manager.data());
// THEN
Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id());
@@ -525,6 +532,7 @@ void tst_RenderViewUtils::topLevelArrayValue()
void tst_RenderViewUtils::nestedShaderDataValue()
{
// GIVEN
+ TestRenderer renderer;
QScopedPointer<ArrayShaderData> arrayShaderData(new ArrayShaderData());
QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager());
QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager());
@@ -549,7 +557,7 @@ void tst_RenderViewUtils::nestedShaderDataValue()
// WHEN
const QVariantList arrayValues = QVariantList() << QVariant::fromValue(id1) << QVariant::fromValue(id2) << QVariant::fromValue(id3);
arrayShaderData->setArray(arrayValues);
- initBackendShaderData(arrayShaderData.data(), manager.data());
+ initBackendShaderData(&renderer, arrayShaderData.data(), manager.data());
// THEN
Qt3DRender::Render::ShaderData *backendArrayShaderData = manager->lookupResource(arrayShaderData->id());
@@ -624,13 +632,14 @@ void tst_RenderViewUtils::topLevelStructValue_data()
void tst_RenderViewUtils::topLevelStructValue()
{
// GIVEN
+ TestRenderer renderer;
QFETCH(StructShaderData *, shaderData);
QFETCH(QString, blockName);
QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager());
QScopedPointer<Qt3DRender::Render::TextureManager> textureManager(new Qt3DRender::Render::TextureManager());
// WHEN
- initBackendShaderData(shaderData, manager.data());
+ initBackendShaderData(&renderer, shaderData, manager.data());
// THEN
Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id());
@@ -665,6 +674,7 @@ void tst_RenderViewUtils::topLevelStructValue()
void tst_RenderViewUtils::topLevelDynamicProperties()
{
// GIVEN
+ TestRenderer renderer;
QScopedPointer<Qt3DRender::QShaderData> shaderData(new Qt3DRender::QShaderData());
QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager());
QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D);
@@ -675,7 +685,7 @@ void tst_RenderViewUtils::topLevelDynamicProperties()
shaderData->setProperty("scalar", 883.0f);
shaderData->setProperty("array", QVariantList() << 454 << 350 << 383 << 427 << 552);
shaderData->setProperty("texture", QVariant::fromValue(texture.data()));
- initBackendShaderData(shaderData.data(), manager.data());
+ initBackendShaderData(&renderer, shaderData.data(), manager.data());
// THEN
Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id());
@@ -709,6 +719,7 @@ void tst_RenderViewUtils::transformedProperties()
// GIVEN
QScopedPointer<Qt3DRender::QShaderData> shaderData(new Qt3DRender::QShaderData());
QScopedPointer<Qt3DRender::Render::ShaderDataManager> manager(new Qt3DRender::Render::ShaderDataManager());
+ TestRenderer renderer;
// WHEN
const Vector3D position = Vector3D(15.0f, -5.0f, 10.0f);
@@ -733,7 +744,7 @@ void tst_RenderViewUtils::transformedProperties()
shaderData->setProperty("position1Transformed", Qt3DRender::Render::ShaderData::ModelToEye);
shaderData->setProperty("position2Transformed", Qt3DRender::Render::ShaderData::ModelToWorld);
shaderData->setProperty("position3Transformed", Qt3DRender::Render::ShaderData::ModelToWorldDirection);
- initBackendShaderData(shaderData.data(), manager.data());
+ initBackendShaderData(&renderer, shaderData.data(), manager.data());
// THEN
Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id());
@@ -751,7 +762,7 @@ void tst_RenderViewUtils::transformedProperties()
const QVariant position0Value = backendShaderData->getTransformedProperty(QStringLiteral("position0"), viewMatrix);
// THEN
- QCOMPARE(position0Value, QVariant());
+ QCOMPARE(position0Value, positionQt);
QCOMPARE(position1Value, viewMatrix * worldMatrix * position);
QCOMPARE(position2Value, worldMatrix * position);
QCOMPARE(position3Value, Vector3D((worldMatrix * Vector4D(position, 0.0f))));
@@ -768,24 +779,20 @@ void tst_RenderViewUtils::shouldNotifyDynamicPropertyChanges()
shaderData->setProperty("scalar", 883.0f);
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- auto change = arbiter.events.first().dynamicCast<Qt3DCore::QDynamicPropertyUpdatedChange>();
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->propertyName(), QByteArrayLiteral("scalar"));
- QCOMPARE(change->value().toFloat(), 883.0f);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), shaderData.data());
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
QScopedPointer<Qt3DRender::QAbstractTexture> texture(new Qt3DRender::QTexture2D);
shaderData->setProperty("texture", QVariant::fromValue(texture.data()));
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().dynamicCast<Qt3DCore::QDynamicPropertyUpdatedChange>();
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
- QCOMPARE(change->propertyName(), QByteArrayLiteral("texture"));
- QCOMPARE(change->value(), QVariant::fromValue(texture->id()));
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), shaderData.data());
}
QTEST_MAIN(tst_RenderViewUtils)
diff --git a/tests/auto/render/scene2d/tst_scene2d.cpp b/tests/auto/render/scene2d/tst_scene2d.cpp
index c30400202..fcb4c0908 100644
--- a/tests/auto/render/scene2d/tst_scene2d.cpp
+++ b/tests/auto/render/scene2d/tst_scene2d.cpp
@@ -128,7 +128,7 @@ private Q_SLOTS:
// WHEN
QScopedPointer<Scene2D> backendScene2d(new Scene2D());
backendScene2d->setRenderer(&renderer);
- simulateInitialization(&frontend, backendScene2d.data());
+ simulateInitializationSync(&frontend, backendScene2d.data());
// THEN
QCOMPARE(backendScene2d->isEnabled(), true);
@@ -144,7 +144,7 @@ private Q_SLOTS:
QScopedPointer<Scene2D> backendScene2d(new Scene2D());
frontend.setEnabled(false);
backendScene2d->setRenderer(&renderer);
- simulateInitialization(&frontend, backendScene2d.data());
+ simulateInitializationSync(&frontend, backendScene2d.data());
// THEN
QCOMPARE(backendScene2d->peerId(), frontend.id());
@@ -156,18 +156,18 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DRender::Quick::QScene2D frontend;
QScopedPointer<Scene2D> backendScene2d(new Scene2D());
TestRenderer renderer;
QScopedPointer<Qt3DRender::QRenderTargetOutput> output(new Qt3DRender::QRenderTargetOutput());
backendScene2d->setRenderer(&renderer);
+ simulateInitializationSync(&frontend, backendScene2d.data());
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendScene2d->sceneChangeEvent(change);
+ frontend.setEnabled(false);
+ backendScene2d->syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backendScene2d->isEnabled(), newValue);
@@ -175,10 +175,8 @@ private Q_SLOTS:
{
// WHEN
const Qt3DCore::QNodeId newValue = output.data()->id();
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("output");
- change->setValue(QVariant::fromValue(newValue));
- backendScene2d->sceneChangeEvent(change);
+ frontend.setOutput(output.data());
+ backendScene2d->syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backendScene2d->m_outputId, newValue);
@@ -186,10 +184,8 @@ private Q_SLOTS:
{
// WHEN
const QScene2D::RenderPolicy newValue = QScene2D::SingleShot;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("renderPolicy");
- change->setValue(QVariant::fromValue(newValue));
- backendScene2d->sceneChangeEvent(change);
+ frontend.setRenderPolicy(newValue);
+ backendScene2d->syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backendScene2d->m_renderPolicy, newValue);
@@ -197,10 +193,7 @@ private Q_SLOTS:
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("mouseEnabled");
- change->setValue(newValue);
- backendScene2d->sceneChangeEvent(change);
+ frontend.setMouseEnabled(newValue);
// THEN
QCOMPARE(backendScene2d->isEnabled(), newValue);
@@ -209,10 +202,11 @@ private Q_SLOTS:
backendScene2d->cleanup();
}
-
void testCoordinateCalculation()
{
// GIVEN
+ qputenv("QT3D_SCENE2D_DISABLE_RENDERING", "1");
+
QScopedPointer<TestWindow> testWindow(new TestWindow());
Scene2DSharedObjectPtr sharedObject(new Scene2DSharedObject(nullptr));
QScopedPointer<Scene2D> scene2d(new Scene2D());
@@ -276,7 +270,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer, backendBuffer);
+ simulateInitializationSync(dataBuffer, backendBuffer);
positionAttribute->setBuffer(dataBuffer);
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -304,28 +298,28 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(
positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute, backendAttribute);
+ simulateInitializationSync(positionAttribute, backendAttribute);
Attribute *backendTexcoordAttribute = nodeManagers->attributeManager()
->getOrCreateResource(texcoordAttribute->id());
backendTexcoordAttribute->setRenderer(&renderer);
- simulateInitialization(texcoordAttribute, backendTexcoordAttribute);
+ simulateInitializationSync(texcoordAttribute, backendTexcoordAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()
->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()
->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer, backendRenderer);
+ simulateInitializationSync(geometryRenderer, backendRenderer);
Entity *backendEntity = nodeManagers->renderNodesManager()->getOrCreateResource(entity->id());
backendEntity->setRenderer(&renderer);
backendEntity->setNodeManagers(nodeManagers.data());
- simulateInitialization(entity.data(), backendEntity);
+ simulateInitializationSync(entity.data(), backendEntity);
#define PICK_TRIANGLE(tri, v0, v1, v2, uvw) \
new Qt3DRender::QPickTriangleEvent(QPointF(), QVector3D(), QVector3D(), 0.0f, \
@@ -336,7 +330,8 @@ private Q_SLOTS:
QVector3D uvw(1.0, 0.0f, 0.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -350,7 +345,8 @@ private Q_SLOTS:
QVector3D uvw(0.0, 1.0f, 0.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -364,7 +360,8 @@ private Q_SLOTS:
QVector3D uvw(0.0, 0.0f, 1.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -378,7 +375,8 @@ private Q_SLOTS:
QVector3D uvw(1.0, 0.0f, 0.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -392,7 +390,8 @@ private Q_SLOTS:
QVector3D uvw(0.0, 1.0f, 0.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -406,7 +405,8 @@ private Q_SLOTS:
QVector3D uvw(0.0, 0.0f, 1.0f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
@@ -420,12 +420,13 @@ private Q_SLOTS:
QVector3D uvw(0.5f, 0.25f, 0.25f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
// THEN
- QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(512.0f, 768.0f)));
+ QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(512.0, 768.0)));
testWindow->clear();
}
@@ -434,14 +435,17 @@ private Q_SLOTS:
QVector3D uvw(0.875f, 0.09375f, 0.03125f);
Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(1, 3, 4, 5, uvw));
Qt3DRender::QPickEventPrivate::get(ev.data())->m_entity = entity->id();
- scene2d->handlePickEvent(QEvent::MouseButtonPress, ev);
+ Qt3DRender::QPickEventPrivate::get(ev.data())->m_entityPtr = entity.data();
+ scene2d->handlePickEvent(QEvent::MouseButtonPress, ev.data());
QCoreApplication::processEvents();
// THEN
- QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(96.0f, 896.0f)));
+ QVERIFY(testWindow->verifyEventPos(0, QEvent::MouseButtonPress, QPointF(96.0, 896.0)));
testWindow->clear();
}
+
+ scene2d.reset();
}
};
diff --git a/tests/auto/render/sceneloader/tst_sceneloader.cpp b/tests/auto/render/sceneloader/tst_sceneloader.cpp
index 8da82b609..d146abfcc 100644
--- a/tests/auto/render/sceneloader/tst_sceneloader.cpp
+++ b/tests/auto/render/sceneloader/tst_sceneloader.cpp
@@ -46,6 +46,7 @@ private Q_SLOTS:
void checkInitialAndCleanedUpState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::Scene sceneLoader;
Qt3DRender::Render::SceneManager sceneManager;
@@ -61,8 +62,9 @@ private Q_SLOTS:
frontendSceneLoader.setSource(newUrl);
// WHEN
+ sceneLoader.setRenderer(&renderer);
sceneLoader.setSceneManager(&sceneManager);
- simulateInitialization(&frontendSceneLoader, &sceneLoader);
+ simulateInitializationSync(&frontendSceneLoader, &sceneLoader);
// THEN
QVERIFY(!sceneLoader.peerId().isNull());
@@ -78,6 +80,7 @@ private Q_SLOTS:
void checkPeerPropertyMirroring()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QSceneLoader frontendSceneLoader;
frontendSceneLoader.setSource(QUrl(QStringLiteral("file:///CorvetteMuseum")));
@@ -85,8 +88,9 @@ private Q_SLOTS:
Qt3DRender::Render::SceneManager sceneManager;
// WHEN
+ sceneLoader.setRenderer(&renderer);
sceneLoader.setSceneManager(&sceneManager);
- simulateInitialization(&frontendSceneLoader, &sceneLoader);
+ simulateInitializationSync(&frontendSceneLoader, &sceneLoader);
// THEN
QCOMPARE(sceneLoader.peerId(), frontendSceneLoader.id());
@@ -100,108 +104,59 @@ private Q_SLOTS:
TestRenderer renderer;
Qt3DRender::Render::Scene sceneLoader;
Qt3DRender::Render::SceneManager sceneManager;
+ Qt3DRender::QSceneLoader frontendSceneLoader;
sceneLoader.setRenderer(&renderer);
sceneLoader.setSceneManager(&sceneManager);
+ simulateInitializationSync(&frontendSceneLoader, &sceneLoader);
// THEN
QVERIFY(sceneManager.takePendingSceneLoaderJobs().isEmpty());
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
const QUrl newUrl(QStringLiteral("file:///Bownling_Green_KY"));
- updateChange->setValue(newUrl);
- updateChange->setPropertyName("source");
- sceneLoader.sceneChangeEvent(updateChange);
+ frontendSceneLoader.setSource(newUrl);
+ sceneLoader.syncFromFrontEnd(&frontendSceneLoader, false);
// THEN
QCOMPARE(sceneLoader.source(), newUrl);
QVERIFY(!sceneManager.takePendingSceneLoaderJobs().isEmpty());
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(false);
- updateChange->setPropertyName("enabled");
- sceneLoader.sceneChangeEvent(updateChange);
+ frontendSceneLoader.setEnabled(false);
+ sceneLoader.syncFromFrontEnd(&frontendSceneLoader, false);
// THEN
QCOMPARE(sceneLoader.isEnabled(), false);
}
- void checkSubtreeTransmission()
- {
- // GIVEN
- TestRenderer renderer;
- TestArbiter arbiter;
- Qt3DRender::Render::Scene sceneLoader;
-
- Qt3DCore::QBackendNodePrivate::get(&sceneLoader)->setArbiter(&arbiter);
- sceneLoader.setRenderer(&renderer);
-
- // WHEN
- Qt3DCore::QEntity subtree;
- sceneLoader.setSceneSubtree(&subtree);
-
- // THEN
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(arbiter.events.count(), 1);
- QCOMPARE(change->propertyName(), "scene");
- QCOMPARE(change->value().value<Qt3DCore::QEntity *>(), &subtree);
-
- arbiter.events.clear();
- }
-
- void checkStatusTransmission()
- {
- // GIVEN
- TestRenderer renderer;
- TestArbiter arbiter;
- Qt3DRender::Render::Scene sceneLoader;
-
- Qt3DCore::QBackendNodePrivate::get(&sceneLoader)->setArbiter(&arbiter);
- sceneLoader.setRenderer(&renderer);
-
- // WHEN
- sceneLoader.setStatus(Qt3DRender::QSceneLoader::Ready);
-
- // THEN
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(arbiter.events.count(), 1);
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<Qt3DRender::QSceneLoader::Status>(), Qt3DRender::QSceneLoader::Ready);
-
- arbiter.events.clear();
- }
-
void checkProcessEmptyPath()
{
// GIVEN
TestRenderer renderer;
Qt3DRender::Render::Scene sceneLoader;
Qt3DRender::Render::SceneManager sceneManager;
+ Qt3DRender::QSceneLoader frontendSceneLoader;
sceneLoader.setRenderer(&renderer);
sceneLoader.setSceneManager(&sceneManager);
+ simulateInitializationSync(&frontendSceneLoader, &sceneLoader);
// THEN
QVERIFY(sceneManager.takePendingSceneLoaderJobs().isEmpty());
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
const QUrl newUrl(QStringLiteral("file:///Bownling_Green_KY"));
- updateChange->setValue(newUrl);
- updateChange->setPropertyName("source");
- sceneLoader.sceneChangeEvent(updateChange);
+ frontendSceneLoader.setSource(newUrl);
+ sceneLoader.syncFromFrontEnd(&frontendSceneLoader, false);
// THEN
QCOMPARE(sceneLoader.source(), newUrl);
QVERIFY(!sceneManager.takePendingSceneLoaderJobs().isEmpty());
// WHEN
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(QUrl());
- updateChange->setPropertyName("source");
- sceneLoader.sceneChangeEvent(updateChange);
+ frontendSceneLoader.setSource(QUrl());
+ sceneLoader.syncFromFrontEnd(&frontendSceneLoader, false);
// THEN -> we should still have generated a job to reset the scene (immediately)
QCOMPARE(sceneLoader.source(), QUrl());
diff --git a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp
index da420e1ac..4db12136a 100644
--- a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp
+++ b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp
@@ -185,7 +185,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -202,16 +202,16 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -254,7 +254,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
indexData.resize(sizeof(uint) * 2 * 5);
@@ -274,7 +274,7 @@ private Q_SLOTS:
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
backendIndexBuffer->setRenderer(&renderer);
backendIndexBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+ simulateInitializationSync(indexDataBuffer.data(), backendIndexBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -298,20 +298,20 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
backendIndexAttribute->setRenderer(&renderer);
- simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+ simulateInitializationSync(indexAttribute.data(), backendIndexAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -354,7 +354,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -371,16 +371,16 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -423,7 +423,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
indexData.resize(sizeof(uint) * 2 * 4);
@@ -437,7 +437,7 @@ private Q_SLOTS:
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
backendIndexBuffer->setRenderer(&renderer);
backendIndexBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+ simulateInitializationSync(indexDataBuffer.data(), backendIndexBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -461,20 +461,20 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
backendIndexAttribute->setRenderer(&renderer);
- simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+ simulateInitializationSync(indexAttribute.data(), backendIndexAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -515,7 +515,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -532,16 +532,16 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -585,7 +585,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
indexData.resize(sizeof(uint) * 2 * 4);
@@ -599,7 +599,7 @@ private Q_SLOTS:
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
backendIndexBuffer->setRenderer(&renderer);
backendIndexBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+ simulateInitializationSync(indexDataBuffer.data(), backendIndexBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -623,20 +623,20 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
backendIndexAttribute->setRenderer(&renderer);
- simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+ simulateInitializationSync(indexAttribute.data(), backendIndexAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -679,7 +679,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -696,16 +696,16 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -747,7 +747,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
indexData.resize(sizeof(uint) * 4);
@@ -761,7 +761,7 @@ private Q_SLOTS:
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
backendIndexBuffer->setRenderer(&renderer);
backendIndexBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+ simulateInitializationSync(indexDataBuffer.data(), backendIndexBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -785,20 +785,20 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
backendIndexAttribute->setRenderer(&renderer);
- simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+ simulateInitializationSync(indexAttribute.data(), backendIndexAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
diff --git a/tests/auto/render/setfence/tst_setfence.cpp b/tests/auto/render/setfence/tst_setfence.cpp
index 82cee4b17..92f7a0acc 100644
--- a/tests/auto/render/setfence/tst_setfence.cpp
+++ b/tests/auto/render/setfence/tst_setfence.cpp
@@ -68,26 +68,32 @@ private Q_SLOTS:
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QSetFence setFence;
{
// WHEN
Qt3DRender::Render::SetFence backendSetFence;
- simulateInitialization(&setFence, &backendSetFence);
+ backendSetFence.setRenderer(&renderer);
+ simulateInitializationSync(&setFence, &backendSetFence);
// THEN
QCOMPARE(backendSetFence.isEnabled(), true);
QCOMPARE(backendSetFence.peerId(), setFence.id());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
Qt3DRender::Render::SetFence backendSetFence;
setFence.setEnabled(false);
- simulateInitialization(&setFence, &backendSetFence);
+ backendSetFence.setRenderer(&renderer);
+ simulateInitializationSync(&setFence, &backendSetFence);
// THEN
QCOMPARE(backendSetFence.peerId(), setFence.id());
QCOMPARE(backendSetFence.isEnabled(), false);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
}
@@ -95,16 +101,16 @@ private Q_SLOTS:
{
// GIVEN
Qt3DRender::Render::SetFence backendSetFence;
+ Qt3DRender::QSetFence setFence;
TestRenderer renderer;
backendSetFence.setRenderer(&renderer);
+ simulateInitializationSync(&setFence, &backendSetFence);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendSetFence.sceneChangeEvent(change);
+ setFence.setEnabled(newValue);
+ backendSetFence.syncFromFrontEnd(&setFence, false);
// THEN
QCOMPARE(backendSetFence.isEnabled(), newValue);
diff --git a/tests/auto/render/shader/tst_shader.cpp b/tests/auto/render/shader/tst_shader.cpp
index 067db55e7..d1578aee7 100644
--- a/tests/auto/render/shader/tst_shader.cpp
+++ b/tests/auto/render/shader/tst_shader.cpp
@@ -97,13 +97,13 @@ void tst_RenderShader::matchesFrontendPeer()
Qt3DRender::Render::Shader backend;
backend.setRenderer(&renderer);
- simulateInitialization(frontend.data(), &backend);
+ simulateInitializationSync(frontend.data(), &backend);
QCOMPARE(backend.isLoaded(), false);
QVERIFY(backend.dna() != 0U);
for (int i = Qt3DRender::QShaderProgram::Vertex; i <= Qt3DRender::QShaderProgram::Compute; ++i)
QCOMPARE(backend.shaderCode()[i],
- frontend->shaderCode( static_cast<const Qt3DRender::QShaderProgram::ShaderType>(i)));
+ frontend->shaderCode(static_cast<Qt3DRender::QShaderProgram::ShaderType>(i)));
}
void tst_RenderShader::cleanupLeavesACoherentState()
@@ -113,7 +113,7 @@ void tst_RenderShader::cleanupLeavesACoherentState()
Qt3DRender::Render::Shader shader;
shader.setRenderer(&renderer);
- simulateInitialization(frontend.data(), &shader);
+ simulateInitializationSync(frontend.data(), &shader);
shader.cleanup();
@@ -130,73 +130,61 @@ void tst_RenderShader::cleanupLeavesACoherentState()
void tst_RenderShader::dealWithPropertyChanges_data()
{
- QTest::addColumn<QByteArray>("property");
QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("type");
- QTest::newRow("vertex") << QByteArrayLiteral("vertexShaderCode")
- << Qt3DRender::QShaderProgram::Vertex;
+ QTest::newRow("vertex") << Qt3DRender::QShaderProgram::Vertex;
- QTest::newRow("tessControl") << QByteArrayLiteral("tessellationControlShaderCode")
- << Qt3DRender::QShaderProgram::TessellationControl;
+ QTest::newRow("tessControl") << Qt3DRender::QShaderProgram::TessellationControl;
- QTest::newRow("tessEval") << QByteArrayLiteral("tessellationEvaluationShaderCode")
- << Qt3DRender::QShaderProgram::TessellationEvaluation;
+ QTest::newRow("tessEval") << Qt3DRender::QShaderProgram::TessellationEvaluation;
- QTest::newRow("geometry") << QByteArrayLiteral("geometryShaderCode")
- << Qt3DRender::QShaderProgram::Geometry;
+ QTest::newRow("geometry") << Qt3DRender::QShaderProgram::Geometry;
- QTest::newRow("fragment") << QByteArrayLiteral("fragmentShaderCode")
- << Qt3DRender::QShaderProgram::Fragment;
+ QTest::newRow("fragment") << Qt3DRender::QShaderProgram::Fragment;
- QTest::newRow("compute") << QByteArrayLiteral("computeShaderCode")
- << Qt3DRender::QShaderProgram::Compute;
+ QTest::newRow("compute") << Qt3DRender::QShaderProgram::Compute;
}
void tst_RenderShader::dealWithPropertyChanges()
{
// GIVEN
- QFETCH(QByteArray, property);
QFETCH(Qt3DRender::QShaderProgram::ShaderType, type);
Qt3DRender::Render::Shader backend;
+ Qt3DRender::QShaderProgram shader;
backend.setLoaded(true);
TestRenderer renderer;
backend.setRenderer(&renderer);
+ simulateInitializationSync(&shader, &backend);
// WHEN
- auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QStringLiteral("foo"));
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+ shader.setShaderCode(type, QByteArrayLiteral("foo"));
+ backend.syncFromFrontEnd(&shader, false);
// THEN
- QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo"));
+ QCOMPARE(backend.shaderCode().at(type), QByteArrayLiteral("foo"));
QVERIFY(!backend.isLoaded());
QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
renderer.resetDirty();
backend.setLoaded(true);
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QStringLiteral("foo"));
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+ shader.setShaderCode(type, QByteArrayLiteral("foo"));
+ backend.syncFromFrontEnd(&shader, false);
// THEN
- QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo"));
+ QCOMPARE(backend.shaderCode().at(type), QByteArrayLiteral("foo"));
QVERIFY(backend.isLoaded());
QCOMPARE(renderer.dirtyBits(), 0);
renderer.resetDirty();
backend.setLoaded(true);
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QStringLiteral("bar"));
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+ shader.setShaderCode(type, QByteArrayLiteral("bar"));
+ backend.syncFromFrontEnd(&shader, false);
// THEN
- QCOMPARE(backend.shaderCode().at(type), QStringLiteral("bar"));
+ QCOMPARE(backend.shaderCode().at(type), QByteArrayLiteral("bar"));
QVERIFY(!backend.isLoaded());
QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
renderer.resetDirty();
@@ -216,7 +204,7 @@ void tst_RenderShader::checkSetRendererDirtyOnInitialization()
QCOMPARE(renderer.dirtyBits(), 0);
// WHEN
- simulateInitialization(frontend.data(), &shader);
+ simulateInitializationSync(frontend.data(), &shader);
// THEN
QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
diff --git a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
index e365256cc..7a08fe018 100644
--- a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
+++ b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
@@ -28,6 +28,7 @@
#include <QtTest/QTest>
#include <qbackendnodetester.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
#include <Qt3DRender/private/shaderbuilder_p.h>
#include <Qt3DRender/qshaderprogram.h>
@@ -35,7 +36,6 @@
#include "testrenderer.h"
#include "testpostmanarbiter.h"
-Q_DECLARE_METATYPE(Qt3DRender::Render::ShaderBuilder::ShaderType)
Q_DECLARE_METATYPE(Qt3DRender::QShaderProgram::ShaderType)
class tst_ShaderBuilder : public Qt3DCore::QBackendNodeTester
@@ -77,8 +77,8 @@ private slots:
// THEN
QVERIFY(!shaderBuilder.isEnabled());
QVERIFY(shaderBuilder.enabledLayers().isEmpty());
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QCOMPARE(shaderBuilder.shaderGraph(type), QUrl());
QCOMPARE(shaderBuilder.shaderCode(type), QByteArray());
QVERIFY(!shaderBuilder.isShaderCodeDirty(type));
@@ -141,9 +141,11 @@ private slots:
// GIVEN
QFETCH(Qt3DRender::QShaderProgramBuilder*, frontend);
Qt3DRender::Render::ShaderBuilder backend;
+ TestRenderer renderer;
// WHEN
- simulateInitialization(frontend, &backend);
+ backend.setRenderer(&renderer);
+ simulateInitializationSync(frontend, &backend);
// THEN
QVERIFY(backend.isEnabled() == frontend->isEnabled());
@@ -155,29 +157,29 @@ private slots:
QCOMPARE(backend.enabledLayers(), frontend->enabledLayers());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Vertex), frontend->vertexShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Vertex), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Vertex), !frontend->vertexShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::Vertex), frontend->vertexShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::Vertex), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::Vertex), !frontend->vertexShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::TessellationControl), frontend->tessellationControlShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::TessellationControl), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::TessellationControl), !frontend->tessellationControlShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::TessellationControl), frontend->tessellationControlShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::TessellationControl), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::TessellationControl), !frontend->tessellationControlShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), frontend->tessellationEvaluationShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::TessellationEvaluation), !frontend->tessellationEvaluationShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::TessellationEvaluation), frontend->tessellationEvaluationShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::TessellationEvaluation), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::TessellationEvaluation), !frontend->tessellationEvaluationShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Geometry), frontend->geometryShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Geometry), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Geometry), !frontend->geometryShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::Geometry), frontend->geometryShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::Geometry), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::Geometry), !frontend->geometryShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Fragment), frontend->fragmentShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Fragment), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Fragment), !frontend->fragmentShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::Fragment), frontend->fragmentShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::Fragment), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::Fragment), !frontend->fragmentShaderGraph().isEmpty());
- QCOMPARE(backend.shaderGraph(Qt3DRender::Render::ShaderBuilder::Compute), frontend->computeShaderGraph());
- QCOMPARE(backend.shaderCode(Qt3DRender::Render::ShaderBuilder::Compute), QByteArray());
- QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::Render::ShaderBuilder::Compute), !frontend->computeShaderGraph().isEmpty());
+ QCOMPARE(backend.shaderGraph(Qt3DRender::QShaderProgram::Compute), frontend->computeShaderGraph());
+ QCOMPARE(backend.shaderCode(Qt3DRender::QShaderProgram::Compute), QByteArray());
+ QCOMPARE(backend.isShaderCodeDirty(Qt3DRender::QShaderProgram::Compute), !frontend->computeShaderGraph().isEmpty());
// WHEN
backend.cleanup();
@@ -185,8 +187,8 @@ private slots:
// THEN
QVERIFY(!backend.isEnabled());
QVERIFY(backend.enabledLayers().isEmpty());
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QCOMPARE(backend.shaderGraph(type), QUrl());
QCOMPARE(backend.shaderCode(type), QByteArray());
QVERIFY(!backend.isShaderCodeDirty(type));
@@ -199,25 +201,14 @@ private slots:
{
// GIVEN
Qt3DRender::Render::ShaderBuilder backend;
+ Qt3DRender::QShaderProgramBuilder frontend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ simulateInitializationSync(&frontend, &backend);
// WHEN
- auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(true);
- updateChange->setPropertyName("enabled");
- backend.sceneChangeEvent(updateChange);
-
- // THEN
- QVERIFY(backend.isEnabled());
- QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
- renderer.resetDirty();
-
- // WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(false);
- updateChange->setPropertyName("enabled");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabled(false);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(!backend.isEnabled());
@@ -225,10 +216,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(true);
- updateChange->setPropertyName("enabled");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabled(true);
+ backend.syncFromFrontEnd(&frontend, false);
// AND
backend.cleanup();
@@ -242,26 +231,24 @@ private slots:
{
// GIVEN
Qt3DRender::Render::ShaderBuilder backend;
+ Qt3DRender::QShaderProgramBuilder frontend;
TestRenderer renderer;
backend.setRenderer(&renderer);
- const auto programId = Qt3DCore::QNodeId::createId();
+ simulateInitializationSync(&frontend, &backend);
// WHEN
- auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(programId));
- updateChange->setPropertyName("shaderProgram");
- backend.sceneChangeEvent(updateChange);
+ Qt3DRender::QShaderProgram prog;
+ frontend.setShaderProgram(&prog);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
- QCOMPARE(backend.shaderProgramId(), programId);
+ QCOMPARE(backend.shaderProgramId(), prog.id());
QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("shaderProgram");
- backend.sceneChangeEvent(updateChange);
+ frontend.setShaderProgram(nullptr);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(backend.shaderProgramId().isNull());
@@ -269,10 +256,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(programId));
- updateChange->setPropertyName("shaderProgram");
- backend.sceneChangeEvent(updateChange);
+ frontend.setShaderProgram(&prog);
+ backend.syncFromFrontEnd(&frontend, false);
// AND
backend.cleanup();
@@ -286,26 +271,39 @@ private slots:
{
// GIVEN
Qt3DRender::Render::ShaderBuilder backend;
+ Qt3DRender::QShaderProgramBuilder frontend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ simulateInitializationSync(&frontend, &backend);
const auto layers = QStringList() << "foo" << "bar";
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ static const std::pair<
+ Qt3DRender::QShaderProgram::ShaderType,
+ void (Qt3DRender::QShaderProgramBuilder::*)(const QUrl &)
+ >
+ shaderTypesToSetters[] = {
+ {Qt3DRender::QShaderProgram::Vertex, &Qt3DRender::QShaderProgramBuilder::setVertexShaderGraph},
+ {Qt3DRender::QShaderProgram::TessellationControl, &Qt3DRender::QShaderProgramBuilder::setTessellationControlShaderGraph},
+ {Qt3DRender::QShaderProgram::TessellationEvaluation, &Qt3DRender::QShaderProgramBuilder::setTessellationEvaluationShaderGraph},
+ {Qt3DRender::QShaderProgram::Geometry, &Qt3DRender::QShaderProgramBuilder::setGeometryShaderGraph},
+ {Qt3DRender::QShaderProgram::Fragment, &Qt3DRender::QShaderProgramBuilder::setFragmentShaderGraph},
+ {Qt3DRender::QShaderProgram::Compute, &Qt3DRender::QShaderProgramBuilder::setComputeShaderGraph},
+ };
+
+
+ for (auto it = std::begin(shaderTypesToSetters), end = std::end(shaderTypesToSetters); it != end; ++it) {
const auto graphUrl = QUrl::fromEncoded("qrc:/input.json");
- backend.setShaderGraph(type, graphUrl);
+ (frontend.*(it->second))(graphUrl);
}
// WHEN
- auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(layers);
- updateChange->setPropertyName("enabledLayers");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabledLayers(layers);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.enabledLayers(), layers);
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QVERIFY(backend.isShaderCodeDirty(type));
backend.generateCode(type); // Resets the dirty flag
}
@@ -313,31 +311,27 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(layers);
- updateChange->setPropertyName("enabledLayers");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabledLayers(layers);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.enabledLayers(), layers);
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QVERIFY(!backend.isShaderCodeDirty(type));
backend.generateCode(type); // Resets the dirty flag
}
- QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
+ QCOMPARE(renderer.dirtyBits(), 0);
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QStringList());
- updateChange->setPropertyName("enabledLayers");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabledLayers(QStringList());
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(backend.shaderProgramId().isNull());
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QVERIFY(backend.isShaderCodeDirty(type));
backend.generateCode(type); // Resets the dirty flag
}
@@ -345,17 +339,15 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(layers);
- updateChange->setPropertyName("enabledLayers");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabledLayers(layers);
+ backend.syncFromFrontEnd(&frontend, false);
// AND
backend.cleanup();
// THEN
QVERIFY(backend.enabledLayers().isEmpty());
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ for (int i = 0; i <= Qt3DRender::QShaderProgram::Compute; i++) {
+ const auto type = static_cast<Qt3DRender::QShaderProgram::ShaderType>(i);
QVERIFY(!backend.isShaderCodeDirty(type));
backend.generateCode(type); // Resets the dirty flag
}
@@ -365,64 +357,68 @@ private slots:
void shouldHandleShaderGraphPropertiesChanges_data()
{
- QTest::addColumn<QByteArray>("property");
- QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type");
+ QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("type");
QTest::addColumn<QUrl>("graphUrl");
- QTest::newRow("vertex") << QByteArrayLiteral("vertexShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::Vertex
+ QTest::newRow("vertex") << Qt3DRender::QShaderProgram::Vertex
<< QUrl::fromEncoded("qrc:/vertex.json");
- QTest::newRow("tessControl") << QByteArrayLiteral("tessellationControlShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::TessellationControl
+ QTest::newRow("tessControl") << Qt3DRender::QShaderProgram::TessellationControl
<< QUrl::fromEncoded("qrc:/tesscontrol.json");
- QTest::newRow("tessEval") << QByteArrayLiteral("tessellationEvaluationShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation
+ QTest::newRow("tessEval") << Qt3DRender::QShaderProgram::TessellationEvaluation
<< QUrl::fromEncoded("qrc:/tesseval.json");
- QTest::newRow("geometry") << QByteArrayLiteral("geometryShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::Geometry
+ QTest::newRow("geometry") << Qt3DRender::QShaderProgram::Geometry
<< QUrl::fromEncoded("qrc:/geometry.json");
- QTest::newRow("fragment") << QByteArrayLiteral("fragmentShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::Fragment
+ QTest::newRow("fragment") << Qt3DRender::QShaderProgram::Fragment
<< QUrl::fromEncoded("qrc:/fragment.json");
- QTest::newRow("compute") << QByteArrayLiteral("computeShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::Compute
+ QTest::newRow("compute") << Qt3DRender::QShaderProgram::Compute
<< QUrl::fromEncoded("qrc:/compute.json");
}
void shouldHandleShaderGraphPropertiesChanges()
{
// GIVEN
- QFETCH(QByteArray, property);
- QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type);
+ QFETCH(Qt3DRender::QShaderProgram::ShaderType, type);
QFETCH(QUrl, graphUrl);
Qt3DRender::Render::ShaderBuilder backend;
+ Qt3DRender::QShaderProgramBuilder frontend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ simulateInitializationSync(&frontend, &backend);
+
+ static const QHash<
+ Qt3DRender::QShaderProgram::ShaderType,
+ void (Qt3DRender::QShaderProgramBuilder::*)(const QUrl &)
+ >
+ shaderTypesToSetters = {
+ {Qt3DRender::QShaderProgram::Vertex, &Qt3DRender::QShaderProgramBuilder::setVertexShaderGraph},
+ {Qt3DRender::QShaderProgram::TessellationControl, &Qt3DRender::QShaderProgramBuilder::setTessellationControlShaderGraph},
+ {Qt3DRender::QShaderProgram::TessellationEvaluation, &Qt3DRender::QShaderProgramBuilder::setTessellationEvaluationShaderGraph},
+ {Qt3DRender::QShaderProgram::Geometry, &Qt3DRender::QShaderProgramBuilder::setGeometryShaderGraph},
+ {Qt3DRender::QShaderProgram::Fragment, &Qt3DRender::QShaderProgramBuilder::setFragmentShaderGraph},
+ {Qt3DRender::QShaderProgram::Compute, &Qt3DRender::QShaderProgramBuilder::setComputeShaderGraph},
+ };
// WHEN
- auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QUrl());
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+
+ (frontend.*(shaderTypesToSetters[type]))(QUrl());
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.shaderGraph(type), QUrl());
QVERIFY(!backend.isShaderCodeDirty(type));
QVERIFY(backend.shaderCode(type).isEmpty());
- QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
+ QCOMPARE(renderer.dirtyBits(), 0);
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(graphUrl);
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+ (frontend.*(shaderTypesToSetters[type]))(graphUrl);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.shaderGraph(type), graphUrl);
@@ -432,10 +428,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QUrl());
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+ (frontend.*(shaderTypesToSetters[type]))(QUrl());
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.shaderGraph(type), QUrl());
@@ -445,10 +439,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(graphUrl);
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+ (frontend.*(shaderTypesToSetters[type]))(graphUrl);
+ backend.syncFromFrontEnd(&frontend, false);
// AND
backend.cleanup();
@@ -462,14 +454,14 @@ private slots:
void shouldHandleShaderCodeGeneration_data()
{
- QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type");
-
- QTest::newRow("vertex") << Qt3DRender::Render::ShaderBuilder::Vertex;
- QTest::newRow("tessControl") << Qt3DRender::Render::ShaderBuilder::TessellationControl;
- QTest::newRow("tessEval") << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation;
- QTest::newRow("geometry") << Qt3DRender::Render::ShaderBuilder::Geometry;
- QTest::newRow("fragment") << Qt3DRender::Render::ShaderBuilder::Fragment;
- QTest::newRow("compute") << Qt3DRender::Render::ShaderBuilder::Compute;
+ QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("type");
+
+ QTest::newRow("vertex") << Qt3DRender::QShaderProgram::Vertex;
+ QTest::newRow("tessControl") << Qt3DRender::QShaderProgram::TessellationControl;
+ QTest::newRow("tessEval") << Qt3DRender::QShaderProgram::TessellationEvaluation;
+ QTest::newRow("geometry") << Qt3DRender::QShaderProgram::Geometry;
+ QTest::newRow("fragment") << Qt3DRender::QShaderProgram::Fragment;
+ QTest::newRow("compute") << Qt3DRender::QShaderProgram::Compute;
}
void shouldHandleShaderCodeGeneration()
@@ -478,7 +470,7 @@ private slots:
Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json");
QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty());
- QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type);
+ QFETCH(Qt3DRender::QShaderProgram::ShaderType, type);
const auto gl3Api = []{
auto api = Qt3DRender::GraphicsApiFilterData();
@@ -547,15 +539,15 @@ private slots:
void checkCodeUpdatedNotification_data()
{
- QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type");
+ QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("type");
QTest::addColumn<Qt3DRender::QShaderProgram::ShaderType>("notificationType");
- QTest::newRow("vertex") << Qt3DRender::Render::ShaderBuilder::Vertex << Qt3DRender::QShaderProgram::Vertex;
- QTest::newRow("tessControl") << Qt3DRender::Render::ShaderBuilder::TessellationControl << Qt3DRender::QShaderProgram::TessellationControl;
- QTest::newRow("tessEval") << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation << Qt3DRender::QShaderProgram::TessellationEvaluation;
- QTest::newRow("geometry") << Qt3DRender::Render::ShaderBuilder::Geometry << Qt3DRender::QShaderProgram::Geometry;
- QTest::newRow("fragment") << Qt3DRender::Render::ShaderBuilder::Fragment << Qt3DRender::QShaderProgram::Fragment;
- QTest::newRow("compute") << Qt3DRender::Render::ShaderBuilder::Compute << Qt3DRender::QShaderProgram::Compute;
+ QTest::newRow("vertex") << Qt3DRender::QShaderProgram::Vertex << Qt3DRender::QShaderProgram::Vertex;
+ QTest::newRow("tessControl") << Qt3DRender::QShaderProgram::TessellationControl << Qt3DRender::QShaderProgram::TessellationControl;
+ QTest::newRow("tessEval") << Qt3DRender::QShaderProgram::TessellationEvaluation << Qt3DRender::QShaderProgram::TessellationEvaluation;
+ QTest::newRow("geometry") << Qt3DRender::QShaderProgram::Geometry << Qt3DRender::QShaderProgram::Geometry;
+ QTest::newRow("fragment") << Qt3DRender::QShaderProgram::Fragment << Qt3DRender::QShaderProgram::Fragment;
+ QTest::newRow("compute") << Qt3DRender::QShaderProgram::Compute << Qt3DRender::QShaderProgram::Compute;
}
@@ -566,7 +558,7 @@ private slots:
Qt3DRender::Render::ShaderBuilder::setPrototypesFile(":/prototypes.json");
QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty());
- QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type);
+ QFETCH(Qt3DRender::QShaderProgram::ShaderType, type);
QFETCH(Qt3DRender::QShaderProgram::ShaderType, notificationType);
const auto gl3Api = []{
@@ -610,15 +602,6 @@ private slots:
QCOMPARE(backend.shaderGraph(type), graphUrl);
QVERIFY(!backend.isShaderCodeDirty(type));
QCOMPARE(backend.shaderCode(type), gl3Code);
-
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(arbiter.events.count(), 1);
- QCOMPARE(change->propertyName(), "generatedShaderCode");
- const QPair<int, QByteArray> value = change->value().value<QPair<int, QByteArray>>();
- QCOMPARE(value.first, int(notificationType));
- QCOMPARE(value.second, gl3Code);
-
- arbiter.events.clear();
}
};
diff --git a/tests/auto/render/shaderimage/shaderimage.pro b/tests/auto/render/shaderimage/shaderimage.pro
new file mode 100644
index 000000000..cbee46356
--- /dev/null
+++ b/tests/auto/render/shaderimage/shaderimage.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+TARGET = tst_shaderimage
+
+QT += 3dcore 3dcore-private 3drender 3drender-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_shaderimage.cpp
+
+include(../../core/common/common.pri)
+include(../commons/commons.pri)
diff --git a/tests/auto/render/shaderimage/tst_shaderimage.cpp b/tests/auto/render/shaderimage/tst_shaderimage.cpp
new file mode 100644
index 000000000..0771f1fe0
--- /dev/null
+++ b/tests/auto/render/shaderimage/tst_shaderimage.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <Qt3DRender/qshaderimage.h>
+#include <Qt3DRender/private/qshaderimage_p.h>
+#include <Qt3DRender/private/shaderimage_p.h>
+#include <Qt3DRender/qtexture.h>
+#include "qbackendnodetester.h"
+#include "testrenderer.h"
+
+class tst_ShaderImage : public Qt3DCore::QBackendNodeTester
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void checkInitialState()
+ {
+ // GIVEN
+ Qt3DRender::Render::ShaderImage backendShaderImage;
+
+ // THEN
+ QCOMPARE(backendShaderImage.isEnabled(), false);
+ QVERIFY(backendShaderImage.peerId().isNull());
+ QCOMPARE(backendShaderImage.textureId(), Qt3DCore::QNodeId());
+ QCOMPARE(backendShaderImage.mipLevel(), int(0));
+ QCOMPARE(backendShaderImage.layer(), int(0));
+ QCOMPARE(backendShaderImage.layered(), false);
+ QCOMPARE(backendShaderImage.access(), Qt3DRender::QShaderImage::ReadWrite);
+ QCOMPARE(backendShaderImage.format(), Qt3DRender::QShaderImage::NoFormat);
+ }
+
+ void checkCleanupState()
+ {
+ // GIVEN
+ Qt3DRender::Render::ShaderImage backendShaderImage;
+
+ // WHEN
+ backendShaderImage.setEnabled(true);
+ backendShaderImage.setTextureId(Qt3DCore::QNodeId::createId());
+ backendShaderImage.setMipLevel(8);
+ backendShaderImage.setLayer(200);
+ backendShaderImage.setLayered(true);
+ backendShaderImage.setAccess(Qt3DRender::QShaderImage::WriteOnly);
+ backendShaderImage.setFormat(Qt3DRender::QShaderImage::R32F);
+
+ backendShaderImage.cleanup();
+
+ // THEN
+ QCOMPARE(backendShaderImage.isEnabled(), false);
+ QCOMPARE(backendShaderImage.textureId(), Qt3DCore::QNodeId());
+ QCOMPARE(backendShaderImage.mipLevel(), int(0));
+ QCOMPARE(backendShaderImage.layer(), int(0));
+ QCOMPARE(backendShaderImage.layered(), false);
+ QCOMPARE(backendShaderImage.access(), Qt3DRender::QShaderImage::ReadWrite);
+ QCOMPARE(backendShaderImage.format(), Qt3DRender::QShaderImage::NoFormat);
+
+ }
+
+ void checkInitializeFromPeer()
+ {
+ // GIVEN
+ Qt3DRender::QShaderImage shaderImage;
+ TestRenderer renderer;
+
+ {
+ // WHEN
+ Qt3DRender::Render::ShaderImage backendShaderImage;
+ backendShaderImage.setRenderer(&renderer);
+ simulateInitializationSync(&shaderImage, &backendShaderImage);
+
+ // THEN
+ QCOMPARE(backendShaderImage.isEnabled(), true);
+ QCOMPARE(backendShaderImage.peerId(), shaderImage.id());
+ QCOMPARE(backendShaderImage.textureId(), Qt3DCore::QNodeId());
+ QCOMPARE(backendShaderImage.mipLevel(), 0);
+ QCOMPARE(backendShaderImage.layer(), 0);
+ QCOMPARE(backendShaderImage.layered(), false);
+ QCOMPARE(backendShaderImage.access(), Qt3DRender::QShaderImage::ReadWrite);
+ QCOMPARE(backendShaderImage.format(), Qt3DRender::QShaderImage::Automatic);
+ }
+ {
+ // WHEN
+ Qt3DRender::Render::ShaderImage backendShaderImage;
+ shaderImage.setEnabled(false);
+ backendShaderImage.setRenderer(&renderer);
+ simulateInitializationSync(&shaderImage, &backendShaderImage);
+
+ // THEN
+ QCOMPARE(backendShaderImage.peerId(), shaderImage.id());
+ QCOMPARE(backendShaderImage.isEnabled(), false);
+ }
+ }
+
+ void checkSceneChangeEvents()
+ {
+ // GIVEN
+ Qt3DRender::QShaderImage shaderImage;
+ Qt3DRender::Render::ShaderImage backendShaderImage;
+ TestRenderer renderer;
+ backendShaderImage.setRenderer(&renderer);
+ simulateInitializationSync(&shaderImage, &backendShaderImage);
+
+ {
+ // WHEN
+ const bool newValue = false;
+ shaderImage.setEnabled(newValue);
+ backendShaderImage.syncFromFrontEnd(&shaderImage, false);
+
+ // THEN
+ QCOMPARE(backendShaderImage.isEnabled(), newValue);
+ }
+ {
+ // WHEN
+ Qt3DRender::QTexture2D tex2D;
+ shaderImage.setTexture(&tex2D);
+ backendShaderImage.syncFromFrontEnd(&shaderImage, false);
+
+ // THEN
+ QCOMPARE(backendShaderImage.textureId(), tex2D.id());
+ }
+ {
+ // WHEN
+ const int newValue = 883;
+ shaderImage.setMipLevel(newValue);
+ backendShaderImage.syncFromFrontEnd(&shaderImage, false);
+
+ // THEN
+ QCOMPARE(backendShaderImage.mipLevel(), newValue);
+ }
+ {
+ // WHEN
+ const int newValue = 1584;
+ shaderImage.setLayer(newValue);
+ backendShaderImage.syncFromFrontEnd(&shaderImage, false);
+
+ // THEN
+ QCOMPARE(backendShaderImage.layer(), newValue);
+ }
+ {
+ // WHEN
+ const bool newValue = true;
+ shaderImage.setLayered(newValue);
+ backendShaderImage.syncFromFrontEnd(&shaderImage, false);
+
+ // THEN
+ QCOMPARE(backendShaderImage.layered(), newValue);
+ }
+ {
+ // WHEN
+ const Qt3DRender::QShaderImage::Access newValue = Qt3DRender::QShaderImage::WriteOnly;
+ shaderImage.setAccess(newValue);
+ backendShaderImage.syncFromFrontEnd(&shaderImage, false);
+
+ // THEN
+ QCOMPARE(backendShaderImage.access(), newValue);
+ }
+ {
+ // WHEN
+ const Qt3DRender::QShaderImage::ImageFormat newValue = Qt3DRender::QShaderImage::RG16F;
+ shaderImage.setFormat(newValue);
+ backendShaderImage.syncFromFrontEnd(&shaderImage, false);
+
+ // THEN
+ QCOMPARE(backendShaderImage.format(), newValue);
+ }
+ }
+
+};
+
+QTEST_MAIN(tst_ShaderImage)
+
+#include "tst_shaderimage.moc"
diff --git a/tests/auto/render/skeleton/tst_skeleton.cpp b/tests/auto/render/skeleton/tst_skeleton.cpp
index 499bb7cc7..63ed51058 100644
--- a/tests/auto/render/skeleton/tst_skeleton.cpp
+++ b/tests/auto/render/skeleton/tst_skeleton.cpp
@@ -34,9 +34,7 @@
#include <Qt3DCore/qskeletonloader.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DCore/private/qscene_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include <Qt3DCore/private/qbackendnode_p.h>
-#include <Qt3DCore/private/qpropertyupdatedchangebase_p.h>
#include <qbackendnodetester.h>
#include <testpostmanarbiter.h>
#include <testrenderer.h>
@@ -49,24 +47,6 @@ Q_DECLARE_METATYPE(Qt3DRender::Render::JointInfo)
Q_DECLARE_METATYPE(Qt3DRender::Render::SkeletonData)
Q_DECLARE_METATYPE(Qt3DCore::Sqt)
-namespace {
-
-void linearizeTreeHelper(QJoint *joint, QVector<QJoint *> &joints)
-{
- joints.push_back(joint);
- for (const auto child : joint->childJoints())
- linearizeTreeHelper(child, joints);
-}
-
-QVector<QJoint *> linearizeTree(QJoint *rootJoint)
-{
- QVector<QJoint *> joints;
- linearizeTreeHelper(rootJoint, joints);
- return joints;
-}
-
-}
-
class tst_Skeleton : public Qt3DCore::QBackendNodeTester
{
Q_OBJECT
@@ -86,7 +66,7 @@ private Q_SLOTS:
skeleton.setSource(QUrl::fromLocalFile("funnybones.json"));
// WHEN
- simulateInitialization(&skeleton, &backendSkeleton);
+ simulateInitializationSync(&skeleton, &backendSkeleton);
// THEN
QCOMPARE(backendSkeleton.peerId(), skeleton.id());
@@ -104,7 +84,7 @@ private Q_SLOTS:
skeleton2.setRootJoint(joint);
// WHEN
- simulateInitialization(&skeleton2, &backendSkeleton2);
+ simulateInitializationSync(&skeleton2, &backendSkeleton2);
// THEN
QCOMPARE(backendSkeleton2.peerId(), skeleton2.id());
@@ -135,7 +115,7 @@ private Q_SLOTS:
skeleton.setSource(QUrl::fromLocalFile("skeleton1.json"));
// WHEN
- simulateInitialization(&skeleton, &backendSkeleton);
+ simulateInitializationSync(&skeleton, &backendSkeleton);
backendSkeleton.cleanup();
// THEN
@@ -145,7 +125,7 @@ private Q_SLOTS:
QCOMPARE(backendSkeleton.rootJointId(), QNodeId());
}
- void checkPropertyChanges()
+ void checkDirectPropertyChanges()
{
// GIVEN
TestRenderer renderer;
@@ -155,78 +135,26 @@ private Q_SLOTS:
backendSkeleton.setRenderer(&renderer);
backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager());
backendSkeleton.setDataType(Skeleton::File);
- Qt3DCore::QPropertyUpdatedChangePtr updateChange;
// Initialize to ensure skeleton manager is set
QSkeletonLoader skeleton;
skeleton.setSource(QUrl::fromLocalFile("skeleton1.json"));
- simulateInitialization(&skeleton, &backendSkeleton);
+ simulateInitializationSync(&skeleton, &backendSkeleton);
// WHEN
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("enabled");
- updateChange->setValue(true);
- backendSkeleton.sceneChangeEvent(updateChange);
+ skeleton.setEnabled(false);
+ backendSkeleton.syncFromFrontEnd(&skeleton, false);
// THEN
- QCOMPARE(backendSkeleton.isEnabled(), true);
+ QCOMPARE(backendSkeleton.isEnabled(), false);
// WHEN
const QUrl newSource = QUrl::fromLocalFile("terminator.json");
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("source");
- updateChange->setValue(newSource);
- backendSkeleton.sceneChangeEvent(updateChange);
+ skeleton.setSource(newSource);
+ backendSkeleton.syncFromFrontEnd(&skeleton, false);
// THEN
QCOMPARE(backendSkeleton.source(), newSource);
-
- // WHEN
- const QNodeId newRootJointId = QNodeId::createId();
- updateChange.reset(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("rootJoint");
- updateChange->setValue(QVariant::fromValue(newRootJointId));
- backendSkeleton.sceneChangeEvent(updateChange);
-
- // THEN
- QCOMPARE(backendSkeleton.rootJointId(), newRootJointId);
- }
-
- void checkStatusPropertyBackendNotification()
- {
- // GIVEN
- TestRenderer renderer;
- NodeManagers nodeManagers;
- renderer.setNodeManagers(&nodeManagers);
- TestArbiter arbiter;
- Skeleton backendSkeleton;
- backendSkeleton.setRenderer(&renderer);
- backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager());
- backendSkeleton.setEnabled(true);
- Qt3DCore::QBackendNodePrivate::get(&backendSkeleton)->setArbiter(&arbiter);
-
- // WHEN
- backendSkeleton.setStatus(QSkeletonLoader::Error);
-
- // THEN
- QCOMPARE(backendSkeleton.status(), QSkeletonLoader::Error);
- QCOMPARE(arbiter.events.count(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "status");
- QCOMPARE(change->value().value<QSkeletonLoader::Status>(), backendSkeleton.status());
- QCOMPARE(Qt3DCore::QPropertyUpdatedChangeBasePrivate::get(change.data())->m_isIntermediate,
- false);
-
- arbiter.events.clear();
-
- // WHEN
- backendSkeleton.setStatus(QSkeletonLoader::Error);
-
- // THEN
- QCOMPARE(backendSkeleton.status(), QSkeletonLoader::Error);
- QCOMPARE(arbiter.events.count(), 0);
-
- arbiter.events.clear();
}
void checkCreateFrontendJoint_data()
@@ -270,134 +198,6 @@ private Q_SLOTS:
joint->setName(name);
QTest::newRow("inverseBind") << m << localPose << name << joint;
}
-
- void checkCreateFrontendJoint()
- {
- // GIVEN
- Skeleton backendSkeleton;
- QFETCH(QMatrix4x4, inverseBindMatrix);
- QFETCH(Qt3DCore::Sqt, localPose);
- QFETCH(QString, jointName);
- QFETCH(QJoint *, expectedJoint);
-
- // WHEN
- const QJoint *actualJoint = backendSkeleton.createFrontendJoint(jointName, localPose, inverseBindMatrix);
-
- // THEN
- QCOMPARE(actualJoint->scale(), expectedJoint->scale());
- QCOMPARE(actualJoint->rotation(), expectedJoint->rotation());
- QCOMPARE(actualJoint->translation(), expectedJoint->translation());
- QCOMPARE(actualJoint->inverseBindMatrix(), expectedJoint->inverseBindMatrix());
- QCOMPARE(actualJoint->name(), expectedJoint->name());
-
- // Cleanup
- delete actualJoint;
- delete expectedJoint;
- }
-
- void checkCreateFrontendJoints_data()
- {
- QTest::addColumn<SkeletonData>("skeletonData");
- QTest::addColumn<QJoint *>("expectedRootJoint");
-
- QTest::newRow("empty") << SkeletonData() << (QJoint*)nullptr;
-
- SkeletonData skeletonData;
- JointInfo rootJointInfo;
- skeletonData.joints.push_back(rootJointInfo);
- skeletonData.jointNames.push_back(QLatin1String("rootJoint"));
- skeletonData.localPoses.push_back(Qt3DCore::Sqt());
- const int childCount = 10;
- for (int i = 0; i < childCount; ++i) {
- JointInfo childJointInfo;
- childJointInfo.parentIndex = 0;
- skeletonData.joints.push_back(childJointInfo);
-
- const float x = static_cast<float>(i);
- Qt3DCore::Sqt localPose;
- localPose.translation = QVector3D(x, x, x);
- skeletonData.localPoses.push_back(localPose);
-
- skeletonData.jointNames.push_back(QString("Child-%1").arg(i));
- }
-
- QJoint *rootJoint = new QJoint();
- for (int i = 0; i < childCount; ++i) {
- QJoint *childJoint = new QJoint();
- const float x = static_cast<float>(i);
- childJoint->setTranslation(QVector3D(x, x, x));
- rootJoint->addChildJoint(childJoint);
- }
-
- QTest::newRow("wide") << skeletonData << rootJoint;
-
- skeletonData.joints.clear();
- skeletonData.joints.push_back(rootJointInfo);
- for (int i = 0; i < childCount; ++i) {
- JointInfo childJointInfo;
- childJointInfo.parentIndex = i;
- skeletonData.joints.push_back(childJointInfo);
-
- const float x = static_cast<float>(i);
- Qt3DCore::Sqt localPose;
- localPose.translation = QVector3D(x, x, x);
- skeletonData.localPoses.push_back(localPose);
-
- skeletonData.jointNames.push_back(QString("Child-%1").arg(i));
- }
-
- rootJoint = new QJoint();
- QJoint *previousJoint = rootJoint;
- for (int i = 0; i < childCount; ++i) {
- QJoint *childJoint = new QJoint();
- const float x = static_cast<float>(i);
- childJoint->setTranslation(QVector3D(x, x, x));
- previousJoint->addChildJoint(childJoint);
- previousJoint = childJoint;
- }
-
- QTest::newRow("deep") << skeletonData << rootJoint;
- }
-
- void checkCreateFrontendJoints()
- {
- // GIVEN
- Skeleton backendSkeleton;
- QFETCH(SkeletonData, skeletonData);
- QFETCH(QJoint *, expectedRootJoint);
-
- // WHEN
- QJoint *actualRootJoint = backendSkeleton.createFrontendJoints(skeletonData);
-
- // THEN
- if (skeletonData.joints.isEmpty()) {
- QVERIFY(actualRootJoint == expectedRootJoint); // nullptr
- return;
- }
-
- // Linearise the tree of joints and check them against the skeletonData
- QVector<QJoint *> joints = linearizeTree(actualRootJoint);
- QCOMPARE(joints.size(), skeletonData.joints.size());
- for (int i = 0; i < joints.size(); ++i) {
- // Check the translations match
- QCOMPARE(joints[i]->translation(), skeletonData.localPoses[i].translation);
- }
-
- // Now we know the order of Joints match. Check the parents match too
- for (int i = 0; i < joints.size(); ++i) {
- // Get parent index from joint info
- const int parentIndex = skeletonData.joints[i].parentIndex;
- if (parentIndex == -1) {
- QVERIFY(joints[i]->parent() == nullptr);
- } else {
- QCOMPARE(joints[i]->parent(), joints[parentIndex]);
- }
- }
-
- // Cleanup
- delete actualRootJoint;
- delete expectedRootJoint;
- }
};
QTEST_APPLESS_MAIN(tst_Skeleton)
diff --git a/tests/auto/render/sortpolicy/tst_sortpolicy.cpp b/tests/auto/render/sortpolicy/tst_sortpolicy.cpp
index 8cab1a9c4..5552a1760 100644
--- a/tests/auto/render/sortpolicy/tst_sortpolicy.cpp
+++ b/tests/auto/render/sortpolicy/tst_sortpolicy.cpp
@@ -29,7 +29,6 @@
#include <QtTest/QTest>
#include <qbackendnodetester.h>
#include <Qt3DRender/private/sortpolicy_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "testrenderer.h"
class tst_SortPolicy : public Qt3DCore::QBackendNodeTester
@@ -52,8 +51,10 @@ private Q_SLOTS:
void checkPeerPropertyMirroring()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QFrameGraphNode parent;
auto parentBackend = new Qt3DRender::Render::FrameGraphNode;
+ parentBackend->setRenderer(&renderer);
simulateInitialization(&parent, parentBackend);
Qt3DRender::Render::FrameGraphManager manager;
@@ -67,12 +68,14 @@ private Q_SLOTS:
sortPolicy.setSortTypes(sortTypes);
// WHEN
- simulateInitialization(&sortPolicy, &backendNode);
+ backendNode.setRenderer(&renderer);
+ simulateInitializationSync(&sortPolicy, &backendNode);
// THEN
QCOMPARE(backendNode.peerId(), sortPolicy.id());
QCOMPARE(backendNode.parentId(), parent.id());
QCOMPARE(backendNode.sortTypes(), sortTypes);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
void checkPropertyChanges()
@@ -84,18 +87,18 @@ private Q_SLOTS:
Qt3DRender::Render::SortPolicy backendNode;
backendNode.setRenderer(&renderer);
+ Qt3DRender::QSortPolicy sortPolicy;
+ sortPolicy.setSortTypes(sortTypes);
+
+ simulateInitializationSync(&sortPolicy, &backendNode);
+
// WHEN
- auto sortTypeInts = QVector<int>();
- std::transform(sortTypes.constBegin(), sortTypes.constEnd(),
- std::back_inserter(sortTypeInts),
- [] (Qt3DRender::QSortPolicy::SortType type) -> int { return type; });
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(QVariant::fromValue(sortTypeInts));
- updateChange->setPropertyName("sortTypes");
- backendNode.sceneChangeEvent(updateChange);
+ sortPolicy.setSortTypes(sortTypes);
+ backendNode.syncFromFrontEnd(&sortPolicy, false);
// THEN
QCOMPARE(backendNode.sortTypes(), sortTypes);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
};
diff --git a/tests/auto/render/technique/tst_technique.cpp b/tests/auto/render/technique/tst_technique.cpp
index 7dfd5b85c..5b6fdb4a4 100644
--- a/tests/auto/render/technique/tst_technique.cpp
+++ b/tests/auto/render/technique/tst_technique.cpp
@@ -39,9 +39,6 @@
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/filterkey_p.h>
#include <Qt3DRender/private/techniquemanager_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
@@ -76,10 +73,12 @@ private Q_SLOTS:
void checkCleanupState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::Technique backendTechnique;
Qt3DRender::Render::NodeManagers nodeManagers;
// WHEN
+ backendTechnique.setRenderer(&renderer);
backendTechnique.setEnabled(true);
backendTechnique.setNodeManager(&nodeManagers);
backendTechnique.setCompatibleWithRenderer(true);
@@ -94,7 +93,7 @@ private Q_SLOTS:
technique.addParameter(&parameter);
technique.addFilterKey(&filterKey);
- simulateInitialization(&technique, &backendTechnique);
+ simulateInitializationSync(&technique, &backendTechnique);
}
backendTechnique.cleanup();
@@ -110,6 +109,7 @@ private Q_SLOTS:
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QTechnique technique;
Qt3DRender::QRenderPass pass;
Qt3DRender::QParameter parameter;
@@ -124,8 +124,9 @@ private Q_SLOTS:
Qt3DRender::Render::Technique backendTechnique;
Qt3DRender::Render::NodeManagers nodeManagers;
+ backendTechnique.setRenderer(&renderer);
backendTechnique.setNodeManager(&nodeManagers);
- simulateInitialization(&technique, &backendTechnique);
+ simulateInitializationSync(&technique, &backendTechnique);
// THEN
QCOMPARE(backendTechnique.isEnabled(), true);
@@ -142,19 +143,23 @@ private Q_SLOTS:
const QVector<Qt3DCore::QNodeId> dirtyTechniques = nodeManagers.techniqueManager()->takeDirtyTechniques();
QCOMPARE(dirtyTechniques.size(), 1);
QCOMPARE(dirtyTechniques.first(), backendTechnique.peerId());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TechniquesDirty);
}
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
Qt3DRender::Render::Technique backendTechnique;
Qt3DRender::Render::NodeManagers nodeManagers;
backendTechnique.setNodeManager(&nodeManagers);
+ backendTechnique.setRenderer(&renderer);
technique.setEnabled(false);
- simulateInitialization(&technique, &backendTechnique);
+ simulateInitializationSync(&technique, &backendTechnique);
// THEN
QCOMPARE(backendTechnique.peerId(), technique.id());
QCOMPARE(backendTechnique.isEnabled(), false);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TechniquesDirty);
}
}
@@ -176,6 +181,7 @@ private Q_SLOTS:
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DRender::QTechnique technique;
Qt3DRender::Render::Technique backendTechnique;
Qt3DRender::Render::NodeManagers nodeManagers;
@@ -185,34 +191,31 @@ private Q_SLOTS:
{
// WHEN
- const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendTechnique.sceneChangeEvent(change);
+ const bool newValue = true;
+ technique.setEnabled(newValue);
+ backendTechnique.syncFromFrontEnd(&technique, false);
// THEN
QCOMPARE(backendTechnique.isEnabled(), newValue);
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TechniquesDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ QCOMPARE(nodeManagers.techniqueManager()->takeDirtyTechniques().size(), 1);
}
{
// WHEN
backendTechnique.setCompatibleWithRenderer(true);
QCOMPARE(nodeManagers.techniqueManager()->takeDirtyTechniques().size(), 0);
- Qt3DRender::GraphicsApiFilterData newValue;
- newValue.m_major = 4;
- newValue.m_minor = 5;
- newValue.m_vendor = QStringLiteral("ATI");
+ technique.graphicsApiFilter()->setMajorVersion(4);
+ technique.graphicsApiFilter()->setMinorVersion(5);
+ technique.graphicsApiFilter()->setVendor(QStringLiteral("ATI"));
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("graphicsApiFilterData");
- change->setValue(QVariant::fromValue(newValue));
- backendTechnique.sceneChangeEvent(change);
+ backendTechnique.syncFromFrontEnd(&technique, false);
// THEN
- QCOMPARE(*backendTechnique.graphicsApiFilter(), newValue);
+ QCOMPARE(backendTechnique.graphicsApiFilter()->m_major, technique.graphicsApiFilter()->majorVersion());
+ QCOMPARE(backendTechnique.graphicsApiFilter()->m_minor, technique.graphicsApiFilter()->minorVersion());
+ QCOMPARE(backendTechnique.graphicsApiFilter()->m_vendor, technique.graphicsApiFilter()->vendor());
QCOMPARE(backendTechnique.isCompatibleWithRenderer(), false);
const QVector<Qt3DCore::QNodeId> dirtyTechniques = nodeManagers.techniqueManager()->takeDirtyTechniques();
@@ -227,9 +230,8 @@ private Q_SLOTS:
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &parameter);
- change->setPropertyName("parameter");
- backendTechnique.sceneChangeEvent(change);
+ technique.addParameter(&parameter);
+ backendTechnique.syncFromFrontEnd(&technique, false);
// THEN
QCOMPARE(backendTechnique.parameters().size(), 1);
@@ -239,9 +241,8 @@ private Q_SLOTS:
}
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &parameter);
- change->setPropertyName("parameter");
- backendTechnique.sceneChangeEvent(change);
+ technique.removeParameter(&parameter);
+ backendTechnique.syncFromFrontEnd(&technique, false);
// THEN
QCOMPARE(backendTechnique.parameters().size(), 0);
@@ -254,9 +255,8 @@ private Q_SLOTS:
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &filterKey);
- change->setPropertyName("filterKeys");
- backendTechnique.sceneChangeEvent(change);
+ technique.addFilterKey(&filterKey);
+ backendTechnique.syncFromFrontEnd(&technique, false);
// THEN
QCOMPARE(backendTechnique.filterKeys().size(), 1);
@@ -266,9 +266,8 @@ private Q_SLOTS:
}
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &filterKey);
- change->setPropertyName("filterKeys");
- backendTechnique.sceneChangeEvent(change);
+ technique.removeFilterKey(&filterKey);
+ backendTechnique.syncFromFrontEnd(&technique, false);
// THEN
QCOMPARE(backendTechnique.filterKeys().size(), 0);
@@ -281,9 +280,8 @@ private Q_SLOTS:
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &pass);
- change->setPropertyName("pass");
- backendTechnique.sceneChangeEvent(change);
+ technique.addRenderPass(&pass);
+ backendTechnique.syncFromFrontEnd(&technique, false);
// THEN
QCOMPARE(backendTechnique.renderPasses().size(), 1);
@@ -293,9 +291,8 @@ private Q_SLOTS:
}
{
// WHEN
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(Qt3DCore::QNodeId(), &pass);
- change->setPropertyName("pass");
- backendTechnique.sceneChangeEvent(change);
+ technique.removeRenderPass(&pass);
+ backendTechnique.syncFromFrontEnd(&technique, false);
// THEN
QCOMPARE(backendTechnique.renderPasses().size(), 0);
@@ -308,6 +305,7 @@ private Q_SLOTS:
void checkIsCompatibleWithFilters()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::Technique backendTechnique;
Qt3DRender::Render::NodeManagers nodeManagers;
@@ -339,11 +337,17 @@ private Q_SLOTS:
Qt3DRender::Render::FilterKey *backendFilterKey4 = nodeManagers.filterKeyManager()->getOrCreateResource(filterKey4->id());
Qt3DRender::Render::FilterKey *backendFilterKey5 = nodeManagers.filterKeyManager()->getOrCreateResource(filterKey5->id());
- simulateInitialization(filterKey1, backendFilterKey1);
- simulateInitialization(filterKey2, backendFilterKey2);
- simulateInitialization(filterKey3, backendFilterKey3);
- simulateInitialization(filterKey4, backendFilterKey4);
- simulateInitialization(filterKey5, backendFilterKey5);
+ backendFilterKey1->setRenderer(&renderer);
+ backendFilterKey2->setRenderer(&renderer);
+ backendFilterKey3->setRenderer(&renderer);
+ backendFilterKey4->setRenderer(&renderer);
+ backendFilterKey5->setRenderer(&renderer);
+
+ simulateInitializationSync(filterKey1, backendFilterKey1);
+ simulateInitializationSync(filterKey2, backendFilterKey2);
+ simulateInitializationSync(filterKey3, backendFilterKey3);
+ simulateInitializationSync(filterKey4, backendFilterKey4);
+ simulateInitializationSync(filterKey5, backendFilterKey5);
// THEN
QCOMPARE(nodeManagers.filterKeyManager()->activeHandles().size(), 5);
diff --git a/tests/auto/render/texture/tst_texture.cpp b/tests/auto/render/texture/tst_texture.cpp
index b0ce782a0..aec79bbbd 100644
--- a/tests/auto/render/texture/tst_texture.cpp
+++ b/tests/auto/render/texture/tst_texture.cpp
@@ -28,9 +28,6 @@
#include <QtTest/QTest>
#include <qbackendnodetester.h>
-#include <Qt3DCore/qdynamicpropertyupdatedchange.h>
-#include <Qt3DCore/qpropertynodeaddedchange.h>
-#include <Qt3DCore/qpropertynoderemovedchange.h>
#include <Qt3DRender/private/texture_p.h>
#include "testpostmanarbiter.h"
@@ -77,6 +74,7 @@ private slots:
void checkPropertyMirroring();
void checkPropertyChanges();
void checkTextureImageBookeeping();
+ void checkInitialUpdateData();
};
void tst_RenderTexture::checkDefaults()
@@ -113,13 +111,11 @@ void tst_RenderTexture::checkFrontendPropertyNotifications()
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "width");
- QCOMPARE(change->value().value<int>(), 512);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &texture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
texture.setWidth(512);
@@ -127,19 +123,18 @@ void tst_RenderTexture::checkFrontendPropertyNotifications()
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
texture.setHeight(256);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "height");
- QCOMPARE(change->value().value<int>(), 256);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &texture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
texture.setHeight(256);
@@ -147,19 +142,18 @@ void tst_RenderTexture::checkFrontendPropertyNotifications()
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
texture.setDepth(128);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "depth");
- QCOMPARE(change->value().value<int>(), 128);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &texture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
texture.setDepth(128);
@@ -167,19 +161,18 @@ void tst_RenderTexture::checkFrontendPropertyNotifications()
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.events.size(), 0);
// WHEN
texture.setLayers(16);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "layers");
- QCOMPARE(change->value().value<int>(), 16);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &texture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
texture.setLayers(16);
@@ -187,19 +180,18 @@ void tst_RenderTexture::checkFrontendPropertyNotifications()
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
texture.setSamples(32);
QCoreApplication::processEvents();
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
- QCOMPARE(change->propertyName(), "samples");
- QCOMPARE(change->value().value<int>(), 32);
- QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &texture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
texture.setSamples(32);
@@ -207,31 +199,28 @@ void tst_RenderTexture::checkFrontendPropertyNotifications()
// THEN
QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 0);
// WHEN
Qt3DRender::QTextureImage img;
texture.addTextureImage(&img);
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- const auto addedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeAddedChange>();
- QCOMPARE(addedChange->propertyName(), "textureImage");
- QCOMPARE(addedChange->addedNodeId(), img.id());
- QCOMPARE(addedChange->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &texture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
// WHEN
texture.removeTextureImage(&img);
// THEN
- QCOMPARE(arbiter.events.size(), 1);
- const auto removedChange = arbiter.events.first().staticCast<Qt3DCore::QPropertyNodeRemovedChange>();
- QCOMPARE(removedChange->propertyName(), "textureImage");
- QCOMPARE(removedChange->removedNodeId(), img.id());
- QCOMPARE(removedChange->type(), Qt3DCore::PropertyValueRemoved);
+ QCOMPARE(arbiter.events.size(), 0);
+ QCOMPARE(arbiter.dirtyNodes.size(), 1);
+ QCOMPARE(arbiter.dirtyNodes.front(), &texture);
- arbiter.events.clear();
+ arbiter.dirtyNodes.clear();
}
template <typename FrontendTextureType, Qt3DRender::QAbstractTexture::Target Target>
@@ -248,7 +237,7 @@ void tst_RenderTexture::checkPropertyMirroring()
frontend.setSamples(32);
// WHEN
- simulateInitialization(&frontend, &backend);
+ simulateInitializationSync(&frontend, &backend);
// THEN
QCOMPARE(backend.peerId(), frontend.id());
@@ -279,15 +268,14 @@ void tst_RenderTexture::checkPropertyChanges()
{
// GIVEN
TestRenderer renderer;
+ Qt3DRender::QSharedGLTexture frontend;
Qt3DRender::Render::Texture backend;
backend.setRenderer(&renderer);
backend.unsetDirty();
// WHEN
- Qt3DCore::QPropertyUpdatedChangePtr updateChange(new Qt3DCore::QPropertyUpdatedChange(Qt3DCore::QNodeId()));
- updateChange->setValue(256);
- updateChange->setPropertyName("width");
- backend.sceneChangeEvent(updateChange);
+ frontend.setWidth(256);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.properties().width, 256);
@@ -297,10 +285,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(128);
- updateChange->setPropertyName("height");
- backend.sceneChangeEvent(updateChange);
+ frontend.setHeight(128);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.properties().height, 128);
@@ -310,10 +296,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(16);
- updateChange->setPropertyName("depth");
- backend.sceneChangeEvent(updateChange);
+ frontend.setDepth(16);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.properties().depth, 16);
@@ -323,10 +307,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DRender::QAbstractTexture::RGB16F));
- updateChange->setPropertyName("format");
- backend.sceneChangeEvent(updateChange);
+ frontend.setFormat(Qt3DRender::QAbstractTexture::RGB16F);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.properties().format, Qt3DRender::QAbstractTexture::RGB16F);
@@ -336,23 +318,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DRender::QAbstractTexture::Target1DArray));
- updateChange->setPropertyName("target");
- backend.sceneChangeEvent(updateChange);
-
- // THEN
- QCOMPARE(backend.properties().target, Qt3DRender::QAbstractTexture::Target1DArray);
- QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty);
- QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyProperties);
- renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- backend.unsetDirty();
-
- // WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(true);
- updateChange->setPropertyName("mipmaps");
- backend.sceneChangeEvent(updateChange);
+ frontend.setGenerateMipMaps(true);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.properties().generateMipMaps, true);
@@ -362,10 +329,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DRender::QAbstractTexture::LinearMipMapLinear));
- updateChange->setPropertyName("minificationFilter");
- backend.sceneChangeEvent(updateChange);
+ frontend.setMinificationFilter(Qt3DRender::QAbstractTexture::LinearMipMapLinear);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.parameters().minificationFilter, Qt3DRender::QAbstractTexture::LinearMipMapLinear);
@@ -375,10 +340,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DRender::QAbstractTexture::Linear));
- updateChange->setPropertyName("magnificationFilter");
- backend.sceneChangeEvent(updateChange);
+ frontend.setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.parameters().magnificationFilter, Qt3DRender::QAbstractTexture::Linear);
@@ -388,10 +351,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DRender::QTextureWrapMode::Repeat));
- updateChange->setPropertyName("wrapModeX");
- backend.sceneChangeEvent(updateChange);
+ frontend.wrapMode()->setX(Qt3DRender::QTextureWrapMode::Repeat);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.parameters().wrapModeX, Qt3DRender::QTextureWrapMode::Repeat);
@@ -401,10 +362,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DRender::QTextureWrapMode::Repeat));
- updateChange->setPropertyName("wrapModeY");
- backend.sceneChangeEvent(updateChange);
+ frontend.wrapMode()->setY(Qt3DRender::QTextureWrapMode::Repeat);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.parameters().wrapModeY, Qt3DRender::QTextureWrapMode::Repeat);
@@ -414,10 +373,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DRender::QTextureWrapMode::Repeat));
- updateChange->setPropertyName("wrapModeZ");
- backend.sceneChangeEvent(updateChange);
+ frontend.wrapMode()->setZ(Qt3DRender::QTextureWrapMode::Repeat);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.parameters().wrapModeZ, Qt3DRender::QTextureWrapMode::Repeat);
@@ -427,10 +384,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(16.0f);
- updateChange->setPropertyName("maximumAnisotropy");
- backend.sceneChangeEvent(updateChange);
+ frontend.setMaximumAnisotropy(16.f);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.parameters().maximumAnisotropy, 16.0f);
@@ -440,10 +395,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DRender::QAbstractTexture::CompareEqual));
- updateChange->setPropertyName("comparisonFunction");
- backend.sceneChangeEvent(updateChange);
+ frontend.setComparisonFunction(Qt3DRender::QAbstractTexture::CompareEqual);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.parameters().comparisonFunction, Qt3DRender::QAbstractTexture::CompareEqual);
@@ -453,10 +406,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DRender::QAbstractTexture::CompareRefToTexture));
- updateChange->setPropertyName("comparisonMode");
- backend.sceneChangeEvent(updateChange);
+ frontend.setComparisonMode(Qt3DRender::QAbstractTexture::CompareRefToTexture);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.parameters().comparisonMode, Qt3DRender::QAbstractTexture::CompareRefToTexture);
@@ -466,10 +417,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(32);
- updateChange->setPropertyName("layers");
- backend.sceneChangeEvent(updateChange);
+ frontend.setLayers(32);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.properties().layers, 32);
@@ -479,10 +428,8 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(64);
- updateChange->setPropertyName("samples");
- backend.sceneChangeEvent(updateChange);
+ frontend.setSamples(64);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.properties().samples, 64);
@@ -492,43 +439,43 @@ void tst_RenderTexture::checkPropertyChanges()
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- Qt3DRender::QTextureGeneratorPtr gen = QSharedPointer<FakeGenerator>::create();
- updateChange->setValue(QVariant::fromValue(gen));
- updateChange->setPropertyName("generator");
- backend.sceneChangeEvent(updateChange);
+ frontend.setTextureId(883);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
- QCOMPARE(backend.dataGenerator(), gen);
+ QCOMPARE(backend.sharedTextureId(), 883);
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty);
- QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyDataGenerator);
+ QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtySharedTextureId);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
backend.unsetDirty();
// WHEN
- updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId());
- updateChange->setValue(883);
- updateChange->setPropertyName("textureId");
- backend.sceneChangeEvent(updateChange);
+ Qt3DRender::QTextureImage img;
+ frontend.addTextureImage(&img);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
- QCOMPARE(backend.sharedTextureId(), 883);
+ QCOMPARE(backend.textureImageIds().size(), 1);
+ QCOMPARE(backend.textureImageIds().first(), img.id());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty);
- QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtySharedTextureId);
+ QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyImageGenerators);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
backend.unsetDirty();
// WHEN
- Qt3DRender::QTextureImage img;
- const auto imageAddChange = Qt3DCore::QPropertyNodeAddedChangePtr::create(Qt3DCore::QNodeId(), &img);
- imageAddChange->setPropertyName("textureImage");
- backend.sceneChangeEvent(imageAddChange);
+ Qt3DRender::QTextureDataUpdate updateData;
+ updateData.setX(100);
+ updateData.setY(100);
+ updateData.setZ(100);
+ frontend.updateData(updateData);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
- QCOMPARE(backend.textureImageIds().size(), 1);
- QCOMPARE(backend.textureImageIds().first(), img.id());
+ const QVector<Qt3DRender::QTextureDataUpdate> pendingUpdates = backend.takePendingTextureDataUpdates();
+ QCOMPARE(pendingUpdates.size(), 1);
+ QCOMPARE(pendingUpdates.first(), updateData);
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty);
- QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyImageGenerators);
+ QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyPendingDataUpdates);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
backend.unsetDirty();
}
@@ -556,7 +503,31 @@ void tst_RenderTexture::checkTextureImageBookeeping()
// THEN
QCOMPARE(texture.textureImages().size(), 0);
+}
+
+void tst_RenderTexture::checkInitialUpdateData()
+{
+ // GIVEN
+ TestRenderer renderer;
+ DummyTexture frontend;
+ Qt3DRender::Render::Texture backend;
+
+ backend.setRenderer(&renderer);
+
+ Qt3DRender::QTextureDataUpdate updateData;
+ updateData.setX(100);
+ updateData.setY(100);
+ updateData.setZ(100);
+
+ // WHEN -> updateData with no backend/arbiter
+ frontend.updateData(updateData);
+ simulateInitializationSync(&frontend, &backend);
+ // THEN -> should have received the update as part of the initial data
+ const QVector<Qt3DRender::QTextureDataUpdate> pendingUpdates = backend.takePendingTextureDataUpdates();
+ QCOMPARE(pendingUpdates.size(), 1);
+ QCOMPARE(pendingUpdates.first(), updateData);
+ QVERIFY(backend.dirtyFlags() & Qt3DRender::Render::Texture::DirtyPendingDataUpdates);
}
QTEST_APPLESS_MAIN(tst_RenderTexture)
diff --git a/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp b/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp
deleted file mode 100644
index eb7177adf..000000000
--- a/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include <QtTest/QTest>
-#include <Qt3DRender/private/texturedatamanager_p.h>
-
-namespace {
-
-class FakeGenerator
-{
-public:
- explicit FakeGenerator(const QString &name)
- : m_name(name)
- {}
-
- bool operator==(const FakeGenerator &other) const
- {
- return other.m_name == m_name;
- }
-
- bool operator!=(const FakeGenerator &other) const
- {
- return !(other == *this);
- }
-private:
- QString m_name;
-};
-typedef QSharedPointer<FakeGenerator> FakeGeneratorPtr;
-
-class FakeData
-{
-public:
- explicit FakeData(int value)
- : m_value(value)
- {
- Q_UNUSED(m_value);
- }
-
-private:
- int m_value;
-};
-typedef QSharedPointer<FakeData> FakeDataPtr;
-
-
-struct FakeAPITexture
-{
- void requestUpload() {}
-};
-
-using Manager = Qt3DRender::Render::GeneratorDataManager<FakeGeneratorPtr, FakeDataPtr, FakeAPITexture*>;
-
-} // anonymous
-
-class tst_TextureDataManager : public QObject
-{
- Q_OBJECT
-
-private Q_SLOTS:
-
- void checkAssumptions()
- {
- // GIVEN
- FakeGeneratorPtr zr1(FakeGeneratorPtr::create(QStringLiteral("ZR1")));
- FakeGeneratorPtr z06(FakeGeneratorPtr::create(QStringLiteral("Z06")));
-
- // THEN
- QVERIFY(*zr1 == *zr1);
- QVERIFY(*z06 == *z06);
- QVERIFY(*zr1 != *z06);
- QVERIFY(*z06 != *zr1);
- }
-
- void checkRequestDataShouldCreate()
- {
- // GIVEN
- Manager manager;
- FakeGeneratorPtr generator(FakeGeneratorPtr::create(QStringLiteral("ZR1")));
- FakeAPITexture texture;
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 0);
-
- // WHEN
- manager.requestData(generator, &texture);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 1);
- }
-
- void checkRequestDataAlreadyExistingGenerator()
- {
- // GIVEN
- Manager manager;
- FakeGeneratorPtr generator(FakeGeneratorPtr::create(QStringLiteral("ZR1")));
- FakeGeneratorPtr generatorClone(FakeGeneratorPtr::create(QStringLiteral("ZR1")));
- FakeAPITexture texture;
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 0);
-
- // WHEN
- for (int i = 0; i < 5; ++i)
- manager.requestData(generator, &texture);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 1);
-
- // WHEN
- for (int i = 0; i < 5; ++i)
- manager.requestData(generatorClone, &texture);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 1);
- }
-
-
- void checkReleaseDataInvalidEntry()
- {
- // GIVEN
- Manager manager;
- FakeGeneratorPtr generator(FakeGeneratorPtr::create(QStringLiteral("ZR1")));
- FakeAPITexture texture;
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 0);
-
- // WHEN
- manager.releaseData(generator, &texture);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 0);
- // and should not crash
- }
-
- void checkReleaseDataValidEntry()
- {
- // GIVEN
- Manager manager;
- FakeGeneratorPtr generator(FakeGeneratorPtr::create(QStringLiteral("ZR1")));
- FakeAPITexture texture;
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 0);
-
- // WHEN
- manager.requestData(generator, &texture);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 1);
-
- // WHEN
- manager.releaseData(generator, &texture);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 0);
- }
-
- void checkAssignGetData()
- {
- // GIVEN
- Manager manager;
- FakeGeneratorPtr generator(FakeGeneratorPtr::create(QStringLiteral("ZR1")));
- FakeDataPtr data(FakeDataPtr::create(883));
- FakeAPITexture texture;
-
- // WHEN
- manager.assignData(generator, data);
-
- // THEN
- QVERIFY(manager.getData(generator).isNull());
-
- // WHEN
- manager.requestData(generator, &texture);
- manager.assignData(generator, data);
-
- // THEN
- QCOMPARE(data, manager.getData(generator));
- }
-
- void checkPendingGenerators()
- {
- // GIVEN
- Manager manager;
- FakeGeneratorPtr generator(FakeGeneratorPtr::create(QStringLiteral("ZR1")));
- FakeDataPtr data(FakeDataPtr::create(883));
- FakeAPITexture texture;
-
- // WHEN
- manager.requestData(generator, &texture);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 1);
- QCOMPARE(manager.pendingGenerators().first(), generator);
-
- // WHEN
- manager.requestData(generator, &texture);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 1);
- QCOMPARE(manager.pendingGenerators().first(), generator);
-
- // WHEN
- FakeGeneratorPtr generator2(FakeGeneratorPtr::create(QStringLiteral("Z06")));
- FakeAPITexture texture2;
- manager.requestData(generator2, &texture2);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 2);
- QCOMPARE(manager.pendingGenerators().first(), generator);
- QCOMPARE(manager.pendingGenerators().last(), generator2);
-
- // WHEN
- manager.releaseData(generator, &texture);
-
- // THEN
- QCOMPARE(manager.pendingGenerators().size(), 1);
- QCOMPARE(manager.pendingGenerators().first(), generator2);
- }
-};
-
-QTEST_MAIN(tst_TextureDataManager)
-
-#include "tst_texturedatamanager.moc"
diff --git a/tests/auto/render/textures/tst_textures.cpp b/tests/auto/render/textures/tst_textures.cpp
index 41e438d01..555bd09a3 100644
--- a/tests/auto/render/textures/tst_textures.cpp
+++ b/tests/auto/render/textures/tst_textures.cpp
@@ -36,7 +36,6 @@
#include <Qt3DRender/private/renderer_p.h>
#include <Qt3DRender/private/texture_p.h>
#include <Qt3DRender/private/textureimage_p.h>
-#include <Qt3DRender/private/texturedatamanager_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/gltexturemanager_p.h>
@@ -142,6 +141,11 @@ public:
{
}
+ void updateGenerator()
+ {
+ Qt3DRender::QAbstractTextureImage::notifyDataGeneratorChanged();
+ }
+
Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const
{
return Qt3DRender::QTextureImageDataGeneratorPtr(new TestImageDataGenerator(m_genId));
@@ -189,20 +193,20 @@ class tst_RenderTextures : public Qt3DCore::QBackendNodeTester
Qt3DRender::Render::Texture *createBackendTexture(Qt3DRender::QAbstractTexture *frontend,
Qt3DRender::Render::TextureManager *texMgr,
Qt3DRender::Render::TextureImageManager *texImgMgr,
- Qt3DRender::Render::TextureImageDataManager *texImgDataManager)
+ Qt3DRender::Render::AbstractRenderer *renderer)
{
Qt3DRender::Render::Texture *backend = texMgr->getOrCreateResource(frontend->id());
- simulateInitialization(frontend, backend);
+ backend->setRenderer(renderer);
+ simulateInitializationSync(frontend, backend);
// create texture images
for (const auto texImgFrontend : frontend->textureImages()) {
// make sure TextureImageManager has backend node for this QTextureImage
if (!texImgMgr->contains(texImgFrontend->id())) {
Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id());
- texImgBackend->setTextureImageDataManager(texImgDataManager);
- simulateInitialization(texImgFrontend, texImgBackend);
+ texImgBackend->setRenderer(renderer);
+ simulateInitializationSync(texImgFrontend, texImgBackend);
}
- backend->addTextureImage(texImgFrontend->id());
}
return backend;
@@ -212,6 +216,7 @@ private Q_SLOTS:
void shouldCreateSameGLTextures()
{
+ QSKIP("Texture Sharing is now disabled");
QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
renderer.setNodeManagers(mgrs.data());
@@ -224,11 +229,11 @@ private Q_SLOTS:
Qt3DRender::Render::Texture *bt1a = createBackendTexture(tex1a,
mgrs->textureManager(),
mgrs->textureImageManager(),
- mgrs->textureImageDataManager());
+ &renderer);
Qt3DRender::Render::Texture *bt1b = createBackendTexture(tex1b,
mgrs->textureManager(),
mgrs->textureImageManager(),
- mgrs->textureImageDataManager());
+ &renderer);
renderer.updateTexture(bt1a);
renderer.updateTexture(bt1b);
@@ -259,7 +264,7 @@ private Q_SLOTS:
Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t,
mgrs->textureManager(),
mgrs->textureImageManager(),
- mgrs->textureImageDataManager());
+ &renderer);
backend.push_back(backendTexture);
renderer.updateTexture(backendTexture);
}
@@ -309,11 +314,11 @@ private Q_SLOTS:
Qt3DRender::Render::Texture *bt1 = createBackendTexture(tex1a,
mgrs->textureManager(),
mgrs->textureImageManager(),
- mgrs->textureImageDataManager());
+ &renderer);
Qt3DRender::Render::Texture *bt2 = createBackendTexture(tex1b,
mgrs->textureManager(),
mgrs->textureImageManager(),
- mgrs->textureImageDataManager());
+ &renderer);
// THEN
QCOMPARE(bt1->sharedTextureId(), 1);
QCOMPARE(bt2->sharedTextureId(), 1);
@@ -340,11 +345,11 @@ private Q_SLOTS:
Qt3DRender::Render::Texture *bt1 = createBackendTexture(tex1a,
mgrs->textureManager(),
mgrs->textureImageManager(),
- mgrs->textureImageDataManager());
+ &renderer);
Qt3DRender::Render::Texture *bt2 = createBackendTexture(tex1b,
mgrs->textureManager(),
mgrs->textureImageManager(),
- mgrs->textureImageDataManager());
+ &renderer);
// THEN
QCOMPARE(bt1->sharedTextureId(), 1);
QCOMPARE(bt2->sharedTextureId(), 2);
@@ -382,7 +387,7 @@ private Q_SLOTS:
Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t,
mgrs->textureManager(),
mgrs->textureImageManager(),
- mgrs->textureImageDataManager());
+ &renderer);
backend.push_back(backendTexture);
renderer.updateTexture(backendTexture);
}
@@ -406,32 +411,6 @@ private Q_SLOTS:
QVERIFY(!(*idg1a == *idg2));
QCOMPARE(*tg1a, *tg1b);
QVERIFY(!(*tg1a == *tg2));
- Qt3DRender::Render::TextureImageDataManager *imgDataMgr = mgrs->textureImageDataManager();
- Qt3DRender::Render::TextureDataManager *texDataMgr = mgrs->textureDataManager();
- QVERIFY(imgDataMgr->getData(idg1a) == nullptr);
- QVERIFY(imgDataMgr->getData(idg2) == nullptr);
- QVERIFY(texDataMgr->getData(tg1a) == nullptr);
- QVERIFY(texDataMgr->getData(tg2) == nullptr);
-
- // WHEN
- for (const auto gen : imgDataMgr->pendingGenerators())
- imgDataMgr->assignData(gen, (*gen)());
- for (const auto gen : texDataMgr->pendingGenerators())
- texDataMgr->assignData(gen, (*gen)());
-
- // THEN
- QVERIFY(imgDataMgr->getData(idg1a) != nullptr);
- QVERIFY(imgDataMgr->getData(idg1b) != nullptr);
- QVERIFY(imgDataMgr->getData(idg2) != nullptr);
- QVERIFY(texDataMgr->getData(tg1a) != nullptr);
- QVERIFY(texDataMgr->getData(tg1b) != nullptr);
- QVERIFY(texDataMgr->getData(tg2) != nullptr);
-
- QCOMPARE(imgDataMgr->getData(idg1a), imgDataMgr->getData(idg1b));
- QVERIFY(imgDataMgr->getData(idg1a) != imgDataMgr->getData(idg2));
-
- QCOMPARE(texDataMgr->getData(tg1a), texDataMgr->getData(tg1b));
- QVERIFY(texDataMgr->getData(tg1a) != texDataMgr->getData(tg2));
renderer.shutdown();
}
@@ -447,23 +426,20 @@ private Q_SLOTS:
QCOMPARE(img.isDirty(), false);
QCOMPARE(img.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX);
QVERIFY(img.dataGenerator().isNull());
- QVERIFY(img.textureImageDataManager() == nullptr);
}
void checkTextureImageCleanupState()
{
// GIVEN
- QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
- Qt3DRender::Render::TextureImageDataManager *texImgDataMgr = mgrs->textureImageDataManager();
-
+ Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
TestTextureImage img(1);
img.setLayer(2);
img.setMipLevel(3);
// WHEN
Qt3DRender::Render::TextureImage texImgBackend;
- texImgBackend.setTextureImageDataManager(texImgDataMgr);
- simulateInitialization(&img, &texImgBackend);
+ texImgBackend.setRenderer(&renderer);
+ simulateInitializationSync(&img, &texImgBackend);
texImgBackend.cleanup();
// THEN
@@ -472,15 +448,14 @@ private Q_SLOTS:
QCOMPARE(texImgBackend.mipLevel(), 0);
QCOMPARE(texImgBackend.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX);
QVERIFY(texImgBackend.dataGenerator().isNull());
- QVERIFY(texImgBackend.textureImageDataManager() != nullptr);
+
+ renderer.shutdown();
}
void checkTextureImageInitializeFromPeer()
{
// GIVEN
- QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
- Qt3DRender::Render::TextureImageDataManager *texImgDataMgr = mgrs->textureImageDataManager();
-
+ Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
TestTextureImage img(1);
{
@@ -489,8 +464,8 @@ private Q_SLOTS:
img.setMipLevel(3);
Qt3DRender::Render::TextureImage texImgBackend;
- texImgBackend.setTextureImageDataManager(texImgDataMgr);
- simulateInitialization(&img, &texImgBackend);
+ texImgBackend.setRenderer(&renderer);
+ simulateInitializationSync(&img, &texImgBackend);
// THEN
QCOMPARE(texImgBackend.isEnabled(), true);
@@ -507,32 +482,31 @@ private Q_SLOTS:
img.setEnabled(false);
Qt3DRender::Render::TextureImage texImgBackend;
- texImgBackend.setTextureImageDataManager(texImgDataMgr);
- simulateInitialization(&img, &texImgBackend);
+ texImgBackend.setRenderer(&renderer);
+ simulateInitializationSync(&img, &texImgBackend);
// THEN
QCOMPARE(texImgBackend.isEnabled(), false);
QCOMPARE(texImgBackend.peerId(), img.id());
}
+
+ renderer.shutdown();
}
void checkTextureImageSceneChangeEvents()
{
// GIVEN
- QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
- Qt3DRender::Render::TextureImageDataManager *texImgDataMgr = mgrs->textureImageDataManager();
Qt3DRender::Render::TextureImage backendImage;
+ TestTextureImage textureImage(1);
TestRenderer renderer;
backendImage.setRenderer(&renderer);
- backendImage.setTextureImageDataManager(texImgDataMgr);
+ simulateInitializationSync(&textureImage, &backendImage);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendImage.sceneChangeEvent(change);
+ textureImage.setEnabled(newValue);
+ backendImage.syncFromFrontEnd(&textureImage, false);
// THEN
QCOMPARE(backendImage.isEnabled(), newValue);
@@ -545,10 +519,8 @@ private Q_SLOTS:
{
// WHEN
const int newValue = 7;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("layer");
- change->setValue(newValue);
- backendImage.sceneChangeEvent(change);
+ textureImage.setLayer(newValue);
+ backendImage.syncFromFrontEnd(&textureImage, false);
// THEN
QCOMPARE(backendImage.layer(), newValue);
@@ -561,10 +533,9 @@ private Q_SLOTS:
{
// WHEN
const int newValue = 3;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("mipLevel");
- change->setValue(newValue);
- backendImage.sceneChangeEvent(change);
+ textureImage.setMipLevel(newValue);
+ backendImage.syncFromFrontEnd(&textureImage, false);
+
// THEN
QCOMPARE(backendImage.mipLevel(), newValue);
@@ -577,10 +548,8 @@ private Q_SLOTS:
{
// WHEN
const Qt3DRender::QAbstractTexture::CubeMapFace newValue = Qt3DRender::QAbstractTexture::CubeMapNegativeX;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("face");
- change->setValue(newValue);
- backendImage.sceneChangeEvent(change);
+ textureImage.setFace(newValue);
+ backendImage.syncFromFrontEnd(&textureImage, false);
// THEN
QCOMPARE(backendImage.face(), newValue);
@@ -592,46 +561,20 @@ private Q_SLOTS:
{
// WHEN
- Qt3DRender::QTextureImageDataGeneratorPtr generator1(new TestImageDataGenerator(883));
- auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("dataGenerator");
- change->setValue(QVariant::fromValue(generator1));
- backendImage.sceneChangeEvent(change);
-
- // THEN
- QCOMPARE(backendImage.dataGenerator(), generator1);
- QVERIFY(texImgDataMgr->contains(generator1));
- QVERIFY(backendImage.isDirty());
- QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
- renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
- backendImage.unsetDirty();
-
- // WHEN
- Qt3DRender::QTextureImageDataGeneratorPtr generator2(new TestImageDataGenerator(1584));
- change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("dataGenerator");
- change->setValue(QVariant::fromValue(generator2));
- backendImage.sceneChangeEvent(change);
+ textureImage.updateGenerator();
+ backendImage.syncFromFrontEnd(&textureImage, false);
// THEN
- QVERIFY(!texImgDataMgr->contains(generator1));
- QVERIFY(texImgDataMgr->contains(generator2));
QVERIFY(backendImage.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
backendImage.unsetDirty();
// WHEN
- Qt3DRender::QTextureImageDataGeneratorPtr generator3;
- change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("dataGenerator");
- change->setValue(QVariant::fromValue(generator3));
- backendImage.sceneChangeEvent(change);
+ textureImage.updateGenerator();
+ backendImage.syncFromFrontEnd(&textureImage, false);
// THEN
- QVERIFY(!texImgDataMgr->contains(generator1));
- QVERIFY(!texImgDataMgr->contains(generator2));
- QVERIFY(backendImage.dataGenerator().isNull());
QVERIFY(backendImage.isDirty());
QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
@@ -647,14 +590,14 @@ private Q_SLOTS:
Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager();
- Qt3DRender::Render::TextureImageDataManager *texImgDataMgr = mgrs->textureImageDataManager();
renderer.setNodeManagers(mgrs.data());
// GIVEN
Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true);
Qt3DRender::Render::Texture *backendTexture = texMgr->getOrCreateResource(frontendTexture->id());
- simulateInitialization(frontendTexture, backendTexture);
+ backendTexture->setRenderer(&renderer);
+ simulateInitializationSync(frontendTexture, backendTexture);
// THEN
QCOMPARE(backendTexture->textureImageIds().size(), 1);
@@ -666,42 +609,17 @@ private Q_SLOTS:
// THEN
QVERIFY(!frontendGenerator.isNull());
- QCOMPARE(texImgDataMgr->pendingGenerators().size(), 0);
- QVERIFY(!texImgDataMgr->contains(frontendGenerator));
- QVERIFY(texImgDataMgr->getData(frontendGenerator).isNull());
// WHEN
Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id());
- texImgBackend->setTextureImageDataManager(texImgDataMgr);
- simulateInitialization(texImgFrontend, texImgBackend);
+ texImgBackend->setRenderer(&renderer);
+ simulateInitializationSync(texImgFrontend, texImgBackend);
// THEN
qDebug() << frontendGenerator << texImgBackend->dataGenerator();
const Qt3DRender::QTextureImageDataGeneratorPtr backendGenerator = texImgFrontend->dataGenerator();
QVERIFY(frontendGenerator != backendGenerator);
QVERIFY(*frontendGenerator == *backendGenerator);
- QVERIFY(texImgDataMgr->contains(frontendGenerator));
- QVERIFY(texImgDataMgr->contains(backendGenerator));
- QVERIFY(texImgDataMgr->getData(frontendGenerator).isNull());
- QCOMPARE(texImgDataMgr->pendingGenerators().size(), 1);
-
- // WHEN
- texImgDataMgr->assignData(frontendGenerator, (*frontendGenerator)());
-
- // THEN
- QVERIFY(!texImgDataMgr->getData(frontendGenerator).isNull());
- QVERIFY(!texImgDataMgr->getData(backendGenerator).isNull());
- QVERIFY(texImgDataMgr->getData(backendGenerator) == texImgDataMgr->getData(frontendGenerator));
-
- // WHEN
- texImgBackend->cleanup();
-
- // THEN
- QVERIFY(!texImgDataMgr->contains(frontendGenerator));
- QVERIFY(!texImgDataMgr->contains(backendGenerator));
- QCOMPARE(texImgDataMgr->pendingGenerators().size(), 0);
- QVERIFY(texImgDataMgr->getData(frontendGenerator).isNull());
- QVERIFY(texImgDataMgr->getData(backendGenerator).isNull());
renderer.shutdown();
}
@@ -720,7 +638,8 @@ private Q_SLOTS:
Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true);
Qt3DRender::Render::Texture *backendTexture = static_cast<Qt3DRender::Render::Texture *>(textureBackendNodeMapper.create(creationChange(frontendTexture)));
- simulateInitialization(frontendTexture, backendTexture);
+ backendTexture->setRenderer(&renderer);
+ simulateInitializationSync(frontendTexture, backendTexture);
// THEN
QVERIFY(backendTexture != nullptr);
@@ -753,7 +672,8 @@ private Q_SLOTS:
Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true);
Qt3DRender::Render::Texture *backendTexture = static_cast<Qt3DRender::Render::Texture *>(textureBackendNodeMapper.create(creationChange(frontendTexture)));
- simulateInitialization(frontendTexture, backendTexture);
+ backendTexture->setRenderer(&renderer);
+ simulateInitializationSync(frontendTexture, backendTexture);
// WHEN
textureBackendNodeMapper.destroy(frontendTexture->id());
@@ -765,7 +685,8 @@ private Q_SLOTS:
// WHEN
backendTexture = static_cast<Qt3DRender::Render::Texture *>(textureBackendNodeMapper.create(creationChange(frontendTexture)));
- simulateInitialization(frontendTexture, backendTexture);
+ backendTexture->setRenderer(&renderer);
+ simulateInitializationSync(frontendTexture, backendTexture);
// THEN
QVERIFY(backendTexture != nullptr);
@@ -785,10 +706,10 @@ private Q_SLOTS:
renderer.setNodeManagers(mgrs.data());
Qt3DRender::QTexture2D *texture1 = new Qt3DRender::QTexture2D();
- Qt3DRender::QAbstractTextureImage *image1 = new EmptyTextureImage();
+ TestTextureImage *image1 = new TestTextureImage(1);
Qt3DRender::QTexture2D *texture2 = new Qt3DRender::QTexture2D();
- Qt3DRender::QAbstractTextureImage *image2 = new EmptyTextureImage();
+ TestTextureImage *image2 = new TestTextureImage(2);
Qt3DRender::QTexture2D *texture3 = new Qt3DRender::QTexture2D();
@@ -803,18 +724,17 @@ private Q_SLOTS:
Qt3DRender::Render::TextureImage *backendImage1 = texImgMgr->getOrCreateResource(image1->id());
Qt3DRender::Render::TextureImage *backendImage2 = texImgMgr->getOrCreateResource(image2->id());
- simulateInitialization(texture1, backendTexture1);
- simulateInitialization(texture2, backendTexture2);
- simulateInitialization(texture3, backendTexture3);
- simulateInitialization(image1, backendImage1);
- simulateInitialization(image2, backendImage2);
-
backendTexture1->setRenderer(&renderer);
backendTexture2->setRenderer(&renderer);
backendTexture3->setRenderer(&renderer);
backendImage1->setRenderer(&renderer);
backendImage2->setRenderer(&renderer);
+ simulateInitializationSync(texture1, backendTexture1);
+ simulateInitializationSync(texture2, backendTexture2);
+ simulateInitializationSync(texture3, backendTexture3);
+ simulateInitializationSync(image1, backendImage1);
+ simulateInitializationSync(image2, backendImage2);
// THEN
QCOMPARE(backendTexture1->textureImageIds().size(), 1);
@@ -847,9 +767,8 @@ private Q_SLOTS:
// WHEN
// Make Image1 dirty
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("dataGenerator");
- backendImage1->sceneChangeEvent(change);
+ image1->updateGenerator();
+ backendImage1->syncFromFrontEnd(image1, false);
// THEN
QVERIFY(backendImage1->isDirty());
@@ -870,7 +789,8 @@ private Q_SLOTS:
backendTexture3->unsetDirty();
// WHEN
- backendImage2->sceneChangeEvent(change);
+ image2->updateGenerator();
+ backendImage2->syncFromFrontEnd(image2, false);
// THEN
QVERIFY(backendImage2->isDirty());
diff --git a/tests/auto/render/transform/tst_transform.cpp b/tests/auto/render/transform/tst_transform.cpp
index 151baff76..a3fcdb9c8 100644
--- a/tests/auto/render/transform/tst_transform.cpp
+++ b/tests/auto/render/transform/tst_transform.cpp
@@ -31,9 +31,11 @@
#include <Qt3DCore/qtransform.h>
#include <Qt3DCore/private/qtransform_p.h>
#include <Qt3DRender/private/transform_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DRender/private/updateworldtransformjob_p.h>
+#include <private/qbackendnode_p.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
+#include "testpostmanarbiter.h"
class tst_Transform : public Qt3DCore::QBackendNodeTester
{
@@ -55,7 +57,9 @@ private Q_SLOTS:
void checkCleanupState()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::Render::Transform backendTransform;
+ backendTransform.setRenderer(&renderer);
// WHEN
{
@@ -63,7 +67,8 @@ private Q_SLOTS:
transform.setScale3D(QVector3D(1.0f, 2.0f, 3.0f));
transform.setTranslation(QVector3D(-1.0, 5.0f, -2.0f));
transform.setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1.0f, 0.0f, 0.0), 30.0f));
- simulateInitialization(&transform, &backendTransform);
+ backendTransform.setRenderer(&renderer);
+ simulateInitializationSync(&transform, &backendTransform);
}
backendTransform.setEnabled(true);
@@ -80,6 +85,7 @@ private Q_SLOTS:
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DCore::QTransform transform;
transform.setScale3D(QVector3D(1.0f, 2.0f, 3.0f));
transform.setTranslation(QVector3D(-1.0, 5.0f, -2.0f));
@@ -88,7 +94,10 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::Transform backendTransform;
- simulateInitialization(&transform, &backendTransform);
+ backendTransform.setRenderer(&renderer);
+ TestRenderer renderer;
+ backendTransform.setRenderer(&renderer);
+ simulateInitializationSync(&transform, &backendTransform);
// THEN
QCOMPARE(backendTransform.isEnabled(), true);
@@ -97,33 +106,39 @@ private Q_SLOTS:
QCOMPARE(backendTransform.rotation(), transform.rotation());
QCOMPARE(backendTransform.scale(), transform.scale3D());
QCOMPARE(backendTransform.translation(), transform.translation());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty);
}
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
Qt3DRender::Render::Transform backendTransform;
+ TestRenderer renderer;
+ backendTransform.setRenderer(&renderer);
transform.setEnabled(false);
- simulateInitialization(&transform, &backendTransform);
+ simulateInitializationSync(&transform, &backendTransform);
// THEN
QCOMPARE(backendTransform.peerId(), transform.id());
QCOMPARE(backendTransform.isEnabled(), false);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TransformDirty);
}
}
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DCore::QTransform frontendTranform;
Qt3DRender::Render::Transform backendTransform;
TestRenderer renderer;
backendTransform.setRenderer(&renderer);
+ backendTransform.syncFromFrontEnd(&frontendTranform, true);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendTransform.sceneChangeEvent(change);
+ frontendTranform.setEnabled(newValue);
+ backendTransform.syncFromFrontEnd(&frontendTranform, false);
// THEN
QCOMPARE(backendTransform.isEnabled(), newValue);
@@ -133,10 +148,8 @@ private Q_SLOTS:
{
// WHEN
const QQuaternion newValue = QQuaternion::fromAxisAndAngle(QVector3D(0.0f, 1.0f, 0.0f), 45.0f);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("rotation");
- change->setValue(QVariant::fromValue(newValue));
- backendTransform.sceneChangeEvent(change);
+ frontendTranform.setRotation(newValue);
+ backendTransform.syncFromFrontEnd(&frontendTranform, false);
// THEN
QCOMPARE(backendTransform.rotation(), newValue);
@@ -146,10 +159,8 @@ private Q_SLOTS:
{
// WHEN
const QVector3D newValue(454.0f, 355.0f, 0.0f);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("scale3D");
- change->setValue(QVariant::fromValue(newValue));
- backendTransform.sceneChangeEvent(change);
+ frontendTranform.setScale3D(newValue);
+ backendTransform.syncFromFrontEnd(&frontendTranform, false);
// THEN
QCOMPARE(backendTransform.scale(), newValue);
@@ -159,10 +170,8 @@ private Q_SLOTS:
{
// WHEN
const QVector3D newValue(383.0f, 0.0f, 427.0f);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("translation");
- change->setValue(QVariant::fromValue(newValue));
- backendTransform.sceneChangeEvent(change);
+ frontendTranform.setTranslation(newValue);
+ backendTransform.syncFromFrontEnd(&frontendTranform, false);
// THEN
QCOMPARE(backendTransform.translation(), newValue);
@@ -170,7 +179,6 @@ private Q_SLOTS:
renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
}
}
-
};
QTEST_MAIN(tst_Transform)
diff --git a/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp b/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp
index fa1cdd0de..287a17b84 100644
--- a/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp
+++ b/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp
@@ -46,7 +46,7 @@
#include <Qt3DRender/qgeometry.h>
#include <Qt3DRender/qgeometryrenderer.h>
#include <Qt3DCore/private/qnodevisitor_p.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qnode_p.h>
Qt3DRender::QGeometryRenderer *customIndexedGeometryRenderer()
{
@@ -95,7 +95,7 @@ Qt3DRender::QGeometryRenderer *customIndexedGeometryRenderer()
QVector3D blue(0.0f, 0.0f, 1.0f);
QVector3D white(1.0f, 1.0f, 1.0f);
- QVector<QVector3D> vertices = QVector<QVector3D>()
+ const QVector<QVector3D> vertices = QVector<QVector3D>()
<< v0 << n0 << red
<< v1 << n1 << blue
<< v2 << n2 << green
@@ -104,7 +104,7 @@ Qt3DRender::QGeometryRenderer *customIndexedGeometryRenderer()
float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
int idx = 0;
- Q_FOREACH (const QVector3D &v, vertices) {
+ for (const QVector3D &v : vertices) {
rawVertexArray[idx++] = v.x();
rawVertexArray[idx++] = v.y();
rawVertexArray[idx++] = v.z();
@@ -237,7 +237,7 @@ Qt3DRender::QGeometryRenderer *customNonIndexedGeometryRenderer()
QVector3D blue(0.0f, 0.0f, 1.0f);
QVector3D white(1.0f, 1.0f, 1.0f);
- QVector<QVector3D> vertices = QVector<QVector3D>()
+ const QVector<QVector3D> vertices = QVector<QVector3D>()
<< v0 << n0 << red
<< v1 << n1 << blue
<< v2 << n2 << green
@@ -258,7 +258,7 @@ Qt3DRender::QGeometryRenderer *customNonIndexedGeometryRenderer()
float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
int idx = 0;
- Q_FOREACH (const QVector3D &v, vertices) {
+ for (const QVector3D &v : vertices) {
rawVertexArray[idx++] = v.x();
rawVertexArray[idx++] = v.y();
rawVertexArray[idx++] = v.z();
@@ -320,19 +320,37 @@ public:
TestAspect(Qt3DCore::QNode *root)
: Qt3DRender::QRenderAspect()
{
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- for (const Qt3DCore::QNodeCreatedChangeBasePtr change : creationChanges)
- d_func()->createBackendNode(change);
+ QVector<Qt3DCore::NodeTreeChange> nodes;
+ Qt3DCore::QNodeVisitor v;
+ v.traverse(root, [&nodes](Qt3DCore::QNode *node) {
+ Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject()));
+ d->m_hasBackendNode = true;
+ nodes.push_back({
+ node->id(),
+ Qt3DCore::QNodePrivate::get(node)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ node
+ });
+ });
+
+ for (const auto &node: nodes)
+ d_func()->createBackendNode(node);
}
+ ~TestAspect();
+
Qt3DRender::Render::NodeManagers *nodeManagers() const
{
return d_func()->m_renderer->nodeManagers();
}
};
+TestAspect::~TestAspect()
+{
+
+}
+
QT_END_NAMESPACE
class tst_TrianglesExtractor : public QObject
diff --git a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp
index 4205d598e..8dfda0eea 100644
--- a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp
+++ b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp
@@ -187,7 +187,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -204,16 +204,16 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -262,7 +262,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
indexData.resize(sizeof(uint) * 3 * 5);
@@ -287,7 +287,7 @@ private Q_SLOTS:
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
backendIndexBuffer->setRenderer(&renderer);
backendIndexBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+ simulateInitializationSync(indexDataBuffer.data(), backendIndexBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -311,20 +311,20 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
backendIndexAttribute->setRenderer(&renderer);
- simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+ simulateInitializationSync(indexAttribute.data(), backendIndexAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -374,7 +374,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -391,16 +391,16 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -451,7 +451,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
indexData.resize(sizeof(uint) * 3 * 4);
@@ -473,7 +473,7 @@ private Q_SLOTS:
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
backendIndexBuffer->setRenderer(&renderer);
backendIndexBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+ simulateInitializationSync(indexDataBuffer.data(), backendIndexBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -497,20 +497,20 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
backendIndexAttribute->setRenderer(&renderer);
- simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+ simulateInitializationSync(indexAttribute.data(), backendIndexAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -563,7 +563,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -580,16 +580,16 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -640,7 +640,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
indexData.resize(sizeof(uint) * 3 * 2);
@@ -656,7 +656,7 @@ private Q_SLOTS:
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
backendIndexBuffer->setRenderer(&renderer);
backendIndexBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+ simulateInitializationSync(indexDataBuffer.data(), backendIndexBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -680,20 +680,20 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
backendIndexAttribute->setRenderer(&renderer);
- simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+ simulateInitializationSync(indexAttribute.data(), backendIndexAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -742,7 +742,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -759,16 +759,16 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -816,7 +816,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
indexData.resize(sizeof(uint) * 3 * 4);
@@ -839,7 +839,7 @@ private Q_SLOTS:
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
backendIndexBuffer->setRenderer(&renderer);
backendIndexBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+ simulateInitializationSync(indexDataBuffer.data(), backendIndexBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -863,20 +863,20 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
backendIndexAttribute->setRenderer(&renderer);
- simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+ simulateInitializationSync(indexAttribute.data(), backendIndexAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -936,7 +936,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -953,16 +953,16 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
@@ -1012,7 +1012,7 @@ private Q_SLOTS:
Buffer *backendBuffer = nodeManagers->bufferManager()->getOrCreateResource(dataBuffer->id());
backendBuffer->setRenderer(&renderer);
backendBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(dataBuffer.data(), backendBuffer);
+ simulateInitializationSync(dataBuffer.data(), backendBuffer);
QByteArray indexData;
indexData.resize(sizeof(uint) * 8);
@@ -1030,7 +1030,7 @@ private Q_SLOTS:
Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id());
backendIndexBuffer->setRenderer(&renderer);
backendIndexBuffer->setManager(nodeManagers->bufferManager());
- simulateInitialization(indexDataBuffer.data(), backendIndexBuffer);
+ simulateInitializationSync(indexDataBuffer.data(), backendIndexBuffer);
positionAttribute->setBuffer(dataBuffer.data());
positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
@@ -1054,20 +1054,20 @@ private Q_SLOTS:
Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id());
backendAttribute->setRenderer(&renderer);
- simulateInitialization(positionAttribute.data(), backendAttribute);
+ simulateInitializationSync(positionAttribute.data(), backendAttribute);
Attribute *backendIndexAttribute = nodeManagers->attributeManager()->getOrCreateResource(indexAttribute->id());
backendIndexAttribute->setRenderer(&renderer);
- simulateInitialization(indexAttribute.data(), backendIndexAttribute);
+ simulateInitializationSync(indexAttribute.data(), backendIndexAttribute);
Geometry *backendGeometry = nodeManagers->geometryManager()->getOrCreateResource(geometry->id());
backendGeometry->setRenderer(&renderer);
- simulateInitialization(geometry, backendGeometry);
+ simulateInitializationSync(geometry, backendGeometry);
GeometryRenderer *backendRenderer = nodeManagers->geometryRendererManager()->getOrCreateResource(geometryRenderer->id());
backendRenderer->setRenderer(&renderer);
backendRenderer->setManager(nodeManagers->geometryRendererManager());
- simulateInitialization(geometryRenderer.data(), backendRenderer);
+ simulateInitializationSync(geometryRenderer.data(), backendRenderer);
// WHEN
visitor.apply(backendRenderer, Qt3DCore::QNodeId());
diff --git a/tests/auto/render/uniform/tst_uniform.cpp b/tests/auto/render/uniform/tst_uniform.cpp
index 5f946afa3..d7775eb62 100644
--- a/tests/auto/render/uniform/tst_uniform.cpp
+++ b/tests/auto/render/uniform/tst_uniform.cpp
@@ -112,7 +112,7 @@ private Q_SLOTS:
QCOMPARE(v.constData<float>()[0], 572.0f);
QCOMPARE(v.constData<float>()[1], 355.0f);
QCOMPARE(v.constData<float>()[2], 383.0f);
- QCOMPARE(v.constData<float>()[4], 0.0f);
+ QCOMPARE(v.constData<float>()[3], 0.0f);
}
{
// GIVEN
diff --git a/tests/auto/render/updatemeshtrianglelistjob/tst_updatemeshtrianglelistjob.cpp b/tests/auto/render/updatemeshtrianglelistjob/tst_updatemeshtrianglelistjob.cpp
index f3fc2ad9b..ae2218739 100644
--- a/tests/auto/render/updatemeshtrianglelistjob/tst_updatemeshtrianglelistjob.cpp
+++ b/tests/auto/render/updatemeshtrianglelistjob/tst_updatemeshtrianglelistjob.cpp
@@ -36,14 +36,54 @@
#include <Qt3DRender/private/loadgeometryjob_p.h>
#include <Qt3DRender/qrenderaspect.h>
#include <Qt3DRender/private/qrenderaspect_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
#include "qmlscenereader.h"
QT_BEGIN_NAMESPACE
namespace Qt3DRender { // Needs to be in that namespace to be friend with QRenderAspect
+QVector<Qt3DCore::QNode *> getNodesForCreation(Qt3DCore::QNode *root)
+{
+ using namespace Qt3DCore;
+
+ QVector<QNode *> nodes;
+ Qt3DCore::QNodeVisitor visitor;
+ visitor.traverse(root, [&nodes](QNode *node) {
+ nodes.append(node);
+
+ // Store the metaobject of the node in the QNode so that we have it available
+ // to us during destruction in the QNode destructor. This allows us to send
+ // the QNodeId and the metaobject as typeinfo to the backend aspects so they
+ // in turn can find the correct QBackendNodeMapper object to handle the destruction
+ // of the corresponding backend nodes.
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(QNodePrivate::findStaticMetaObject(node->metaObject()));
+
+ // Mark this node as having been handled for creation so that it is picked up
+ d->m_hasBackendNode = true;
+ });
+
+ return nodes;
+}
+
+QVector<Qt3DCore::NodeTreeChange> nodeTreeChangesForNodes(const QVector<Qt3DCore::QNode *> nodes)
+{
+ QVector<Qt3DCore::NodeTreeChange> nodeTreeChanges;
+ nodeTreeChanges.reserve(nodes.size());
+
+ for (Qt3DCore::QNode *n : nodes) {
+ nodeTreeChanges.push_back({
+ n->id(),
+ Qt3DCore::QNodePrivate::get(n)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ n
+ });
+ }
+
+ return nodeTreeChanges;
+}
+
class TestAspect : public Qt3DRender::QRenderAspect
{
public:
@@ -53,10 +93,8 @@ public:
{
Qt3DRender::QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), creationChanges);
+ const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root);
+ d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), nodeTreeChangesForNodes(nodes));
Qt3DRender::Render::Entity *rootEntity = nodeManagers()->lookupResource<Qt3DRender::Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
diff --git a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp
index e38d6ba08..b2d0b612c 100644
--- a/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp
+++ b/tests/auto/render/updateshaderdatatransformjob/tst_updateshaderdatatransformjob.cpp
@@ -29,7 +29,6 @@
#include <QtTest/QTest>
#include <Qt3DRender/private/updateshaderdatatransformjob_p.h>
#include <Qt3DRender/private/updateworldtransformjob_p.h>
-#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/qrenderaspect.h>
@@ -39,12 +38,54 @@
#include <Qt3DRender/private/shaderdata_p.h>
#include <Qt3DRender/private/qrenderaspect_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
#include "qmlscenereader.h"
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+QVector<Qt3DCore::QNode *> getNodesForCreation(Qt3DCore::QNode *root)
+{
+ using namespace Qt3DCore;
+
+ QVector<QNode *> nodes;
+ Qt3DCore::QNodeVisitor visitor;
+ visitor.traverse(root, [&nodes](QNode *node) {
+ nodes.append(node);
+
+ // Store the metaobject of the node in the QNode so that we have it available
+ // to us during destruction in the QNode destructor. This allows us to send
+ // the QNodeId and the metaobject as typeinfo to the backend aspects so they
+ // in turn can find the correct QBackendNodeMapper object to handle the destruction
+ // of the corresponding backend nodes.
+ QNodePrivate *d = QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(QNodePrivate::findStaticMetaObject(node->metaObject()));
+
+ // Mark this node as having been handled for creation so that it is picked up
+ d->m_hasBackendNode = true;
+ });
+
+ return nodes;
+}
+
+QVector<Qt3DCore::NodeTreeChange> nodeTreeChangesForNodes(const QVector<Qt3DCore::QNode *> nodes)
+{
+ QVector<Qt3DCore::NodeTreeChange> nodeTreeChanges;
+ nodeTreeChanges.reserve(nodes.size());
+
+ for (Qt3DCore::QNode *n : nodes) {
+ nodeTreeChanges.push_back({
+ n->id(),
+ Qt3DCore::QNodePrivate::get(n)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ n
+ });
+ }
+
+ return nodeTreeChanges;
+}
+
class TestAspect : public Qt3DRender::QRenderAspect
{
public:
@@ -54,10 +95,8 @@ public:
{
Qt3DRender::QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), creationChanges);
+ const QVector<Qt3DCore::QNode *> nodes = getNodesForCreation(root);
+ d_func()->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(root), nodeTreeChangesForNodes(nodes));
Qt3DRender::Render::Entity *rootEntity = nodeManagers()->lookupResource<Qt3DRender::Render::Entity, Render::EntityManager>(rootEntityId());
Q_ASSERT(rootEntity);
@@ -89,10 +128,6 @@ namespace {
void runRequiredJobs(Qt3DRender::TestAspect *test)
{
- Qt3DRender::Render::UpdateEntityHierarchyJob updateEntitiesJob;
- updateEntitiesJob.setManager(test->nodeManagers());
- updateEntitiesJob.run();
-
Qt3DRender::Render::UpdateWorldTransformJob updateWorldTransform;
updateWorldTransform.setRoot(test->sceneRoot());
updateWorldTransform.setManagers(test->nodeManagers());
@@ -172,11 +207,11 @@ private Q_SLOTS:
// THEN
QCOMPARE(backendShaderData->properties().size(), 3);
- QVERIFY(backendShaderData->properties().contains(QLatin1String("eyePosition")));
- QVERIFY(backendShaderData->properties().contains(QLatin1String("eyePositionTransformed")));
+ QVERIFY(backendShaderData->properties().contains(QStringLiteral("eyePosition")));
+ QVERIFY(backendShaderData->properties().contains(QStringLiteral("eyePositionTransformed")));
- QCOMPARE(backendShaderData->properties()[QLatin1String("eyePosition")].value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f));
- QCOMPARE(backendShaderData->properties()[QLatin1String("eyePositionTransformed")].toInt(), int(Qt3DRender::Render::ShaderData::ModelToEye));
+ QCOMPARE(backendShaderData->properties()[QStringLiteral("eyePosition")].value.value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f));
+ QCOMPARE(backendShaderData->properties()[QStringLiteral("eyePositionTransformed")].value.toInt(), int(Qt3DRender::Render::ShaderData::ModelToEye));
// WHEN
Qt3DRender::Render::UpdateShaderDataTransformJob backendUpdateShaderDataTransformJob;
@@ -185,7 +220,7 @@ private Q_SLOTS:
// THEN
// See scene file to find translation
- QCOMPARE(backendShaderData->getTransformedProperty(QLatin1String("eyePosition"), Matrix4x4(camera->viewMatrix())).value<Vector3D>(),
+ QCOMPARE(backendShaderData->getTransformedProperty(QStringLiteral("eyePosition"), Matrix4x4(camera->viewMatrix())).value<Vector3D>(),
Matrix4x4(camera->viewMatrix()) * (Vector3D(1.0f, 1.0f, 1.0f) + Vector3D(0.0f, 5.0f, 0.0f)));
}
@@ -213,11 +248,11 @@ private Q_SLOTS:
// THEN
QCOMPARE(backendShaderData->properties().size(), 3);
- QVERIFY(backendShaderData->properties().contains(QLatin1String("position")));
- QVERIFY(backendShaderData->properties().contains(QLatin1String("positionTransformed")));
+ QVERIFY(backendShaderData->properties().contains(QStringLiteral("position")));
+ QVERIFY(backendShaderData->properties().contains(QStringLiteral("positionTransformed")));
- QCOMPARE(backendShaderData->properties()[QLatin1String("position")].value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f));
- QCOMPARE(backendShaderData->properties()[QLatin1String("positionTransformed")].toInt(), int(Qt3DRender::Render::ShaderData::ModelToWorld));
+ QCOMPARE(backendShaderData->properties()[QStringLiteral("position")].value.value<QVector3D>(), QVector3D(1.0f, 1.0f, 1.0f));
+ QCOMPARE(backendShaderData->properties()[QStringLiteral("positionTransformed")].value.toInt(), int(Qt3DRender::Render::ShaderData::ModelToWorld));
// WHEN
Qt3DRender::Render::UpdateShaderDataTransformJob backendUpdateShaderDataTransformJob;
@@ -226,7 +261,7 @@ private Q_SLOTS:
// THEN
// See scene file to find translation
- QCOMPARE(backendShaderData->getTransformedProperty(QLatin1String("position"), Matrix4x4(camera->viewMatrix())).value<Vector3D>(),
+ QCOMPARE(backendShaderData->getTransformedProperty(QStringLiteral("position"), Matrix4x4(camera->viewMatrix())).value<Vector3D>(),
Vector3D(1.0f, 1.0f, 1.0f) + Vector3D(5.0f, 5.0f, 5.0f));
}
};
diff --git a/tests/auto/render/waitfence/tst_waitfence.cpp b/tests/auto/render/waitfence/tst_waitfence.cpp
index 8141fbb1c..26f473f45 100644
--- a/tests/auto/render/waitfence/tst_waitfence.cpp
+++ b/tests/auto/render/waitfence/tst_waitfence.cpp
@@ -43,7 +43,6 @@
#include <Qt3DRender/qwaitfence.h>
#include <Qt3DRender/private/qwaitfence_p.h>
#include <Qt3DRender/private/waitfence_p.h>
-#include <Qt3DCore/qpropertyupdatedchange.h>
#include "qbackendnodetester.h"
#include "testrenderer.h"
@@ -71,6 +70,7 @@ private Q_SLOTS:
void checkInitializeFromPeer()
{
// GIVEN
+ TestRenderer renderer;
Qt3DRender::QWaitFence waitFence;
waitFence.setHandle(QVariant(883));
waitFence.setWaitOnCPU(true);
@@ -80,7 +80,8 @@ private Q_SLOTS:
{
// WHEN
Qt3DRender::Render::WaitFence backendWaitFence;
- simulateInitialization(&waitFence, &backendWaitFence);
+ backendWaitFence.setRenderer(&renderer);
+ simulateInitializationSync(&waitFence, &backendWaitFence);
// THEN
QCOMPARE(backendWaitFence.isEnabled(), true);
@@ -89,12 +90,15 @@ private Q_SLOTS:
QCOMPARE(backendWaitFence.data().handle, QVariant(883));
QCOMPARE(backendWaitFence.data().waitOnCPU, true);
QCOMPARE(backendWaitFence.data().timeout, quint64(8));
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
{
// WHEN
Qt3DRender::Render::WaitFence backendWaitFence;
waitFence.setEnabled(false);
- simulateInitialization(&waitFence, &backendWaitFence);
+ backendWaitFence.setRenderer(&renderer);
+ simulateInitializationSync(&waitFence, &backendWaitFence);
// THEN
QCOMPARE(backendWaitFence.peerId(), waitFence.id());
@@ -103,23 +107,24 @@ private Q_SLOTS:
QCOMPARE(backendWaitFence.data().handle, QVariant(883));
QCOMPARE(backendWaitFence.data().waitOnCPU, true);
QCOMPARE(backendWaitFence.data().timeout, quint64(8));
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::FrameGraphDirty);
}
}
void checkSceneChangeEvents()
{
// GIVEN
+ Qt3DRender::QWaitFence waitFence;
Qt3DRender::Render::WaitFence backendWaitFence;
TestRenderer renderer;
backendWaitFence.setRenderer(&renderer);
+ simulateInitializationSync(&waitFence, &backendWaitFence);
{
// WHEN
const bool newValue = false;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("enabled");
- change->setValue(newValue);
- backendWaitFence.sceneChangeEvent(change);
+ waitFence.setEnabled(newValue);
+ backendWaitFence.syncFromFrontEnd(&waitFence, false);
// THEN
QCOMPARE(backendWaitFence.isEnabled(), newValue);
@@ -129,10 +134,8 @@ private Q_SLOTS:
{
// WHEN
const QVariant newValue(984);
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("handle");
- change->setValue(QVariant::fromValue(newValue));
- backendWaitFence.sceneChangeEvent(change);
+ waitFence.setHandle(newValue);
+ backendWaitFence.syncFromFrontEnd(&waitFence, false);
// THEN
QCOMPARE(backendWaitFence.data().handle, QVariant(984));
@@ -142,10 +145,8 @@ private Q_SLOTS:
{
// WHEN
const Qt3DRender::QWaitFence::HandleType newValue = Qt3DRender::QWaitFence::OpenGLFenceId;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("handleType");
- change->setValue(QVariant::fromValue(newValue));
- backendWaitFence.sceneChangeEvent(change);
+ waitFence.setHandleType(newValue);
+ backendWaitFence.syncFromFrontEnd(&waitFence, false);
// THEN
QCOMPARE(backendWaitFence.data().handleType, Qt3DRender::QWaitFence::OpenGLFenceId);
@@ -155,10 +156,8 @@ private Q_SLOTS:
{
// WHEN
const bool newValue = true;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("waitOnCPU");
- change->setValue(QVariant::fromValue(newValue));
- backendWaitFence.sceneChangeEvent(change);
+ waitFence.setWaitOnCPU(newValue);
+ backendWaitFence.syncFromFrontEnd(&waitFence, false);
// THEN
QCOMPARE(backendWaitFence.data().waitOnCPU, true);
@@ -168,10 +167,8 @@ private Q_SLOTS:
{
// WHEN
const quint64 newValue = 984;
- const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- change->setPropertyName("timeout");
- change->setValue(QVariant::fromValue(newValue));
- backendWaitFence.sceneChangeEvent(change);
+ waitFence.setTimeout(newValue);
+ backendWaitFence.syncFromFrontEnd(&waitFence, false);
// THEN
QCOMPARE(backendWaitFence.data().timeout, quint64(984));
diff --git a/tests/benchmarks/core/qframeallocator/tst_bench_qframeallocator.cpp b/tests/benchmarks/core/qframeallocator/tst_bench_qframeallocator.cpp
index 91b8f887d..d6aca6219 100644
--- a/tests/benchmarks/core/qframeallocator/tst_bench_qframeallocator.cpp
+++ b/tests/benchmarks/core/qframeallocator/tst_bench_qframeallocator.cpp
@@ -62,7 +62,7 @@ void benchmarkAlloc()
items[i] = allocator.allocate< Object<Size> >();
}
}
- foreach (Object<Size>* item, items) {
+ for (Object<Size>* item : qAsConst(items)) {
allocator.deallocate(item);
}
}
@@ -76,7 +76,7 @@ void benchmarkDealloc()
items[i] = allocator.allocate< Object<Size> >();
}
QBENCHMARK_ONCE {
- foreach (Object<Size>* item, items) {
+ for (Object<Size>* item : qAsConst(items)) {
allocator.deallocate(item);
}
}
diff --git a/tests/benchmarks/core/qresourcesmanager/arraypolicy/tst_bench_arraypolicy.cpp b/tests/benchmarks/core/qresourcesmanager/arraypolicy/tst_bench_arraypolicy.cpp
index 0813fff91..870a256c9 100644
--- a/tests/benchmarks/core/qresourcesmanager/arraypolicy/tst_bench_arraypolicy.cpp
+++ b/tests/benchmarks/core/qresourcesmanager/arraypolicy/tst_bench_arraypolicy.cpp
@@ -75,7 +75,7 @@ void benchmarkReleaseResources()
}
QBENCHMARK_ONCE {
- foreach (auto ptr, resources) {
+ for (auto ptr : qAsConst(resources)) {
allocator.releaseResource(ptr);
}
}
diff --git a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp
index 454cb9f6a..b611f3cdc 100644
--- a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp
+++ b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp
@@ -48,9 +48,8 @@
#include <Qt3DCore/private/qaspectjobmanager_p.h>
#include <Qt3DCore/private/qaspectengine_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
-#include <Qt3DCore/private/qaspectthread_p.h>
#include <Qt3DCore/private/qnodevisitor_p.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <Qt3DCore/private/qnode_p.h>
#include <QQmlComponent>
#include <QScopedPointer>
@@ -124,11 +123,22 @@ namespace Qt3DRender {
void onRootEntityChanged(Qt3DCore::QEntity *root)
{
if (!m_window) {
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- for (const Qt3DCore::QNodeCreatedChangeBasePtr change : creationChanges)
- d_func()->createBackendNode(change);
+ QVector<Qt3DCore::NodeTreeChange> nodes;
+ Qt3DCore::QNodeVisitor v;
+ v.traverse(root, [&nodes](Qt3DCore::QNode *node) {
+ Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject()));
+ d->m_hasBackendNode = true;
+ nodes.push_back({
+ node->id(),
+ Qt3DCore::QNodePrivate::get(node)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ node
+ });
+ });
+
+ for (const auto &node: nodes)
+ d_func()->createBackendNode(node);
static_cast<Qt3DRender::Render::Renderer *>(d_func()->m_renderer)->m_renderSceneRoot =
d_func()->m_renderer->nodeManagers()
@@ -241,8 +251,7 @@ private Q_SLOTS:
QFETCH(Qt3DCore::QEntity*, rootEntity);
QRenderAspectTester aspect;
- Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity),
- QVector<Qt3DCore::QNodeCreatedChangeBasePtr>());
+ Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity), {});
// WHEN
QVector<Qt3DCore::QAspectJobPtr> jobs = aspect.worldTransformJob();
@@ -265,8 +274,7 @@ private Q_SLOTS:
QFETCH(Qt3DCore::QEntity*, rootEntity);
QRenderAspectTester aspect;
- Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity),
- QVector<Qt3DCore::QNodeCreatedChangeBasePtr>());
+ Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity), {});
// WHEN
QVector<Qt3DCore::QAspectJobPtr> jobs = aspect.updateBoundingJob();
@@ -289,8 +297,7 @@ private Q_SLOTS:
QFETCH(Qt3DCore::QEntity*, rootEntity);
QRenderAspectTester aspect;
- Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity),
- QVector<Qt3DCore::QNodeCreatedChangeBasePtr>());
+ Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity), {});
// WHEN
QVector<Qt3DCore::QAspectJobPtr> jobs = aspect.calculateBoundingVolumeJob();
@@ -313,8 +320,7 @@ private Q_SLOTS:
QFETCH(Qt3DCore::QEntity*, rootEntity);
QRenderAspectTester aspect;
- Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity),
- QVector<Qt3DCore::QNodeCreatedChangeBasePtr>());
+ Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity), {});
// WHEN
QVector<Qt3DCore::QAspectJobPtr> jobs = aspect.framePreparationJob();
@@ -337,8 +343,7 @@ private Q_SLOTS:
QFETCH(Qt3DCore::QEntity*, rootEntity);
QRenderAspectTester aspect;
- Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity),
- QVector<Qt3DCore::QNodeCreatedChangeBasePtr>());
+ Qt3DCore::QAbstractAspectPrivate::get(&aspect)->setRootAndCreateNodes(qobject_cast<Qt3DCore::QEntity *>(rootEntity), {});
// WHEN
QVector<Qt3DCore::QAspectJobPtr> jobs = aspect.frameCleanupJob();
diff --git a/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp b/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp
index 2f88043a4..5523457be 100644
--- a/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp
+++ b/tests/benchmarks/render/layerfiltering/tst_bench_layerfiltering.cpp
@@ -28,8 +28,9 @@
#include <QtTest/QtTest>
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
@@ -54,11 +55,22 @@ public:
Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data();
QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- for (const Qt3DCore::QNodeCreatedChangeBasePtr change : creationChanges)
- d_func()->createBackendNode(change);
+ QVector<Qt3DCore::NodeTreeChange> nodes;
+ Qt3DCore::QNodeVisitor v;
+ v.traverse(root, [&nodes](Qt3DCore::QNode *node) {
+ Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject()));
+ d->m_hasBackendNode = true;
+ nodes.push_back({
+ node->id(),
+ Qt3DCore::QNodePrivate::get(node)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ node
+ });
+ });
+
+ for (const auto &node: nodes)
+ d_func()->createBackendNode(node);
}
~TestAspect()
diff --git a/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp b/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp
index b0d64b564..210d82dcf 100644
--- a/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp
+++ b/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp
@@ -28,8 +28,9 @@
#include <QtTest/QTest>
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qaspectjobmanager_p.h>
+#include <Qt3DCore/private/qnodevisitor_p.h>
+#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
@@ -55,11 +56,22 @@ public:
Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data();
QRenderAspect::onRegistered();
- const Qt3DCore::QNodeCreatedChangeGenerator generator(root);
- const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = generator.creationChanges();
-
- for (const Qt3DCore::QNodeCreatedChangeBasePtr change : creationChanges)
- d_func()->createBackendNode(change);
+ QVector<Qt3DCore::NodeTreeChange> nodes;
+ Qt3DCore::QNodeVisitor v;
+ v.traverse(root, [&nodes](Qt3DCore::QNode *node) {
+ Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node);
+ d->m_typeInfo = const_cast<QMetaObject*>(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject()));
+ d->m_hasBackendNode = true;
+ nodes.push_back({
+ node->id(),
+ Qt3DCore::QNodePrivate::get(node)->m_typeInfo,
+ Qt3DCore::NodeTreeChange::Added,
+ node
+ });
+ });
+
+ for (const auto &node: nodes)
+ d_func()->createBackendNode(node);
const auto handles = nodeManagers()->techniqueManager()->activeHandles();
for (const auto handle: handles) {
diff --git a/tests/manual/assimp/main.cpp b/tests/manual/assimp/main.cpp
index 5df575e32..307ff87c2 100644
--- a/tests/manual/assimp/main.cpp
+++ b/tests/manual/assimp/main.cpp
@@ -85,8 +85,8 @@ QObject *SceneHelper::findEntity(Qt3DRender::QSceneLoader *loader, const QString
QObject *SceneHelper::findComponent(Qt3DCore::QEntity *entity, const QString &componentMetatype)
{
Q_ASSERT(entity);
- Qt3DCore::QComponentVector components = entity->components();
- Q_FOREACH (Qt3DCore::QComponent *component, components) {
+ const Qt3DCore::QComponentVector components = entity->components();
+ for (Qt3DCore::QComponent *component : components) {
qDebug() << component->metaObject()->className();
if (component->metaObject()->className() == componentMetatype) {
return component;
diff --git a/tests/manual/compressed_textures/compressed_textures.pro b/tests/manual/compressed_textures/compressed_textures.pro
new file mode 100644
index 000000000..37871a4cb
--- /dev/null
+++ b/tests/manual/compressed_textures/compressed_textures.pro
@@ -0,0 +1,12 @@
+QT += 3dcore 3drender 3dinput 3dquick 3dlogic qml quick 3dquickextras
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ compressed_textures.qrc
+
+DEFINES += DATA_DIR=\\\"$$PWD/data\\\"
diff --git a/tests/manual/compressed_textures/compressed_textures.qrc b/tests/manual/compressed_textures/compressed_textures.qrc
new file mode 100644
index 000000000..5f6483ac3
--- /dev/null
+++ b/tests/manual/compressed_textures/compressed_textures.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/compressed_textures/data/16_16.png b/tests/manual/compressed_textures/data/16_16.png
new file mode 100644
index 000000000..aefb48dc4
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16.png
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ASTC_7.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ASTC_7.KTX
new file mode 100644
index 000000000..953f300ad
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ASTC_7.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ASTC_8.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ASTC_8.KTX
new file mode 100644
index 000000000..4c23241e4
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ASTC_8.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGBA_11.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGBA_11.KTX
new file mode 100644
index 000000000..01646e99a
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGBA_11.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGB_13.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGB_13.KTX
new file mode 100644
index 000000000..2d2efff1b
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ETC2_RGB_13.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16_16_PNG_ETC_RGB_12.KTX b/tests/manual/compressed_textures/data/16_16_PNG_ETC_RGB_12.KTX
new file mode 100644
index 000000000..15e30abc8
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16_16_PNG_ETC_RGB_12.KTX
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16-etc1.pkm b/tests/manual/compressed_textures/data/16x16-etc1.pkm
new file mode 100644
index 000000000..62ae2a11f
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16-etc1.pkm
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16-etc2.pkm b/tests/manual/compressed_textures/data/16x16-etc2.pkm
new file mode 100644
index 000000000..be391113e
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16-etc2.pkm
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc1-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc1-dx10.dds
new file mode 100644
index 000000000..feacae8d1
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc1-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips-dx10.dds
new file mode 100644
index 000000000..40da98cde
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips.dds
new file mode 100644
index 000000000..1dd3e1e91
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc1-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc1.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc1.dds
new file mode 100644
index 000000000..e31f410d2
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc1.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc3-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc3-dx10.dds
new file mode 100644
index 000000000..76c820f31
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc3-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips-dx10.dds
new file mode 100644
index 000000000..0a2964f12
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips.dds
new file mode 100644
index 000000000..c8c94d85f
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc3-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-bc3.dds b/tests/manual/compressed_textures/data/16x16x1-1-bc3.dds
new file mode 100644
index 000000000..4a08d324a
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-bc3.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-lumi-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-1-lumi-nomips.dds
new file mode 100644
index 000000000..8fdd5e3e1
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-lumi-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-lumi.dds b/tests/manual/compressed_textures/data/16x16x1-1-lumi.dds
new file mode 100644
index 000000000..82ab57958
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-lumi.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-rgb-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-1-rgb-nomips.dds
new file mode 100644
index 000000000..94d06c2c4
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-rgb-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-1-rgb.dds b/tests/manual/compressed_textures/data/16x16x1-1-rgb.dds
new file mode 100644
index 000000000..45635dd97
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-1-rgb.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc1-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc1-dx10.dds
new file mode 100644
index 000000000..209b796f0
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc1-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips-dx10.dds
new file mode 100644
index 000000000..e79e29ab5
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips.dds
new file mode 100644
index 000000000..de6796d9f
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc1-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc1.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc1.dds
new file mode 100644
index 000000000..92b95ae73
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc1.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc3-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc3-dx10.dds
new file mode 100644
index 000000000..f56fa09fd
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc3-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips-dx10.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips-dx10.dds
new file mode 100644
index 000000000..31e137553
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips-dx10.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips.dds
new file mode 100644
index 000000000..644274601
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc3-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-bc3.dds b/tests/manual/compressed_textures/data/16x16x1-6-bc3.dds
new file mode 100644
index 000000000..144515bb0
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-bc3.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-lumi-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-6-lumi-nomips.dds
new file mode 100644
index 000000000..baa884a36
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-lumi-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-lumi.dds b/tests/manual/compressed_textures/data/16x16x1-6-lumi.dds
new file mode 100644
index 000000000..1a4e6f46f
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-lumi.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-rgb-nomips.dds b/tests/manual/compressed_textures/data/16x16x1-6-rgb-nomips.dds
new file mode 100644
index 000000000..318a0bd35
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-rgb-nomips.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/data/16x16x1-6-rgb.dds b/tests/manual/compressed_textures/data/16x16x1-6-rgb.dds
new file mode 100644
index 000000000..1f3c8f9cf
--- /dev/null
+++ b/tests/manual/compressed_textures/data/16x16x1-6-rgb.dds
Binary files differ
diff --git a/tests/manual/compressed_textures/main.cpp b/tests/manual/compressed_textures/main.cpp
new file mode 100644
index 000000000..ca4cf7c2d
--- /dev/null
+++ b/tests/manual/compressed_textures/main.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QQuickView>
+#include <QGuiApplication>
+#include <QQmlContext>
+#include <QDir>
+
+QStringList createTextureFileList()
+{
+ QDir dir(QString::fromUtf8(DATA_DIR));
+ return dir.entryList();
+}
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+ QQuickView view;
+
+ QQmlContext *ctx =view.rootContext();
+ ctx->setContextProperty(QStringLiteral("_pathPrefix"), QString::fromUtf8(DATA_DIR));
+ ctx->setContextProperty(QStringLiteral("_texturesList"), createTextureFileList());
+
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/compressed_textures/main.qml b/tests/manual/compressed_textures/main.qml
new file mode 100644
index 000000000..b5ad0990e
--- /dev/null
+++ b/tests/manual/compressed_textures/main.qml
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12 as QQ2
+import QtQuick.Scene3D 2.12
+import QtQuick.Controls 2.12
+import Qt3D.Core 2.12
+import Qt3D.Render 2.12
+import Qt3D.Input 2.12
+import Qt3D.Extras 2.12
+
+QQ2.Item {
+ id: root
+ width: 1280
+ height: 720
+
+ readonly property string textureSource: "file://" + _pathPrefix + "/" + textureSelector.textAt(textureSelector.currentIndex)
+
+ Scene3D {
+ anchors.fill: parent
+ focus: true
+ aspects: ["input", "logic"]
+
+ Entity {
+ id: sceneRoot
+
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ aspectRatio: 16/9
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d(0.0, 0.0, -2.0)
+ upVector: Qt.vector3d(0.0, 1.0, 0.0)
+ viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
+ }
+
+ OrbitCameraController {
+ camera: camera
+ }
+
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ clearColor: Qt.rgba(0, 0.5, 1, 1)
+ camera: camera
+ }
+ },
+ // Event Source will be set by the Qt3DQuickWindow
+ InputSettings { }
+ ]
+
+ Entity {
+ readonly property CuboidMesh mesh: CuboidMesh { }
+ readonly property DiffuseMapMaterial material: DiffuseMapMaterial {
+ diffuse: TextureLoader {
+ source: textureSource
+ }
+ }
+ components: [ mesh, material ]
+ }
+ }
+ }
+
+ ComboBox {
+ id: textureSelector
+ model: _texturesList
+ width: 200
+ }
+}
diff --git a/tests/manual/compute-manual/ComputeFrameGraph.qml b/tests/manual/compute-manual/ComputeFrameGraph.qml
new file mode 100644
index 000000000..47d57161c
--- /dev/null
+++ b/tests/manual/compute-manual/ComputeFrameGraph.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+
+Viewport {
+ property alias camera: selector.camera
+
+ RenderSurfaceSelector {
+ id: surfaceSelector
+
+ // Clear Buffer
+ ClearBuffers {
+ buffers: ClearBuffers.ColorDepthBuffer
+ NoDraw {}
+ }
+
+ // Compute Pass
+ DispatchCompute {
+ // 1024 x 1024 particles
+ // We will launch 1024 local workgroup that will work
+ // on 1024 particles each
+ workGroupX: 1024; workGroupY: 1; workGroupZ: 1
+ TechniqueFilter {
+ matchAll: [
+ FilterKey { name: "type"; value: "compute"}
+ ]
+ }
+ }
+
+ // Draw particles from buffer computed in the Compute Pass
+ CameraSelector {
+ id: selector
+ TechniqueFilter {
+ MemoryBarrier { waitFor: MemoryBarrier.VertexAttributeArray }
+ matchAll: [
+ FilterKey { name: "type"; value: "draw"}
+ ]
+ }
+ }
+ }
+}
+
diff --git a/tests/manual/compute-manual/ComputeMaterial.qml b/tests/manual/compute-manual/ComputeMaterial.qml
new file mode 100644
index 000000000..9116a8b66
--- /dev/null
+++ b/tests/manual/compute-manual/ComputeMaterial.qml
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+
+Material {
+ property Buffer dataBuffer;
+ property real particleStep: 0.4
+ property real finalCollisionFactor: 0.2
+
+ parameters: [
+ Parameter { name: "particleStep"; value: particleStep },
+ Parameter { name: "finalCollisionFactor"; value: finalCollisionFactor }
+ ]
+
+ ShaderProgram {
+ id: computeShader
+ computeShaderCode: loadSource("qrc:/particles.comp")
+ }
+
+ ShaderProgram {
+ id: drawShader
+ vertexShaderCode: loadSource("qrc:/particles.vert")
+ fragmentShaderCode: loadSource("qrc:/particles.frag")
+ }
+
+ effect: Effect {
+ techniques: [
+ Technique {
+ renderPasses: [
+ RenderPass {
+ shaderProgram: computeShader
+ // We set the buffer as the parameter data
+ parameters: [
+ Parameter { name: "Particles"; value: dataBuffer }
+ ]
+ }
+ ]
+ filterKeys: [
+ FilterKey { name: "type"; value: "compute" }
+ ]
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 4
+ minorVersion: 3
+ }
+ },
+ Technique {
+ renderPasses: [
+ RenderPass {
+ shaderProgram: drawShader
+ // We assume the mesh to be drawn will also receive
+ // Vertex buffers attributes that will be used to position and color
+ }
+ ]
+ filterKeys: [
+ FilterKey { name: "type"; value: "draw" }
+ ]
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 4
+ minorVersion: 3
+ }
+ }
+ ] // techniques
+ }
+}
+
diff --git a/tests/manual/compute-manual/ParticlesScene.qml b/tests/manual/compute-manual/ParticlesScene.qml
new file mode 100644
index 000000000..68572f6b4
--- /dev/null
+++ b/tests/manual/compute-manual/ParticlesScene.qml
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Extras 2.14
+import Qt3D.Input 2.14
+
+Entity {
+
+ property alias computeMode: particlesComputeJob.runType
+
+ function triggerCompute(frames) {
+ particlesComputeJob.trigger(frames)
+ }
+
+ components: [
+ RenderSettings {
+ ComputeFrameGraph {
+ camera: sceneCamera
+ }
+ // explicitly set RenderingPolicy to AlwaysRender, as changes in the
+ // scene won't be reflected in actual Qt scene-graph changes (due to
+ // GPU compute calls)
+ renderPolicy: RenderSettings.Always
+ },
+ InputSettings {}
+ ]
+
+ FirstPersonCameraController { camera: sceneCamera }
+
+ Camera {
+ id: sceneCamera
+ projectionType: CameraLens.PerspectiveProjection
+ viewCenter: Qt.vector3d(0, 0, 0)
+ position: Qt.vector3d(0, 20, -800)
+ nearPlane: 0.1
+ farPlane: 1000
+ fieldOfView: 60
+ }
+
+ property int particlesCount: 1024 * 1024
+ readonly property int floatSize: 4
+
+ function buildParticlesBuffer() {
+ var byteSizeOfParticleData = 8;
+ var bufferData = new Float32Array(particlesCount * byteSizeOfParticleData);
+ for (var x = 0; x < 1024; ++x) {
+ for (var z = 0; z < 1024; ++z) {
+ var i = x * 1024 + z;
+ var positionIdx = i * byteSizeOfParticleData;
+ var colorIdx = i * byteSizeOfParticleData + 8;
+
+ bufferData[positionIdx] = -1024 + x * 2;
+ bufferData[positionIdx + 1] = 0;
+ bufferData[positionIdx + 2] = -1024 + z * 2;
+ bufferData[positionIdx + 3] = 1.0;
+
+ bufferData[colorIdx] = 0.25 + Math.sin(x / 1024) * 0.75;
+ bufferData[colorIdx + 1] = 0.25 + Math.sin(z / 1024) * 0.75;
+ bufferData[colorIdx + 2] = 0.25 + Math.sin(x / 1024) * 0.75;
+ bufferData[colorIdx + 3] = 1.0;
+ }
+ }
+ return bufferData
+ }
+
+ Buffer {
+ id: particleBuffer
+ type: Buffer.VertexBuffer
+ // struct ParticleData
+ // {
+ // vec3 position; // Aligned to 4 floats
+ // vec3 color; // Aligned to 4 floats
+ // };
+ data: buildParticlesBuffer()
+ }
+
+ Attribute {
+ id: particlePositionDataAttribute
+ name: "particlePosition"
+ attributeType: Attribute.VertexAttribute
+ vertexBaseType: Attribute.Float
+ vertexSize: 3
+ divisor: 1
+ byteStride: 8 * floatSize
+ buffer: particleBuffer
+ }
+
+ Attribute {
+ id: particleColorDataAttribute
+ name: "particleColor"
+ attributeType: Attribute.VertexAttribute
+ vertexBaseType: Attribute.Float
+ vertexSize: 3
+ divisor: 1
+ byteOffset: 4 * floatSize
+ byteStride: 8 * floatSize
+ buffer: particleBuffer
+ }
+
+ ComputeMaterial {
+ id: computeMaterial
+ dataBuffer: particleBuffer
+ }
+
+ ComputeCommand {
+ id: particlesComputeJob
+ onRunTypeChanged: {
+ // Don't forget to re-enable the command
+ // when switching back to continuous
+ if (runType === ComputeCommand.Continuous)
+ enabled = true
+ }
+ }
+
+ Entity {
+ id: particleComputeEntity
+ components: [
+ particlesComputeJob,
+ computeMaterial
+ ]
+ }
+
+ SphereGeometry {
+ id: sphereGeometry
+ rings: 10
+ slices: 10
+ radius: 1
+ // Additional Attributes
+ attributes: [
+ particlePositionDataAttribute,
+ particleColorDataAttribute
+ ]
+ }
+
+ Entity {
+ id: particleRenderEntity
+ readonly property GeometryRenderer particlesRenderer: GeometryRenderer {
+ instanceCount: particlesCount
+ indexOffset: 0
+ firstInstance: 0
+ primitiveType: GeometryRenderer.Triangles
+ geometry: sphereGeometry
+ }
+
+ components: [
+ particlesRenderer,
+ computeMaterial
+ ]
+ }
+}
+
diff --git a/tests/manual/compute-manual/compute-manual.pro b/tests/manual/compute-manual/compute-manual.pro
new file mode 100644
index 000000000..e2a9116db
--- /dev/null
+++ b/tests/manual/compute-manual/compute-manual.pro
@@ -0,0 +1,14 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dquick 3dinput quick qml
+
+HEADERS += \
+
+
+RESOURCES += \
+ compute-manual.qrc
+
+SOURCES += \
+ main.cpp
diff --git a/tests/manual/compute-manual/compute-manual.qrc b/tests/manual/compute-manual/compute-manual.qrc
new file mode 100644
index 000000000..0f94fddd5
--- /dev/null
+++ b/tests/manual/compute-manual/compute-manual.qrc
@@ -0,0 +1,11 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>ComputeFrameGraph.qml</file>
+ <file>ComputeMaterial.qml</file>
+ <file>particles.frag</file>
+ <file>particles.vert</file>
+ <file>ParticlesScene.qml</file>
+ <file>particles.comp</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/compute-manual/main.cpp b/tests/manual/compute-manual/main.cpp
new file mode 100644
index 000000000..afc9df36a
--- /dev/null
+++ b/tests/manual/compute-manual/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQuickView>
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ view.resize(1024, 1024);
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/compute-manual/main.qml b/tests/manual/compute-manual/main.qml
new file mode 100644
index 000000000..a76c8ae0c
--- /dev/null
+++ b/tests/manual/compute-manual/main.qml
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import QtQuick.Scene3D 2.14
+import QtQuick.Controls 2.14
+import QtQuick.Layouts 1.1
+import Qt3D.Render 2.14
+
+Item {
+
+ Scene3D {
+ anchors.fill: parent
+ aspects: ["input", "logic"]
+ focus: true
+ ParticlesScene {
+ id: scene
+ computeMode: runModeCombo.currentIndex === 0 ? ComputeCommand.Continuous : ComputeCommand.Manual
+ }
+ }
+
+ RowLayout {
+ id: colorLayout
+ anchors.left: parent.left
+ anchors.leftMargin: 35
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 35
+ spacing: 15
+
+ RowLayout {
+ Text {
+ text: "Run Mode:"
+ color: "white"
+ }
+ ComboBox {
+ id: runModeCombo
+ model: ["Continuous", "Manual"]
+ }
+ }
+ RowLayout {
+ visible: runModeCombo.currentIndex === 1
+ Text {
+ color: "white"
+ text: "Frames"
+ }
+ SpinBox {
+ id: frameCountSpinBox
+ value: 5
+ from: 1
+ to: 10
+ stepSize: 1
+ }
+ Button {
+ text: "Trigger"
+ onClicked: {
+ // Trigger Compute Manual
+ scene.triggerCompute(frameCountSpinBox.value)
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/compute-manual/particles.comp b/tests/manual/compute-manual/particles.comp
new file mode 100644
index 000000000..b05e49c1d
--- /dev/null
+++ b/tests/manual/compute-manual/particles.comp
@@ -0,0 +1,31 @@
+#version 430 core
+
+uniform float time;
+
+layout (local_size_x = 1024) in;
+
+struct ParticleData
+{
+ vec4 position;
+ vec4 color;
+};
+
+// Particles from previouse frame
+layout (std430, binding = 0) coherent buffer Particles
+{
+ ParticleData particles[];
+} data;
+
+void main(void)
+{
+ uint globalId = gl_GlobalInvocationID.x;
+
+ // Retrieve current particle from previous frame
+ ParticleData currentParticle = data.particles[globalId];
+
+ // New position = old position + sin(time)
+ currentParticle.position = currentParticle.position + vec4(0.0, 1.0, 0.0, 0.0) * sin(time * globalId);
+
+ // Save updated particle
+ data.particles[globalId] = currentParticle;
+}
diff --git a/tests/manual/compute-manual/particles.frag b/tests/manual/compute-manual/particles.frag
new file mode 100644
index 000000000..3f11b9868
--- /dev/null
+++ b/tests/manual/compute-manual/particles.frag
@@ -0,0 +1,33 @@
+#version 430 core
+
+out vec4 color;
+
+in VertexBlock
+{
+ flat vec3 color;
+ vec3 pos;
+ vec3 normal;
+} frag_in;
+
+const vec4 lightPosition = vec4(0.0, 0.0, 0.0, 0.0);
+const vec3 lightIntensity = vec3(1.0, 1.0, 1.0);
+const vec3 ka = vec3(0.1, 0.1, 0.1);
+const vec3 ks = vec3(0.8, 0.8, 0.8);
+const float shininess = 50.0;
+
+vec3 ads()
+{
+ vec3 n = normalize( frag_in.normal);
+ vec3 s = normalize( vec3(lightPosition) - frag_in.pos );
+ vec3 v = normalize( -frag_in.pos );
+ vec3 h = normalize( v + s );
+ return lightIntensity * (ka +
+ frag_in.color * max( dot(s, frag_in.normal ), 0.0 ) +
+ ks * pow( max( dot( h, n ), 0.0 ), shininess ) );
+}
+
+
+void main(void)
+{
+ color = vec4(ads(), 1.0);
+}
diff --git a/tests/manual/compute-manual/particles.vert b/tests/manual/compute-manual/particles.vert
new file mode 100644
index 000000000..5f2da2a00
--- /dev/null
+++ b/tests/manual/compute-manual/particles.vert
@@ -0,0 +1,27 @@
+#version 430 core
+
+in vec3 vertexPosition;
+in vec3 vertexNormal;
+
+in vec3 particlePosition;
+in vec3 particleColor;
+
+out VertexBlock
+{
+ flat vec3 color;
+ vec3 pos;
+ vec3 normal;
+} v_out;
+
+uniform mat4 mvp;
+uniform mat3 modelViewNormal;
+uniform mat4 modelView;
+
+void main(void)
+{
+ vec4 pos = vec4(vertexPosition.xyz, 1.0) + vec4(particlePosition, 0.0);
+ gl_Position = mvp * pos;
+ v_out.pos = vec4(modelView * pos).xyz;
+ v_out.normal = normalize(modelViewNormal * vertexNormal);
+ v_out.color = mix(particleColor * 0.2, particleColor, smoothstep(0.5, 0.8, abs(v_out.normal).z));
+}
diff --git a/tests/manual/custom-mesh-cpp-indirect/main.cpp b/tests/manual/custom-mesh-cpp-indirect/main.cpp
index bac4a7227..3e26e3d10 100644
--- a/tests/manual/custom-mesh-cpp-indirect/main.cpp
+++ b/tests/manual/custom-mesh-cpp-indirect/main.cpp
@@ -149,7 +149,7 @@ int main(int argc, char* argv[])
QVector3D blue(0.0f, 0.0f, 1.0f);
QVector3D white(1.0f, 1.0f, 1.0f);
- QVector<QVector3D> vertices = QVector<QVector3D>()
+ const QVector<QVector3D> vertices = QVector<QVector3D>()
<< v0 << n0 << red
<< v1 << n1 << blue
<< v2 << n2 << green
@@ -168,9 +168,9 @@ int main(int argc, char* argv[])
Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
- Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);
- Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, customGeometry);
- Qt3DRender::QBuffer *indirectDrawDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::DrawIndirectBuffer, customGeometry);
+ Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
+ Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
+ Qt3DRender::QBuffer *indirectDrawDataBuffer = new Qt3DRender::QBuffer(customGeometry);
// 4 distinct vertices
QByteArray vertexBufferData;
@@ -179,7 +179,7 @@ int main(int argc, char* argv[])
float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
int idx = 0;
- Q_FOREACH (const QVector3D &v, vertices) {
+ for (const QVector3D &v : vertices) {
rawVertexArray[idx++] = v.x();
rawVertexArray[idx++] = v.y();
rawVertexArray[idx++] = v.z();
@@ -300,8 +300,8 @@ int main(int argc, char* argv[])
Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
- Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);
- Qt3DRender::QBuffer *indirectDrawDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::DrawIndirectBuffer, customGeometry);
+ Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
+ Qt3DRender::QBuffer *indirectDrawDataBuffer = new Qt3DRender::QBuffer(customGeometry);
QVector<QVector3D> orderedPositionVertices;
diff --git a/tests/manual/custom-mesh-cpp/main.cpp b/tests/manual/custom-mesh-cpp/main.cpp
index e51321e65..275d97088 100644
--- a/tests/manual/custom-mesh-cpp/main.cpp
+++ b/tests/manual/custom-mesh-cpp/main.cpp
@@ -107,8 +107,8 @@ int main(int argc, char* argv[])
Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
- Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);
- Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, customGeometry);
+ Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
+ Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
// vec3 for position
// vec3 for colors
@@ -149,7 +149,7 @@ int main(int argc, char* argv[])
QVector3D blue(0.0f, 0.0f, 1.0f);
QVector3D white(1.0f, 1.0f, 1.0f);
- QVector<QVector3D> vertices = QVector<QVector3D>()
+ const QVector<QVector3D> vertices = QVector<QVector3D>()
<< v0 << n0 << red
<< v1 << n1 << blue
<< v2 << n2 << green
@@ -158,7 +158,7 @@ int main(int argc, char* argv[])
float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
int idx = 0;
- Q_FOREACH (const QVector3D &v, vertices) {
+ for (const QVector3D &v : vertices) {
rawVertexArray[idx++] = v.x();
rawVertexArray[idx++] = v.y();
rawVertexArray[idx++] = v.z();
diff --git a/tests/manual/custom-mesh-update-data-cpp/main.cpp b/tests/manual/custom-mesh-update-data-cpp/main.cpp
index 80ee2088d..2b6b6b3cf 100644
--- a/tests/manual/custom-mesh-update-data-cpp/main.cpp
+++ b/tests/manual/custom-mesh-update-data-cpp/main.cpp
@@ -126,8 +126,8 @@ int main(int argc, char* argv[])
Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
- vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);
- Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, customGeometry);
+ vertexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
+ Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
// vec3 for position
// vec3 for colors
@@ -167,7 +167,7 @@ int main(int argc, char* argv[])
QVector3D blue(0.0f, 0.0f, 1.0f);
QVector3D white(1.0f, 1.0f, 1.0f);
- QVector<QVector3D> vertices = QVector<QVector3D>()
+ const QVector<QVector3D> vertices = QVector<QVector3D>()
<< v0 << n0 << red
<< v1 << n1 << blue
<< v2 << n2 << green
@@ -176,7 +176,7 @@ int main(int argc, char* argv[])
float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
int idx = 0;
- Q_FOREACH (const QVector3D &v, vertices) {
+ for (const QVector3D &v : vertices) {
rawVertexArray[idx++] = v.x();
rawVertexArray[idx++] = v.y();
rawVertexArray[idx++] = v.z();
@@ -211,8 +211,7 @@ int main(int argc, char* argv[])
Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute();
positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
positionAttribute->setBuffer(vertexDataBuffer);
- positionAttribute->setDataType(Qt3DRender::QAttribute::Float);
- positionAttribute->setDataSize(3);
+ positionAttribute->setVertexSize(3);
positionAttribute->setByteOffset(0);
positionAttribute->setByteStride(9 * sizeof(float));
positionAttribute->setCount(4);
@@ -221,8 +220,7 @@ int main(int argc, char* argv[])
Qt3DRender::QAttribute *normalAttribute = new Qt3DRender::QAttribute();
normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
normalAttribute->setBuffer(vertexDataBuffer);
- normalAttribute->setDataType(Qt3DRender::QAttribute::Float);
- normalAttribute->setDataSize(3);
+ normalAttribute->setVertexSize(3);
normalAttribute->setByteOffset(3 * sizeof(float));
normalAttribute->setByteStride(9 * sizeof(float));
normalAttribute->setCount(4);
@@ -231,8 +229,7 @@ int main(int argc, char* argv[])
Qt3DRender::QAttribute *colorAttribute = new Qt3DRender::QAttribute();
colorAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
colorAttribute->setBuffer(vertexDataBuffer);
- colorAttribute->setDataType(Qt3DRender::QAttribute::Float);
- colorAttribute->setDataSize(3);
+ colorAttribute->setVertexSize(3);
colorAttribute->setByteOffset(6 * sizeof(float));
colorAttribute->setByteStride(9 * sizeof(float));
colorAttribute->setCount(4);
@@ -241,8 +238,8 @@ int main(int argc, char* argv[])
Qt3DRender::QAttribute *indexAttribute = new Qt3DRender::QAttribute();
indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
indexAttribute->setBuffer(indexDataBuffer);
- indexAttribute->setDataType(Qt3DRender::QAttribute::UnsignedShort);
- indexAttribute->setDataSize(1);
+ indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedShort);
+ indexAttribute->setVertexSize(1);
indexAttribute->setByteOffset(0);
indexAttribute->setByteStride(0);
indexAttribute->setCount(12);
@@ -287,12 +284,12 @@ void TimerObject::timeout()
QVector3D c2(qFabs(qSin(angle)), qFabs(qCos(angle + M_PI_4)), qFabs(qSin(angle + M_PI_4)));
QVector3D c3(qFabs(qSin(angle + M_PI_4)), qFabs(qSin(angle)), qFabs(qCos(angle)));
- QVector<QVector3D> colors = QVector<QVector3D>() << c1 << c2 << c3;
+ const QVector<QVector3D> colors = QVector<QVector3D>() << c1 << c2 << c3;
float *rawVertexArray = reinterpret_cast<float *>(updateData.data());
int pos = 6 * sizeof(float); //color offset
- Q_FOREACH (const QVector3D &v, colors) {
+ for (const QVector3D &v : colors) {
rawVertexArray[0] = v.x();
rawVertexArray[1] = v.y();
rawVertexArray[2] = v.z();
diff --git a/tests/manual/deferred-renderer-cpp/deferredrenderer.cpp b/tests/manual/deferred-renderer-cpp/deferredrenderer.cpp
index 48f8ad3fe..d069d609d 100644
--- a/tests/manual/deferred-renderer-cpp/deferredrenderer.cpp
+++ b/tests/manual/deferred-renderer-cpp/deferredrenderer.cpp
@@ -85,13 +85,13 @@ void DeferredRenderer::setSceneCamera(Qt3DCore::QEntity *camera)
void DeferredRenderer::setGeometryPassCriteria(QList<Qt3DRender::QFilterKey *> criteria)
{
- Q_FOREACH (Qt3DRender::QFilterKey *c, criteria)
+ for (Qt3DRender::QFilterKey *c : qAsConst(criteria))
m_geometryPassFilter->addMatch(c);
}
void DeferredRenderer::setFinalPassCriteria(QList<Qt3DRender::QFilterKey *> criteria)
{
- Q_FOREACH (Qt3DRender::QFilterKey *c, criteria)
+ for (Qt3DRender::QFilterKey *c : qAsConst(criteria))
c->setParent(m_finalPassFilter);
}
diff --git a/tests/manual/manual-renderloop/main.cpp b/tests/manual/manual-renderloop/main.cpp
new file mode 100644
index 000000000..f2a49cb86
--- /dev/null
+++ b/tests/manual/manual-renderloop/main.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QTimer>
+#include <QOpenGLContext>
+#include <QWindow>
+#include <qmath.h>
+
+#include <Qt3DCore/QNode>
+#include <Qt3DCore/QEntity>
+#include <Qt3DCore/QTransform>
+#include <Qt3DCore/QAspectEngine>
+
+#include <Qt3DExtras/QTorusMesh>
+#include <Qt3DExtras/QForwardRenderer>
+#include <Qt3DExtras/QPhongMaterial>
+
+#include <Qt3DRender/QCamera>
+#include <Qt3DRender/QCameraLens>
+#include <Qt3DRender/QCameraSelector>
+#include <Qt3DRender/QMesh>
+#include <Qt3DRender/QPointLight>
+#include <Qt3DRender/QRenderAspect>
+#include <Qt3DRender/QRenderSettings>
+#include <Qt3DRender/QRenderSurfaceSelector>
+#include <Qt3DRender/private/qrenderaspect_p.h>
+
+
+class ManualRenderer
+{
+public:
+ ManualRenderer()
+ : m_aspectEngine(new Qt3DCore::QAspectEngine())
+ , m_renderAspect(new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous))
+ {
+ }
+
+ ~ManualRenderer() {
+ m_aspectEngine->setRootEntity(Qt3DCore::QEntityPtr());
+ m_aspectEngine->unregisterAspect(m_renderAspect);
+ delete m_renderAspect;
+ delete m_aspectEngine;
+ }
+
+ void initialize(QWindow *window, QOpenGLContext *glCtx)
+ {
+ m_aspectEngine->registerAspect(m_renderAspect);
+ m_aspectEngine->setRunMode(Qt3DCore::QAspectEngine::Manual);
+
+ Qt3DRender::QRenderAspectPrivate *dRenderAspect = static_cast<decltype(dRenderAspect)>
+ (Qt3DRender::QRenderAspectPrivate::get(m_renderAspect));
+ dRenderAspect->renderInitialize(glCtx);
+
+ m_rootEntity.reset(createSceneTree(window));
+ m_aspectEngine->setRootEntity(m_rootEntity);
+ }
+
+ void render() {
+ qDebug() << Q_FUNC_INFO << "Updating Scene";
+ updateScene();
+ qDebug() << Q_FUNC_INFO << "Processing Frame";
+ // Launch jobs to process the frame
+ m_aspectEngine->processFrame();
+ qDebug() << Q_FUNC_INFO << "Rendering Frame";
+ // Submit Render Queues
+ Qt3DRender::QRenderAspectPrivate *dRenderAspect = static_cast<decltype(dRenderAspect)>
+ (Qt3DRender::QRenderAspectPrivate::get(m_renderAspect));
+ dRenderAspect->renderSynchronous(true);
+ }
+
+private:
+ Qt3DCore::QEntity *createSceneTree(QWindow *surface) {
+ // Root entity in the 3D scene.
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
+ auto camera = new Qt3DRender::QCamera(rootEntity);
+ camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
+ camera->setPosition(QVector3D(0, 0, 40.0f));
+ camera->setViewCenter(QVector3D(0, 0, 0));
+
+ // Torus
+ Qt3DCore::QEntity *torusEntity = new Qt3DCore::QEntity(rootEntity);
+ auto material = new Qt3DExtras::QPhongMaterial(rootEntity);
+ auto torusTransform = new Qt3DCore::QTransform;
+ auto torusMesh = new Qt3DExtras::QTorusMesh;
+
+ torusMesh->setRadius(5);
+ torusMesh->setMinorRadius(1);
+ torusMesh->setRings(100);
+ torusMesh->setSlices(20);
+
+ torusTransform->setScale3D(QVector3D(1.5, 1, 0.5));
+ torusTransform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.0f));
+
+ torusEntity->addComponent(torusMesh);
+ torusEntity->addComponent(material);
+ torusEntity->addComponent(torusTransform);
+
+ // FrameGraph
+ auto forwardRenderer = new Qt3DExtras::QForwardRenderer();
+ forwardRenderer->setSurface(surface);
+ forwardRenderer->setCamera(camera);
+ forwardRenderer->setClearColor(QColor(Qt::black));
+
+ auto renderSettings = new Qt3DRender::QRenderSettings();
+ renderSettings->setActiveFrameGraph(forwardRenderer);
+ rootEntity->addComponent(renderSettings);
+
+ return rootEntity;
+ }
+
+ void updateScene()
+ {
+ static int angle = 0;
+ // Update camera position
+ auto camera = m_rootEntity->findChild<Qt3DRender::QCamera *>();
+ Q_ASSERT(camera);
+
+ const double angleRad = qDegreesToRadians(double(angle));
+ const QVector3D newPos(qSin(angleRad), 0.0, qCos(angleRad));
+ camera->setPosition(newPos * 40.0f);
+
+ qDebug() << Q_FUNC_INFO << "Camera Transform Matrix" << camera->transform()->matrix();
+ qDebug() << Q_FUNC_INFO << "Camera ViewMatrix" << camera->viewMatrix();
+
+ angle = (angle + 1) % 360;
+ }
+
+ Qt3DCore::QEntityPtr m_rootEntity;
+ Qt3DCore::QAspectEngine *m_aspectEngine;
+ Qt3DRender::QRenderAspect *m_renderAspect;
+};
+
+int main(int ac, char **av)
+{
+ QSurfaceFormat format = QSurfaceFormat::defaultFormat();
+#ifdef QT_OPENGL_ES_2
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+#else
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
+ format.setVersion(4, 3);
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ }
+#endif
+ format.setDepthBufferSize(24);
+ format.setSamples(4);
+ format.setStencilBufferSize(8);
+ QSurfaceFormat::setDefaultFormat(format);
+
+ QGuiApplication app(ac, av);
+
+ QWindow win;
+ win.setSurfaceType(QSurface::OpenGLSurface);
+ win.resize(1024, 768);
+ win.setFormat(format);
+ win.show();
+
+ QOpenGLContext ctx;
+ ctx.setFormat(format);
+ const bool ctxCreated = ctx.create();
+
+ if (!ctxCreated) {
+ qWarning() << "Failed to create GL context";
+ return -1;
+ }
+
+ ManualRenderer renderer;
+ renderer.initialize(&win, &ctx);
+
+ QTimer t;
+ QObject::connect(&t, &QTimer::timeout, [&] { renderer.render(); });
+ t.start(16);
+
+ return app.exec();
+}
diff --git a/tests/manual/manual-renderloop/manual-renderloop.pro b/tests/manual/manual-renderloop/manual-renderloop.pro
new file mode 100644
index 000000000..d126a48c5
--- /dev/null
+++ b/tests/manual/manual-renderloop/manual-renderloop.pro
@@ -0,0 +1,8 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3drender-private 3dinput 3dextras
+
+SOURCES += \
+ main.cpp
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index 8554d4aba..2f630e0d9 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -61,8 +61,19 @@ SUBDIRS += \
raycasting-qml \
shared_texture_image \
texture_property_updates \
+ raster-cpp \
+ raster-qml \
qtbug-72236 \
- qtbug-76766
+ qtbug-76766 \
+ shader-image-qml \
+ scene3d-in-sync \
+ compressed_textures \
+ subtree-enabler-qml \
+ scene3d-visibility \
+ manual-renderloop
+
+!macos:!uikit: SUBDIRS += compute-manual
+
qtHaveModule(multimedia): {
SUBDIRS += \
@@ -74,5 +85,6 @@ qtHaveModule(widgets): {
SUBDIRS += \
assimp-cpp \
paintedtexture-cpp \
- rendercapture-cpp
+ rendercapture-cpp \
+ texture-updates-cpp
}
diff --git a/tests/manual/raster-cpp/main.cpp b/tests/manual/raster-cpp/main.cpp
new file mode 100644
index 000000000..2eaeea6ec
--- /dev/null
+++ b/tests/manual/raster-cpp/main.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+
+#include <Qt3DInput/QInputAspect>
+
+#include <Qt3DRender/qcamera.h>
+#include <Qt3DRender/qcameralens.h>
+#include <Qt3DExtras/qcylindermesh.h>
+#include <Qt3DRender/qmesh.h>
+#include <Qt3DRender/qtechnique.h>
+#include <Qt3DExtras/qphongmaterial.h>
+#include <Qt3DRender/qeffect.h>
+#include <Qt3DRender/qtexture.h>
+#include <Qt3DRender/qrenderpass.h>
+#include <Qt3DRender/qrenderaspect.h>
+#include <Qt3DExtras/qforwardrenderer.h>
+
+#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qtransform.h>
+#include <Qt3DCore/qaspectengine.h>
+
+#include <Qt3DRender/QRenderStateSet>
+#include <Qt3DRender/QRasterMode>
+
+#include <Qt3DExtras/qt3dwindow.h>
+#include <Qt3DExtras/qorbitcameracontroller.h>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+ Qt3DExtras::Qt3DWindow view;
+
+ // Add a raster mode
+ Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet();
+ view.activeFrameGraph()->setParent(renderStateSet);
+ Qt3DRender::QRasterMode *rasterModeRenderState = new Qt3DRender::QRasterMode(renderStateSet);
+ rasterModeRenderState->setRasterMode(Qt3DRender::QRasterMode::RasterMode::Lines);
+ renderStateSet->addRenderState(rasterModeRenderState);
+ view.setActiveFrameGraph(renderStateSet);
+
+ // Root entity
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
+
+ // Camera
+ Qt3DRender::QCamera *camera = view.camera();
+ camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
+ camera->setPosition(QVector3D(0, 0, 20.0f));
+ camera->setUpVector(QVector3D(0, 1, 0));
+ camera->setViewCenter(QVector3D(0, 0, 0));
+
+ // For camera controls
+ Qt3DExtras::QOrbitCameraController *cameraController = new Qt3DExtras::QOrbitCameraController(rootEntity);
+ cameraController->setCamera(camera);
+
+ // Cylinder shape data
+ Qt3DExtras::QCylinderMesh *mesh = new Qt3DExtras::QCylinderMesh();
+ mesh->setRadius(1);
+ mesh->setLength(3);
+ mesh->setRings(100);
+ mesh->setSlices(20);
+
+ // Transform for cylinder
+ Qt3DCore::QTransform *transform = new Qt3DCore::QTransform;
+ transform->setScale(1.5f);
+ transform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.0f));
+
+ // Material
+ Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial(rootEntity);
+ material->setDiffuse(Qt::red);
+
+ // Cylinder
+ Qt3DCore::QEntity *cylinder = new Qt3DCore::QEntity(rootEntity);
+ cylinder->addComponent(mesh);
+ cylinder->addComponent(transform);
+ cylinder->addComponent(material);
+
+ // Set root object of the scene
+ view.setRootEntity(rootEntity);
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/raster-cpp/raster-cpp.pro b/tests/manual/raster-cpp/raster-cpp.pro
new file mode 100644
index 000000000..d3db3bc76
--- /dev/null
+++ b/tests/manual/raster-cpp/raster-cpp.pro
@@ -0,0 +1,9 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dinput 3dextras
+
+SOURCES += main.cpp
+
+
diff --git a/tests/manual/raster-qml/main.cpp b/tests/manual/raster-qml/main.cpp
new file mode 100644
index 000000000..3741265c7
--- /dev/null
+++ b/tests/manual/raster-qml/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DQuickExtras/qt3dquickwindow.h>
+#include <QGuiApplication>
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+ Qt3DExtras::Quick::Qt3DQuickWindow view;
+
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/raster-qml/main.qml b/tests/manual/raster-qml/main.qml
new file mode 100644
index 000000000..91fc288d0
--- /dev/null
+++ b/tests/manual/raster-qml/main.qml
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.0
+import Qt3D.Render 2.13
+import Qt3D.Input 2.0
+import Qt3D.Extras 2.0
+
+Entity {
+ id: sceneRoot
+
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ aspectRatio: 16/9
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 0.0, 20.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ OrbitCameraController { camera: camera }
+
+ RenderSettings {
+ id : external_forward_renderer
+ activeFrameGraph : RenderStateSet {
+ renderStates: [
+ RasterMode {
+ rasterMode: RasterMode.Lines
+ }
+ ]
+ ForwardRenderer {
+ camera: camera
+ clearColor: "black"
+ }
+ }
+ }
+
+ // Event Source will be set by the Qt3DQuickWindow
+ InputSettings { id: inputSettings }
+
+ components: [external_forward_renderer, inputSettings]
+
+ CylinderMesh {
+ id: mesh
+ radius: 1
+ length: 3
+ rings: 100
+ slices: 20
+ }
+
+ Transform {
+ id: transform
+ scale: 1.5
+ rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45)
+ }
+
+ PhongMaterial {
+ id: material
+ diffuse: "green"
+ }
+
+ Entity {
+ id: mainEntity
+ objectName: "mainEntity"
+ components: [ mesh, material, transform ]
+ }
+}
diff --git a/tests/manual/raster-qml/raster-qml.pro b/tests/manual/raster-qml/raster-qml.pro
new file mode 100644
index 000000000..a3d377ca3
--- /dev/null
+++ b/tests/manual/raster-qml/raster-qml.pro
@@ -0,0 +1,14 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ raster-qml.qrc
diff --git a/tests/manual/raster-qml/raster-qml.qrc b/tests/manual/raster-qml/raster-qml.qrc
new file mode 100644
index 000000000..5f6483ac3
--- /dev/null
+++ b/tests/manual/raster-qml/raster-qml.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/scene3d-in-sync/main.cpp b/tests/manual/scene3d-in-sync/main.cpp
new file mode 100644
index 000000000..8886263f4
--- /dev/null
+++ b/tests/manual/scene3d-in-sync/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQuickView>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ view.resize(500, 500);
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/scene3d-in-sync/main.qml b/tests/manual/scene3d-in-sync/main.qml
new file mode 100644
index 000000000..31d4096a7
--- /dev/null
+++ b/tests/manual/scene3d-in-sync/main.qml
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt3D.Core 2.9
+import Qt3D.Render 2.9
+import Qt3D.Input 2.0
+import Qt3D.Extras 2.9
+import QtQuick.Scene3D 2.0
+
+Item {
+ id: root
+ property int _trackingPosition : 0
+ readonly property int squareSize: 100
+
+ Timer {
+ running: true
+ interval: 16
+ repeat: true
+ onTriggered: {
+ _trackingPosition += 1
+ if ((_trackingPosition + squareSize) >= root.width)
+ _trackingPosition = 0
+ }
+ }
+
+ // Scene3D + Qt3D content
+ Scene3D {
+ id: sceneThreeD
+ readonly property double halfWidth: width * 0.5
+
+ focus: true
+ anchors.fill: parent
+ // anchors.margins: -15
+ // Make sure to define the input aspect if we want to handle inputs
+ aspects: ["render", "input"]
+ multisample: false
+
+ Entity { // Root
+ id: sceneRoot
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ id: forwardRenderer
+ camera: planeCamera
+ clearColor: "yellow"
+ }
+ },
+ // Event Source is the Scene3D in that case
+ InputSettings { }
+ ]
+
+ Camera {
+ id: planeCamera
+ left: -sceneThreeD.halfWidth
+ right: sceneThreeD.halfWidth
+ bottom: -(sceneThreeD.height * 0.5)
+ top: (sceneThreeD.height * 0.5)
+ nearPlane: -100
+ farPlane: 100
+ projectionType: CameraLens.OrthographicProjection
+ position: Qt.vector3d(0, 0, 10)
+ viewCenter: Qt.vector3d(0, 0, 0)
+ }
+
+ Entity {
+ id: trackingCube
+ components: [
+ CuboidMesh {
+ xExtent: 100
+ yExtent: 100
+ zExtent: 2
+ },
+
+ PhongMaterial {
+ diffuse: "orange"
+ ambient: "orange"
+ },
+
+ Transform {
+ translation: Qt.vector3d(-sceneThreeD.halfWidth + squareSize * 0.5 + _trackingPosition, -50, 0)
+ }
+ ]
+ }
+ }
+ }
+
+ // QtQuick Content
+ Rectangle {
+ id: qtQuickTracer
+ x: _trackingPosition
+ onXChanged: {
+ console.info("Tracking position is now:" + _trackingPosition);
+ }
+
+ y: root.height * 0.5 - height
+ width: squareSize; height: squareSize
+ color: "red"
+ //transformOrigin: Item.Center
+ Text {
+ color: "white"
+ text: "Rendered with QtQuick"
+ anchors.fill: parent
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ wrapMode: Text.WrapAnywhere
+ }
+
+ Text {
+ color: "white"
+ text: "Rendered with Qt3D"
+ width: parent.width
+ height: parent.height
+ anchors.top: parent.bottom
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ wrapMode: Text.WrapAnywhere
+ }
+
+ Rectangle {
+ width: 1
+ height: 200
+ x: 100
+ color: "black"
+ }
+ }
+}
diff --git a/tests/manual/scene3d-in-sync/scene3d-in-sync.pro b/tests/manual/scene3d-in-sync/scene3d-in-sync.pro
new file mode 100644
index 000000000..521bf2a44
--- /dev/null
+++ b/tests/manual/scene3d-in-sync/scene3d-in-sync.pro
@@ -0,0 +1,10 @@
+QT += qml quick 3dinput
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ scene3d-in-sync.qrc
diff --git a/tests/manual/scene3d-in-sync/scene3d-in-sync.qrc b/tests/manual/scene3d-in-sync/scene3d-in-sync.qrc
new file mode 100644
index 000000000..5f6483ac3
--- /dev/null
+++ b/tests/manual/scene3d-in-sync/scene3d-in-sync.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/scene3d-visibility/main.cpp b/tests/manual/scene3d-visibility/main.cpp
new file mode 100644
index 000000000..8886263f4
--- /dev/null
+++ b/tests/manual/scene3d-visibility/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQuickView>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ QQuickView view;
+
+ view.resize(500, 500);
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/scene3d-visibility/main.qml b/tests/manual/scene3d-visibility/main.qml
new file mode 100644
index 000000000..ccfa3227f
--- /dev/null
+++ b/tests/manual/scene3d-visibility/main.qml
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Input 2.14
+import Qt3D.Extras 2.14
+import QtQuick.Scene3D 2.14
+
+Item {
+ id: root
+
+ Timer {
+ running: true
+ repeat: true
+ interval: 2000
+ onTriggered: scene3d.visible = !scene3d.visible
+ }
+
+ // Scene3D
+ Scene3D {
+ id: scene3d
+ visible: false
+ readonly property double halfWidth: width * 0.5
+
+ focus: true
+ anchors.fill: parent
+ // Make sure to define the input aspect if we want to handle inputs
+ aspects: ["render", "input"]
+ multisample: false
+
+ Entity { // Root
+ id: sceneRoot
+ components: [
+ RenderSettings {
+ activeFrameGraph: ForwardRenderer {
+ id: forwardRenderer
+ camera: mainCamera
+ clearColor: "yellow"
+ }
+ },
+ // Event Source is the Scene3D in that case
+ InputSettings { }
+ ]
+
+ Camera {
+ id: mainCamera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 0.0, -40.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ PhongMaterial {
+ id: material
+ }
+
+ TorusMesh {
+ id: torusMesh
+ radius: 5
+ minorRadius: 1
+ rings: 100
+ slices: 20
+ }
+
+ SphereMesh {
+ id: sphereMesh
+ radius: 3
+ }
+
+ Transform {
+ id: torusTransform
+ scale3D: Qt.vector3d(1.5, 1, 0.5)
+ rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45)
+ }
+
+ Transform {
+ id: sphereTransform
+ property real userAngle: 0.0
+ matrix: {
+ var m = Qt.matrix4x4();
+ m.rotate(userAngle, Qt.vector3d(0, 1, 0));
+ m.translate(Qt.vector3d(20, 0, 0));
+ return m;
+ }
+
+ onWorldMatrixChanged: console.log("Sphere WorldMatrix " + worldMatrix)
+ }
+
+ NumberAnimation {
+ target: sphereTransform
+ property: "userAngle"
+ duration: 1000
+ from: 0
+ to: 360
+ loops: Animation.Infinite
+ running: true
+ }
+
+ Entity {
+ id: torusEntity
+ components: [ torusMesh, material, torusTransform ]
+ }
+ Entity {
+ id: sphereEntity
+ components: [ sphereMesh, material, sphereTransform ]
+ }
+ }
+ }
+}
diff --git a/tests/manual/scene3d-visibility/scene3d-visibility.pro b/tests/manual/scene3d-visibility/scene3d-visibility.pro
new file mode 100644
index 000000000..a1c20a502
--- /dev/null
+++ b/tests/manual/scene3d-visibility/scene3d-visibility.pro
@@ -0,0 +1,10 @@
+QT += qml quick 3dinput
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ scene3d-visibility.qrc
diff --git a/tests/manual/scene3d-visibility/scene3d-visibility.qrc b/tests/manual/scene3d-visibility/scene3d-visibility.qrc
new file mode 100644
index 000000000..5f6483ac3
--- /dev/null
+++ b/tests/manual/scene3d-visibility/scene3d-visibility.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/shader-image-qml/image_512x512.jpg b/tests/manual/shader-image-qml/image_512x512.jpg
new file mode 100644
index 000000000..2164904cf
--- /dev/null
+++ b/tests/manual/shader-image-qml/image_512x512.jpg
Binary files differ
diff --git a/tests/manual/shader-image-qml/main.cpp b/tests/manual/shader-image-qml/main.cpp
new file mode 100644
index 000000000..7e359fd4c
--- /dev/null
+++ b/tests/manual/shader-image-qml/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DQuickExtras/qt3dquickwindow.h>
+#include <QGuiApplication>
+
+int main(int argc, char* argv[])
+{
+ QGuiApplication app(argc, argv);
+ Qt3DExtras::Quick::Qt3DQuickWindow view;
+
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/shader-image-qml/main.qml b/tests/manual/shader-image-qml/main.qml
new file mode 100644
index 000000000..fb3878503
--- /dev/null
+++ b/tests/manual/shader-image-qml/main.qml
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Input 2.0
+import Qt3D.Extras 2.0
+
+Entity {
+ id: sceneRoot
+
+ components: [
+ RenderSettings {
+ id : external_forward_renderer
+ activeFrameGraph : RenderSurfaceSelector {
+ Viewport {
+ // Launch Compute Shader Instances
+ DispatchCompute {
+ }
+
+ // Draw Textures
+ CameraSelector {
+ camera: camera
+ ClearBuffers { buffers: ClearBuffers.ColorDepthBuffer
+ // Ensure we won't be reading from textures if Compute Shader instances aren't completed
+ MemoryBarrier { waitFor: MemoryBarrier.ShaderImageAccess|MemoryBarrier.TextureFetch }
+ }
+ }
+ }
+ }
+ },
+ // Event Source will be set by the Qt3DQuickWindow
+ InputSettings { id: inputSettings }
+ ]
+
+ Camera {
+ id: camera
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ aspectRatio: 16/9
+ nearPlane : 0.1
+ farPlane : 1000.0
+ position: Qt.vector3d( 0.0, 0.0, 3.0 )
+ upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
+ viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
+ }
+
+ Texture2D {
+ id: inputTexture
+ width: 512
+ height: 512
+ format: Texture.RGBA8_UNorm
+ generateMipMaps: false
+ magnificationFilter: Texture.Linear
+ minificationFilter: Texture.Linear
+ wrapMode {
+ x: WrapMode.ClampToEdge
+ y: WrapMode.ClampToEdge
+ }
+
+ // Texture image which are referencing regular image extensions (jpg, png)
+ // are loaded through a QImage based texture image generator which generates
+ // RGBA8_UNorm based content
+ TextureImage {
+ source: "qrc:/image_512x512.jpg"
+ mirrored: false
+ }
+ }
+
+ Texture2D {
+ id: outputTexture
+ width: 512
+ height: 512
+ format: Texture.RGBA8_UNorm
+ generateMipMaps: false
+ magnificationFilter: Texture.Linear
+ minificationFilter: Texture.Linear
+ wrapMode {
+ x: WrapMode.ClampToEdge
+ y: WrapMode.ClampToEdge
+ }
+ }
+
+ // Compute -> Generate Output Texture Content
+ Entity {
+ readonly property Material material: Material {
+ parameters: [
+ Parameter {
+ name: "inputImage"
+ value: ShaderImage {
+ texture: inputTexture
+ layer: 0 // default
+ layered: false // default
+ mipLevel: 0 // default
+ access: ShaderImage.ReadOnly // default is ReadWrite
+ format: ShaderImage.Automatic // default
+ }
+ },
+ Parameter {
+ name: "outputImage"
+ value: ShaderImage {
+ texture: outputTexture
+ access: ShaderImage.WriteOnly // default is ReadWrite
+ format: ShaderImage.RGBA8_UNorm
+ }
+ }
+ ]
+
+ effect: Effect {
+ techniques: Technique {
+ graphicsApiFilter {
+ api: GraphicsApiFilter.OpenGL
+ profile: GraphicsApiFilter.CoreProfile
+ majorVersion: 4
+ minorVersion: 3
+ }
+ renderPasses: RenderPass {
+ shaderProgram: ShaderProgram {
+ computeShaderCode:
+ "#version 430
+
+ layout(local_size_x = 16, local_size_y = 16) in;
+ layout(rgba8) readonly uniform image2D inputImage;
+ layout(rgba8) writeonly uniform image2D outputImage;
+ uniform float time;
+ void main(void) {
+ ivec2 imageCoords = ivec2(gl_GlobalInvocationID.xy);
+
+ // Early return if we are past the image's bounds
+ if (any(greaterThan(imageCoords, imageSize(inputImage))))
+ return;
+
+ // Read from input image
+ vec4 inputContent = imageLoad(inputImage, imageCoords);
+
+ // Store inputContent into output Image
+ imageStore(outputImage, imageCoords, inputContent * abs(sin(time)));
+ }"
+ }
+ }
+ }
+ }
+ }
+
+ readonly property ComputeCommand command: ComputeCommand {
+ readonly property int localWorkGroupSize: 16
+ workGroupX: Math.ceil(inputTexture.width / localWorkGroupSize)
+ workGroupY: Math.ceil(inputTexture.height / localWorkGroupSize)
+ }
+
+ components: [command, material]
+ }
+
+ // Preview Texture Scene
+ Entity {
+ PlaneMesh { id: planeMesh }
+
+ components: Transform {
+ rotationX: 90
+ }
+
+ Entity {
+ id: inputTexturePreview
+ readonly property Material material: TextureMaterial {
+ texture: inputTexture
+ }
+ readonly property Transform transform: Transform {
+ translation: Qt.vector3d(-1, 0, 0)
+ }
+ components: [planeMesh, material, transform]
+ }
+
+ Entity {
+ id: outputTexturePreview
+ readonly property Material material: TextureMaterial {
+ texture: outputTexture
+ }
+ readonly property Transform transform: Transform {
+ translation: Qt.vector3d(1, 0, 0)
+ }
+ components: [planeMesh, material, transform]
+ }
+ }
+}
diff --git a/tests/manual/shader-image-qml/shader-image-qml.pro b/tests/manual/shader-image-qml/shader-image-qml.pro
new file mode 100644
index 000000000..3b839f8a3
--- /dev/null
+++ b/tests/manual/shader-image-qml/shader-image-qml.pro
@@ -0,0 +1,14 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ shader-image-qml.qrc
diff --git a/tests/manual/shader-image-qml/shader-image-qml.qrc b/tests/manual/shader-image-qml/shader-image-qml.qrc
new file mode 100644
index 000000000..c5fbef1c6
--- /dev/null
+++ b/tests/manual/shader-image-qml/shader-image-qml.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>image_512x512.jpg</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/sharedtexture/main.cpp b/tests/manual/sharedtexture/main.cpp
index a85f90ee6..6f2ef42f2 100644
--- a/tests/manual/sharedtexture/main.cpp
+++ b/tests/manual/sharedtexture/main.cpp
@@ -137,8 +137,7 @@ int main(int argc, char* argv[])
// Multimedia player
TextureWidget textureWidget;
- VideoPlayerThread *videoPlayer = new VideoPlayerThread(&textureWidget);
- videoPlayer->start();
+ VideoPlayer *videoPlayer = new VideoPlayer(&textureWidget);
textureWidget.resize(800, 600);
textureWidget.show();
diff --git a/tests/manual/sharedtexture/videoplayer.cpp b/tests/manual/sharedtexture/videoplayer.cpp
index f970116b5..2e52b85e0 100644
--- a/tests/manual/sharedtexture/videoplayer.cpp
+++ b/tests/manual/sharedtexture/videoplayer.cpp
@@ -57,8 +57,6 @@ TextureWidget::TextureWidget(QWidget *parent)
: QOpenGLWidget(parent)
, m_texture(QOpenGLTexture::Target2D)
{
- // Lock mutex so that we never process a frame until we have been initialized
- m_mutex.lock();
}
// Main thread
@@ -104,14 +102,11 @@ void TextureWidget::initializeGL()
qDebug() << Q_FUNC_INFO << context()->shareContext();
m_vao.create();
- // Allow rendering/frame acquisition to go on
- m_mutex.unlock();
}
// Main thread
void TextureWidget::paintGL()
{
- QMutexLocker lock(&m_mutex);
glViewport(0, 0, width(), height());
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
@@ -131,12 +126,8 @@ void TextureWidget::paintGL()
m_shader.release();
}
-// Video Player thread
void TextureWidget::setVideoFrame(const QVideoFrame &frame)
{
- // Ensure we won't be rendering while we are processing the frame
- QMutexLocker lock(&m_mutex);
-
QVideoFrame f = frame;
// Map frame
@@ -194,16 +185,14 @@ bool GLVideoSurface::present(const QVideoFrame &frame)
return true;
}
-VideoPlayerThread::VideoPlayerThread(TextureWidget *textureWidget)
- : QThread(textureWidget)
+VideoPlayer::VideoPlayer(TextureWidget *textureWidget)
+ : QObject(textureWidget)
, m_player(new QMediaPlayer(nullptr, QMediaPlayer::VideoSurface))
, m_surface(new GLVideoSurface())
{
- m_player->moveToThread(this);
- m_player->setMedia(QUrl("https://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"));
+ m_player->setMedia(QUrl("https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4"));
// Tell player to render on GLVideoSurface
- m_surface->moveToThread(this);
m_player->setVideoOutput(m_surface.get());
// Display errors
@@ -218,16 +207,13 @@ VideoPlayerThread::VideoPlayerThread(TextureWidget *textureWidget)
m_player->play();
});
- // Start playing when thread starts
- QObject::connect(this, &QThread::started, this, [this] { m_player->play(); });
-
- // Direct connection between 2 objects living in different threads
QObject::connect(m_surface.get(), &GLVideoSurface::onNewFrame,
textureWidget, &TextureWidget::setVideoFrame, Qt::DirectConnection);
+
+ // Start playing
+ m_player->play();
}
-VideoPlayerThread::~VideoPlayerThread()
+VideoPlayer::~VideoPlayer()
{
- exit(0);
- wait();
}
diff --git a/tests/manual/sharedtexture/videoplayer.h b/tests/manual/sharedtexture/videoplayer.h
index 377ea57fe..a96cb16b1 100644
--- a/tests/manual/sharedtexture/videoplayer.h
+++ b/tests/manual/sharedtexture/videoplayer.h
@@ -48,9 +48,6 @@
**
****************************************************************************/
-#include <QThread>
-#include <QMutex>
-
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLVertexArrayObject>
@@ -90,7 +87,6 @@ private:
QOpenGLVertexArrayObject m_vao;
QOpenGLShaderProgram m_shader;
QOpenGLTexture m_texture;
- QMutex m_mutex;
};
@@ -108,12 +104,12 @@ Q_SIGNALS:
};
-class VideoPlayerThread : public QThread
+class VideoPlayer : public QObject
{
Q_OBJECT
public:
- VideoPlayerThread(TextureWidget *textureWidget);
- ~VideoPlayerThread();
+ VideoPlayer(TextureWidget *textureWidget);
+ ~VideoPlayer();
private:
TextureWidget *m_textureWidget;
diff --git a/tests/manual/sharedtextureqml/main.cpp b/tests/manual/sharedtextureqml/main.cpp
index 5c7ae9cff..c0a79e6f8 100644
--- a/tests/manual/sharedtextureqml/main.cpp
+++ b/tests/manual/sharedtextureqml/main.cpp
@@ -108,8 +108,7 @@ int main(int argc, char* argv[])
// Multimedia player
TextureWidget textureWidget;
- VideoPlayerThread *videoPlayer = new VideoPlayerThread(&textureWidget);
- videoPlayer->start();
+ VideoPlayer *videoPlayer = new VideoPlayer(&textureWidget);
textureWidget.resize(800, 600);
textureWidget.show();
diff --git a/tests/manual/subtree-enabler-qml/FrameGraph.qml b/tests/manual/subtree-enabler-qml/FrameGraph.qml
new file mode 100644
index 000000000..b9cdce9ea
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/FrameGraph.qml
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import QtQuick 2.14 as QQ2
+
+RenderSettings {
+ id: frameGraph
+
+ property alias leftCamera: cameraSelectorLeftViewport.camera;
+ property alias rightCamera: cameraSelectorRightViewport.camera;
+ property alias window: surfaceSelector.surface
+
+ activeFrameGraph: RenderSurfaceSelector {
+ id: surfaceSelector
+
+ Viewport {
+ id: mainViewport
+ normalizedRect: Qt.rect(0, 0, 1, 1)
+
+ ClearBuffers {
+ buffers: ClearBuffers.ColorDepthBuffer
+ clearColor: Qt.rgba(0.6, 0.6, 0.6, 1.0)
+ NoDraw {}
+ }
+
+ Viewport {
+ id: leftViewport
+ normalizedRect: Qt.rect(0, 0, 0.5, 0.5)
+ CameraSelector { id: cameraSelectorLeftViewport }
+ }
+
+ SubtreeEnabler {
+ id: enabler
+ enabled: true
+
+ QQ2.Timer {
+ running: true
+ repeat: true
+ interval: 1000
+ onTriggered: enabler.enabled = !enabler.enabled
+ }
+
+ Viewport {
+ id: rightViewport
+ normalizedRect: Qt.rect(0.5, 0.5, 0.5, 0.5)
+ CameraSelector { id: cameraSelectorRightViewport }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/manual/subtree-enabler-qml/SimpleCamera.qml b/tests/manual/subtree-enabler-qml/SimpleCamera.qml
new file mode 100644
index 000000000..a1ef6d01c
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/SimpleCamera.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+
+Entity {
+ id: root
+
+ property vector3d position: Qt.vector3d(0.0, 0.0, 10.0)
+ property vector3d viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
+ property vector3d upVector: Qt.vector3d(0.0, 1.0, 0.0)
+ property CameraLens lens: null
+
+ components: [lens, transform]
+
+ Transform {
+ id: transform
+ matrix: {
+ var m = Qt.matrix4x4();
+ m.translate(root.position)
+ var zAxis = root.position.minus(root.viewCenter).normalized()
+ var xAxis = root.upVector.crossProduct(zAxis).normalized();
+ var yAxis = zAxis.crossProduct(xAxis);
+ var r = Qt.matrix4x4(xAxis.x, yAxis.x, zAxis.x, 0,
+ xAxis.y, yAxis.y, zAxis.y, 0,
+ xAxis.z, yAxis.z, zAxis.z, 0,
+ 0, 0, 0, 1)
+ return m.times(r);
+ }
+ }
+}
diff --git a/tests/manual/subtree-enabler-qml/main.cpp b/tests/manual/subtree-enabler-qml/main.cpp
new file mode 100644
index 000000000..ce5b883bd
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <Qt3DQuickExtras/qt3dquickwindow.h>
+#include <QGuiApplication>
+
+int main(int ac, char **av)
+{
+ QGuiApplication app(ac, av);
+ Qt3DExtras::Quick::Qt3DQuickWindow view;
+ view.setSource(QUrl("qrc:/main.qml"));
+ view.show();
+
+ return app.exec();
+}
+
+
diff --git a/tests/manual/subtree-enabler-qml/main.qml b/tests/manual/subtree-enabler-qml/main.qml
new file mode 100644
index 000000000..c2e530893
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/main.qml
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import Qt3D.Core 2.14
+import Qt3D.Render 2.14
+import Qt3D.Input 2.14
+import Qt3D.Extras 2.14
+
+Entity {
+ id: rootNode
+ components: [frameGraph]
+
+ FrameGraph {
+ id: frameGraph
+ leftCamera: camera1
+ rightCamera: camera2
+ }
+
+ CameraLens {
+ id: cameraLens
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ aspectRatio: 16/9
+ nearPlane: 0.01
+ farPlane: 1000.0
+ }
+
+ SimpleCamera {
+ id: camera1
+ lens: cameraLens
+ position: Qt.vector3d(10.0, 1.0, 10.0)
+ viewCenter: Qt.vector3d(0.0, 1.0, 0.0)
+ }
+
+ SimpleCamera {
+ id: camera2
+ lens: cameraLens
+ position: Qt.vector3d(0.0, 0.0, 5.0)
+ viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
+ }
+
+ Entity {
+ id: sceneRoot
+ property real rotationAngle: 0
+
+ SequentialAnimation {
+ running: true
+ loops: Animation.Infinite
+ NumberAnimation { target: sceneRoot; property: "rotationAngle"; to: 360; duration: 4000; }
+ }
+
+ Entity {
+ components: [
+ Transform {
+ rotation: fromAxisAndAngle(Qt.vector3d(0, 0, 1), -sceneRoot.rotationAngle)
+ },
+ CylinderMesh {},
+ MetalRoughMaterial {}
+ ]
+ }
+ } // sceneRoot
+} // rootNode
diff --git a/tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro
new file mode 100644
index 000000000..ddd0ae561
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro
@@ -0,0 +1,17 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras
+
+HEADERS += \
+
+SOURCES += \
+ main.cpp
+
+OTHER_FILES += \
+ main.qml
+
+RESOURCES += \
+ subtree-enabler-qml.qrc \
+
diff --git a/tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc
new file mode 100644
index 000000000..e565b719f
--- /dev/null
+++ b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>FrameGraph.qml</file>
+ <file>SimpleCamera.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/tessellation-modes/tessellatedquadmesh.cpp b/tests/manual/tessellation-modes/tessellatedquadmesh.cpp
index 5fd1aedb2..8e9a09d98 100644
--- a/tests/manual/tessellation-modes/tessellatedquadmesh.cpp
+++ b/tests/manual/tessellation-modes/tessellatedquadmesh.cpp
@@ -61,7 +61,7 @@ public:
TessellatedGeometry(Qt3DCore::QNode *parent = nullptr)
: Qt3DRender::QGeometry(parent)
, m_positionAttribute(new Qt3DRender::QAttribute(this))
- , m_vertexBuffer(new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, this))
+ , m_vertexBuffer(new Qt3DRender::QBuffer(this))
{
const float positionData[] = {
-0.8f, -0.8f, 0.0f,
diff --git a/tests/manual/texture-updates-cpp/main.cpp b/tests/manual/texture-updates-cpp/main.cpp
new file mode 100644
index 000000000..4bdcb6b42
--- /dev/null
+++ b/tests/manual/texture-updates-cpp/main.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scene.h"
+
+#include <QGuiApplication>
+
+#include <Qt3DCore/qentity.h>
+#include <QtGui/QScreen>
+
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QSlider>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QPushButton>
+
+#include <Qt3DRender/qcamera.h>
+#include <Qt3DInput/QInputAspect>
+#include <Qt3DExtras/qforwardrenderer.h>
+#include <Qt3DExtras/qt3dwindow.h>
+#include <Qt3DExtras/qfirstpersoncameracontroller.h>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
+ view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f)));
+ QWidget *container = QWidget::createWindowContainer(view);
+ QSize screenSize = view->screen()->size();
+ container->setMinimumSize(QSize(200, 100));
+ container->setMaximumSize(screenSize);
+
+ Qt3DInput::QInputAspect *input = new Qt3DInput::QInputAspect;
+ view->registerAspect(input);
+
+ // Root entity
+ Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
+
+ // Camera
+ Qt3DRender::QCamera *cameraEntity = view->camera();
+
+ cameraEntity->setPosition(QVector3D(0, 0, 20.0f));
+ cameraEntity->setUpVector(QVector3D(0, 1, 0));
+ cameraEntity->setViewCenter(QVector3D(0, 0, 0));
+
+ // For camera controls
+ Qt3DExtras::QFirstPersonCameraController *camController = new Qt3DExtras::QFirstPersonCameraController(rootEntity);
+ camController->setCamera(cameraEntity);
+
+ // scene
+ Scene *scene = new Scene(rootEntity);
+ scene->run();
+
+ // Set root object of the scene
+ view->setRootEntity(rootEntity);
+
+ // create widget
+ QWidget *widget = new QWidget;
+ widget->setWindowTitle(QStringLiteral("QPaintedTexture Example"));
+
+ QVBoxLayout *hLayout = new QVBoxLayout(widget);
+ hLayout->addWidget(container, 1);
+
+ // Show window
+ widget->show();
+ widget->resize(1200, 800);
+
+ return app.exec();
+}
diff --git a/tests/manual/texture-updates-cpp/scene.cpp b/tests/manual/texture-updates-cpp/scene.cpp
new file mode 100644
index 000000000..274b9422f
--- /dev/null
+++ b/tests/manual/texture-updates-cpp/scene.cpp
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scene.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+#include <QtCore/QDateTime>
+
+#include <Qt3DExtras/QCuboidMesh>
+#include <Qt3DExtras/QDiffuseMapMaterial>
+#include <Qt3DRender/QTextureDataUpdate>
+#include <cstring>
+
+
+Scene::Scene(Qt3DCore::QEntity *rootEntity)
+ : m_rootEntity(rootEntity)
+{
+ // Cuboid shape data
+ Qt3DExtras::QCuboidMesh *cuboid = new Qt3DExtras::QCuboidMesh();
+
+ // CuboidMesh Transform
+ m_transform = new Qt3DCore::QTransform();
+ m_transform->setScale(4.0f);;
+
+ // create texture
+ m_texture = new Qt3DRender::QTexture2D();
+ m_texture->setWidth(512);
+ m_texture->setHeight(512);
+ m_texture->setFormat(Qt3DRender::QTexture2D::RGBA8_UNorm);
+ m_texture->setLayers(1);
+ m_texture->setGenerateMipMaps(false);
+ m_texture->setMinificationFilter(Qt3DRender::QTexture2D::Nearest);
+ m_texture->setMagnificationFilter(Qt3DRender::QTexture2D::Nearest);
+
+ Qt3DExtras::QDiffuseMapMaterial *mat = new Qt3DExtras::QDiffuseMapMaterial();
+ mat->setAmbient(QColor(64, 64, 64));
+ mat->setSpecular(QColor(255, 255, 255));
+ mat->setDiffuse(m_texture);
+
+ //Cuboid
+ m_cuboidEntity = new Qt3DCore::QEntity(m_rootEntity);
+ m_cuboidEntity->addComponent(cuboid);
+ m_cuboidEntity->addComponent(mat);
+ m_cuboidEntity->addComponent(m_transform);
+}
+
+Scene::~Scene()
+{
+}
+
+void Scene::run()
+{
+ QTimer *timer = new QTimer(this);
+ connect(timer, &QTimer::timeout, this, &Scene::updateTimer);
+ timer->start(50);
+}
+
+void Scene::updateTimer()
+{
+ static int yPos = 0;
+ static uchar pixelValue = 255;
+
+ m_transform->setRotation(QQuaternion::fromAxisAndAngle(0, 1, 0, m_angle));
+ m_angle += 0.4f;
+
+ QByteArray rawPixelData;
+ const int rows = 32;
+ rawPixelData.resize(512 * 4 * rows * sizeof(uchar));
+ uchar *pixels = reinterpret_cast<uchar *>(rawPixelData.data());
+ std::memset(pixels, pixelValue, 512 * rows * 4 * sizeof(uchar));
+
+ // QTextureImageData hold our raw content and size of subcontent
+ Qt3DRender::QTextureImageDataPtr imageData = Qt3DRender::QTextureImageDataPtr::create();
+ imageData->setWidth(512);
+ imageData->setHeight(rows);
+ imageData->setMipLevels(1);
+ imageData->setLayers(1);
+ // We upload the 4 components of an RGBA pixel as 4 uchar
+ imageData->setPixelFormat(QOpenGLTexture::RGBA);
+ imageData->setPixelType(QOpenGLTexture::UInt8);
+ imageData->setFormat(QOpenGLTexture::RGBA8_UNorm);
+ imageData->setData(rawPixelData, 4, false);
+
+ // QTextureDataUpdate references our updated content
+ // as well as x, y offsets where content needs to be uploaded
+ Qt3DRender::QTextureDataUpdate update;
+ update.setX(0);
+ update.setY(yPos);
+ update.setMipLevel(0);
+ update.setData(imageData);
+ // Send update to texture
+ m_texture->updateData(update);
+
+ if (yPos + rows >= 512)
+ pixelValue = pixelValue > 0U ? 0U : 255U;
+ yPos = (yPos + rows) % 512;
+
+}
diff --git a/tests/manual/texture-updates-cpp/scene.h b/tests/manual/texture-updates-cpp/scene.h
new file mode 100644
index 000000000..ce0db4331
--- /dev/null
+++ b/tests/manual/texture-updates-cpp/scene.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SCENE_H
+#define SCENE_H
+
+#include <QtCore/QObject>
+
+#include <Qt3DCore/QEntity>
+#include <Qt3DCore/QTransform>
+#include <Qt3DRender/QTexture>
+
+class Scene : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit Scene(Qt3DCore::QEntity *rootEntity);
+ ~Scene();
+
+ void run();
+
+private Q_SLOTS:
+ void updateTimer();
+
+private:
+ Qt3DCore::QEntity *m_rootEntity;
+
+ Qt3DCore::QEntity *m_cuboidEntity;
+ Qt3DCore::QTransform *m_transform;
+ Qt3DRender::QTexture2D *m_texture;
+
+ float m_angle = 0;
+};
+
+#endif // SCENE_H
+
diff --git a/tests/manual/texture-updates-cpp/texture-updates-cpp.pro b/tests/manual/texture-updates-cpp/texture-updates-cpp.pro
new file mode 100644
index 000000000..448d90ecd
--- /dev/null
+++ b/tests/manual/texture-updates-cpp/texture-updates-cpp.pro
@@ -0,0 +1,12 @@
+!include( ../manual.pri ) {
+ error( "Couldn't find the manual.pri file!" )
+}
+
+QT += 3dcore 3drender 3dinput 3dextras widgets
+
+SOURCES += \
+ main.cpp \
+ scene.cpp
+
+HEADERS += \
+ scene.h
diff --git a/tools/qgltf/qgltf.cpp b/tools/qgltf/qgltf.cpp
index 3cbe6f3d2..562e50911 100644
--- a/tools/qgltf/qgltf.cpp
+++ b/tools/qgltf/qgltf.cpp
@@ -83,14 +83,10 @@ private:
class AssimpIOSystem : public Assimp::IOSystem
{
public:
- AssimpIOSystem();
bool Exists(const char *pFile) const override;
char getOsSeparator() const override;
Assimp::IOStream *Open(const char *pFile, const char *pMode) override;
void Close(Assimp::IOStream *pFile) override;
-
-private:
- QHash<QByteArray, QIODevice::OpenMode> m_openModeMap;
};
AssimpIOStream::AssimpIOStream(QIODevice *device) :
@@ -151,18 +147,29 @@ void AssimpIOStream::Flush()
// we don't write via assimp
}
-AssimpIOSystem::AssimpIOSystem()
-{
- m_openModeMap[QByteArrayLiteral("r")] = QIODevice::ReadOnly;
- m_openModeMap[QByteArrayLiteral("r+")] = QIODevice::ReadWrite;
- m_openModeMap[QByteArrayLiteral("w")] = QIODevice::WriteOnly | QIODevice::Truncate;
- m_openModeMap[QByteArrayLiteral("w+")] = QIODevice::ReadWrite | QIODevice::Truncate;
- m_openModeMap[QByteArrayLiteral("a")] = QIODevice::WriteOnly | QIODevice::Append;
- m_openModeMap[QByteArrayLiteral("a+")] = QIODevice::ReadWrite | QIODevice::Append;
- m_openModeMap[QByteArrayLiteral("wb")] = QIODevice::WriteOnly;
- m_openModeMap[QByteArrayLiteral("wt")] = QIODevice::WriteOnly | QIODevice::Text;
- m_openModeMap[QByteArrayLiteral("rb")] = QIODevice::ReadOnly;
- m_openModeMap[QByteArrayLiteral("rt")] = QIODevice::ReadOnly | QIODevice::Text;
+static QIODevice::OpenMode openModeFromText(const char *name) noexcept
+{
+ static const struct OpenModeMapping {
+ char name[2];
+ ushort mode;
+ } openModeMapping[] = {
+ { { 'r', 0 }, QIODevice::ReadOnly },
+ { { 'r', '+' }, QIODevice::ReadWrite },
+ { { 'w', 0 }, QIODevice::WriteOnly | QIODevice::Truncate },
+ { { 'w', '+' }, QIODevice::ReadWrite | QIODevice::Truncate },
+ { { 'a', 0 }, QIODevice::WriteOnly | QIODevice::Append },
+ { { 'a', '+' }, QIODevice::ReadWrite | QIODevice::Append },
+ { { 'w', 'b' }, QIODevice::WriteOnly },
+ { { 'w', 't' }, QIODevice::WriteOnly | QIODevice::Text },
+ { { 'r', 'b' }, QIODevice::ReadOnly },
+ { { 'r', 't' }, QIODevice::ReadOnly | QIODevice::Text },
+ };
+
+ for (auto e : openModeMapping) {
+ if (qstrncmp(e.name, name, sizeof(OpenModeMapping::name)) == 0)
+ return static_cast<QIODevice::OpenMode>(e.mode);
+ }
+ return QIODevice::NotOpen;
}
bool AssimpIOSystem::Exists(const char *pFile) const
@@ -178,13 +185,13 @@ char AssimpIOSystem::getOsSeparator() const
Assimp::IOStream *AssimpIOSystem::Open(const char *pFile, const char *pMode)
{
const QString fileName(QString::fromUtf8(pFile));
- const QByteArray cleanedMode(QByteArray(pMode).trimmed());
+ const QLatin1String cleanedMode = QLatin1String{pMode}.trimmed();
- const QIODevice::OpenMode openMode = m_openModeMap.value(cleanedMode, QIODevice::NotOpen);
-
- QScopedPointer<QFile> file(new QFile(fileName));
- if (file->open(openMode))
- return new AssimpIOStream(file.take());
+ if (const QIODevice::OpenMode openMode = openModeFromText(cleanedMode.data())) {
+ QScopedPointer<QFile> file(new QFile(fileName));
+ if (file->open(openMode))
+ return new AssimpIOStream(file.take());
+ }
return nullptr;
}
diff --git a/tools/qgltf/qgltf.pro b/tools/qgltf/qgltf.pro
index df6dfa202..c40016015 100644
--- a/tools/qgltf/qgltf.pro
+++ b/tools/qgltf/qgltf.pro
@@ -1,8 +1,5 @@
option(host_build)
-# Qt3D is free of Q_FOREACH - make sure it stays that way:
-DEFINES *= QT_NO_FOREACH
-
SOURCES = qgltf.cpp
include(../../src/3rdparty/assimp/assimp_dependency.pri)