diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 1363debf4c..550658dc95 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -480,37 +480,6 @@ var elZTextureURL = document.getElementById("property-z-texture-url"); var elPreviewCameraButton = document.getElementById("preview-camera-button"); - - var urlUpdaters = document.getElementsByClassName("update-url-version"); - var PARAM_REGEXP = /(?:\?)(\S+)/; // Check if this has any parameters. - var TIMESTAMP_REGEXP = /(&?HFTime=\d+)/; - - var refreshEvent = function (event) { - var urlElement = event.target.parentElement.getElementsByTagName("INPUT")[0]; - var content = urlElement.value; - var date = new Date(); - var timeStamp = date.getTime(); - - if(content.length > 0){ - if(PARAM_REGEXP.test(content)){ - // Has params, so lets remove existing definition and append again. - content = content.replace(TIMESTAMP_REGEXP,"") + "&"; - }else{ - content += "?"; - } - content = content.replace("?&","?"); - urlElement.value = content + "HFTime=" + timeStamp; - } - - var evt = document.createEvent("HTMLEvents"); - evt.initEvent("change", true, true ); - urlElement.dispatchEvent(evt); - }; - - for(var index = 0; index < urlUpdaters.length; index++){ - var urlUpdater = urlUpdaters[index]; - urlUpdater.addEventListener("click", refreshEvent, true); - } if (window.EventBridge !== undefined) { var properties; @@ -1433,20 +1402,17 @@ -
+
-
-
+
-
-
+
-

@@ -1593,17 +1559,16 @@

-
+
-

-
+
-
M
-
+
-
-
+
-

-
+
-
@@ -1756,10 +1717,9 @@
-
+
-
@@ -1808,20 +1768,18 @@
-
+
-
M
-
+
-
diff --git a/examples/voxels.js b/examples/voxels.js index 4ca5d46ff7..19a31487fe 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -7,7 +7,8 @@ Script.include([ ]); var isActive = false; -var toolIconUrl = "http://headache.hungry.com/~seth/hifi/"; +var toolIconUrl = "https://s3-us-west-1.amazonaws.com/hifi-content/seth/production/icons/" + var toolHeight = 50; var toolWidth = 50; diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 409c468878..59278a17b4 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -21,7 +21,7 @@ Desktop { Component.onCompleted: { WebEngine.settings.javascriptCanOpenWindows = true; WebEngine.settings.javascriptCanAccessClipboard = false; - WebEngine.settings.spatialNavigationEnabled = true; + WebEngine.settings.spatialNavigationEnabled = false; WebEngine.settings.localContentCanAccessRemoteUrls = true; } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 64a2388a42..e31a874ba3 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -187,9 +187,10 @@ void Avatar::simulate(float deltaTime) { // simple frustum check float boundingRadius = getBoundingRadius(); - bool inView = qApp->getDisplayViewFrustum()->sphereIntersectsFrustum(getPosition(), boundingRadius); + bool avatarPositionInView = qApp->getDisplayViewFrustum()->sphereIntersectsFrustum(getPosition(), boundingRadius); + bool avatarMeshInView = qApp->getDisplayViewFrustum()->boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound()); - if (_shouldAnimate && !_shouldSkipRender && inView) { + if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) { { PerformanceTimer perfTimer("skeleton"); _skeletonModel->getRig()->copyJointsFromJointData(_jointData); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 30d3f9d83c..92bb98ad32 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -92,7 +92,7 @@ private: public: \ virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override { return _renderHelper.addToScene(self, scene, pendingChanges); } \ virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) override { _renderHelper.removeFromScene(self, scene, pendingChanges); } \ - virtual void locationChanged() override { EntityItem::locationChanged(); _renderHelper.notifyChanged(); } \ + virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); _renderHelper.notifyChanged(); } \ virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); _renderHelper.notifyChanged(); } \ private: \ SimpleRenderableEntityItem _renderHelper; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b510f58b12..879ff01056 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -271,10 +271,10 @@ bool RenderableModelEntityItem::getAnimationFrame() { return false; } - if (!hasAnimation() || !_jointMappingCompleted) { + if (!hasRenderAnimation() || !_jointMappingCompleted) { return false; } - AnimationPointer myAnimation = getAnimation(_animationProperties.getURL()); // FIXME: this could be optimized + AnimationPointer myAnimation = getAnimation(getRenderAnimationURL()); // FIXME: this could be optimized if (myAnimation && myAnimation->isLoaded()) { const QVector& frames = myAnimation->getFramesReference(); // NOTE: getFrames() is too heavy @@ -384,7 +384,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } if (_model) { - if (hasAnimation()) { + if (hasRenderAnimation()) { if (!jointsMapped()) { QStringList modelJointNames = _model->getJointNames(); mapJoints(modelJointNames); @@ -528,6 +528,9 @@ void RenderableModelEntityItem::update(const quint64& now) { } } + // make a copy of the animation properites + _renderAnimationProperties = _animationProperties; + ModelEntityItem::update(now); } @@ -795,8 +798,8 @@ void RenderableModelEntityItem::setJointTranslationsSet(const QVector& tra } -void RenderableModelEntityItem::locationChanged() { - EntityItem::locationChanged(); +void RenderableModelEntityItem::locationChanged(bool tellPhysics) { + EntityItem::locationChanged(tellPhysics); if (_model && _model->isActive()) { _model->setRotation(getRotation()); _model->setTranslation(getPosition()); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 6d40a80950..bf55c829e9 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -75,13 +75,18 @@ public: virtual void setJointTranslationsSet(const QVector& translationsSet) override; virtual void loader() override; - virtual void locationChanged() override; + virtual void locationChanged(bool tellPhysics = true) override; virtual void resizeJointArrays(int newSize = -1) override; virtual int getJointIndex(const QString& name) const override; virtual QStringList getJointNames() const override; + // These operate on a copy of the renderAnimationProperties, so they can be accessed + // without having the entityTree lock. + bool hasRenderAnimation() const { return !_renderAnimationProperties.getURL().isEmpty(); } + const QString& getRenderAnimationURL() const { return _renderAnimationProperties.getURL(); } + private: QVariantMap parseTexturesToMap(QString textures); void remapTextures(); @@ -97,6 +102,8 @@ private: QVector> _points; bool _dimensionsInitialized = true; + AnimationPropertyGroup _renderAnimationProperties; + render::ItemID _myMetaItem{ render::Item::INVALID_ITEM_ID }; bool _showCollisionHull = false; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 4d8eebf05b..a199c6b10e 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -39,6 +39,7 @@ public: InterpolationData radius; InterpolationData color; // rgba float lifespan; + glm::vec3 spare; }; struct ParticlePrimitive { diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 1f066a81fd..a36c3640d6 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -29,7 +29,7 @@ public: virtual void removeFromScene(EntityItemPointer self, render::ScenePointer scene, render::PendingChanges& pendingChanges) override; protected: - virtual void locationChanged() override { EntityItem::locationChanged(); notifyBoundChanged(); } + virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); } virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); notifyBoundChanged(); } void notifyBoundChanged(); diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index 4ba862fff8..241a066341 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -42,7 +42,7 @@ public: virtual void removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges); private: - virtual void locationChanged() override { EntityItem::locationChanged(); notifyBoundChanged(); } + virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); } virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); notifyBoundChanged(); } void notifyBoundChanged(); diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index d3747d21eb..79f75187c5 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -30,10 +30,10 @@ struct Colors { struct ParticleUniforms { Radii radius; Colors color; - float lifespan; + vec4 lifespan; // x is lifespan, 3 spare floats }; -uniform particleBuffer { +layout(std140) uniform particleBuffer { ParticleUniforms particle; }; @@ -112,7 +112,7 @@ void main(void) { int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; // Particle properties - float age = inColor.x / particle.lifespan; + float age = inColor.x / particle.lifespan.x; float seed = inColor.y; // Pass the texcoord and the z texcoord is representing the texture icon diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index 97c8a1816a..015d24ab74 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -244,6 +244,10 @@ void AnimationPropertyGroup::markAllChanged() { _fpsChanged = true; _currentFrameChanged = true; _runningChanged = true; + _loopChanged = true; + _firstFrameChanged = true; + _lastFrameChanged = true; + _holdChanged = true; } EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 4cd8a34248..6731bcc9fb 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -888,9 +888,6 @@ void EntityItem::simulateKinematicMotion(float timeElapsed, bool setFlags) { if (hasActions()) { return; } - if (!_parentID.isNull()) { - return; - } if (hasLocalAngularVelocity()) { glm::vec3 localAngularVelocity = getLocalAngularVelocity(); @@ -1976,14 +1973,16 @@ QList EntityItem::getActionsOfType(EntityActionType typeToG return result; } -void EntityItem::locationChanged() { +void EntityItem::locationChanged(bool tellPhysics) { requiresRecalcBoxes(); - _dirtyFlags |= Simulation::DIRTY_TRANSFORM; + if (tellPhysics) { + _dirtyFlags |= Simulation::DIRTY_TRANSFORM; + } EntityTreePointer tree = getTree(); if (tree) { tree->entityChanged(getThisPointer()); } - SpatiallyNestable::locationChanged(); // tell all the children, also + SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also } void EntityItem::dimensionsChanged() { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 622f78b2d3..08550c9ce5 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -432,7 +432,7 @@ protected: const QByteArray getActionDataInternal() const; void setActionDataInternal(QByteArray actionData); - virtual void locationChanged() override; + virtual void locationChanged(bool tellPhysics = true) override; virtual void dimensionsChanged() override; EntityTypes::EntityType _type; diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index c9de3ccd90..ffeaed4e4f 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -12,11 +12,12 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() { // Qt Quick may need a depth and stencil buffer. Always make sure these are available. format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS); format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS); - format.setVersion(4, 5); + setGLFormatVersion(format); #ifdef DEBUG format.setOption(QSurfaceFormat::DebugContext); #endif format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + QSurfaceFormat::setDefaultFormat(format); }); return format; } @@ -27,11 +28,12 @@ const QGLFormat& getDefaultGLFormat() { static QGLFormat glFormat; static std::once_flag once; std::call_once(once, [] { - glFormat.setVersion(4, 5); + setGLFormatVersion(glFormat); glFormat.setProfile(QGLFormat::CoreProfile); // Requires >=Qt-4.8.0 glFormat.setSampleBuffers(false); glFormat.setDepth(false); glFormat.setStencil(false); + QGLFormat::setDefaultFormat(glFormat); }); return glFormat; } diff --git a/libraries/gl/src/gl/GLHelpers.h b/libraries/gl/src/gl/GLHelpers.h index 335272d991..6e3d678d0c 100644 --- a/libraries/gl/src/gl/GLHelpers.h +++ b/libraries/gl/src/gl/GLHelpers.h @@ -19,6 +19,9 @@ class QSurfaceFormat; class QGLFormat; +template +void setGLFormatVersion(F& format, int major = 4, int minor = 5) { format.setVersion(major, minor); } + const QSurfaceFormat& getDefaultOpenGLSurfaceFormat(); const QGLFormat& getDefaultGLFormat(); #endif diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 1d7824f789..5f86bc13ec 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -569,7 +569,7 @@ QPointF OffscreenQmlSurface::mapToVirtualScreen(const QPointF& originalPoint, QO // Event handling customization // -bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* event) { +bool OffscreenQmlSurface::filterEnabled(QObject* originalDestination, QEvent* event) const { if (_renderer->_quickWindow == originalDestination) { return false; } @@ -577,7 +577,13 @@ bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* even if (_paused) { return false; } + return true; +} +bool OffscreenQmlSurface::eventFilter(QObject* originalDestination, QEvent* event) { + if (!filterEnabled(originalDestination, event)) { + return false; + } #ifdef DEBUG // Don't intercept our own events, or we enter an infinite recursion QObject* recurseTest = originalDestination; diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.h b/libraries/gl/src/gl/OffscreenQmlSurface.h index 3160df1c9d..22a1b99fe6 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.h +++ b/libraries/gl/src/gl/OffscreenQmlSurface.h @@ -66,7 +66,7 @@ public: QQmlContext* getRootContext(); QPointF mapToVirtualScreen(const QPointF& originalPoint, QObject* originalWidget); - virtual bool eventFilter(QObject* originalDestination, QEvent* event); + bool eventFilter(QObject* originalDestination, QEvent* event) override; signals: void textureUpdated(unsigned int texture); @@ -76,6 +76,9 @@ public slots: void requestRender(); void onAboutToQuit(); +protected: + bool filterEnabled(QObject* originalDestination, QEvent* event) const; + private: QObject* finishQmlLoad(std::function f); QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 700160514c..a9dcb4a16c 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -207,8 +207,16 @@ void EntityMotionState::setWorldTransform(const btTransform& worldTrans) { assert(entityTreeIsLocked()); measureBodyAcceleration(); - _entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset()); - _entity->setRotation(bulletToGLM(worldTrans.getRotation())); + bool positionSuccess; + _entity->setPosition(bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset(), positionSuccess, false); + if (!positionSuccess) { + qDebug() << "EntityMotionState::setWorldTransform setPosition failed" << _entity->getID(); + } + bool orientationSuccess; + _entity->setOrientation(bulletToGLM(worldTrans.getRotation()), orientationSuccess, false); + if (!orientationSuccess) { + qDebug() << "EntityMotionState::setWorldTransform setOrientation failed" << _entity->getID(); + } _entity->setVelocity(getBodyLinearVelocity()); _entity->setAngularVelocity(getBodyAngularVelocity()); _entity->setLastSimulated(usecTimestampNow()); diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 96a5a1d8ae..11d0668001 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -314,7 +314,7 @@ glm::vec3 SpatiallyNestable::getPosition(int jointIndex, bool& success) const { return getTransform(jointIndex, success).getTranslation(); } -void SpatiallyNestable::setPosition(const glm::vec3& position, bool& success) { +void SpatiallyNestable::setPosition(const glm::vec3& position, bool& success, bool tellPhysics) { // guard against introducing NaN into the transform if (isNaN(position)) { success = false; @@ -328,7 +328,7 @@ void SpatiallyNestable::setPosition(const glm::vec3& position, bool& success) { Transform::inverseMult(_transform, parentTransform, myWorldTransform); }); if (success) { - locationChanged(); + locationChanged(tellPhysics); } else { qDebug() << "setPosition failed for" << getID(); } @@ -363,7 +363,7 @@ glm::quat SpatiallyNestable::getOrientation(int jointIndex, bool& success) const return getTransform(jointIndex, success).getRotation(); } -void SpatiallyNestable::setOrientation(const glm::quat& orientation, bool& success) { +void SpatiallyNestable::setOrientation(const glm::quat& orientation, bool& success, bool tellPhysics) { // guard against introducing NaN into the transform if (isNaN(orientation)) { success = false; @@ -378,7 +378,7 @@ void SpatiallyNestable::setOrientation(const glm::quat& orientation, bool& succe Transform::inverseMult(_transform, parentTransform, myWorldTransform); }); if (success) { - locationChanged(); + locationChanged(tellPhysics); } } @@ -422,8 +422,18 @@ void SpatiallyNestable::setVelocity(const glm::vec3& velocity, bool& success) { glm::vec3 parentVelocity = getParentVelocity(success); Transform parentTransform = getParentTransform(success); _velocityLock.withWriteLock([&] { - // TODO: take parent angularVelocity into account. - _velocity = glm::inverse(parentTransform.getRotation()) * (velocity - parentVelocity); + // HACK: until we are treating _velocity the same way we treat _position (meaning, + // _velocity is a vs parent value and any request for a world-frame velocity must + // be computed), do this to avoid equipped (parenting-grabbed) things from drifting. + // turning a zero velocity into a non-zero _velocity (because the avatar is moving) + // causes EntityItem::simulateKinematicMotion to have an effect on the equipped entity, + // which causes it to drift from the hand. + if (hasAncestorOfType(NestableType::Avatar)) { + _velocity = velocity; + } else { + // TODO: take parent angularVelocity into account. + _velocity = glm::inverse(parentTransform.getRotation()) * (velocity - parentVelocity); + } }); } @@ -751,9 +761,9 @@ void SpatiallyNestable::forEachDescendant(std::functionlocationChanged(); + object->locationChanged(tellPhysics); }); } diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 58a141b1fa..c120c1010c 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -59,13 +59,13 @@ public: virtual glm::vec3 getPosition(bool& success) const; virtual glm::vec3 getPosition() const; - virtual void setPosition(const glm::vec3& position, bool& success); + virtual void setPosition(const glm::vec3& position, bool& success, bool tellPhysics = true); virtual void setPosition(const glm::vec3& position); virtual glm::quat getOrientation(bool& success) const; virtual glm::quat getOrientation() const; virtual glm::quat getOrientation(int jointIndex, bool& success) const; - virtual void setOrientation(const glm::quat& orientation, bool& success); + virtual void setOrientation(const glm::quat& orientation, bool& success, bool tellPhysics = true); virtual void setOrientation(const glm::quat& orientation); virtual glm::vec3 getVelocity(bool& success) const; @@ -159,7 +159,7 @@ protected: mutable ReadWriteLockable _childrenLock; mutable QHash _children; - virtual void locationChanged(); // called when a this object's location has changed + virtual void locationChanged(bool tellPhysics = true); // called when a this object's location has changed virtual void dimensionsChanged() { } // called when a this object's dimensions have changed // _queryAACube is used to decide where something lives in the octree diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 269cf86e2d..8cc0522ce5 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -563,5 +563,38 @@ QString OffscreenUi::getSaveFileName(void* ignored, const QString &caption, cons return DependencyManager::get()->fileSaveDialog(caption, dir, filter, selectedFilter, options); } +bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) { + if (!filterEnabled(originalDestination, event)) { + return false; + } + + // let the parent class do it's work + bool result = OffscreenQmlSurface::eventFilter(originalDestination, event); + + // Check if this is a key press/release event that might need special attention + auto type = event->type(); + if (type != QEvent::KeyPress && type != QEvent::KeyRelease) { + return result; + } + + QKeyEvent* keyEvent = dynamic_cast(event); + bool& pressed = _pressedKeys[keyEvent->key()]; + + // Keep track of which key press events the QML has accepted + if (result && QEvent::KeyPress == type) { + pressed = true; + } + + // QML input elements absorb key press, but apparently not key release. + // therefore we want to ensure that key release events for key presses that were + // accepted by the QML layer are suppressed + if (!result && type == QEvent::KeyRelease && pressed) { + pressed = false; + return true; + } + + return result; +} #include "OffscreenUi.moc" + diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index 0188ac5365..f219d0fea8 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -12,6 +12,7 @@ #ifndef hifi_OffscreenUi_h #define hifi_OffscreenUi_h +#include #include #include #include @@ -37,6 +38,7 @@ public: void setNavigationFocused(bool focused); void unfocusWindows(); void toggleMenu(const QPoint& screenCoordinates); + bool eventFilter(QObject* originalDestination, QEvent* event) override; QQuickItem* getDesktop(); QQuickItem* getToolWindow(); @@ -131,6 +133,7 @@ private: QQuickItem* _desktop { nullptr }; QQuickItem* _toolWindow { nullptr }; + std::unordered_map _pressedKeys; }; #endif diff --git a/tests/gpu-test/src/main.cpp b/tests/gpu-test/src/main.cpp index 87ce2d7622..d1cd4389a7 100644 --- a/tests/gpu-test/src/main.cpp +++ b/tests/gpu-test/src/main.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -141,7 +142,7 @@ public: // Qt Quick may need a depth and stencil buffer. Always make sure these are available. format.setDepthBufferSize(16); format.setStencilBufferSize(8); - format.setVersion(4, 3); + setGLFormatVersion(format); format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); format.setOption(QSurfaceFormat::DebugContext); format.setSwapInterval(0); diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index 6a4154c8c3..6973ca075e 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -98,7 +99,7 @@ public: // Qt Quick may need a depth and stencil buffer. Always make sure these are available. format.setDepthBufferSize(16); format.setStencilBufferSize(8); - format.setVersion(4, 1); + setGLFormatVersion(format); format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); format.setOption(QSurfaceFormat::DebugContext);