From f9891775fcb0a1246ff669fbbfd5a0fdf93544dc Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 21 Jan 2019 23:07:59 -0800 Subject: [PATCH 001/139] Enabling msaa framebuffer and testing for forward --- .../gpu-gl-common/src/gpu/gl/GLTexture.cpp | 14 ++++++++++++-- .../gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp | 5 +++++ .../gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp | 17 ++++++++++++++--- libraries/gpu/src/gpu/State.h | 2 +- libraries/gpu/src/gpu/Texture.cpp | 8 ++++++++ libraries/gpu/src/gpu/Texture.h | 3 +++ .../render-utils/src/RenderForwardTask.cpp | 17 +++++++++++------ 7 files changed, 54 insertions(+), 12 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLTexture.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLTexture.cpp index e9494a1271..c8d6dbfdf0 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLTexture.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLTexture.cpp @@ -60,9 +60,17 @@ GLenum GLTexture::getGLTextureType(const Texture& texture) { switch (texture.getType()) { case Texture::TEX_2D: if (!texture.isArray()) { - return GL_TEXTURE_2D; + if (!texture.isMultisample()) { + return GL_TEXTURE_2D; + } else { + return GL_TEXTURE_2D_MULTISAMPLE; + } } else { - return GL_TEXTURE_2D_ARRAY; + if (!texture.isMultisample()) { + return GL_TEXTURE_2D_ARRAY; + } else { + return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; + } } break; @@ -81,7 +89,9 @@ GLenum GLTexture::getGLTextureType(const Texture& texture) { uint8_t GLTexture::getFaceCount(GLenum target) { switch (target) { case GL_TEXTURE_2D: + case GL_TEXTURE_2D_MULTISAMPLE: case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: return TEXTURE_2D_NUM_FACES; case GL_TEXTURE_CUBE_MAP: return TEXTURE_CUBE_NUM_FACES; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp index 86332558e3..7a299e792b 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendOutput.cpp @@ -62,6 +62,8 @@ public: if (gltexture) { if (gltexture->_target == GL_TEXTURE_2D) { glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0); + } else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) { + glNamedFramebufferTexture(_id, colorAttachments[unit], gltexture->_texture, 0); } else { glNamedFramebufferTextureLayer(_id, colorAttachments[unit], gltexture->_texture, 0, b._subresource); } @@ -93,6 +95,9 @@ public: if (gltexture) { if (gltexture->_target == GL_TEXTURE_2D) { glNamedFramebufferTexture(_id, attachement, gltexture->_texture, 0); + } + else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) { + glNamedFramebufferTexture(_id, attachement, gltexture->_texture, 0); } else { glNamedFramebufferTextureLayer(_id, attachement, gltexture->_texture, 0, _gpuObject.getDepthStencilBufferSubresource()); diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index e02f12819e..4f193e0ae8 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -375,11 +375,22 @@ void GL45FixedAllocationTexture::allocateStorage() const { const auto dimensions = _gpuObject.getDimensions(); const auto mips = _gpuObject.getNumMips(); const auto numSlices = _gpuObject.getNumSlices(); + const auto numSamples = _gpuObject.getNumSamples(); - if (!_gpuObject.isArray()) { - glTextureStorage2D(_id, mips, texelFormat.internalFormat, dimensions.x, dimensions.y); + + if (!_gpuObject.isMultisample()) { + if (!_gpuObject.isArray()) { + glTextureStorage2D(_id, mips, texelFormat.internalFormat, dimensions.x, dimensions.y); + } else { + glTextureStorage3D(_id, mips, texelFormat.internalFormat, dimensions.x, dimensions.y, numSlices); + } } else { - glTextureStorage3D(_id, mips, texelFormat.internalFormat, dimensions.x, dimensions.y, numSlices); + if (!_gpuObject.isArray()) { + glTextureStorage2DMultisample(_id, numSamples, texelFormat.internalFormat, dimensions.x, dimensions.y, GL_FALSE); + } + else { + glTextureStorage3DMultisample(_id, numSamples, texelFormat.internalFormat, dimensions.x, dimensions.y, numSlices, GL_FALSE); + } } glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0); diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index e68e829fb5..83f96f7925 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -263,7 +263,7 @@ public: frontFaceClockwise(false), depthClampEnable(false), scissorEnable(false), - multisampleEnable(false), + multisampleEnable(true), antialisedLineEnable(true), alphaToCoverageEnable(false) {} diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index c6f3cd9b9a..5c2e181810 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -176,10 +176,18 @@ TexturePointer Texture::createRenderBuffer(const Element& texelFormat, uint16 wi return create(TextureUsageType::RENDERBUFFER, TEX_2D, texelFormat, width, height, 1, 1, 0, numMips, sampler); } +TexturePointer Texture::createRenderBufferMultisample(const Element& texelFormat, uint16 width, uint16 height, uint16 numSamples, const Sampler& sampler) { + return create(TextureUsageType::RENDERBUFFER, TEX_2D, texelFormat, width, height, 1, numSamples, 0, gpu::Texture::SINGLE_MIP, sampler); +} + TexturePointer Texture::createRenderBufferArray(const Element& texelFormat, uint16 width, uint16 height, uint16 numSlices, uint16 numMips, const Sampler& sampler) { return create(TextureUsageType::RENDERBUFFER, TEX_2D, texelFormat, width, height, 1, 1, numSlices, numMips, sampler); } +TexturePointer Texture::createRenderBufferMultisampleArray(const Element& texelFormat, uint16 width, uint16 height, uint16 numSlices, uint16 numSamples, const Sampler& sampler) { + return create(TextureUsageType::RENDERBUFFER, TEX_2D, texelFormat, width, height, 1, numSamples, numSlices, gpu::Texture::SINGLE_MIP, sampler); +} + TexturePointer Texture::create1D(const Element& texelFormat, uint16 width, uint16 numMips, const Sampler& sampler) { return create(TextureUsageType::RESOURCE, TEX_1D, texelFormat, width, 1, 1, 1, 0, numMips, sampler); } diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 73ed1b15dc..24ee536a1b 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -383,7 +383,9 @@ public: static TexturePointer create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); static TexturePointer createCube(const Element& texelFormat, uint16 width, uint16 numMips = 1, const Sampler& sampler = Sampler()); static TexturePointer createRenderBuffer(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); + static TexturePointer createRenderBufferMultisample(const Element& texelFormat, uint16 width, uint16 height, uint16 numSamples, const Sampler& sampler = Sampler()); static TexturePointer createRenderBufferArray(const Element& texelFormat, uint16 width, uint16 height, uint16 numSlices, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); + static TexturePointer createRenderBufferMultisampleArray(const Element& texelFormat, uint16 width, uint16 height, uint16 numSlices, uint16 numSamples, const Sampler& sampler = Sampler()); static TexturePointer createStrict(const Element& texelFormat, uint16 width, uint16 height, uint16 numMips = SINGLE_MIP, const Sampler& sampler = Sampler()); static TexturePointer createExternal(const ExternalRecycler& recycler, const Sampler& sampler = Sampler()); @@ -431,6 +433,7 @@ public: uint16 getNumSamples() const { return _numSamples; } // NumSamples can only have certain values based on the hw static uint16 evalNumSamplesUsed(uint16 numSamplesTried); + bool isMultisample() const { return _numSamples > 1; } // max mip is in the range [ 0 if no sub mips, log2(max(width, height, depth))] // It is defined at creation time (immutable) diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index ffdbc1c4b1..8616214992 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -118,7 +118,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto transparentInputs = DrawForward::Inputs(transparents, lightingModel).asVarying(); task.addJob("DrawTransparents", transparentInputs, shapePlumber); - { // Debug the bounds of the rendered items, still look at the zbuffer + /* { // Debug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); task.addJob("DrawBounds", opaques); @@ -127,7 +127,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend task.addJob("DrawZones", zones); const auto debugZoneInputs = DebugZoneLighting::Inputs(deferredFrameTransform, lightFrame, backgroundFrame).asVarying(); task.addJob("DrawZoneStack", debugZoneInputs); - } + }*/ // Lighting Buffer ready for tone mapping // Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify @@ -141,7 +141,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // Disable blit because we do tonemapping and compositing directly to the blit FBO // Blit! - // task.addJob("Blit", framebuffer); + task.addJob("Blit", framebuffer); } void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { @@ -157,13 +157,18 @@ void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::Fra auto colorFormat = gpu::Element::COLOR_SRGBA_32; auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - auto colorTexture = + /* auto colorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); + _framebuffer->setRenderBuffer(0, colorTexture);*/ + auto colorTexture = + gpu::Texture::createRenderBufferMultisample(colorFormat, frameSize.x, frameSize.y, 16, defaultSampler); _framebuffer->setRenderBuffer(0, colorTexture); - auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format - auto depthTexture = + /* auto depthTexture = gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); + _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat);*/ + auto depthTexture = + gpu::Texture::createRenderBufferMultisample(depthFormat, frameSize.x, frameSize.y, 16, defaultSampler); _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); } From 217ff2b1b28ea027254c72d30cff6646532e0289 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 23 Jan 2019 18:33:35 -0800 Subject: [PATCH 002/139] keyboardFocusOverlay --- interface/src/Application.cpp | 34 +++++++++---------- interface/src/Application.h | 6 ++-- interface/src/ui/DialogsManager.cpp | 4 +-- interface/src/ui/overlays/Overlays.cpp | 8 ----- interface/src/ui/overlays/Overlays.h | 20 ++++++----- .../entities/src/EntityScriptingInterface.cpp | 10 ++++++ .../entities/src/EntityScriptingInterface.h | 18 ++++++++++ 7 files changed, 61 insertions(+), 39 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 68ac05ef18..cdb1829c60 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1898,7 +1898,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo [this](const EntityItemID& entityItemID, const PointerEvent& event) { if (event.shouldFocus()) { if (getEntities()->wantsKeyboardFocus(entityItemID)) { - setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); + setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); setKeyboardFocusEntity(entityItemID); } else { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); @@ -1990,13 +1990,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Keyboard focus handling for Web overlays. auto overlays = &(qApp->getOverlays()); connect(overlays, &Overlays::overlayDeleted, [this](const OverlayID& overlayID) { - if (overlayID == _keyboardFocusedOverlay.get()) { - setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); + if (overlayID == _keyboardFocusedLocalEntity.get()) { + setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); } }); connect(this, &Application::aboutToQuit, [this]() { - setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); + setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); }); @@ -3821,12 +3821,12 @@ bool Application::handleKeyEventForFocusedEntityOrOverlay(QEvent* event) { } } - if (_keyboardFocusedOverlay.get() != UNKNOWN_OVERLAY_ID) { + if (_keyboardFocusedLocalEntity.get() != UNKNOWN_OVERLAY_ID) { switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: { - // Only Web overlays can have focus. - auto overlay = std::dynamic_pointer_cast(getOverlays().getOverlay(_keyboardFocusedOverlay.get())); + // Only Web entities can have focus. + auto overlay = std::dynamic_pointer_cast(getOverlays().getOverlay(_keyboardFocusedLocalEntity.get())); if (overlay && overlay->getEventHandler()) { event->setAccepted(false); QCoreApplication::sendEvent(overlay->getEventHandler(), event); @@ -4923,12 +4923,12 @@ void Application::idle() { // Update focus highlight for entity or overlay. { - if (!_keyboardFocusedEntity.get().isInvalidID() || _keyboardFocusedOverlay.get() != UNKNOWN_OVERLAY_ID) { + if (!_keyboardFocusedEntity.get().isInvalidID() || _keyboardFocusedLocalEntity.get() != UNKNOWN_OVERLAY_ID) { const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress; if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); - setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); + setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); } else { // update position of highlight overlay if (!_keyboardFocusedEntity.get().isInvalidID()) { @@ -4940,7 +4940,7 @@ void Application::idle() { } else { // Only Web overlays can have focus. auto overlay = - std::dynamic_pointer_cast(getOverlays().getOverlay(_keyboardFocusedOverlay.get())); + std::dynamic_pointer_cast(getOverlays().getOverlay(_keyboardFocusedLocalEntity.get())); if (overlay && _keyboardFocusHighlight) { _keyboardFocusHighlight->setWorldOrientation(overlay->getWorldOrientation()); _keyboardFocusHighlight->setWorldPosition(overlay->getWorldPosition()); @@ -5779,7 +5779,7 @@ void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { if (_keyboardFocusedEntity.get() != entityItemID) { _keyboardFocusedEntity.set(entityItemID); - if (_keyboardFocusHighlight && _keyboardFocusedOverlay.get() == UNKNOWN_OVERLAY_ID) { + if (_keyboardFocusHighlight && _keyboardFocusedLocalEntity.get() == UNKNOWN_OVERLAY_ID) { _keyboardFocusHighlight->setVisible(false); } @@ -5810,12 +5810,12 @@ void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { } } -OverlayID Application::getKeyboardFocusOverlay() { - return _keyboardFocusedOverlay.get(); +EntityItemID Application::getKeyboardFocusLocalEntity() { + return _keyboardFocusedLocalEntity.get(); } -void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) { - if (overlayID != _keyboardFocusedOverlay.get()) { +void Application::setKeyboardFocusLocalEntity(const EntityItemID& overlayID) { + if (overlayID != _keyboardFocusedLocalEntity.get()) { if (qApp->getLoginDialogPoppedUp() && !_loginDialogOverlayID.isNull()) { if (overlayID == _loginDialogOverlayID) { emit loginDialogFocusEnabled(); @@ -5825,7 +5825,7 @@ void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) { } } - _keyboardFocusedOverlay.set(overlayID); + _keyboardFocusedLocalEntity.set(overlayID); if (_keyboardFocusHighlight && _keyboardFocusedEntity.get() == UNKNOWN_ENTITY_ID) { _keyboardFocusHighlight->setVisible(false); @@ -8802,7 +8802,7 @@ void Application::createLoginDialogOverlay() { overlays.editOverlay(keyboard->getAnchorID(), properties); keyboard->setResetKeyboardPositionOnRaise(false); } - setKeyboardFocusOverlay(_loginDialogOverlayID); + setKeyboardFocusLocalEntity(_loginDialogOverlayID); emit loginDialogFocusEnabled(); getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false); getApplicationCompositor().getReticleInterface()->setVisible(false); diff --git a/interface/src/Application.h b/interface/src/Application.h index fbf6e8bc9c..4f31a3cf6a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -439,8 +439,8 @@ public slots: QUuid getKeyboardFocusEntity() const; // thread-safe void setKeyboardFocusEntity(const EntityItemID& entityItemID); - OverlayID getKeyboardFocusOverlay(); - void setKeyboardFocusOverlay(const OverlayID& overlayID); + EntityItemID getKeyboardFocusLocalEntity(); + void setKeyboardFocusLocalEntity(const EntityItemID& overlayID); void addAssetToWorldMessageClose(); @@ -720,7 +720,7 @@ private: DialogsManagerScriptingInterface* _dialogsManagerScriptingInterface = new DialogsManagerScriptingInterface(); ThreadSafeValueCache _keyboardFocusedEntity; - ThreadSafeValueCache _keyboardFocusedOverlay; + ThreadSafeValueCache _keyboardFocusedLocalEntity; quint64 _lastAcceptedKeyPress = 0; bool _isForeground = true; // starts out assumed to be in foreground bool _isGLInitialized { false }; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 24083956ff..435cd66bf7 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -57,7 +57,7 @@ void DialogsManager::showAddressBar() { if (!hmd->getShouldShowTablet()) { hmd->openTablet(); } - qApp->setKeyboardFocusOverlay(hmd->getCurrentTabletScreenID()); + qApp->setKeyboardFocusLocalEntity(hmd->getCurrentTabletScreenID()); setAddressBarVisible(true); } @@ -70,7 +70,7 @@ void DialogsManager::hideAddressBar() { tablet->gotoHomeScreen(); hmd->closeTablet(); } - qApp->setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); + qApp->setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); setAddressBarVisible(false); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 754c8d26a9..2efef6233d 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -738,14 +738,6 @@ void Overlays::sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEv hoverLeavePointerEvent(overlayID, event); } -OverlayID Overlays::getKeyboardFocusOverlay() { - return qApp->getKeyboardFocusOverlay(); -} - -void Overlays::setKeyboardFocusOverlay(const OverlayID& id) { - qApp->setKeyboardFocusOverlay(id); -} - float Overlays::width() { if (QThread::currentThread() != thread()) { float result; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 208fc8d78d..3945a7d808 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -28,6 +28,8 @@ #include "PanelAttachable.h" +#include + class PickRay; class OverlayPropertyResult { @@ -88,9 +90,9 @@ public: * @hifi-interface * @hifi-client-entity * - * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Overlays.OverlayType|web3d} overlay that has keyboard focus. - * If no overlay has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to - * clear keyboard focus. + * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Entities.EntityTypes|Web} local entity that has keyboard focus. + * If no local entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to + * clear keyboard focus. Deprecated. */ class Overlays : public QObject { @@ -586,20 +588,20 @@ public slots: void sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event); /**jsdoc - * Get the ID of the Web3D overlay that has keyboard focus. + * Get the ID of the Web3D local entity that has keyboard focus. Deprecated. * @function Overlays.getKeyboardFocusOverlay - * @returns {Uuid} The ID of the {@link Overlays.OverlayType|web3d} overlay that has focus, if any, otherwise + * @returns {Uuid} The ID of the {@link Entities.EntityTypes|Web} overlay that has focus, if any, otherwise * null. */ - OverlayID getKeyboardFocusOverlay(); + EntityItemID getKeyboardFocusOverlay() { return DependencyManager::get()->getKeyboardFocusLocalEntity(); } /**jsdoc - * Set the Web3D overlay that has keyboard focus. + * Set the Web3D local entity that has keyboard focus. Deprecated. * @function Overlays.setKeyboardFocusOverlay - * @param {Uuid} overlayID - The ID of the {@link Overlays.OverlayType|web3d} overlay to set keyboard focus to. Use + * @param {Uuid} overlayID - The ID of the {@link Entities.EntityTypes|Web} overlay to set keyboard focus to. Use * null or {@link Uuid|Uuid.NULL} to unset keyboard focus from an overlay. */ - void setKeyboardFocusOverlay(const OverlayID& id); + void Overlays::setKeyboardFocusOverlay(const EntityItemID& id) { DependencyManager::get()->setKeyboardFocusLocalEntity(id); } signals: /**jsdoc diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 286f0dd650..17c956c96c 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -2118,6 +2118,16 @@ void EntityScriptingInterface::setKeyboardFocusEntity(const EntityItemID& id) { QMetaObject::invokeMethod(qApp, "setKeyboardFocusEntity", Qt::DirectConnection, Q_ARG(EntityItemID, id)); } +QUuid EntityScriptingInterface::getKeyboardFocusLocalEntity() const { + QUuid result; + QMetaObject::invokeMethod(qApp, "getKeyboardFocusLocalEntity", Qt::DirectConnection, Q_RETURN_ARG(QUuid, result)); + return result; +} + +void EntityScriptingInterface::setKeyboardFocusLocalEntity(const EntityItemID& id) { + QMetaObject::invokeMethod(qApp, "setKeyboardFocusLocalEntity", Qt::DirectConnection, Q_ARG(EntityItemID, id)); +} + void EntityScriptingInterface::sendMousePressOnEntity(const EntityItemID& id, const PointerEvent& event) { emit mousePressOnEntity(id, event); } diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 0e96cb2d25..939e257a8c 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -115,11 +115,15 @@ public: * @property {Uuid} keyboardFocusEntity - Get or set the {@link Entities.EntityType|Web} entity that has keyboard focus. * If no entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to * clear keyboard focus. + * @property {Uuid} keyboardFocusLocalEntity - Get or set the {@link Entities.EntityType|Web} local entity that has keyboard focus. + * If no local entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to + * clear keyboard focus. */ /// handles scripting of Entity commands from JS passed to assigned clients class EntityScriptingInterface : public OctreeScriptingInterface, public Dependency { Q_OBJECT Q_PROPERTY(QUuid keyboardFocusEntity READ getKeyboardFocusEntity WRITE setKeyboardFocusEntity) + Q_PROPERTY(QUuid keyboardFocusLocalEntity READ getKeyboardFocusLocalEntity WRITE setKeyboardFocusLocalEntity) friend EntityPropertyMetadataRequest; public: @@ -1387,6 +1391,20 @@ public slots: */ Q_INVOKABLE void setKeyboardFocusEntity(const EntityItemID& id); + /**jsdoc + * Get the ID of the {@link Entities.EntityType|Web} local entity that has keyboard focus. + * @function Entities.getKeyboardFocusEntity + * @returns {Uuid} The ID of the {@link Entities.EntityType|Web} local entity that has focus, if any, otherwise null. + */ + Q_INVOKABLE QUuid getKeyboardFocusLocalEntity() const; + + /**jsdoc + * Set the {@link Entities.EntityType|Web} local entity that has keyboard focus. + * @function Entities.setKeyboardFocusEntity + * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|Web} local entity to set keyboard focus to. Use + * null or {@link Uuid|Uuid.NULL} to unset keyboard focus from an entity. + */ + Q_INVOKABLE void setKeyboardFocusLocalEntity(const EntityItemID& id); /**jsdoc * Emit a {@link Entities.mousePressOnEntity|mousePressOnEntity} event. From a75fe4b48bf39e36e21786ff5f226bd4ed831cb8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 23 Jan 2019 18:54:39 -0800 Subject: [PATCH 003/139] cloneOverlay, deleteOverlay, findOverlays --- interface/src/ui/overlays/Overlays.cpp | 83 ++++---------------------- interface/src/ui/overlays/Overlays.h | 51 +++++----------- 2 files changed, 24 insertions(+), 110 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 2efef6233d..c8894d0aef 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -298,28 +298,6 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { return thisID; } -OverlayID Overlays::cloneOverlay(OverlayID id) { - if (_shuttingDown) { - return UNKNOWN_OVERLAY_ID; - } - - if (QThread::currentThread() != thread()) { - OverlayID result; - PROFILE_RANGE(script, __FUNCTION__); - BLOCKING_INVOKE_METHOD(this, "cloneOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(OverlayID, id)); - return result; - } - - Overlay::Pointer thisOverlay = getOverlay(id); - - if (thisOverlay) { - OverlayID cloneId = addOverlay(Overlay::Pointer(thisOverlay->createClone(), [](Overlay* ptr) { ptr->deleteLater(); })); - return cloneId; - } - - return UNKNOWN_OVERLAY_ID; // Not found -} - bool Overlays::editOverlay(OverlayID id, const QVariant& properties) { if (_shuttingDown) { return false; @@ -378,30 +356,12 @@ bool Overlays::editOverlays(const QVariant& propertiesById) { return success; } -void Overlays::deleteOverlay(OverlayID id) { +void Overlays::deleteOverlay(EntityItemID id) { if (_shuttingDown) { return; } - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "deleteOverlay", Q_ARG(OverlayID, id)); - return; - } - - Overlay::Pointer overlayToDelete; - - { - QMutexLocker locker(&_mutex); - if (_overlaysHUD.contains(id)) { - overlayToDelete = _overlaysHUD.take(id); - } else if (_overlaysWorld.contains(id)) { - overlayToDelete = _overlaysWorld.take(id); - } else { - return; - } - } - - _overlaysToDelete.push_back(overlayToDelete); + DependencyManager::get()->deleteEntity(id); emit overlayDeleted(id); } @@ -1043,38 +1003,15 @@ void Overlays::mouseMovePointerEvent(const OverlayID& overlayID, const PointerEv } QVector Overlays::findOverlays(const glm::vec3& center, float radius) { + PROFILE_RANGE(script_entities, __FUNCTION__); + QVector result; - //if (QThread::currentThread() != thread()) { - // PROFILE_RANGE(script, __FUNCTION__); - // BLOCKING_INVOKE_METHOD(this, "findOverlays", Q_RETURN_ARG(QVector, result), Q_ARG(glm::vec3, center), Q_ARG(float, radius)); - // return result; - //} - - QMutexLocker locker(&_mutex); - QMapIterator i(_overlaysWorld); - int checked = 0; - while (i.hasNext()) { - checked++; - i.next(); - OverlayID thisID = i.key(); - auto overlay = std::dynamic_pointer_cast(i.value()); - - if (overlay && overlay->getVisible() && overlay->isLoaded()) { - // get AABox in frame of overlay - glm::vec3 dimensions = overlay->getDimensions(); - glm::vec3 low = dimensions * -0.5f; - AABox overlayFrameBox(low, dimensions); - - Transform overlayToWorldMatrix = overlay->getTransform(); - overlayToWorldMatrix.setScale(1.0f); // ignore inherited scale factor from parents - glm::mat4 worldToOverlayMatrix = glm::inverse(overlayToWorldMatrix.getMatrix()); - glm::vec3 overlayFrameSearchPosition = glm::vec3(worldToOverlayMatrix * glm::vec4(center, 1.0f)); - glm::vec3 penetration; - if (overlayFrameBox.findSpherePenetration(overlayFrameSearchPosition, radius, penetration)) { - result.append(thisID); - } - } + auto entityTree = DependencyManager::get()->getEntityTree(); + if (entityTree) { + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); + entityTree->withReadLock([&] { + entityTree->evalEntitiesInSphere(center, radius, PickFilter(searchFilter), result); + }); } - return result; } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 3945a7d808..818726f54e 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -83,7 +83,7 @@ public: }; /**jsdoc - * The Overlays API provides facilities to create and interact with overlays. Overlays are 2D and 3D objects visible only to + * Deprecated. Use local entities instead. The Overlays API provides facilities to create and interact with overlays. Overlays are 2D and 3D objects visible only to * yourself and that aren't persisted to the domain. They are used for UI. * @namespace Overlays * @@ -92,7 +92,7 @@ public: * * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Entities.EntityTypes|Web} local entity that has keyboard focus. * If no local entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to - * clear keyboard focus. Deprecated. + * clear keyboard focus. */ class Overlays : public QObject { @@ -150,26 +150,12 @@ public slots: OverlayID addOverlay(const QString& type, const QVariant& properties); /**jsdoc - * Create a clone of an existing overlay. + * Create a clone of an existing entity. * @function Overlays.cloneOverlay - * @param {Uuid} overlayID - The ID of the overlay to clone. - * @returns {Uuid} The ID of the new overlay if successful, otherwise {@link Uuid|Uuid.NULL}. - * @example Add an overlay in front of your avatar, clone it, and move the clone to be above the - * original. - * var position = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })); - * var original = Overlays.addOverlay("cube", { - * position: position, - * rotation: MyAvatar.orientation, - * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, - * solid: true - * }); - * - * var clone = Overlays.cloneOverlay(original); - * Overlays.editOverlay(clone, { - * position: Vec3.sum({ x: 0, y: 0.5, z: 0}, position) - * }); + * @param {Uuid} id - The ID of the entity to clone. + * @returns {Uuid} The ID of the new entity if successful, otherwise {@link Uuid|Uuid.NULL}. */ - OverlayID cloneOverlay(OverlayID id); + EntityItemID cloneOverlay(EntityItemID id) { return DependencyManager::get()->cloneEntity(id); } /**jsdoc * Edit an overlay's properties. @@ -222,20 +208,11 @@ public slots: bool editOverlays(const QVariant& propertiesById); /**jsdoc - * Delete an overlay. + * Delete an entity. * @function Overlays.deleteOverlay - * @param {Uuid} overlayID - The ID of the overlay to delete. - * @example Create an overlay in front of your avatar then delete it. - * var overlay = Overlays.addOverlay("cube", { - * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), - * rotation: MyAvatar.orientation, - * dimensions: { x: 0.3, y: 0.3, z: 0.3 }, - * solid: true - * }); - * print("Overlay: " + overlay); - * Overlays.deleteOverlay(overlay); + * @param {Uuid} id - The ID of the entity to delete. */ - void deleteOverlay(OverlayID id); + void deleteOverlay(EntityItemID id); /**jsdoc * Get the type of an overlay. @@ -421,12 +398,12 @@ public slots: bool collidableOnly = false); /**jsdoc - * Return a list of 3D overlays with bounding boxes that touch a search sphere. + * Return a list of local entities with bounding boxes that touch a search sphere. * @function Overlays.findOverlays * @param {Vec3} center - The center of the search sphere. * @param {number} radius - The radius of the search sphere. - * @returns {Uuid[]} An array of overlay IDs with bounding boxes that touch a search sphere. - * @example Create two cube overlays in front of your avatar then search for overlays near your avatar. + * @returns {Uuid[]} An array of entity IDs with bounding boxes that touch a search sphere. + * @example Create two cube entities in front of your avatar then search for entities near your avatar. * var overlayA = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: -0.3, y: 0, z: -3 })), * rotation: MyAvatar.orientation, @@ -588,7 +565,7 @@ public slots: void sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event); /**jsdoc - * Get the ID of the Web3D local entity that has keyboard focus. Deprecated. + * Get the ID of the Web3D local entity that has keyboard focus. * @function Overlays.getKeyboardFocusOverlay * @returns {Uuid} The ID of the {@link Entities.EntityTypes|Web} overlay that has focus, if any, otherwise * null. @@ -596,7 +573,7 @@ public slots: EntityItemID getKeyboardFocusOverlay() { return DependencyManager::get()->getKeyboardFocusLocalEntity(); } /**jsdoc - * Set the Web3D local entity that has keyboard focus. Deprecated. + * Set the Web3D local entity that has keyboard focus. * @function Overlays.setKeyboardFocusOverlay * @param {Uuid} overlayID - The ID of the {@link Entities.EntityTypes|Web} overlay to set keyboard focus to. Use * null or {@link Uuid|Uuid.NULL} to unset keyboard focus from an overlay. From 0bfcde67eadf07c86e35167399430e5c3e240226 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 24 Jan 2019 14:11:24 -0800 Subject: [PATCH 004/139] remove overlays from application.cpp --- interface/src/Application.cpp | 362 ++++++++---------- interface/src/Application.h | 18 +- interface/src/ui/LoginDialog.cpp | 4 +- interface/src/ui/overlays/Overlays.cpp | 339 ++++++++-------- interface/src/ui/overlays/Overlays.h | 192 +++++----- .../RenderableParticleEffectEntityItem.cpp | 4 +- .../src/RenderableTextEntityItem.cpp | 12 + .../src/RenderableTextEntityItem.h | 2 + .../src/RenderableWebEntityItem.h | 6 +- .../entities/src/EntityScriptingInterface.cpp | 81 ++-- .../entities/src/EntityScriptingInterface.h | 86 +++-- libraries/entities/src/EntityTree.cpp | 18 +- libraries/entities/src/EntityTree.h | 9 +- 13 files changed, 587 insertions(+), 546 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cdb1829c60..5dc283e8b4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -151,6 +151,7 @@ #include #include #include +#include #include #include #include "recording/ClipCache.h" @@ -196,8 +197,6 @@ #include "ui/AvatarInputs.h" #include "ui/DialogsManager.h" #include "ui/LoginDialog.h" -#include "ui/overlays/Cube3DOverlay.h" -#include "ui/overlays/Web3DOverlay.h" #include "ui/Snapshot.h" #include "ui/SnapshotAnimated.h" #include "ui/StandAloneJSConsole.h" @@ -618,8 +617,6 @@ public: switch (type) { case NestableType::Entity: return getEntityModelProvider(static_cast(uuid)); - case NestableType::Overlay: - return getOverlayModelProvider(static_cast(uuid)); case NestableType::Avatar: return getAvatarModelProvider(uuid); } @@ -643,22 +640,6 @@ private: return provider; } - scriptable::ModelProviderPointer getOverlayModelProvider(OverlayID overlayID) { - scriptable::ModelProviderPointer provider; - auto &overlays = qApp->getOverlays(); - if (auto overlay = overlays.getOverlay(overlayID)) { - if (auto base3d = std::dynamic_pointer_cast(overlay)) { - provider = std::dynamic_pointer_cast(base3d); - provider->modelProviderType = NestableType::Overlay; - } else { - qCWarning(interfaceapp) << "no renderer for overlay ID" << overlayID.toString(); - } - } else { - qCWarning(interfaceapp) << "overlay not found" << overlayID.toString(); - } - return provider; - } - scriptable::ModelProviderPointer getAvatarModelProvider(QUuid sessionUUID) { scriptable::ModelProviderPointer provider; auto avatarManager = DependencyManager::get(); @@ -935,9 +916,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { // FIXME move to header, or better yet, design some kind of UI manager // to take care of highlighting keyboard focused items, rather than // continuing to overburden Application.cpp -std::shared_ptr _keyboardFocusHighlight{ nullptr }; -OverlayID _keyboardFocusHighlightID{ UNKNOWN_OVERLAY_ID }; - +QUuid _keyboardFocusHighlightID; OffscreenGLCanvas* _qmlShareContext { nullptr }; @@ -1206,9 +1185,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (tabletScriptingInterface) { tabletScriptingInterface->setQmlTabletRoot(SYSTEM_TABLET, nullptr); } - getOverlays().deleteOverlay(getTabletScreenID()); - getOverlays().deleteOverlay(getTabletHomeButtonID()); - getOverlays().deleteOverlay(getTabletFrameID()); + auto entityScriptingInterface = DependencyManager::get(); + entityScriptingInterface->deleteEntity(getTabletScreenID()); + entityScriptingInterface->deleteEntity(getTabletHomeButtonID()); + entityScriptingInterface->deleteEntity(getTabletFrameID()); _failedToConnectToEntityServer = false; }); @@ -1298,10 +1278,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (isHMDMode()) { emit loginDialogFocusDisabled(); dialogsManager->hideLoginDialog(); - createLoginDialogOverlay(); + createLoginDialog(); } else { - getOverlays().deleteOverlay(_loginDialogOverlayID); - _loginDialogOverlayID = OverlayID(); + DependencyManager::get()->deleteEntity(_loginDialogID); + _loginDialogID = QUuid(); _loginStateManager.tearDown(); dialogsManager->showLoginDialog(); emit loginDialogFocusEnabled(); @@ -1898,7 +1878,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo [this](const EntityItemID& entityItemID, const PointerEvent& event) { if (event.shouldFocus()) { if (getEntities()->wantsKeyboardFocus(entityItemID)) { - setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); + setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); setKeyboardFocusEntity(entityItemID); } else { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); @@ -1970,33 +1950,25 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return false; }); - EntityTree::setAddMaterialToOverlayOperator([this](const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) { - auto overlay = _overlays.getOverlay(overlayID); - if (overlay) { - overlay->addMaterial(material, parentMaterialName); - return true; + EntityTree::setTextSizeOperator([this](const QUuid& id, const QString& text) { + auto entities = getEntities(); + if (auto entity = entities->renderableForEntityId(id)) { + if (auto renderable = std::dynamic_pointer_cast(entity)) { + return renderable->textSize(text); + } } - return false; - }); - EntityTree::setRemoveMaterialFromOverlayOperator([this](const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName) { - auto overlay = _overlays.getOverlay(overlayID); - if (overlay) { - overlay->removeMaterial(material, parentMaterialName); - return true; - } - return false; + return QSizeF(0.0f, 0.0f); }); - // Keyboard focus handling for Web overlays. - auto overlays = &(qApp->getOverlays()); - connect(overlays, &Overlays::overlayDeleted, [this](const OverlayID& overlayID) { - if (overlayID == _keyboardFocusedLocalEntity.get()) { - setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); + // Keyboard focus handling for local Web entities. + connect(&qApp->getOverlays(), &Overlays::overlayDeleted, [this](const QUuid& id) { + if (id == _keyboardFocusedLocalEntity.get()) { + setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); } }); connect(this, &Application::aboutToQuit, [this]() { - setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); + setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); }); @@ -2344,7 +2316,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }); }); auto rootItemLoadedFunctor = [webSurface, url, isTablet] { - Application::setupQmlSurface(webSurface->getSurfaceContext(), isTablet || url == OVERLAY_LOGIN_DIALOG.toString()); + Application::setupQmlSurface(webSurface->getSurfaceContext(), isTablet || url == LOGIN_DIALOG.toString()); }; if (webSurface->getRootItem()) { rootItemLoadedFunctor(); @@ -2600,11 +2572,10 @@ void Application::cleanupBeforeQuit() { _applicationStateDevice.reset(); { - if (_keyboardFocusHighlightID != UNKNOWN_OVERLAY_ID) { - getOverlays().deleteOverlay(_keyboardFocusHighlightID); - _keyboardFocusHighlightID = UNKNOWN_OVERLAY_ID; + if (_keyboardFocusHighlightID != UNKNOWN_ENTITY_ID) { + DependencyManager::get()->deleteEntity(_keyboardFocusHighlightID); + _keyboardFocusHighlightID = UNKNOWN_ENTITY_ID; } - _keyboardFocusHighlight = nullptr; } { @@ -3080,7 +3051,7 @@ void Application::initializeUi() { }); #if !defined(DISABLE_QML) - // Pre-create a couple of Web3D overlays to speed up tablet UI + // Pre-create a couple of offscreen surfaces to speed up tablet UI auto offscreenSurfaceCache = DependencyManager::get(); offscreenSurfaceCache->setOnRootContextCreated([&](const QString& rootObject, QQmlContext* surfaceContext) { if (rootObject == TabletScriptingInterface::QML) { @@ -3799,7 +3770,7 @@ static inline bool isKeyEvent(QEvent::Type type) { return type == QEvent::KeyPress || type == QEvent::KeyRelease; } -bool Application::handleKeyEventForFocusedEntityOrOverlay(QEvent* event) { +bool Application::handleKeyEventForFocusedEntity(QEvent* event) { if (!_keyboardFocusedEntity.get().isInvalidID()) { switch (event->type()) { case QEvent::KeyPress: @@ -3821,15 +3792,14 @@ bool Application::handleKeyEventForFocusedEntityOrOverlay(QEvent* event) { } } - if (_keyboardFocusedLocalEntity.get() != UNKNOWN_OVERLAY_ID) { + if (!_keyboardFocusedLocalEntity.get().isInvalidID()) { switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: { - // Only Web entities can have focus. - auto overlay = std::dynamic_pointer_cast(getOverlays().getOverlay(_keyboardFocusedLocalEntity.get())); - if (overlay && overlay->getEventHandler()) { + auto eventHandler = getEntities()->getEventHandler(_keyboardFocusedEntity.get()); + if (eventHandler) { event->setAccepted(false); - QCoreApplication::sendEvent(overlay->getEventHandler(), event); + QCoreApplication::sendEvent(eventHandler, event); if (event->isAccepted()) { _lastAcceptedKeyPress = usecTimestampNow(); return true; @@ -3885,8 +3855,8 @@ bool Application::event(QEvent* event) { return false; } - // Allow focused Entities and Overlays to handle keyboard input - if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntityOrOverlay(event)) { + // Allow focused Entities to handle keyboard input + if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntity(event)) { return true; } @@ -4352,7 +4322,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { buttons, event->modifiers()); if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() || - getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_OVERLAY_ID) { + !getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())).isNull()) { getOverlays().mouseMoveEvent(&mappedEvent); getEntities()->mouseMoveEvent(&mappedEvent); } @@ -4921,29 +4891,31 @@ void Application::idle() { } - // Update focus highlight for entity or overlay. + // Update focus highlight for entities { - if (!_keyboardFocusedEntity.get().isInvalidID() || _keyboardFocusedLocalEntity.get() != UNKNOWN_OVERLAY_ID) { + if (!_keyboardFocusedEntity.get().isInvalidID() || !_keyboardFocusedLocalEntity.get().isInvalidID()) { const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress; if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); - setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); + setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); } else { // update position of highlight overlay if (!_keyboardFocusedEntity.get().isInvalidID()) { auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get()); - if (entity && _keyboardFocusHighlight) { - _keyboardFocusHighlight->setWorldOrientation(entity->getWorldOrientation()); - _keyboardFocusHighlight->setWorldPosition(entity->getWorldPosition()); + if (entity && !_keyboardFocusHighlightID.isNull()) { + EntityItemProperties properties; + properties.setPosition(entity->getWorldPosition()); + properties.setRotation(entity->getWorldOrientation()); + DependencyManager::get()->editEntity(_keyboardFocusHighlightID, properties); } } else { - // Only Web overlays can have focus. - auto overlay = - std::dynamic_pointer_cast(getOverlays().getOverlay(_keyboardFocusedLocalEntity.get())); - if (overlay && _keyboardFocusHighlight) { - _keyboardFocusHighlight->setWorldOrientation(overlay->getWorldOrientation()); - _keyboardFocusHighlight->setWorldPosition(overlay->getWorldPosition()); + auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get()); + if (entity && !_keyboardFocusHighlightID.isNull()) { + EntityItemProperties properties; + properties.setPosition(entity->getWorldPosition()); + properties.setRotation(entity->getWorldOrientation()); + DependencyManager::get()->editEntity(_keyboardFocusHighlightID, properties); } } } @@ -5746,24 +5718,28 @@ void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm if (qApp->getLoginDialogPoppedUp()) { return; } - if (_keyboardFocusHighlightID == UNKNOWN_OVERLAY_ID || !getOverlays().isAddedOverlay(_keyboardFocusHighlightID)) { - _keyboardFocusHighlight = std::make_shared(); - _keyboardFocusHighlight->setAlpha(1.0f); - _keyboardFocusHighlight->setColor({ 0xFF, 0xEF, 0x00 }); - _keyboardFocusHighlight->setIsSolid(false); - _keyboardFocusHighlight->setPulseMin(0.5); - _keyboardFocusHighlight->setPulseMax(1.0); - _keyboardFocusHighlight->setColorPulse(1.0); - _keyboardFocusHighlight->setIgnorePickIntersection(true); - _keyboardFocusHighlight->setDrawInFront(false); - _keyboardFocusHighlightID = getOverlays().addOverlay(_keyboardFocusHighlight); + + auto entityScriptingInterface = DependencyManager::get(); + if (_keyboardFocusHighlightID == UNKNOWN_ENTITY_ID || !entityScriptingInterface->isAddedEntity(_keyboardFocusHighlightID)) { + EntityItemProperties properties; + properties.setType(EntityTypes::Box); + properties.setAlpha(1.0f); + properties.setColor({ 0xFF, 0xEF, 0x00 }); + properties.setPrimitiveMode(PrimitiveMode::LINES); + properties.getPulse().setMin(0.5); + properties.getPulse().setMax(1.0f); + properties.getPulse().setColorMode(PulseMode::IN_PHASE); + properties.setIgnorePickIntersection(true); + _keyboardFocusHighlightID = entityScriptingInterface->addEntity(properties, "local"); } // Position focus - _keyboardFocusHighlight->setWorldOrientation(rotation); - _keyboardFocusHighlight->setWorldPosition(position); - _keyboardFocusHighlight->setDimensions(dimensions); - _keyboardFocusHighlight->setVisible(true); + EntityItemProperties properties; + properties.setPosition(position); + properties.setRotation(rotation); + properties.setDimensions(dimensions); + properties.setVisible(true); + entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties); } QUuid Application::getKeyboardFocusEntity() const { @@ -5779,18 +5755,16 @@ void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { if (_keyboardFocusedEntity.get() != entityItemID) { _keyboardFocusedEntity.set(entityItemID); - if (_keyboardFocusHighlight && _keyboardFocusedLocalEntity.get() == UNKNOWN_OVERLAY_ID) { - _keyboardFocusHighlight->setVisible(false); - } - + auto entityScriptingInterface = DependencyManager::get(); if (entityItemID == UNKNOWN_ENTITY_ID) { + EntityItemProperties properties; + properties.setVisible(false); + entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties); return; } - auto entityScriptingInterface = DependencyManager::get(); auto properties = entityScriptingInterface->getEntityProperties(entityItemID); if (!properties.getLocked() && properties.getVisible()) { - auto entities = getEntities(); auto entityId = _keyboardFocusedEntity.get(); if (entities->wantsKeyboardFocus(entityId)) { @@ -5814,44 +5788,43 @@ EntityItemID Application::getKeyboardFocusLocalEntity() { return _keyboardFocusedLocalEntity.get(); } -void Application::setKeyboardFocusLocalEntity(const EntityItemID& overlayID) { - if (overlayID != _keyboardFocusedLocalEntity.get()) { - if (qApp->getLoginDialogPoppedUp() && !_loginDialogOverlayID.isNull()) { - if (overlayID == _loginDialogOverlayID) { +void Application::setKeyboardFocusLocalEntity(const EntityItemID& entityItemID) { + if (entityItemID != _keyboardFocusedLocalEntity.get()) { + if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) { + if (entityItemID == _loginDialogID) { emit loginDialogFocusEnabled(); } else { - // that's the only overlay we want in focus; + // that's the only entity we want in focus; return; } } - _keyboardFocusedLocalEntity.set(overlayID); + _keyboardFocusedLocalEntity.set(entityItemID); - if (_keyboardFocusHighlight && _keyboardFocusedEntity.get() == UNKNOWN_ENTITY_ID) { - _keyboardFocusHighlight->setVisible(false); - } - - if (overlayID == UNKNOWN_OVERLAY_ID) { + auto entityScriptingInterface = DependencyManager::get(); + if (entityItemID == UNKNOWN_ENTITY_ID) { + EntityItemProperties properties; + properties.setVisible(false); + entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties); return; } - auto overlayType = getOverlays().getOverlayType(overlayID); - auto isVisible = getOverlays().getProperty(overlayID, "visible").value.toBool(); - if (overlayType == Web3DOverlay::TYPE && isVisible) { - auto overlay = std::dynamic_pointer_cast(getOverlays().getOverlay(overlayID)); - overlay->setProxyWindow(_window->windowHandle()); + auto properties = entityScriptingInterface->getEntityProperties(entityItemID); + if (!properties.getLocked() && properties.getVisible()) { + auto entities = getEntities(); + auto entityId = _keyboardFocusedLocalEntity.get(); + if (entities->wantsKeyboardFocus(entityId)) { + entities->setProxyWindow(entityId, _window->windowHandle()); + if (_keyboardMouseDevice->isActive()) { + _keyboardMouseDevice->pluginFocusOutEvent(); + } + _lastAcceptedKeyPress = usecTimestampNow(); - if (_keyboardMouseDevice->isActive()) { - _keyboardMouseDevice->pluginFocusOutEvent(); - } - _lastAcceptedKeyPress = usecTimestampNow(); - - if (overlay->getProperty("showKeyboardFocusHighlight").toBool()) { - auto size = overlay->getSize() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR; - const float OVERLAY_DEPTH = 0.0105f; - setKeyboardFocusHighlight(overlay->getWorldPosition(), overlay->getWorldOrientation(), glm::vec3(size.x, size.y, OVERLAY_DEPTH)); - } else if (_keyboardFocusHighlight) { - _keyboardFocusHighlight->setVisible(false); + auto entity = getEntities()->getEntity(entityId); + if (entity) { + setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), + entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); + } } } } @@ -6367,9 +6340,9 @@ void Application::update(float deltaTime) { updateLOD(deltaTime); - if (!_loginDialogOverlayID.isNull()) { - _loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogOverlayID); - updateLoginDialogOverlayPosition(); + if (!_loginDialogID.isNull()) { + _loginStateManager.update(getMyAvatar()->getDominantHand(), _loginDialogID); + updateLoginDialogPosition(); } // TODO: break these out into distinct perfTimers when they prove interesting @@ -7148,7 +7121,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe connect(scriptEngine.data(), &ScriptEngine::finished, clipboardScriptable, &ClipboardScriptingInterface::deleteLater); scriptEngine->registerGlobalObject("Overlays", &_overlays); - qScriptRegisterMetaType(scriptEngine.data(), OverlayPropertyResultToScriptValue, OverlayPropertyResultFromScriptValue); qScriptRegisterMetaType(scriptEngine.data(), RayToOverlayIntersectionResultToScriptValue, RayToOverlayIntersectionResultFromScriptValue); @@ -7265,8 +7237,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("HifiAbout", AboutUtil::getInstance()); scriptEngine->registerGlobalObject("ResourceRequestObserver", DependencyManager::get().data()); - qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue); - registerInteractiveWindowMetaType(scriptEngine.data()); auto pickScriptingInterface = DependencyManager::get(); @@ -8764,45 +8734,48 @@ void Application::setShowBulletConstraintLimits(bool value) { _physicsEngine->setShowBulletConstraintLimits(value); } -void Application::createLoginDialogOverlay() { - const glm::vec2 LOGIN_OVERLAY_DIMENSIONS{ 0.89f, 0.5f }; - const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f); +void Application::createLoginDialog() { + const glm::vec3 LOGIN_DIMENSIONS { 0.89f, 0.5f, 0.01f }; + const auto OFFSET = glm::vec2(0.7f, -0.1f); auto cameraPosition = _myCamera.getPosition(); auto cameraOrientation = _myCamera.getOrientation(); auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y; auto headLookVec = (cameraOrientation * Vectors::FRONT); // DEFAULT_DPI / tablet scale percentage - const float OVERLAY_DPI = 31.0f / (75.0f / 100.0f); - auto offset = headLookVec * OVERLAY_OFFSET.x; - auto overlayPosition = (cameraPosition + offset) + (upVec * OVERLAY_OFFSET.y); - QVariantMap overlayProperties = { - { "name", "LoginDialogOverlay" }, - { "url", OVERLAY_LOGIN_DIALOG }, - { "position", vec3toVariant(overlayPosition) }, - { "orientation", quatToVariant(cameraOrientation) }, - { "isSolid", true }, - { "grabbable", false }, - { "ignorePickIntersection", false }, - { "alpha", 1.0 }, - { "dimensions", vec2ToVariant(LOGIN_OVERLAY_DIMENSIONS)}, - { "dpi", OVERLAY_DPI }, - { "visible", true } - }; - auto& overlays = getOverlays(); - _loginDialogOverlayID = overlays.addOverlay("web3d", overlayProperties); - auto loginOverlay = std::dynamic_pointer_cast(overlays.getOverlay(_loginDialogOverlayID)); + const float DPI = 31.0f / (75.0f / 100.0f); + auto offset = headLookVec * OFFSET.x; + auto position = (cameraPosition + offset) + (upVec * OFFSET.y); + + EntityItemProperties properties; + properties.setType(EntityTypes::Web); + properties.setName("LoginDialogEntity"); + properties.setSourceUrl(LOGIN_DIALOG); + properties.setPosition(position); + properties.setRotation(cameraOrientation); + properties.setDimensions(LOGIN_DIMENSIONS); + properties.setPrimitiveMode(PrimitiveMode::SOLID); + properties.getGrab().setGrabbable(false); + properties.setIgnorePickIntersection(false); + properties.setAlpha(1.0f); + properties.setDPI(DPI); + properties.setVisible(true); + + auto entityScriptingInterface = DependencyManager::get(); + _loginDialogID = entityScriptingInterface->addEntity(properties, "local"); + auto keyboard = DependencyManager::get().data(); - if (!keyboard->getAnchorID().isNull() && !_loginDialogOverlayID.isNull()) { + if (!keyboard->getAnchorID().isNull() && !_loginDialogID.isNull()) { const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f); auto keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); - QVariantMap properties { - { "position", vec3toVariant(overlayPosition + keyboardLocalOffset) }, - { "orientation", quatToVariant(cameraOrientation * KEYBOARD_LOCAL_ORIENTATION) }, - }; - overlays.editOverlay(keyboard->getAnchorID(), properties); + + EntityItemProperties properties; + properties.setPosition(position + keyboardLocalOffset); + properties.setRotation(cameraOrientation * KEYBOARD_LOCAL_ORIENTATION); + + entityScriptingInterface->editEntity(keyboard->getAnchorID(), properties); keyboard->setResetKeyboardPositionOnRaise(false); } - setKeyboardFocusLocalEntity(_loginDialogOverlayID); + setKeyboardFocusLocalEntity(_loginDialogID); emit loginDialogFocusEnabled(); getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false); getApplicationCompositor().getReticleInterface()->setVisible(false); @@ -8811,38 +8784,44 @@ void Application::createLoginDialogOverlay() { } } -void Application::updateLoginDialogOverlayPosition() { +void Application::updateLoginDialogPosition() { const float LOOK_AWAY_THRESHOLD_ANGLE = 70.0f; - const auto OVERLAY_OFFSET = glm::vec2(0.7f, -0.1f); - auto& overlays = getOverlays(); - auto loginOverlay = std::dynamic_pointer_cast(overlays.getOverlay(_loginDialogOverlayID)); - auto overlayPositionVec = loginOverlay->getWorldPosition(); + const auto OFFSET = glm::vec2(0.7f, -0.1f); + + auto entityScriptingInterface = DependencyManager::get(); + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_POSITION; + auto properties = entityScriptingInterface->getEntityProperties(_loginDialogID, desiredProperties); + auto positionVec = properties.getPosition(); auto cameraPositionVec = _myCamera.getPosition(); auto cameraOrientation = cancelOutRollAndPitch(_myCamera.getOrientation()); auto headLookVec = (cameraOrientation * Vectors::FRONT); - auto overlayToHeadVec = overlayPositionVec - cameraPositionVec; - auto pointAngle = (glm::acos(glm::dot(glm::normalize(overlayToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI); + auto entityToHeadVec = positionVec - cameraPositionVec; + auto pointAngle = (glm::acos(glm::dot(glm::normalize(entityToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI); auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y; - auto offset = headLookVec * OVERLAY_OFFSET.x; - auto newOverlayPositionVec = (cameraPositionVec + offset) + (upVec * OVERLAY_OFFSET.y); - auto newOverlayOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newOverlayPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180; + auto offset = headLookVec * OFFSET.x; + auto newPositionVec = (cameraPositionVec + offset) + (upVec * OFFSET.y); + auto newOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180; - bool overlayOutOfBounds = glm::distance(overlayPositionVec, cameraPositionVec) > 1.0f; + bool outOfBounds = glm::distance(positionVec, cameraPositionVec) > 1.0f; - if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || overlayOutOfBounds) { - QVariantMap properties { - {"position", vec3toVariant(newOverlayPositionVec)}, - {"orientation", quatToVariant(newOverlayOrientation)} - }; - overlays.editOverlay(_loginDialogOverlayID, properties); - const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f); - auto keyboardLocalOffset = newOverlayOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); - QVariantMap keyboardProperties { - { "position", vec3toVariant(newOverlayPositionVec + keyboardLocalOffset) }, - { "orientation", quatToVariant(newOverlayOrientation * KEYBOARD_LOCAL_ORIENTATION) }, - }; - auto keyboard = DependencyManager::get().data(); - overlays.editOverlay(keyboard->getAnchorID(), keyboardProperties); + if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || outOfBounds) { + { + EntityItemProperties properties; + properties.setPosition(newPositionVec); + properties.setRotation(newOrientation); + entityScriptingInterface->editEntity(_loginDialogID, properties); + } + + { + const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f); + auto keyboardLocalOffset = newOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); + + EntityItemProperties properties; + properties.setPosition(newPositionVec + keyboardLocalOffset); + properties.setRotation(newOrientation * KEYBOARD_LOCAL_ORIENTATION); + entityScriptingInterface->editEntity(DependencyManager::get()->getAnchorID(), properties); + } } } @@ -8859,10 +8838,9 @@ void Application::onDismissedLoginDialog() { loginDialogPoppedUp.set(false); auto keyboard = DependencyManager::get().data(); keyboard->setResetKeyboardPositionOnRaise(true); - if (!_loginDialogOverlayID.isNull()) { - // deleting overlay. - getOverlays().deleteOverlay(_loginDialogOverlayID); - _loginDialogOverlayID = OverlayID(); + if (!_loginDialogID.isNull()) { + DependencyManager::get()->deleteEntity(_loginDialogID); + _loginDialogID = QUuid(); _loginStateManager.tearDown(); } resumeAfterLoginDialogActionTaken(); @@ -9028,12 +9006,12 @@ void Application::updateSystemTabletMode() { } } -OverlayID Application::getTabletScreenID() const { +QUuid Application::getTabletScreenID() const { auto HMD = DependencyManager::get(); return HMD->getCurrentTabletScreenID(); } -OverlayID Application::getTabletHomeButtonID() const { +QUuid Application::getTabletHomeButtonID() const { auto HMD = DependencyManager::get(); return HMD->getCurrentHomeButtonID(); } @@ -9044,7 +9022,7 @@ QUuid Application::getTabletFrameID() const { } QVector Application::getTabletIDs() const { - // Most important overlays first. + // Most important first. QVector result; auto HMD = DependencyManager::get(); result << HMD->getCurrentTabletScreenID(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 4f31a3cf6a..150675d823 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -297,10 +297,10 @@ public: void shareSnapshot(const QString& filename, const QUrl& href = QUrl("")); - OverlayID getTabletScreenID() const; - OverlayID getTabletHomeButtonID() const; - QUuid getTabletFrameID() const; // may be an entity or an overlay - QVector getTabletIDs() const; // In order of most important IDs first. + QUuid getTabletScreenID() const; + QUuid getTabletHomeButtonID() const; + QUuid getTabletFrameID() const; + QVector getTabletIDs() const; void setAvatarOverrideUrl(const QUrl& url, bool save); void clearAvatarOverrideUrl() { _avatarOverrideUrl = QUrl(); _saveAvatarOverrideUrl = false; } @@ -323,8 +323,8 @@ public: void setOtherAvatarsReplicaCount(int count) { DependencyManager::get()->setReplicaCount(count); } bool getLoginDialogPoppedUp() const { return _loginDialogPoppedUp; } - void createLoginDialogOverlay(); - void updateLoginDialogOverlayPosition(); + void createLoginDialog(); + void updateLoginDialogPosition(); // Check if a headset is connected bool hasRiftControllers(); @@ -440,7 +440,7 @@ public slots: void setKeyboardFocusEntity(const EntityItemID& entityItemID); EntityItemID getKeyboardFocusLocalEntity(); - void setKeyboardFocusLocalEntity(const EntityItemID& overlayID); + void setKeyboardFocusLocalEntity(const EntityItemID& id); void addAssetToWorldMessageClose(); @@ -531,7 +531,7 @@ private: void init(); void pauseUntilLoginDetermined(); void resumeAfterLoginDialogActionTaken(); - bool handleKeyEventForFocusedEntityOrOverlay(QEvent* event); + bool handleKeyEventForFocusedEntity(QEvent* event); bool handleFileOpenEvent(QFileOpenEvent* event); void cleanupBeforeQuit(); @@ -702,7 +702,7 @@ private: QString _previousAvatarSkeletonModel; float _previousAvatarTargetScale; CameraMode _previousCameraMode; - OverlayID _loginDialogOverlayID; + QUuid _loginDialogID; LoginStateManager _loginStateManager; quint64 _lastFaceTrackerUpdate; diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 6e9c91785f..1b170e7a32 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -33,7 +33,7 @@ HIFI_QML_DEF(LoginDialog) static const QUrl TABLET_LOGIN_DIALOG_URL("dialogs/TabletLoginDialog.qml"); -const QUrl OVERLAY_LOGIN_DIALOG = PathUtils::qmlUrl("OverlayLoginDialog.qml"); +const QUrl LOGIN_DIALOG = PathUtils::qmlUrl("OverlayLoginDialog.qml"); LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) { auto accountManager = DependencyManager::get(); @@ -70,7 +70,7 @@ void LoginDialog::showWithSelection() { if (!qApp->getLoginDialogPoppedUp()) { tablet->initialScreen(TABLET_LOGIN_DIALOG_URL); } else { - qApp->createLoginDialogOverlay(); + qApp->createLoginDialog(); } } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index c8894d0aef..df65b26a3f 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -54,18 +54,13 @@ Overlays::Overlays() { void Overlays::cleanupAllOverlays() { _shuttingDown = true; - QMap overlaysHUD; - QMap overlaysWorld; + QMap overlays; { QMutexLocker locker(&_mutex); - overlaysHUD.swap(_overlaysHUD); - overlaysWorld.swap(_overlaysWorld); + overlays.swap(_overlays); } - foreach(Overlay::Pointer overlay, overlaysHUD) { - _overlaysToDelete.push_back(overlay); - } - foreach(Overlay::Pointer overlay, overlaysWorld) { + foreach(Overlay::Pointer overlay, overlays) { _overlaysToDelete.push_back(overlay); } cleanupOverlaysToDelete(); @@ -77,10 +72,7 @@ void Overlays::init() { void Overlays::update(float deltatime) { { QMutexLocker locker(&_mutex); - foreach(const auto& thisOverlay, _overlaysHUD) { - thisOverlay->update(deltatime); - } - foreach(const auto& thisOverlay, _overlaysWorld) { + foreach(const auto& thisOverlay, _overlays) { thisOverlay->update(deltatime); } } @@ -110,7 +102,7 @@ void Overlays::cleanupOverlaysToDelete() { } } -void Overlays::renderHUD(RenderArgs* renderArgs) { +void Overlays::render(RenderArgs* renderArgs) { PROFILE_RANGE(render_overlays, __FUNCTION__); gpu::Batch& batch = *renderArgs->_batch; @@ -123,7 +115,7 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { mat4 legacyProjection = glm::ortho(0, width, height, 0, -1000, 1000); QMutexLocker locker(&_mutex); - foreach(Overlay::Pointer thisOverlay, _overlaysHUD) { + foreach(Overlay::Pointer thisOverlay, _overlays) { // Reset all batch pipeline settings between overlay geometryCache->useSimpleDrawPipeline(batch); @@ -146,29 +138,28 @@ void Overlays::enable() { // Note, can't be invoked by scripts, but can be called by the InterfaceParentFinder // class on packet processing threads -Overlay::Pointer Overlays::getOverlay(OverlayID id) const { +Overlay::Pointer Overlays::get2DOverlay(const QUuid& id) const { if (_shuttingDown) { return nullptr; } QMutexLocker locker(&_mutex); - if (_overlaysHUD.contains(id)) { - return _overlaysHUD[id]; - } else if (_overlaysWorld.contains(id)) { - return _overlaysWorld[id]; + auto overlayIter = _overlays.find(id); + if (overlayIter != _overlays.end()) { + return overlayIter.value(); } return nullptr; } -OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) { +QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { if (_shuttingDown) { return UNKNOWN_OVERLAY_ID; } if (QThread::currentThread() != thread()) { - OverlayID result; + QUuid result; PROFILE_RANGE(script, __FUNCTION__); - BLOCKING_INVOKE_METHOD(this, "addOverlay", Q_RETURN_ARG(OverlayID, result), Q_ARG(QString, type), Q_ARG(QVariant, properties)); + BLOCKING_INVOKE_METHOD(this, "addOverlay", Q_RETURN_ARG(QUuid, result), Q_ARG(const QString&, type), Q_ARG(const QVariant&, properties)); return result; } @@ -267,58 +258,69 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) if (thisOverlay) { thisOverlay->setProperties(properties.toMap()); - return addOverlay(thisOverlay); + return add2DOverlay(thisOverlay); } return UNKNOWN_OVERLAY_ID; } -OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { +QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) { if (_shuttingDown) { return UNKNOWN_OVERLAY_ID; } - OverlayID thisID = OverlayID(QUuid::createUuid()); + QUuid thisID = QUuid::createUuid(); overlay->setOverlayID(thisID); overlay->setStackOrder(_stackOrder++); - if (overlay->is3D()) { - { - QMutexLocker locker(&_mutex); - _overlaysWorld[thisID] = overlay; - } - - render::ScenePointer scene = qApp->getMain3DScene(); - render::Transaction transaction; - overlay->addToScene(overlay, scene, transaction); - scene->enqueueTransaction(transaction); - } else { + { QMutexLocker locker(&_mutex); - _overlaysHUD[thisID] = overlay; + _overlays[thisID] = overlay; } return thisID; } -bool Overlays::editOverlay(OverlayID id, const QVariant& properties) { +QUuid Overlays::cloneOverlay(const QUuid& id) { + if (_shuttingDown) { + return UNKNOWN_OVERLAY_ID; + } + + if (QThread::currentThread() != thread()) { + QUuid result; + PROFILE_RANGE(script, __FUNCTION__); + BLOCKING_INVOKE_METHOD(this, "cloneOverlay", Q_RETURN_ARG(QUuid, result), Q_ARG(const QUuid&, id)); + return result; + } + + Overlay::Pointer overlay = get2DOverlay(id); + if (overlay) { + return add2DOverlay(Overlay::Pointer(overlay->createClone(), [](Overlay* ptr) { ptr->deleteLater(); })); + } + + return DependencyManager::get()->cloneEntity(id); +} + +bool Overlays::editOverlay(const QUuid& id, const QVariant& properties) { if (_shuttingDown) { return false; } - auto thisOverlay = getOverlay(id); - if (!thisOverlay) { - return false; - } + auto overlay = get2DOverlay(id); + if (overlay) { + if (QThread::currentThread() != thread()) { + // NOTE editOverlay can be called very frequently in scripts and can't afford to + // block waiting on the main thread. Additionally, no script actually + // examines the return value and does something useful with it, so use a non-blocking + // invoke and just always return true + QMetaObject::invokeMethod(this, "editOverlay", Q_ARG(const QUuid&, id), Q_ARG(const QVariant&, properties)); + return true; + } - if (!thisOverlay->is3D() && QThread::currentThread() != thread()) { - // NOTE editOverlay can be called very frequently in scripts and can't afford to - // block waiting on the main thread. Additionally, no script actually - // examines the return value and does something useful with it, so use a non-blocking - // invoke and just always return true - QMetaObject::invokeMethod(this, "editOverlay", Q_ARG(OverlayID, id), Q_ARG(QVariant, properties)); + overlay->setProperties(properties.toMap()); return true; } - thisOverlay->setProperties(properties.toMap()); - return true; + EntityItemProperties entityProperties = convertOverlayToEntityProperties(properties.toMap()); + return !DependencyManager::get()->editEntity(id, entityProperties).isNull(); } bool Overlays::editOverlays(const QVariant& propertiesById) { @@ -326,165 +328,166 @@ bool Overlays::editOverlays(const QVariant& propertiesById) { return false; } - bool defer2DOverlays = QThread::currentThread() != thread(); + bool deferOverlays = QThread::currentThread() != thread(); - QVariantMap deferrred; + QVariantMap deferred; const QVariantMap map = propertiesById.toMap(); - bool success = true; for (const auto& key : map.keys()) { - OverlayID id = OverlayID(key); - Overlay::Pointer thisOverlay = getOverlay(id); - if (!thisOverlay) { - success = false; - continue; - } - + QUuid id = QUuid(key); const QVariant& properties = map[key]; - if (defer2DOverlays && !thisOverlay->is3D()) { - deferrred[key] = properties; - continue; + + Overlay::Pointer overlay = get2DOverlay(id); + if (overlay) { + if (deferOverlays) { + deferred[key] = properties; + continue; + } + overlay->setProperties(properties.toMap()); + } else { + EntityItemProperties entityProperties = convertOverlayToEntityProperties(properties.toMap()); + DependencyManager::get()->editEntity(id, entityProperties); } - thisOverlay->setProperties(properties.toMap()); } // For 2D/QML overlays, we need to perform the edit on the main thread - if (defer2DOverlays && !deferrred.empty()) { + if (!deferred.empty()) { // NOTE see comment on editOverlay for why this is not a blocking call - QMetaObject::invokeMethod(this, "editOverlays", Q_ARG(QVariant, deferrred)); + QMetaObject::invokeMethod(this, "editOverlays", Q_ARG(const QVariant&, deferred)); } - return success; + return true; } -void Overlays::deleteOverlay(EntityItemID id) { +void Overlays::deleteOverlay(const QUuid& id) { if (_shuttingDown) { return; } + Overlay::Pointer overlay = get2DOverlay(id); + if (overlay) { + _overlaysToDelete.push_back(overlay); + emit overlayDeleted(id); + return; + } + DependencyManager::get()->deleteEntity(id); emit overlayDeleted(id); } -QString Overlays::getOverlayType(OverlayID overlayId) { +QString Overlays::getOverlayType(const QUuid& id) { if (_shuttingDown) { return ""; } + if (QThread::currentThread() != thread()) { QString result; PROFILE_RANGE(script, __FUNCTION__); - BLOCKING_INVOKE_METHOD(this, "getOverlayType", Q_RETURN_ARG(QString, result), Q_ARG(OverlayID, overlayId)); + BLOCKING_INVOKE_METHOD(this, "getOverlayType", Q_RETURN_ARG(QString, result), Q_ARG(const QUuid&, id)); return result; } - Overlay::Pointer overlay = getOverlay(overlayId); + Overlay::Pointer overlay = get2DOverlay(id); if (overlay) { return overlay->getType(); } - return ""; + + return entityToOverlayType(DependencyManager::get()->getEntityType(id)); } -QObject* Overlays::getOverlayObject(OverlayID id) { +QObject* Overlays::getOverlayObject(const QUuid& id) { if (QThread::currentThread() != thread()) { QObject* result; PROFILE_RANGE(script, __FUNCTION__); - BLOCKING_INVOKE_METHOD(this, "getOverlayObject", Q_RETURN_ARG(QObject*, result), Q_ARG(OverlayID, id)); + BLOCKING_INVOKE_METHOD(this, "getOverlayObject", Q_RETURN_ARG(QObject*, result), Q_ARG(const QUuid&, id)); return result; } - Overlay::Pointer thisOverlay = getOverlay(id); - if (thisOverlay) { - return qobject_cast(&(*thisOverlay)); + Overlay::Pointer overlay = get2DOverlay(id); + if (overlay) { + return qobject_cast(&(*overlay)); } - return nullptr; + + return DependencyManager::get()->getEntityObject(id); } -OverlayID Overlays::getOverlayAtPoint(const glm::vec2& point) { +QUuid Overlays::getOverlayAtPoint(const glm::vec2& point) { if (_shuttingDown || !_enabled) { - return UNKNOWN_OVERLAY_ID; + return UNKNOWN_ENTITY_ID; } QMutexLocker locker(&_mutex); - QMapIterator i(_overlaysHUD); + QMapIterator i(_overlays); unsigned int bestStackOrder = 0; - OverlayID bestOverlayID = UNKNOWN_OVERLAY_ID; + QUuid bestID = UNKNOWN_ENTITY_ID; while (i.hasNext()) { i.next(); auto thisOverlay = std::dynamic_pointer_cast(i.value()); if (thisOverlay && thisOverlay->getVisible() && thisOverlay->isLoaded() && thisOverlay->getBoundingRect().contains(point.x, point.y, false)) { if (thisOverlay->getStackOrder() > bestStackOrder) { - bestOverlayID = i.key(); + bestID = i.key(); bestStackOrder = thisOverlay->getStackOrder(); } } } - return bestOverlayID; + return bestID; } -OverlayPropertyResult Overlays::getProperty(OverlayID id, const QString& property) { - Overlay::Pointer thisOverlay = getOverlay(id); - OverlayPropertyResult result; - if (thisOverlay && thisOverlay->supportsGetProperty()) { - result.value = thisOverlay->getProperty(property); - } - return result; -} - -OverlayPropertyResult Overlays::getProperties(const OverlayID& id, const QStringList& properties) { - Overlay::Pointer thisOverlay = getOverlay(id); - OverlayPropertyResult result; - if (thisOverlay && thisOverlay->supportsGetProperty()) { - QVariantMap mapResult; - for (const auto& property : properties) { - mapResult.insert(property, thisOverlay->getProperty(property)); +QVariant Overlays::getProperty(const QUuid& id, const QString& property) { + Overlay::Pointer overlay = get2DOverlay(id); + if (overlay) { + if (overlay->supportsGetProperty()) { + return overlay->getProperty(property); } - result.value = mapResult; + return QVariant(); } - return result; + + QVariantMap overlayProperties = convertEntityToOverlayProperties(DependencyManager::get()->getEntityProperties(id)); + auto propIter = overlayProperties.find(property); + if (propIter != overlayProperties.end()) { + return propIter.value(); + } + return QVariant(); } -OverlayPropertyResult Overlays::getOverlaysProperties(const QVariant& propertiesById) { - QVariantMap map = propertiesById.toMap(); - OverlayPropertyResult result; - QVariantMap resultMap; - for (const auto& key : map.keys()) { - OverlayID id = OverlayID(key); - QVariantMap overlayResult; - Overlay::Pointer thisOverlay = getOverlay(id); - if (thisOverlay && thisOverlay->supportsGetProperty()) { - QStringList propertiesToFetch = map[key].toStringList(); - for (const auto& property : propertiesToFetch) { - overlayResult[property] = thisOverlay->getProperty(property); +QVariantMap Overlays::getProperties(const QUuid& id, const QStringList& properties) { + Overlay::Pointer overlay = get2DOverlay(id); + QVariantMap result; + if (overlay) { + if (overlay->supportsGetProperty()) { + for (const auto& property : properties) { + result.insert(property, overlay->getProperty(property)); } } - resultMap[key] = overlayResult; + return result; + } + + QVariantMap overlayProperties = convertEntityToOverlayProperties(DependencyManager::get()->getEntityProperties(id)); + for (const auto& property : properties) { + auto propIter = overlayProperties.find(property); + if (propIter != overlayProperties.end()) { + result.insert(property, propIter.value()); + } } - result.value = resultMap; return result; } -OverlayPropertyResult::OverlayPropertyResult() { -} - -QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value) { - if (!value.value.isValid()) { - return QScriptValue::UndefinedValue; +QVariantMap Overlays::getOverlaysProperties(const QVariant& propertiesById) { + QVariantMap map = propertiesById.toMap(); + QVariantMap result; + for (const auto& key : map.keys()) { + result[key] = getProperties(QUuid(key), map[key].toStringList()); } - return engine->toScriptValue(value.value); + return result; } -void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value) { - value.value = object.toVariant(); -} - - RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, bool precisionPicking, const QScriptValue& overlayIDsToInclude, const QScriptValue& overlayIDsToDiscard, bool visibleOnly, bool collidableOnly) { - const QVector overlaysToInclude = qVectorOverlayIDFromScriptValue(overlayIDsToInclude); - const QVector overlaysToDiscard = qVectorOverlayIDFromScriptValue(overlayIDsToDiscard); + const QVector overlaysToInclude = qVectorQUuidFromScriptValue(overlayIDsToInclude); + const QVector overlaysToDiscard = qVectorQUuidFromScriptValue(overlayIDsToDiscard); return findRayIntersectionVector(ray, precisionPicking, overlaysToInclude, overlaysToDiscard, visibleOnly, collidableOnly); @@ -492,8 +495,8 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay& ray, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, + const QVector& overlaysToInclude, + const QVector& overlaysToDiscard, bool visibleOnly, bool collidableOnly) { float bestDistance = std::numeric_limits::max(); bool bestIsFront = false; @@ -624,77 +627,71 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R value.extraInfo = object.property("extraInfo").toVariant().toMap(); } -bool Overlays::isLoaded(OverlayID id) { +bool Overlays::isLoaded(const QUuid& id) { if (QThread::currentThread() != thread()) { bool result; PROFILE_RANGE(script, __FUNCTION__); - BLOCKING_INVOKE_METHOD(this, "isLoaded", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); + BLOCKING_INVOKE_METHOD(this, "isLoaded", Q_RETURN_ARG(bool, result), Q_ARG(const QUuid&, id)); return result; } - Overlay::Pointer thisOverlay = getOverlay(id); - if (!thisOverlay) { - return false; // not found + Overlay::Pointer overlay = get2DOverlay(id); + if (overlay) { + return overlay->isLoaded(); } - return thisOverlay->isLoaded(); + + return DependencyManager::get()->isLoaded(id); } -QSizeF Overlays::textSize(OverlayID id, const QString& text) { +QSizeF Overlays::textSize(const QUuid& id, const QString& text) { if (QThread::currentThread() != thread()) { QSizeF result; PROFILE_RANGE(script, __FUNCTION__); - BLOCKING_INVOKE_METHOD(this, "textSize", Q_RETURN_ARG(QSizeF, result), Q_ARG(OverlayID, id), Q_ARG(QString, text)); + BLOCKING_INVOKE_METHOD(this, "textSize", Q_RETURN_ARG(QSizeF, result), Q_ARG(const QUuid&, id), Q_ARG(QString, text)); return result; } - Overlay::Pointer thisOverlay = getOverlay(id); - if (thisOverlay) { - if (thisOverlay->is3D()) { - if (auto text3dOverlay = std::dynamic_pointer_cast(thisOverlay)) { - return text3dOverlay->textSize(text); - } - } else { - if (auto textOverlay = std::dynamic_pointer_cast(thisOverlay)) { - return textOverlay->textSize(text); - } + Overlay::Pointer overlay = get2DOverlay(id); + if (overlay) { + if (auto textOverlay = std::dynamic_pointer_cast(overlay)) { + return textOverlay->textSize(text); } + return QSizeF(0.0f, 0.0f); + } else { + return DependencyManager::get()->textSize(id, text); } - return QSizeF(0.0f, 0.0f); } -bool Overlays::isAddedOverlay(OverlayID id) { - if (QThread::currentThread() != thread()) { - bool result; - PROFILE_RANGE(script, __FUNCTION__); - BLOCKING_INVOKE_METHOD(this, "isAddedOverlay", Q_RETURN_ARG(bool, result), Q_ARG(OverlayID, id)); - return result; +bool Overlays::isAddedOverlay(const QUuid& id) { + Overlay::Pointer overlay = get2DOverlay(id); + if (overlay) { + return true; } - QMutexLocker locker(&_mutex); - return _overlaysHUD.contains(id) || _overlaysWorld.contains(id); + return DependencyManager::get()->isAddedEntity(id); } -void Overlays::sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::sendMousePressOnOverlay(const QUuid& overlayID, const PointerEvent& event) { mousePressPointerEvent(overlayID, event); } -void Overlays::sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::sendMouseReleaseOnOverlay(const QUuid& overlayID, const PointerEvent& event) { mouseReleasePointerEvent(overlayID, event); } -void Overlays::sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::sendMouseMoveOnOverlay(const QUuid& overlayID, const PointerEvent& event) { mouseMovePointerEvent(overlayID, event); } -void Overlays::sendHoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::sendHoverEnterOverlay(const QUuid& overlayID, const PointerEvent& event) { hoverEnterPointerEvent(overlayID, event); } -void Overlays::sendHoverOverOverlay(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::sendHoverOverOverlay(const QUuid& overlayID, const PointerEvent& event) { hoverOverPointerEvent(overlayID, event); } -void Overlays::sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::sendHoverLeaveOverlay(const QUuid& overlayID, const PointerEvent& event) { hoverLeavePointerEvent(overlayID, event); } @@ -765,10 +762,10 @@ static PointerEvent::Button toPointerButton(const QMouseEvent& event) { } } -PointerEvent Overlays::calculateOverlayPointerEvent(OverlayID overlayID, PickRay ray, - RayToOverlayIntersectionResult rayPickResult, QMouseEvent* event, +PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, + const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, PointerEvent::EventType eventType) { - auto overlay = std::dynamic_pointer_cast(getOverlay(overlayID)); + auto overlay = std::dynamic_pointer_cast(getOverlay(id)); if (getOverlayType(overlayID) == "web3d") { overlay = std::dynamic_pointer_cast(getOverlay(overlayID)); } @@ -793,8 +790,7 @@ bool Overlays::mousePressEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mousePressEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), - QVector()); + RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); if (rayPickResult.intersects) { _currentClickingOnOverlayID = rayPickResult.overlayID; @@ -839,8 +835,7 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), - QVector()); + RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); if (rayPickResult.intersects) { _currentClickingOnOverlayID = rayPickResult.overlayID; diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 818726f54e..d39c847457 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -32,19 +32,6 @@ class PickRay; -class OverlayPropertyResult { -public: - OverlayPropertyResult(); - QVariant value; -}; - -Q_DECLARE_METATYPE(OverlayPropertyResult); - -QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value); -void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value); - -const OverlayID UNKNOWN_OVERLAY_ID = OverlayID(); - /**jsdoc * The result of a {@link PickRay} search using {@link Overlays.findRayIntersection|findRayIntersection}. * @typedef {object} Overlays.RayToOverlayIntersectionResult @@ -59,7 +46,7 @@ const OverlayID UNKNOWN_OVERLAY_ID = OverlayID(); class RayToOverlayIntersectionResult { public: bool intersects { false }; - OverlayID overlayID { UNKNOWN_OVERLAY_ID }; + QUuid overlayID { UNKNOWN_OVERLAY_ID }; float distance { 0.0f }; BoxFace face { UNKNOWN_FACE }; glm::vec3 surfaceNormal; @@ -73,7 +60,7 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R class ParabolaToOverlayIntersectionResult { public: bool intersects { false }; - OverlayID overlayID { UNKNOWN_OVERLAY_ID }; + QUuid overlayID { UNKNOWN_OVERLAY_ID }; float distance { 0.0f }; float parabolicDistance { 0.0f }; BoxFace face { UNKNOWN_FACE }; @@ -83,7 +70,7 @@ public: }; /**jsdoc - * Deprecated. Use local entities instead. The Overlays API provides facilities to create and interact with overlays. Overlays are 2D and 3D objects visible only to + * (Note: 3D Overlays are deprecated. Use local entities instead.) The Overlays API provides facilities to create and interact with overlays. Overlays are 2D and 3D objects visible only to * yourself and that aren't persisted to the domain. They are used for UI. * @namespace Overlays * @@ -98,31 +85,31 @@ public: class Overlays : public QObject { Q_OBJECT - Q_PROPERTY(OverlayID keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay) + Q_PROPERTY(QUuid keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay) public: Overlays(); void init(); void update(float deltatime); - void renderHUD(RenderArgs* renderArgs); + void render(RenderArgs* renderArgs); void disable(); void enable(); - Overlay::Pointer getOverlay(OverlayID id) const; + Overlay::Pointer get2DOverlay(const QUuid& id) const; /// adds an overlay that's already been created - OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); } - OverlayID addOverlay(const Overlay::Pointer& overlay); + QUuid addOverlay(Overlay* overlay) { return add2DOverlay(Overlay::Pointer(overlay)); } + QUuid add2DOverlay(const Overlay::Pointer& overlay); RayToOverlayIntersectionResult findRayIntersectionVector(const PickRay& ray, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, + const QVector& overlaysToInclude, + const QVector& overlaysToDiscard, bool visibleOnly = false, bool collidableOnly = false); ParabolaToOverlayIntersectionResult findParabolaIntersectionVector(const PickParabola& parabola, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, + const QVector& overlaysToInclude, + const QVector& overlaysToDiscard, bool visibleOnly = false, bool collidableOnly = false); bool mousePressEvent(QMouseEvent* event); @@ -147,20 +134,20 @@ public slots: * solid: true * }); */ - OverlayID addOverlay(const QString& type, const QVariant& properties); + QUuid addOverlay(const QString& type, const QVariant& properties); /**jsdoc - * Create a clone of an existing entity. + * Create a clone of an existing entity (or 2D overlay). * @function Overlays.cloneOverlay - * @param {Uuid} id - The ID of the entity to clone. - * @returns {Uuid} The ID of the new entity if successful, otherwise {@link Uuid|Uuid.NULL}. + * @param {Uuid} id - The ID of the entity/2D overlay to clone. + * @returns {Uuid} The ID of the new object if successful, otherwise {@link Uuid|Uuid.NULL}. */ - EntityItemID cloneOverlay(EntityItemID id) { return DependencyManager::get()->cloneEntity(id); } + QUuid cloneOverlay(const QUuid& id); /**jsdoc * Edit an overlay's properties. * @function Overlays.editOverlay - * @param {Uuid} overlayID - The ID of the overlay to edit. + * @param {Uuid} id - The ID of the overlay to edit. * @param {Overlays.OverlayProperties} properties - The properties changes to make. * @returns {boolean} true if the overlay was found and edited, otherwise false. * @example Add an overlay in front of your avatar then change its color. @@ -176,7 +163,7 @@ public slots: * }); * print("Success: " + success); */ - bool editOverlay(OverlayID id, const QVariant& properties); + bool editOverlay(const QUuid& id, const QVariant& properties); /**jsdoc * Edit multiple overlays' properties. @@ -208,18 +195,18 @@ public slots: bool editOverlays(const QVariant& propertiesById); /**jsdoc - * Delete an entity. + * Delete an entity or 2D overlay. * @function Overlays.deleteOverlay - * @param {Uuid} id - The ID of the entity to delete. + * @param {Uuid} id - The ID of the object to delete. */ - void deleteOverlay(EntityItemID id); + void deleteOverlay(const QUuid& id); /**jsdoc - * Get the type of an overlay. + * Get the type of an entity or 2D overlay. * @function Overlays.getOverlayType - * @param {Uuid} overlayID - The ID of the overlay to get the type of. - * @returns {Overlays.OverlayType} The type of the overlay if found, otherwise an empty string. - * @example Create an overlay in front of your avatar then get and report its type. + * @param {Uuid} id - The ID of the object to get the type of. + * @returns {string} The type of the object if found, otherwise an empty string. + * @example Create an object in front of your avatar then get and report its type. * var overlay = Overlays.addOverlay("cube", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -3 })), * rotation: MyAvatar.orientation, @@ -229,7 +216,7 @@ public slots: * var type = Overlays.getOverlayType(overlay); * print("Type: " + type); */ - QString getOverlayType(OverlayID overlayId); + QString getOverlayType(const QUuid& id); /**jsdoc * Get the overlay script object. In particular, this is useful for accessing the event bridge for a web3d @@ -273,7 +260,7 @@ public slots: * Overlays.deleteOverlay(web3dOverlay); * }); */ - QObject* getOverlayObject(OverlayID id); + QObject* getOverlayObject(const QUuid& id); /**jsdoc * Get the ID of the 2D overlay at a particular point on the screen or HUD. @@ -292,12 +279,12 @@ public slots: * print("Clicked: " + overlay); * }); */ - OverlayID getOverlayAtPoint(const glm::vec2& point); + QUuid getOverlayAtPoint(const glm::vec2& point); /**jsdoc * Get the value of a 3D overlay's property. * @function Overlays.getProperty - * @param {Uuid} overlayID - The ID of the overlay. Must be for a 3D {@link Overlays.OverlayType|OverlayType}. + * @param {Uuid} id - The ID of the overlay. Must be for a 3D {@link Overlays.OverlayType|OverlayType}. * @param {string} property - The name of the property value to get. * @returns {object} The value of the property if the 3D overlay and property can be found, otherwise * undefined. @@ -311,12 +298,12 @@ public slots: * var alpha = Overlays.getProperty(overlay, "alpha"); * print("Overlay alpha: " + alpha); */ - OverlayPropertyResult getProperty(OverlayID id, const QString& property); + QVariant getProperty(const QUuid& id, const QString& property); /**jsdoc * Get the values of an overlay's properties. * @function Overlays.getProperties - * @param {Uuid} overlayID - The ID of the overlay. + * @param {Uuid} id - The ID of the overlay. * @param {Array.} properties - An array of names of properties to get the values of. * @returns {Overlays.OverlayProperties} The values of valid properties if the overlay can be found, otherwise * undefined. @@ -330,7 +317,7 @@ public slots: * var properties = Overlays.getProperties(overlay, ["color", "alpha", "grabbable"]); * print("Overlay properties: " + JSON.stringify(properties)); */ - OverlayPropertyResult getProperties(const OverlayID& id, const QStringList& properties); + QVariantMap getProperties(const QUuid& id, const QStringList& properties); /**jsdoc * Get the values of multiple overlays' properties. @@ -358,7 +345,7 @@ public slots: * var properties = Overlays.getOverlaysProperties(propertiesToGet); * print("Overlays properties: " + JSON.stringify(properties)); */ - OverlayPropertyResult getOverlaysProperties(const QVariant& overlaysProperties); + QVariantMap getOverlaysProperties(const QVariant& overlaysProperties); /**jsdoc * Find the closest 3D overlay intersected by a {@link PickRay}. Overlays with their drawInFront property set @@ -428,7 +415,7 @@ public slots: * Check whether an overlay's assets have been loaded. For example, for an image overlay the result indicates * whether its image has been loaded. * @function Overlays.isLoaded - * @param {Uuid} overlayID - The ID of the overlay to check. + * @param {Uuid} id - The ID of the overlay to check. * @returns {boolean} true if the overlay's assets have been loaded, otherwise false. * @example Create an image overlay and report whether its image is loaded after 1s. * var overlay = Overlays.addOverlay("image", { @@ -440,17 +427,17 @@ public slots: * print("Image loaded: " + isLoaded); * }, 1000); */ - bool isLoaded(OverlayID id); + bool isLoaded(const QUuid& id); /**jsdoc - * Calculates the size of the given text in the specified overlay if it is a text overlay. + * Calculates the size of the given text in the specified object if it is a text entity or overlay. * @function Overlays.textSize - * @param {Uuid} overlayID - The ID of the overlay to use for calculation. + * @param {Uuid} id - The ID of the object to use for calculation. * @param {string} text - The string to calculate the size of. - * @returns {Size} The size of the text if the overlay is a text overlay, otherwise - * { height: 0, width : 0 }. If the overlay is a 2D overlay, the size is in pixels; if the overlay is a 3D - * overlay, the size is in meters. - * @example Calculate the size of "hello" in a 3D text overlay. + * @returns {Size} The size of the text if the object is a text entity or overlay, otherwise + * { height: 0, width : 0 }. If the object is a 2D overlay, the size is in pixels; if the object is an entity, + * the size is in meters. + * @example Calculate the size of "hello" in a 3D text entity. * var overlay = Overlays.addOverlay("text3d", { * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0, z: -2 })), * rotation: MyAvatar.orientation, @@ -460,7 +447,7 @@ public slots: * var textSize = Overlays.textSize(overlay, "hello"); * print("Size of \"hello\": " + JSON.stringify(textSize)); */ - QSizeF textSize(OverlayID id, const QString& text); + QSizeF textSize(const QUuid& id, const QString& text); /**jsdoc * Get the width of the window or HUD. @@ -477,17 +464,17 @@ public slots: float height(); /**jsdoc - * Check if there is an overlay of a given ID. + * Check if there is an object of a given ID. * @function Overlays.isAddedOverlay - * @param {Uuid} overlayID - The ID to check. - * @returns {boolean} true if an overlay with the given ID exists, false otherwise. + * @param {Uuid} id - The ID to check. + * @returns {boolean} true if an object with the given ID exists, false otherwise. */ - bool isAddedOverlay(OverlayID id); + bool isAddedOverlay(const QUuid& id); /**jsdoc * Generate a mouse press event on an overlay. * @function Overlays.sendMousePressOnOverlay - * @param {Uuid} overlayID - The ID of the overlay to generate a mouse press event on. + * @param {Uuid} id - The ID of the overlay to generate a mouse press event on. * @param {PointerEvent} event - The mouse press event details. * @example Create a 2D rectangle overlay plus a 3D cube overlay and generate mousePressOnOverlay events for the 2D * overlay. @@ -522,23 +509,23 @@ public slots: * } * }); */ - void sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event); + void sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Generate a mouse release event on an overlay. * @function Overlays.sendMouseReleaseOnOverlay - * @param {Uuid} overlayID - The ID of the overlay to generate a mouse release event on. + * @param {Uuid} id - The ID of the overlay to generate a mouse release event on. * @param {PointerEvent} event - The mouse release event details. */ - void sendMouseReleaseOnOverlay(const OverlayID& overlayID, const PointerEvent& event); + void sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Generate a mouse move event on an overlay. * @function Overlays.sendMouseMoveOnOverlay - * @param {Uuid} overlayID - The ID of the overlay to generate a mouse move event on. + * @param {Uuid} id - The ID of the overlay to generate a mouse move event on. * @param {PointerEvent} event - The mouse move event details. */ - void sendMouseMoveOnOverlay(const OverlayID& overlayID, const PointerEvent& event); + void sendMouseMoveOnOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Generate a hover enter event on an overlay. @@ -546,23 +533,23 @@ public slots: * @param {Uuid} id - The ID of the overlay to generate a hover enter event on. * @param {PointerEvent} event - The hover enter event details. */ - void sendHoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event); + void sendHoverEnterOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Generate a hover over event on an overlay. * @function Overlays.sendHoverOverOverlay - * @param {Uuid} overlayID - The ID of the overlay to generate a hover over event on. + * @param {Uuid} id - The ID of the overlay to generate a hover over event on. * @param {PointerEvent} event - The hover over event details. */ - void sendHoverOverOverlay(const OverlayID& overlayID, const PointerEvent& event); + void sendHoverOverOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Generate a hover leave event on an overlay. * @function Overlays.sendHoverLeaveOverlay - * @param {Uuid} overlayID - The ID of the overlay to generate a hover leave event on. + * @param {Uuid} id - The ID of the overlay to generate a hover leave event on. * @param {PointerEvent} event - The hover leave event details. */ - void sendHoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event); + void sendHoverLeaveOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Get the ID of the Web3D local entity that has keyboard focus. @@ -575,16 +562,16 @@ public slots: /**jsdoc * Set the Web3D local entity that has keyboard focus. * @function Overlays.setKeyboardFocusOverlay - * @param {Uuid} overlayID - The ID of the {@link Entities.EntityTypes|Web} overlay to set keyboard focus to. Use + * @param {Uuid} id - The ID of the {@link Entities.EntityTypes|Web} overlay to set keyboard focus to. Use * null or {@link Uuid|Uuid.NULL} to unset keyboard focus from an overlay. */ - void Overlays::setKeyboardFocusOverlay(const EntityItemID& id) { DependencyManager::get()->setKeyboardFocusLocalEntity(id); } + void setKeyboardFocusOverlay(const EntityItemID& id) { DependencyManager::get()->setKeyboardFocusLocalEntity(id); } signals: /**jsdoc * Triggered when an overlay is deleted. * @function Overlays.overlayDeleted - * @param {Uuid} overlayID - The ID of the overlay that was deleted. + * @param {Uuid} id - The ID of the overlay that was deleted. * @returns {Signal} * @example Create an overlay then delete it after 1s. * var overlay = Overlays.addOverlay("cube", { @@ -602,13 +589,13 @@ signals: * Overlays.deleteOverlay(overlay); * }, 1000); */ - void overlayDeleted(OverlayID id); + void overlayDeleted(const QUuid& id); /**jsdoc * Triggered when a mouse press event occurs on an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendMousePressOnOverlay|sendMousePressOnOverlay} for a 2D overlay). * @function Overlays.mousePressOnOverlay - * @param {Uuid} overlayID - The ID of the overlay the mouse press event occurred on. + * @param {Uuid} id - The ID of the overlay the mouse press event occurred on. * @param {PointerEvent} event - The mouse press event details. * @returns {Signal} * @example Create a cube overlay in front of your avatar and report mouse clicks on it. @@ -626,36 +613,36 @@ signals: * } * }); */ - void mousePressOnOverlay(OverlayID overlayID, const PointerEvent& event); + void mousePressOnOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Triggered when a mouse double press event occurs on an overlay. Only occurs for 3D overlays. * @function Overlays.mouseDoublePressOnOverlay - * @param {Uuid} overlayID - The ID of the overlay the mouse double press event occurred on. + * @param {Uuid} id - The ID of the overlay the mouse double press event occurred on. * @param {PointerEvent} event - The mouse double press event details. * @returns {Signal} */ - void mouseDoublePressOnOverlay(OverlayID overlayID, const PointerEvent& event); + void mouseDoublePressOnOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Triggered when a mouse release event occurs on an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendMouseReleaseOnOverlay|sendMouseReleaseOnOverlay} for a 2D overlay). * @function Overlays.mouseReleaseOnOverlay - * @param {Uuid} overlayID - The ID of the overlay the mouse release event occurred on. + * @param {Uuid} id - The ID of the overlay the mouse release event occurred on. * @param {PointerEvent} event - The mouse release event details. * @returns {Signal} */ - void mouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event); + void mouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Triggered when a mouse move event occurs on an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendMouseMoveOnOverlay|sendMouseMoveOnOverlay} for a 2D overlay). * @function Overlays.mouseMoveOnOverlay - * @param {Uuid} overlayID - The ID of the overlay the mouse moved event occurred on. + * @param {Uuid} id - The ID of the overlay the mouse moved event occurred on. * @param {PointerEvent} event - The mouse move event details. * @returns {Signal} */ - void mouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event); + void mouseMoveOnOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Triggered when a mouse press event occurs on something other than a 3D overlay. @@ -675,7 +662,7 @@ signals: * Triggered when a mouse cursor starts hovering over an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendHoverEnterOverlay|sendHoverEnterOverlay} for a 2D overlay). * @function Overlays.hoverEnterOverlay - * @param {Uuid} overlayID - The ID of the overlay the mouse moved event occurred on. + * @param {Uuid} id - The ID of the overlay the mouse moved event occurred on. * @param {PointerEvent} event - The mouse move event details. * @returns {Signal} * @example Create a cube overlay in front of your avatar and report when you start hovering your mouse over @@ -691,54 +678,53 @@ signals: * print("Hover enter: " + overlayID); * }); */ - void hoverEnterOverlay(OverlayID overlayID, const PointerEvent& event); + void hoverEnterOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Triggered when a mouse cursor continues hovering over an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendHoverOverOverlay|sendHoverOverOverlay} for a 2D overlay). * @function Overlays.hoverOverOverlay - * @param {Uuid} overlayID - The ID of the overlay the hover over event occurred on. + * @param {Uuid} id - The ID of the overlay the hover over event occurred on. * @param {PointerEvent} event - The hover over event details. * @returns {Signal} */ - void hoverOverOverlay(OverlayID overlayID, const PointerEvent& event); + void hoverOverOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc * Triggered when a mouse cursor finishes hovering over an overlay. Only occurs for 3D overlays (unless you use * {@link Overlays.sendHoverLeaveOverlay|sendHoverLeaveOverlay} for a 2D overlay). * @function Overlays.hoverLeaveOverlay - * @param {Uuid} overlayID - The ID of the overlay the hover leave event occurred on. + * @param {Uuid} id - The ID of the overlay the hover leave event occurred on. * @param {PointerEvent} event - The hover leave event details. * @returns {Signal} */ - void hoverLeaveOverlay(OverlayID overlayID, const PointerEvent& event); + void hoverLeaveOverlay(const QUuid& id, const PointerEvent& event); private: void cleanupOverlaysToDelete(); mutable QMutex _mutex { QMutex::Recursive }; - QMap _overlaysHUD; - QMap _overlaysWorld; - + QMap _overlays; QList _overlaysToDelete; + unsigned int _stackOrder { 1 }; - bool _enabled = true; - std::atomic _shuttingDown{ false }; + bool _enabled { true }; + std::atomic _shuttingDown { false }; - PointerEvent calculateOverlayPointerEvent(OverlayID overlayID, PickRay ray, RayToOverlayIntersectionResult rayPickResult, + PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, PointerEvent::EventType eventType); - OverlayID _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID }; - OverlayID _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID }; + QUuid _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID }; + QUuid _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID }; private slots: - void mousePressPointerEvent(const OverlayID& overlayID, const PointerEvent& event); - void mouseMovePointerEvent(const OverlayID& overlayID, const PointerEvent& event); - void mouseReleasePointerEvent(const OverlayID& overlayID, const PointerEvent& event); - void hoverEnterPointerEvent(const OverlayID& overlayID, const PointerEvent& event); - void hoverOverPointerEvent(const OverlayID& overlayID, const PointerEvent& event); - void hoverLeavePointerEvent(const OverlayID& overlayID, const PointerEvent& event); + void mousePressPointerEvent(const QUuid& id, const PointerEvent& event); + void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event); + void mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event); + void hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event); + void hoverOverPointerEvent(const QUuid& id, const PointerEvent& event); + void hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event); }; #endif // hifi_Overlays_h diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 4ede5e5057..c139fbf320 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -104,8 +104,8 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi }); _emitting = entity->getIsEmitting(); - bool hasTexture = resultWithReadLock([&]{ return _particleProperties.textures.isEmpty(); }); - if (hasTexture) { + bool textureEmpty = resultWithReadLock([&]{ return _particleProperties.textures.isEmpty(); }); + if (textureEmpty) { if (_networkTexture) { withWriteLock([&] { _networkTexture.reset(); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 5614e976b5..d5f0843049 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -23,6 +23,9 @@ using namespace render; using namespace render::entities; static const int FIXED_FONT_POINT_SIZE = 40; +const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 92.0f; // Determined through experimentation to fit font to line + // height. +const float LINE_SCALE_RATIO = 1.2f; TextEntityRenderer::TextEntityRenderer(const EntityItemPointer& entity) : Parent(entity), @@ -205,3 +208,12 @@ void TextEntityRenderer::doRender(RenderArgs* args) { dimensions.y - (_topMargin + _bottomMargin)); _textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale); } + +QSizeF TextEntityRenderer::textSize(const QString& text) const { + auto extents = _textRenderer->computeExtent(text); + + float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO; + float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; + + return QSizeF(extents.x, extents.y) * pointToWorldScale; +} \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 6c9e8324f8..a7c0b77974 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -29,6 +29,8 @@ public: bool isTransparent() const override; ShapeKey getShapeKey() override; + QSizeF textSize(const QString& text) const; + private: virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 5d97eb5b8e..e5eff5818b 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -47,6 +47,9 @@ public: } } + virtual void setProxyWindow(QWindow* proxyWindow) override; + virtual QObject* getEventHandler() override; + protected: virtual bool needsRenderUpdate() const override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; @@ -57,9 +60,6 @@ protected: virtual bool wantsHandControllerPointerEvents() const override { return true; } virtual bool wantsKeyboardFocus() const override { return true; } - virtual void setProxyWindow(QWindow* proxyWindow) override; - virtual QObject* getEventHandler() override; - void handlePointerEventAsTouch(const PointerEvent& event); void handlePointerEventAsMouse(const PointerEvent& event); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 17c956c96c..17fed5ff54 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -571,7 +571,7 @@ QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QStrin return addEntity(properties); } -QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { +QUuid EntityScriptingInterface::cloneEntity(const QUuid& entityIDToClone) { EntityItemID newEntityID; EntityItemProperties properties = getEntityProperties(entityIDToClone); bool cloneAvatarEntity = properties.getCloneAvatarEntity(); @@ -596,12 +596,12 @@ QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { } } -EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid entityID) { +EntityItemProperties EntityScriptingInterface::getEntityProperties(const QUuid& entityID) { const EntityPropertyFlags noSpecificProperties; return getEntityProperties(entityID, noSpecificProperties); } -EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid entityID, EntityPropertyFlags desiredProperties) { +EntityItemProperties EntityScriptingInterface::getEntityProperties(const QUuid& entityID, EntityPropertyFlags desiredProperties) { PROFILE_RANGE(script_entities, __FUNCTION__); bool scalesWithParent { false }; @@ -775,7 +775,7 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri return finalResult; } -QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) { +QUuid EntityScriptingInterface::editEntity(const QUuid& id, const EntityItemProperties& scriptSideProperties) { PROFILE_RANGE(script_entities, __FUNCTION__); _activityTracking.editedEntityCount++; @@ -960,7 +960,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& return id; } -void EntityScriptingInterface::deleteEntity(QUuid id) { +void EntityScriptingInterface::deleteEntity(const QUuid& id) { PROFILE_RANGE(script_entities, __FUNCTION__); _activityTracking.deletedEntityCount++; @@ -1005,12 +1005,49 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { } } +QString EntityScriptingInterface::getEntityType(const QUuid& entityID) { + QString toReturn; + _entityTree->withReadLock([&] { + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); + if (entity) { + toReturn = EntityTypes::getEntityTypeName(entity->getType()); + } + }); + return toReturn; +} + +QObject* EntityScriptingInterface::getEntityObject(const QUuid& id) { + QObject* toReturn { nullptr }; + _entityTree->withReadLock([&] { + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(id); + if (entity) { + toReturn = qobject_cast(&(*entity)); + } + }); + return toReturn; +} + +bool EntityScriptingInterface::isLoaded(const QUuid& id) { + bool toReturn = false; + _entityTree->withReadLock([&] { + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(id); + if (entity) { + toReturn = entity->isVisuallyReady(); + } + }); + return toReturn; +} + +QSizeF EntityScriptingInterface::textSize(const QUuid& id, const QString& text) { + return EntityTree::textSize(id, text); +} + void EntityScriptingInterface::setEntitiesScriptEngine(QSharedPointer engine) { std::lock_guard lock(_entitiesScriptEngineLock); _entitiesScriptEngine = engine; } -void EntityScriptingInterface::callEntityMethod(QUuid id, const QString& method, const QStringList& params) { +void EntityScriptingInterface::callEntityMethod(const QUuid& id, const QString& method, const QStringList& params) { PROFILE_RANGE(script_entities, __FUNCTION__); std::lock_guard lock(_entitiesScriptEngineLock); @@ -1020,12 +1057,12 @@ void EntityScriptingInterface::callEntityMethod(QUuid id, const QString& method, } } -void EntityScriptingInterface::callEntityServerMethod(QUuid id, const QString& method, const QStringList& params) { +void EntityScriptingInterface::callEntityServerMethod(const QUuid& id, const QString& method, const QStringList& params) { PROFILE_RANGE(script_entities, __FUNCTION__); DependencyManager::get()->callEntityServerMethod(id, method, params); } -void EntityScriptingInterface::callEntityClientMethod(QUuid clientSessionID, QUuid entityID, const QString& method, const QStringList& params) { +void EntityScriptingInterface::callEntityClientMethod(const QUuid& clientSessionID, const QUuid& entityID, const QString& method, const QStringList& params) { PROFILE_RANGE(script_entities, __FUNCTION__); auto scriptServerServices = DependencyManager::get(); @@ -1262,7 +1299,7 @@ ParabolaToEntityIntersectionResult EntityScriptingInterface::evalParabolaInterse return result; } -bool EntityScriptingInterface::reloadServerScripts(QUuid entityID) { +bool EntityScriptingInterface::reloadServerScripts(const QUuid& entityID) { auto client = DependencyManager::get(); return client->reloadServerScript(entityID); } @@ -1335,7 +1372,7 @@ bool EntityPropertyMetadataRequest::serverScripts(EntityItemID entityID, QScript return true; } -bool EntityScriptingInterface::queryPropertyMetadata(QUuid entityID, QScriptValue property, QScriptValue scopeOrCallback, QScriptValue methodOrName) { +bool EntityScriptingInterface::queryPropertyMetadata(const QUuid& entityID, QScriptValue property, QScriptValue scopeOrCallback, QScriptValue methodOrName) { auto name = property.toString(); auto handler = makeScopedHandlerObject(scopeOrCallback, methodOrName); QPointer engine = dynamic_cast(handler.engine()); @@ -1379,7 +1416,7 @@ bool EntityScriptingInterface::queryPropertyMetadata(QUuid entityID, QScriptValu } } -bool EntityScriptingInterface::getServerScriptStatus(QUuid entityID, QScriptValue callback) { +bool EntityScriptingInterface::getServerScriptStatus(const QUuid& entityID, QScriptValue callback) { auto client = DependencyManager::get(); auto request = client->createScriptStatusRequest(entityID); connect(request, &GetScriptStatusRequest::finished, callback.engine(), [callback](GetScriptStatusRequest* request) mutable { @@ -1518,14 +1555,14 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::function& points) { +bool EntityScriptingInterface::setAllPoints(const QUuid& entityID, const QVector& points) { PROFILE_RANGE(script_entities, __FUNCTION__); EntityItemPointer entity = static_cast(_entityTree->findEntityByEntityItemID(entityID)); @@ -1580,7 +1617,7 @@ bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector(_entityTree->findEntityByEntityItemID(entityID)); @@ -2040,7 +2077,7 @@ QVector EntityScriptingInterface::getChildrenIDs(const QUuid& parentID) { return result; } -bool EntityScriptingInterface::isChildOfParent(QUuid childID, QUuid parentID) { +bool EntityScriptingInterface::isChildOfParent(const QUuid& childID, const QUuid& parentID) { bool isChild = false; if (!_entityTree) { @@ -2062,7 +2099,7 @@ bool EntityScriptingInterface::isChildOfParent(QUuid childID, QUuid parentID) { return isChild; } -QString EntityScriptingInterface::getNestableType(QUuid id) { +QString EntityScriptingInterface::getNestableType(const QUuid& id) { QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { return "unknown"; @@ -2164,7 +2201,7 @@ void EntityScriptingInterface::sendHoverLeaveEntity(const EntityItemID& id, cons emit hoverLeaveEntity(id, event); } -bool EntityScriptingInterface::wantsHandControllerPointerEvents(QUuid id) { +bool EntityScriptingInterface::wantsHandControllerPointerEvents(const QUuid& id) { bool result = false; if (_entityTree) { _entityTree->withReadLock([&] { @@ -2196,7 +2233,7 @@ bool EntityScriptingInterface::AABoxIntersectsCapsule(const glm::vec3& low, cons return aaBox.findCapsulePenetration(start, end, radius, penetration); } -void EntityScriptingInterface::getMeshes(QUuid entityID, QScriptValue callback) { +void EntityScriptingInterface::getMeshes(const QUuid& entityID, QScriptValue callback) { PROFILE_RANGE(script_entities, __FUNCTION__); EntityItemPointer entity = static_cast(_entityTree->findEntityByEntityItemID(entityID)); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 939e257a8c..7b6a191e1e 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -296,7 +296,7 @@ public slots: * @param {Uuid} entityID - The ID of the entity to clone. * @returns {Uuid} The ID of the new entity if successfully cloned, otherwise {@link Uuid|Uuid.NULL}. */ - Q_INVOKABLE QUuid cloneEntity(QUuid entityIDToClone); + Q_INVOKABLE QUuid cloneEntity(const QUuid& entityID); /**jsdoc * Get the properties of an entity. @@ -315,8 +315,8 @@ public slots: * var properties = Entities.getEntityProperties(entityID, ["color"]); * print("Entity color: " + JSON.stringify(properties.color)); */ - Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID); - Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID, EntityPropertyFlags desiredProperties); + Q_INVOKABLE EntityItemProperties getEntityProperties(const QUuid& entityID); + Q_INVOKABLE EntityItemProperties getEntityProperties(const QUuid& entityID, EntityPropertyFlags desiredProperties); /**jsdoc * Update an entity with specified properties. @@ -340,7 +340,7 @@ public slots: * properties = Entities.getEntityProperties(entityID, ["color"]); * print("Entity color: " + JSON.stringify(properties.color)); */ - Q_INVOKABLE QUuid editEntity(QUuid entityID, const EntityItemProperties& properties); + Q_INVOKABLE QUuid editEntity(const QUuid& entityID, const EntityItemProperties& properties); /**jsdoc * Delete an entity. @@ -358,8 +358,50 @@ public slots: * Entities.deleteEntity(entityID); * }, 3000); */ - Q_INVOKABLE void deleteEntity(QUuid entityID); + Q_INVOKABLE void deleteEntity(const QUuid& entityID); + /**jsdoc + * Get an entities type as a string. + * @function Entities.deleteEntity + * @param {Uuid} id - The id of the entity to get the type of. + */ + Q_INVOKABLE QString getEntityType(const QUuid& entityID); + + /**jsdoc + * Get the entity script object. In particular, this is useful for accessing the event bridge for a Web + * entity. + * @function Entities.getEntityObject + * @param {Uuid} id - The ID of the entity to get the script object of. + * @returns {object} The script object for the entity if found. + */ + Q_INVOKABLE QObject* getEntityObject(const QUuid& id); + + /**jsdoc + * Check whether an entities's assets have been loaded. For example, for an Model entity the result indicates + * whether its textures have been loaded. + * @function Entities.isLoaded + * @param {Uuid} id - The ID of the entity to check. + * @returns {boolean} true if the entity's assets have been loaded, otherwise false. + */ + Q_INVOKABLE bool isLoaded(const QUuid& id); + + /**jsdoc + * Check if there is an object of a given ID. + * @function Entities.isAddedEntity + * @param {Uuid} id - The ID to check. + * @returns {boolean} true if an object with the given ID exists, false otherwise. + */ + Q_INVOKABLE bool isAddedEntity(const QUuid& id); + + /**jsdoc + * Calculates the size of the given text in the specified object if it is a text entity. + * @function Entities.textSize + * @param {Uuid} id - The ID of the entity to use for calculation. + * @param {string} text - The string to calculate the size of. + * @returns {Size} The size of the text in meters if the object is a text entity, otherwise + * { height: 0, width : 0 }. + */ + Q_INVOKABLE QSizeF textSize(const QUuid& id, const QString& text); /**jsdoc * Call a method in a client entity script from a client script or client entity script, or call a method in a server @@ -371,7 +413,7 @@ public slots: * @param {string} method - The name of the method to call. * @param {string[]} [parameters=[]] - The parameters to call the specified method with. */ - Q_INVOKABLE void callEntityMethod(QUuid entityID, const QString& method, const QStringList& params = QStringList()); + Q_INVOKABLE void callEntityMethod(const QUuid& entityID, const QString& method, const QStringList& params = QStringList()); /**jsdoc * Call a method in a server entity script from a client script or client entity script. The entity script method must be @@ -383,7 +425,7 @@ public slots: * @param {string} method - The name of the method to call. * @param {string[]} [parameters=[]] - The parameters to call the specified method with. */ - Q_INVOKABLE void callEntityServerMethod(QUuid entityID, const QString& method, const QStringList& params = QStringList()); + Q_INVOKABLE void callEntityServerMethod(const QUuid& entityID, const QString& method, const QStringList& params = QStringList()); /**jsdoc * Call a method in a specific user's client entity script from a server entity script. The entity script method must be @@ -394,7 +436,7 @@ public slots: * @param {string} method - The name of the method to call. * @param {string[]} [parameters=[]] - The parameters to call the specified method with. */ - Q_INVOKABLE void callEntityClientMethod(QUuid clientSessionID, QUuid entityID, const QString& method, + Q_INVOKABLE void callEntityClientMethod(const QUuid& clientSessionID, const QUuid& entityID, const QString& method, const QStringList& params = QStringList()); /**jsdoc @@ -524,7 +566,7 @@ public slots: * @returns {boolean} true if the reload request was successfully sent to the server, otherwise * false. */ - Q_INVOKABLE bool reloadServerScripts(QUuid entityID); + Q_INVOKABLE bool reloadServerScripts(const QUuid& entityID); /**jsdoc * Gets the status of server entity script attached to an entity @@ -543,7 +585,7 @@ public slots: * @param {string} errorInfo - "" if there is a server entity script running, otherwise it may contain extra * information on the error. */ - Q_INVOKABLE bool getServerScriptStatus(QUuid entityID, QScriptValue callback); + Q_INVOKABLE bool getServerScriptStatus(const QUuid& entityID, QScriptValue callback); /**jsdoc * Get metadata for certain entity properties such as script and serverScripts. @@ -573,7 +615,7 @@ public slots: * @param {object} result - The metadata for the requested entity property if there was no error, otherwise * undefined. */ - Q_INVOKABLE bool queryPropertyMetadata(QUuid entityID, QScriptValue property, QScriptValue scopeOrCallback, + Q_INVOKABLE bool queryPropertyMetadata(const QUuid& entityID, QScriptValue property, QScriptValue scopeOrCallback, QScriptValue methodOrName = QScriptValue()); @@ -657,7 +699,7 @@ public slots: * Entities.setVoxelSphere(polyVox, position, 0.9, 255); */ // FIXME move to a renderable entity interface - Q_INVOKABLE bool setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value); + Q_INVOKABLE bool setVoxelSphere(const QUuid& entityID, const glm::vec3& center, float radius, int value); /**jsdoc * Set the values of all voxels in a capsule-shaped portion of a {@link Entities.EntityType|PolyVox} entity. @@ -681,7 +723,7 @@ public slots: * Entities.setVoxelCapsule(polyVox, startPosition, endPosition, 0.5, 255); */ // FIXME move to a renderable entity interface - Q_INVOKABLE bool setVoxelCapsule(QUuid entityID, const glm::vec3& start, const glm::vec3& end, float radius, int value); + Q_INVOKABLE bool setVoxelCapsule(const QUuid& entityID, const glm::vec3& start, const glm::vec3& end, float radius, int value); /**jsdoc * Set the value of a particular voxels in a {@link Entities.EntityType|PolyVox} entity. @@ -703,7 +745,7 @@ public slots: * Entities.setVoxel(entity, { x: 0, y: 0, z: 0 }, 0); */ // FIXME move to a renderable entity interface - Q_INVOKABLE bool setVoxel(QUuid entityID, const glm::vec3& position, int value); + Q_INVOKABLE bool setVoxel(const QUuid& entityID, const glm::vec3& position, int value); /**jsdoc * Set the values of all voxels in a {@link Entities.EntityType|PolyVox} entity. @@ -721,7 +763,7 @@ public slots: * Entities.setAllVoxels(entity, 1); */ // FIXME move to a renderable entity interface - Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value); + Q_INVOKABLE bool setAllVoxels(const QUuid& entityID, int value); /**jsdoc * Set the values of all voxels in a cubic portion of a {@link Entities.EntityType|PolyVox} entity. @@ -746,7 +788,7 @@ public slots: * Entities.setVoxelsInCuboid(polyVox, cuboidPosition, cuboidSize, 0); */ // FIXME move to a renderable entity interface - Q_INVOKABLE bool setVoxelsInCuboid(QUuid entityID, const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int value); + Q_INVOKABLE bool setVoxelsInCuboid(const QUuid& entityID, const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int value); /**jsdoc * Convert voxel coordinates in a {@link Entities.EntityType|PolyVox} entity to world coordinates. Voxel coordinates are @@ -862,7 +904,7 @@ public slots: * ]); * }, 2000); */ - Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector& points); + Q_INVOKABLE bool setAllPoints(const QUuid& entityID, const QVector& points); /**jsdoc * Append a point to a {@link Entities.EntityType|Line} entity. @@ -890,7 +932,7 @@ public slots: * // Add a third point to create a "V". * Entities.appendPoint(entity, { x: 1, y: 1, z: 0 }); */ - Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point); + Q_INVOKABLE bool appendPoint(const QUuid& entityID, const glm::vec3& point); /**jsdoc * Dumps debug information about all entities in Interface's local in-memory tree of entities it knows about to the program log. @@ -1355,7 +1397,7 @@ public slots: * * print("grandChild has root as parent: " + Entities.isChildOfParent(grandChild, root)); // true */ - Q_INVOKABLE bool isChildOfParent(QUuid childID, QUuid parentID); + Q_INVOKABLE bool isChildOfParent(const QUuid& childID, const QUuid& parentID); /**jsdoc * Get the type — entity, overlay, or avatar — of an in-world item. @@ -1374,7 +1416,7 @@ public slots: * print(Entities.getNestableType(entity)); // "entity" * print(Entities.getNestableType(Uuid.generate())); // "unknown" */ - Q_INVOKABLE QString getNestableType(QUuid entityID); + Q_INVOKABLE QString getNestableType(const QUuid& entityID); /**jsdoc * Get the ID of the {@link Entities.EntityType|Web} entity that has keyboard focus. @@ -1486,7 +1528,7 @@ public slots: * @returns {boolean} true if the entity can be found and it wants hand controller pointer events, otherwise * false. */ - Q_INVOKABLE bool wantsHandControllerPointerEvents(QUuid id); + Q_INVOKABLE bool wantsHandControllerPointerEvents(const QUuid& id); /**jsdoc * Send a script event over a {@link Entities.EntityType|Web} entity's EventBridge to the Web page's scripts. @@ -1527,7 +1569,7 @@ public slots: * @deprecated Use the {@link Graphics} API instead. */ // FIXME move to a renderable entity interface - Q_INVOKABLE void getMeshes(QUuid entityID, QScriptValue callback); + Q_INVOKABLE void getMeshes(const QUuid& entityID, QScriptValue callback); /**jsdoc * Get the object to world transform, excluding scale, of an entity. diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 954462a9f2..90f1044f5b 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2957,8 +2957,7 @@ std::function E std::function EntityTree::_removeMaterialFromEntityOperator = nullptr; std::function EntityTree::_addMaterialToAvatarOperator = nullptr; std::function EntityTree::_removeMaterialFromAvatarOperator = nullptr; -std::function EntityTree::_addMaterialToOverlayOperator = nullptr; -std::function EntityTree::_removeMaterialFromOverlayOperator = nullptr; +std::function EntityTree::_textSizeOperator = nullptr; bool EntityTree::addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { if (_addMaterialToEntityOperator) { @@ -2988,18 +2987,11 @@ bool EntityTree::removeMaterialFromAvatar(const QUuid& avatarID, graphics::Mater return false; } -bool EntityTree::addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) { - if (_addMaterialToOverlayOperator) { - return _addMaterialToOverlayOperator(overlayID, material, parentMaterialName); +QSizeF EntityTree::textSize(const QUuid& id, const QString& text) { + if (_textSizeOperator) { + return _textSizeOperator(id, text); } - return false; -} - -bool EntityTree::removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName) { - if (_removeMaterialFromOverlayOperator) { - return _removeMaterialFromOverlayOperator(overlayID, material, parentMaterialName); - } - return false; + return QSizeF(0.0f, 0.0f); } void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender, diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index f9b7b8d67f..dda9ecaf17 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -272,10 +272,8 @@ public: static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName); static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName); - static void setAddMaterialToOverlayOperator(std::function addMaterialToOverlayOperator) { _addMaterialToOverlayOperator = addMaterialToOverlayOperator; } - static void setRemoveMaterialFromOverlayOperator(std::function removeMaterialFromOverlayOperator) { _removeMaterialFromOverlayOperator = removeMaterialFromOverlayOperator; } - static bool addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName); - static bool removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName); + static void setTextSizeOperator(std::function textSizeOperator) { _textSizeOperator = textSizeOperator; } + static QSizeF textSize(const QUuid& id, const QString& text); std::map getNamedPaths() const { return _namedPaths; } @@ -389,8 +387,7 @@ private: static std::function _removeMaterialFromEntityOperator; static std::function _addMaterialToAvatarOperator; static std::function _removeMaterialFromAvatarOperator; - static std::function _addMaterialToOverlayOperator; - static std::function _removeMaterialFromOverlayOperator; + static std::function _textSizeOperator; std::vector _staleProxies; From ca8d64bc05c3289b6acd6a4d1e2baab366dc5b4d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 24 Jan 2019 14:59:45 -0800 Subject: [PATCH 005/139] removing overlays wip --- interface/src/avatar/MyAvatar.h | 2 +- interface/src/avatar/OtherAvatar.cpp | 51 +++++++++-------- interface/src/avatar/OtherAvatar.h | 4 +- interface/src/devices/DdeFaceTracker.cpp | 1 - interface/src/devices/DdeFaceTracker.h | 2 +- interface/src/raypick/CollisionPick.cpp | 4 -- interface/src/raypick/CollisionPick.h | 1 - interface/src/raypick/LaserPointer.cpp | 55 ++++++++++++------- interface/src/raypick/LaserPointer.h | 10 ++-- .../raypick/LaserPointerScriptingInterface.h | 4 +- interface/src/raypick/ParabolaPick.cpp | 14 ----- interface/src/raypick/ParabolaPick.h | 2 - interface/src/raypick/ParabolaPointer.cpp | 5 +- interface/src/raypick/ParabolaPointer.h | 2 +- interface/src/raypick/PathPointer.cpp | 22 +++----- interface/src/raypick/PathPointer.h | 22 ++++---- .../src/RenderableTextEntityItem.cpp | 2 +- .../entities/src/EntityItemProperties.cpp | 7 +-- libraries/entities/src/EntityTypes.h | 3 +- libraries/entities/src/LineEntityItem.cpp | 1 - libraries/entities/src/MaterialEntityItem.cpp | 12 +--- .../src/graphics-scripting/Forward.h | 2 +- .../GraphicsScriptingInterface.h | 10 ++-- libraries/pointers/src/Pick.h | 1 - 24 files changed, 105 insertions(+), 134 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 20dc2ae42b..3ebde748b1 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -136,7 +136,7 @@ class MyAvatar : public Avatar { * your avatar when rolling your HMD in degrees per second. * @property {number} userHeight=1.75 - The height of the user in sensor space. * @property {number} userEyeHeight=1.65 - The estimated height of the user's eyes in sensor space. Read-only. - * @property {Uuid} SELF_ID - UUID representing "my avatar". Only use for local-only entities and overlays in situations + * @property {Uuid} SELF_ID - UUID representing "my avatar". Only use for local-only entities in situations * where MyAvatar.sessionUUID is not available (e.g., if not connected to a domain). Note: Likely to be deprecated. * Read-only. * @property {number} walkSpeed diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 1f4fdc5e52..409fa51388 100644 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -54,44 +54,47 @@ OtherAvatar::~OtherAvatar() { void OtherAvatar::removeOrb() { if (!_otherAvatarOrbMeshPlaceholderID.isNull()) { - qApp->getOverlays().deleteOverlay(_otherAvatarOrbMeshPlaceholderID); - _otherAvatarOrbMeshPlaceholderID = UNKNOWN_OVERLAY_ID; + DependencyManager::get()->deleteEntity(_otherAvatarOrbMeshPlaceholderID); + _otherAvatarOrbMeshPlaceholderID = UNKNOWN_ENTITY_ID; } } void OtherAvatar::updateOrbPosition() { - if (_otherAvatarOrbMeshPlaceholder != nullptr) { - _otherAvatarOrbMeshPlaceholder->setWorldPosition(getHead()->getPosition()); - if (_otherAvatarOrbMeshPlaceholderID.isNull()) { - _otherAvatarOrbMeshPlaceholderID = qApp->getOverlays().addOverlay(_otherAvatarOrbMeshPlaceholder); - } + if (_otherAvatarOrbMeshPlaceholderID.isNull()) { + EntityItemProperties properties; + properties.setPosition(getHead()->getPosition()); + DependencyManager::get()->editEntity(_otherAvatarOrbMeshPlaceholderID, properties); } } void OtherAvatar::createOrb() { if (_otherAvatarOrbMeshPlaceholderID.isNull()) { - _otherAvatarOrbMeshPlaceholder = std::make_shared(); - _otherAvatarOrbMeshPlaceholder->setAlpha(1.0f); - _otherAvatarOrbMeshPlaceholder->setColor(getLoadingOrbColor(_loadingStatus)); - _otherAvatarOrbMeshPlaceholder->setIsSolid(false); - _otherAvatarOrbMeshPlaceholder->setPulseMin(0.5); - _otherAvatarOrbMeshPlaceholder->setPulseMax(1.0); - _otherAvatarOrbMeshPlaceholder->setColorPulse(1.0); - _otherAvatarOrbMeshPlaceholder->setIgnorePickIntersection(true); - _otherAvatarOrbMeshPlaceholder->setDrawInFront(false); - _otherAvatarOrbMeshPlaceholderID = qApp->getOverlays().addOverlay(_otherAvatarOrbMeshPlaceholder); - // Position focus - _otherAvatarOrbMeshPlaceholder->setWorldOrientation(glm::quat(0.0f, 0.0f, 0.0f, 1.0)); - _otherAvatarOrbMeshPlaceholder->setWorldPosition(getHead()->getPosition()); - _otherAvatarOrbMeshPlaceholder->setDimensions(glm::vec3(0.5f, 0.5f, 0.5f)); - _otherAvatarOrbMeshPlaceholder->setVisible(true); + EntityItemProperties properties; + properties.setType(EntityTypes::Sphere); + properties.setAlpha(1.0f); + properties.setColor(getLoadingOrbColor(_loadingStatus)); + properties.setPrimitiveMode(PrimitiveMode::LINES); + properties.getPulse().setMin(0.5f); + properties.getPulse().setMax(1.0f); + properties.getPulse().setColorMode(PulseMode::IN_PHASE); + properties.setIgnorePickIntersection(true); + + properties.setPosition(getHead()->getPosition()); + properties.setRotation(glm::quat(0.0f, 0.0f, 0.0f, 1.0)); + properties.setDimensions(glm::vec3(0.5f, 0.5f, 0.5f)); + properties.setVisible(true); + + _otherAvatarOrbMeshPlaceholderID = DependencyManager::get()->addEntity(properties, "local"); } } void OtherAvatar::indicateLoadingStatus(LoadingStatus loadingStatus) { Avatar::indicateLoadingStatus(loadingStatus); - if (_otherAvatarOrbMeshPlaceholder) { - _otherAvatarOrbMeshPlaceholder->setColor(getLoadingOrbColor(_loadingStatus)); + + if (_otherAvatarOrbMeshPlaceholderID != UNKNOWN_ENTITY_ID) { + EntityItemProperties properties; + properties.setColor(getLoadingOrbColor(_loadingStatus)); + DependencyManager::get()->editEntity(_otherAvatarOrbMeshPlaceholderID, properties); } } diff --git a/interface/src/avatar/OtherAvatar.h b/interface/src/avatar/OtherAvatar.h index a1dc5724a9..8e31609e3e 100644 --- a/interface/src/avatar/OtherAvatar.h +++ b/interface/src/avatar/OtherAvatar.h @@ -17,7 +17,6 @@ #include "InterfaceLogging.h" #include "ui/overlays/Overlays.h" -#include "ui/overlays/Sphere3DOverlay.h" class AvatarManager; class AvatarMotionState; @@ -59,8 +58,7 @@ protected: void onRemoveAttachedAvatarEntity(const QUuid& id); std::vector _attachedAvatarEntities; - std::shared_ptr _otherAvatarOrbMeshPlaceholder { nullptr }; - OverlayID _otherAvatarOrbMeshPlaceholderID { UNKNOWN_OVERLAY_ID }; + QUuid _otherAvatarOrbMeshPlaceholderID { UNKNOWN_ENTITY_ID }; AvatarMotionState* _motionState { nullptr }; int32_t _spaceIndex { -1 }; uint8_t _workloadRegion { workload::Region::INVALID }; diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index ed52083d77..fed5b702cb 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -194,7 +194,6 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui _calibrationCount(0), _calibrationValues(), _calibrationBillboard(NULL), - _calibrationBillboardID(UNKNOWN_OVERLAY_ID), _calibrationMessage(QString()), _isCalibrated(false) { diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 4fe36b582e..c74f0f9cd0 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -168,7 +168,7 @@ private: int _calibrationCount; QVector _calibrationValues; TextOverlay* _calibrationBillboard; - OverlayID _calibrationBillboardID; + QUuid _calibrationBillboardID; QString _calibrationMessage; bool _isCalibrated; void addCalibrationDatum(); diff --git a/interface/src/raypick/CollisionPick.cpp b/interface/src/raypick/CollisionPick.cpp index d30f98051e..82d75257df 100644 --- a/interface/src/raypick/CollisionPick.cpp +++ b/interface/src/raypick/CollisionPick.cpp @@ -409,10 +409,6 @@ PickResultPointer CollisionPick::getEntityIntersection(const CollisionRegion& pi return std::make_shared(pick, entityIntersections, std::vector()); } -PickResultPointer CollisionPick::getOverlayIntersection(const CollisionRegion& pick) { - return std::make_shared(pick, std::vector(), std::vector()); -} - PickResultPointer CollisionPick::getAvatarIntersection(const CollisionRegion& pick) { if (!pick.loaded) { // Cannot compute result diff --git a/interface/src/raypick/CollisionPick.h b/interface/src/raypick/CollisionPick.h index 92aa415f9e..c742c089b4 100644 --- a/interface/src/raypick/CollisionPick.h +++ b/interface/src/raypick/CollisionPick.h @@ -54,7 +54,6 @@ public: return std::make_shared(pickVariant, std::vector(), std::vector()); } PickResultPointer getEntityIntersection(const CollisionRegion& pick) override; - PickResultPointer getOverlayIntersection(const CollisionRegion& pick) override; PickResultPointer getAvatarIntersection(const CollisionRegion& pick) override; PickResultPointer getHUDIntersection(const CollisionRegion& pick) override; Transform getResultTransform() const override; diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 236512f2fe..3319f01b57 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -17,6 +17,8 @@ #include "PickManager.h" #include "RayPick.h" +#include "PolyLineEntityItem.h" + LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover, const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalTime, bool centerEndY, bool lockEnd, bool distanceScaleEnd, bool scaleWithParent, bool enabled) : @@ -28,7 +30,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende void LaserPointer::editRenderStatePath(const std::string& state, const QVariant& pathProps) { auto renderState = std::static_pointer_cast(_renderStates[state]); if (renderState) { - updateRenderStateOverlay(renderState->getPathID(), pathProps); + updateRenderState(renderState->getPathID(), pathProps); QVariant lineWidth = pathProps.toMap()["lineWidth"]; if (lineWidth.isValid()) { renderState->setLineWidth(lineWidth.toFloat()); @@ -121,48 +123,61 @@ void LaserPointer::setVisualPickResultInternal(PickResultPointer pickResult, Int } } -LaserPointer::RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) : +LaserPointer::RenderState::RenderState(const QUuid& startID, const QUuid& pathID, const QUuid& endID) : StartEndRenderState(startID, endID), _pathID(pathID) { - if (!_pathID.isNull()) { - _pathIgnoreRays = qApp->getOverlays().getProperty(_pathID, "ignorePickIntersection").value.toBool(); - _lineWidth = qApp->getOverlays().getProperty(_pathID, "lineWidth").value.toFloat(); + if (!getPathID().isNull()) { + auto entityScriptingInterface = DependencyManager::get(); + { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_IGNORE_PICK_INTERSECTION; + _pathIgnorePicks = entityScriptingInterface->getEntityProperties(getPathID(), desiredProperties).getIgnorePickIntersection(); + } + { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_STROKE_WIDTHS; + auto widths = entityScriptingInterface->getEntityProperties(getPathID(), desiredProperties).getStrokeWidths(); + _lineWidth = widths.length() == 0 ? PolyLineEntityItem::DEFAULT_LINE_WIDTH : widths[0]; + } } } void LaserPointer::RenderState::cleanup() { StartEndRenderState::cleanup(); - if (!_pathID.isNull()) { - qApp->getOverlays().deleteOverlay(_pathID); + if (!getPathID().isNull()) { + DependencyManager::get()->deleteEntity(getPathID()); } } void LaserPointer::RenderState::disable() { StartEndRenderState::disable(); if (!getPathID().isNull()) { - QVariantMap pathProps; - pathProps.insert("visible", false); - pathProps.insert("ignorePickIntersection", true); - qApp->getOverlays().editOverlay(getPathID(), pathProps); + EntityItemProperties properties; + properties.setVisible(false); + properties.setIgnorePickIntersection(true); + DependencyManager::get()->editEntity(getPathID(), properties); } } void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY, bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) { StartEndRenderState::update(origin, end, surfaceNormal, parentScale, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult); - QVariant endVariant = vec3toVariant(end); if (!getPathID().isNull()) { - QVariantMap pathProps; - pathProps.insert("start", vec3toVariant(origin)); - pathProps.insert("end", endVariant); - pathProps.insert("visible", true); - pathProps.insert("ignorePickIntersection", doesPathIgnoreRays()); - pathProps.insert("lineWidth", getLineWidth() * parentScale); - qApp->getOverlays().editOverlay(getPathID(), pathProps); + EntityItemProperties properties; + QVector points; + points.append(origin); + points.append(end); + properties.setLinePoints(points); + properties.setVisible(true); + properties.setIgnorePickIntersection(doesPathIgnorePicks()); + QVector widths; + widths.append(getLineWidth() * parentScale); + DependencyManager::get()->editEntity(getPathID(), properties); } } std::shared_ptr LaserPointer::buildRenderState(const QVariantMap& propMap) { + // FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers QUuid startID; if (propMap["start"].isValid()) { QVariantMap startMap = propMap["start"].toMap(); @@ -233,8 +248,6 @@ glm::vec3 LaserPointer::findIntersection(const PickedObject& pickedObject, const switch (pickedObject.type) { case ENTITY: return RayPick::intersectRayWithEntityXYPlane(pickedObject.objectID, origin, direction); - case OVERLAY: - return RayPick::intersectRayWithOverlayXYPlane(pickedObject.objectID, origin, direction); default: return glm::vec3(NAN); } diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index bcd4bb607d..13d108baee 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -19,10 +19,10 @@ public: class RenderState : public StartEndRenderState { public: RenderState() {} - RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID); + RenderState(const QUuid& startID, const QUuid& pathID, const QUuid& endID); - const OverlayID& getPathID() const { return _pathID; } - const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; } + const QUuid& getPathID() const { return _pathID; } + const bool& doesPathIgnorePicks() const { return _pathIgnorePicks; } void setLineWidth(float width) { _lineWidth = width; } float getLineWidth() const { return _lineWidth; } @@ -33,9 +33,9 @@ public: bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override; private: - OverlayID _pathID; - bool _pathIgnoreRays; + QUuid _pathID; + bool _pathIgnorePicks; float _lineWidth; }; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index d85e329e9a..326917f62d 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -111,10 +111,10 @@ public: * @function LaserPointers.setLockEndUUID * @param {number} id * @param {Uuid} itemID - * @param {boolean} isOverlay + * @param {boolean} isAvatar * @param {Mat4} [offsetMat] */ - Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay, offsetMat); } + Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); } /**jsdoc diff --git a/interface/src/raypick/ParabolaPick.cpp b/interface/src/raypick/ParabolaPick.cpp index b93ced17c6..5349f8a113 100644 --- a/interface/src/raypick/ParabolaPick.cpp +++ b/interface/src/raypick/ParabolaPick.cpp @@ -10,7 +10,6 @@ #include "Application.h" #include "EntityScriptingInterface.h" #include "PickScriptingInterface.h" -#include "ui/overlays/Overlays.h" #include "avatar/AvatarManager.h" #include "scripting/HMDScriptingInterface.h" #include "DependencyManager.h" @@ -74,19 +73,6 @@ PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick) return std::make_shared(pick.toVariantMap()); } -PickResultPointer ParabolaPick::getOverlayIntersection(const PickParabola& pick) { - if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) { - bool precisionPicking = !(getFilter().isCoarse() || DependencyManager::get()->getForceCoarsePicking()); - ParabolaToOverlayIntersectionResult overlayRes = - qApp->getOverlays().findParabolaIntersectionVector(pick, precisionPicking, - getIncludeItemsAs(), getIgnoreItemsAs(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable()); - if (overlayRes.intersects) { - return std::make_shared(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.parabolicDistance, overlayRes.intersection, pick, overlayRes.surfaceNormal, overlayRes.extraInfo); - } - } - return std::make_shared(pick.toVariantMap()); -} - PickResultPointer ParabolaPick::getAvatarIntersection(const PickParabola& pick) { if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) { ParabolaToAvatarIntersectionResult avatarRes = DependencyManager::get()->findParabolaIntersectionVector(pick, getIncludeItemsAs(), getIgnoreItemsAs()); diff --git a/interface/src/raypick/ParabolaPick.h b/interface/src/raypick/ParabolaPick.h index 8cbbc79bf5..0adbb01954 100644 --- a/interface/src/raypick/ParabolaPick.h +++ b/interface/src/raypick/ParabolaPick.h @@ -12,7 +12,6 @@ #include class EntityItemID; -class OverlayID; class ParabolaPickResult : public PickResult { public: @@ -80,7 +79,6 @@ public: PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared(pickVariant); } PickResultPointer getEntityIntersection(const PickParabola& pick) override; - PickResultPointer getOverlayIntersection(const PickParabola& pick) override; PickResultPointer getAvatarIntersection(const PickParabola& pick) override; PickResultPointer getHUDIntersection(const PickParabola& pick) override; Transform getResultTransform() const override; diff --git a/interface/src/raypick/ParabolaPointer.cpp b/interface/src/raypick/ParabolaPointer.cpp index e45b11b479..771d5c20de 100644 --- a/interface/src/raypick/ParabolaPointer.cpp +++ b/interface/src/raypick/ParabolaPointer.cpp @@ -149,7 +149,7 @@ void ParabolaPointer::setVisualPickResultInternal(PickResultPointer pickResult, } } -ParabolaPointer::RenderState::RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float pathWidth, +ParabolaPointer::RenderState::RenderState(const QUuid& startID, const QUuid& endID, const glm::vec3& pathColor, float pathAlpha, float pathWidth, bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled) : StartEndRenderState(startID, endID) { @@ -230,6 +230,7 @@ void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::ve } std::shared_ptr ParabolaPointer::buildRenderState(const QVariantMap& propMap) { + // FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers QUuid startID; if (propMap["start"].isValid()) { QVariantMap startMap = propMap["start"].toMap(); @@ -322,8 +323,6 @@ glm::vec3 ParabolaPointer::findIntersection(const PickedObject& pickedObject, co switch (pickedObject.type) { case ENTITY: //return ParabolaPick::intersectParabolaWithEntityXYPlane(pickedObject.objectID, origin, velocity, acceleration); - case OVERLAY: - //return ParabolaPick::intersectParabolaWithOverlayXYPlane(pickedObject.objectID, origin, velocity, acceleration); default: return glm::vec3(NAN); } diff --git a/interface/src/raypick/ParabolaPointer.h b/interface/src/raypick/ParabolaPointer.h index 3e9a22db4f..5594f101d0 100644 --- a/interface/src/raypick/ParabolaPointer.h +++ b/interface/src/raypick/ParabolaPointer.h @@ -79,7 +79,7 @@ public: }; RenderState() {} - RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float parentScale, + RenderState(const QUuid& startID, const QUuid& endID, const glm::vec3& pathColor, float pathAlpha, float parentScale, bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled); void setPathWidth(float width) { _pathWidth = width; } diff --git a/interface/src/raypick/PathPointer.cpp b/interface/src/raypick/PathPointer.cpp index ae0ce4671b..3cd444c0b3 100644 --- a/interface/src/raypick/PathPointer.cpp +++ b/interface/src/raypick/PathPointer.cpp @@ -73,10 +73,10 @@ void PathPointer::setLength(float length) { }); } -void PathPointer::setLockEndUUID(const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat) { +void PathPointer::setLockEndUUID(const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat) { withWriteLock([&] { _lockEndObject.id = objectID; - _lockEndObject.isOverlay = isOverlay; + _lockEndObject.isAvatar = isAvatar; _lockEndObject.offsetMat = offsetMat; }); } @@ -97,12 +97,8 @@ PickResultPointer PathPointer::getVisualPickResult(const PickResultPointer& pick glm::quat rot; glm::vec3 dim; glm::vec3 registrationPoint; - if (_lockEndObject.isOverlay) { - pos = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "position").value); - rot = quatFromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "rotation").value); - dim = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "dimensions").value); - registrationPoint = glm::vec3(0.5f); - } else { + // TODO: use isAvatar + { EntityItemProperties props = DependencyManager::get()->getEntityProperties(_lockEndObject.id); glm::mat4 entityMat = createMatFromQuatAndPos(props.getRotation(), props.getPosition()); glm::mat4 finalPosAndRotMat = entityMat * _lockEndObject.offsetMat; @@ -117,7 +113,7 @@ PickResultPointer PathPointer::getVisualPickResult(const PickResultPointer& pick distance = glm::distance(origin, endVec); glm::vec3 normalizedDirection = glm::normalize(direction); - type = _lockEndObject.isOverlay ? IntersectionType::OVERLAY : IntersectionType::ENTITY; + type = IntersectionType::ENTITY; id = _lockEndObject.id; intersection = endVec; surfaceNormal = -normalizedDirection; @@ -126,8 +122,6 @@ PickResultPointer PathPointer::getVisualPickResult(const PickResultPointer& pick id = getPickedObjectID(pickResult); if (type == IntersectionType::ENTITY) { endVec = DependencyManager::get()->getEntityTransform(id)[3]; - } else if (type == IntersectionType::OVERLAY) { - endVec = vec3FromVariant(qApp->getOverlays().getProperty(id, "position").value); } else if (type == IntersectionType::AVATAR) { endVec = DependencyManager::get()->getAvatar(id)->getPosition(); } @@ -184,8 +178,8 @@ void PathPointer::editRenderState(const std::string& state, const QVariant& star withWriteLock([&] { auto renderState = _renderStates.find(state); if (renderState != _renderStates.end()) { - updateRenderStateOverlay(renderState->second->getStartID(), startProps); - updateRenderStateOverlay(renderState->second->getEndID(), endProps); + updateRenderState(renderState->second->getStartID(), startProps); + updateRenderState(renderState->second->getEndID(), endProps); QVariant startDim = startProps.toMap()["dimensions"]; if (startDim.isValid()) { renderState->second->setStartDim(vec3FromVariant(startDim)); @@ -204,7 +198,7 @@ void PathPointer::editRenderState(const std::string& state, const QVariant& star }); } -void PathPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) { +void PathPointer::updateRenderState(const QUuid& id, const QVariant& props) { if (!id.isNull() && props.isValid()) { QVariantMap propMap = props.toMap(); propMap.remove("visible"); diff --git a/interface/src/raypick/PathPointer.h b/interface/src/raypick/PathPointer.h index 1aa4165c87..759d46842e 100644 --- a/interface/src/raypick/PathPointer.h +++ b/interface/src/raypick/PathPointer.h @@ -19,20 +19,20 @@ struct LockEndObject { QUuid id { QUuid() }; - bool isOverlay { false }; + bool isAvatar { false }; glm::mat4 offsetMat { glm::mat4() }; }; class StartEndRenderState { public: StartEndRenderState() {} - StartEndRenderState(const OverlayID& startID, const OverlayID& endID); + StartEndRenderState(const QUuid& startID, const QUuid& endID); virtual ~StartEndRenderState() = default; - const OverlayID& getStartID() const { return _startID; } - const OverlayID& getEndID() const { return _endID; } - const bool& doesStartIgnoreRays() const { return _startIgnoreRays; } - const bool& doesEndIgnoreRays() const { return _endIgnoreRays; } + const QUuid& getStartID() const { return _startID; } + const QUuid& getEndID() const { return _endID; } + const bool& doesStartIgnorePicks() const { return _startIgnorePicks; } + const bool& doesEndIgnorePicks() const { return _endIgnorePicks; } void setStartDim(const glm::vec3& startDim) { _startDim = startDim; } const glm::vec3& getStartDim() const { return _startDim; } @@ -51,10 +51,10 @@ public: bool isEnabled() const { return _enabled; } protected: - OverlayID _startID; - OverlayID _endID; - bool _startIgnoreRays; - bool _endIgnoreRays; + QUuid _startID; + QUuid _endID; + bool _startIgnorePicks; + bool _endIgnorePicks; glm::vec3 _startDim; glm::vec3 _endDim; @@ -82,7 +82,7 @@ public: void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) override; void setLength(float length) override; - void setLockEndUUID(const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) override; + void setLockEndUUID(const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) override; void updateVisuals(const PickResultPointer& prevRayPickResult) override; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index d5f0843049..94ecf5d4eb 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -199,7 +199,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) { geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false); geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID); - // FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline for a gpu performance increase. + // FIXME: Factor out textRenderer so that text parts can be grouped by pipeline for a gpu performance increase. float scale = _lineHeight / _textRenderer->getFontSize(); transformToTopLeft.setScale(scale); // Scale to have the correct line height batch.setModelTransform(transformToTopLeft); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 0f77bd6bc7..ad5c9660f4 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -945,12 +945,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { */ /**jsdoc - * The "Material" {@link Entities.EntityType|EntityType} modifies the existing materials on - * {@link Entities.EntityType|Model} entities, {@link Entities.EntityType|Shape} entities (albedo only), - * {@link Overlays.OverlayType|model overlays}, and avatars. + * The "Material" {@link Entities.EntityType|EntityType} modifies the existing materials on entities and avatars. * It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}.
- * To apply a material to an entity or overlay, set the material entity's parentID property to the entity or - * overlay's ID. + * To apply a material to an entity, set the material entity's parentID property to the entity ID. * To apply a material to an avatar, set the material entity's parentID property to the avatar's session UUID. * To apply a material to your avatar such that it persists across domains and log-ins, create the material as an avatar entity * by setting the entityHostType parameter in {@link Entities.addEntity} to "avatar". diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 8ad654c638..91b71513dc 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -84,8 +84,7 @@ public: * {@link Entities.EntityProperties-Light|EntityProperties-Light} * "Zone"A volume of lighting effects and avatar permissions. * {@link Entities.EntityProperties-Zone|EntityProperties-Zone} - * "Material"Modifies the existing materials on Model entities, Shape entities, - * {@link Overlays.OverlayType|model overlays}, and avatars. + * "Material"Modifies the existing materials on entities and avatars. * {@link Entities.EntityProperties-Material|EntityProperties-Material} * * diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 12d1178690..acb5bc08f6 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -23,7 +23,6 @@ const int LineEntityItem::MAX_POINTS_PER_LINE = 70; - EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity(new LineEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); entity->setProperties(properties); diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index cec602a5e1..1baa0b213a 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -310,7 +310,7 @@ void MaterialEntityItem::removeMaterial() { return; } - // Our parent could be an entity, an avatar, or an overlay + // Our parent could be an entity or an avatar if (EntityTree::removeMaterialFromEntity(parentID, material, getParentMaterialName().toStdString())) { return; } @@ -319,10 +319,6 @@ void MaterialEntityItem::removeMaterial() { return; } - if (EntityTree::removeMaterialFromOverlay(parentID, material, getParentMaterialName().toStdString())) { - return; - } - // if a remove fails, our parent is gone, so we don't need to retry } @@ -349,7 +345,7 @@ void MaterialEntityItem::applyMaterial() { graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, getPriority()); - // Our parent could be an entity, an avatar, or an overlay + // Our parent could be an entity or an avatar if (EntityTree::addMaterialToEntity(parentID, materialLayer, getParentMaterialName().toStdString())) { return; } @@ -358,10 +354,6 @@ void MaterialEntityItem::applyMaterial() { return; } - if (EntityTree::addMaterialToOverlay(parentID, materialLayer, getParentMaterialName().toStdString())) { - return; - } - // if we've reached this point, we couldn't find our parent, so we need to try again later _retryApply = true; } diff --git a/libraries/graphics-scripting/src/graphics-scripting/Forward.h b/libraries/graphics-scripting/src/graphics-scripting/Forward.h index 104674eddc..90bd083d02 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/Forward.h +++ b/libraries/graphics-scripting/src/graphics-scripting/Forward.h @@ -149,7 +149,7 @@ namespace scriptable { // QVariantMap armature; }; - // mixin class for Avatar/Entity/Overlay Rendering that expose their in-memory graphics::Meshes + // mixin class for Avatar + Entity Rendering that expose their in-memory graphics::Meshes class ModelProvider { public: NestableType modelProviderType; diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h index 1ec60c4244..f99d6438e4 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h @@ -38,13 +38,13 @@ public: public slots: /**jsdoc - * Returns a model reference object associated with the specified UUID ({@link EntityID}, {@link OverlayID}, or {@link AvatarID}). + * Returns a model reference object associated with the specified UUID ({@link EntityID} or {@link AvatarID}). * * @function Graphics.getModel * @param {UUID} entityID - The objectID of the model whose meshes are to be retrieved. * @returns {Graphics.Model} the resulting Model object */ - scriptable::ScriptableModelPointer getModel(QUuid uuid); + scriptable::ScriptableModelPointer getModel(const QUuid& uuid); /**jsdoc * @function Graphics.updateModel @@ -52,7 +52,7 @@ public slots: * @param {Graphics.Model} model * @returns {boolean} */ - bool updateModel(QUuid uuid, const scriptable::ScriptableModelPointer& model); + bool updateModel(const QUuid& uuid, const scriptable::ScriptableModelPointer& model); /**jsdoc * @function Graphics.canUpdateModel @@ -61,7 +61,7 @@ public slots: * @param {number} [partNumber=-1] * @returns {boolean} */ - bool canUpdateModel(QUuid uuid, int meshIndex = -1, int partNumber = -1); + bool canUpdateModel(const QUuid& uuid, int meshIndex = -1, int partNumber = -1); /**jsdoc * @function Graphics.newModel @@ -94,7 +94,7 @@ public slots: QString exportModelToOBJ(const scriptable::ScriptableModel& in); private: - scriptable::ModelProviderPointer getModelProvider(QUuid uuid); + scriptable::ModelProviderPointer getModelProvider(const QUuid& uuid); void jsThrowError(const QString& error); scriptable::MeshPointer getMeshPointer(scriptable::ScriptableMeshPointer meshProxy); scriptable::MeshPointer getMeshPointer(scriptable::ScriptableMesh& meshProxy); diff --git a/libraries/pointers/src/Pick.h b/libraries/pointers/src/Pick.h index 857a72caa8..2db8aa95f5 100644 --- a/libraries/pointers/src/Pick.h +++ b/libraries/pointers/src/Pick.h @@ -23,7 +23,6 @@ enum IntersectionType { NONE = 0, ENTITY, - OVERLAY, AVATAR, HUD }; From 5ce8f566cc3eba5bae9a46de2a708cfebac0d5bb Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 25 Jan 2019 11:10:11 -0800 Subject: [PATCH 006/139] more overlay wip --- .../resources/qml/+android/Web3DSurface.qml | 2 +- interface/resources/qml/Web3DSurface.qml | 2 +- interface/src/Application.cpp | 3 +- interface/src/InterfaceParentFinder.cpp | 9 - interface/src/LoginStateManager.cpp | 10 +- interface/src/LoginStateManager.h | 2 +- interface/src/avatar/OtherAvatar.h | 1 - interface/src/raypick/LaserPointer.cpp | 1 + interface/src/raypick/ParabolaPick.cpp | 10 +- interface/src/raypick/ParabolaPointer.cpp | 1 + interface/src/raypick/PathPointer.cpp | 80 +-- interface/src/raypick/PathPointer.h | 6 +- .../src/raypick/PickScriptingInterface.cpp | 9 +- .../src/raypick/PickScriptingInterface.h | 16 +- .../src/raypick/PointerScriptingInterface.cpp | 22 +- .../src/raypick/PointerScriptingInterface.h | 16 +- interface/src/raypick/RayPick.cpp | 37 +- interface/src/raypick/RayPick.h | 4 - .../src/raypick/RayPickScriptingInterface.h | 9 +- interface/src/raypick/StylusPick.cpp | 60 +-- interface/src/raypick/StylusPick.h | 1 - interface/src/raypick/StylusPointer.cpp | 57 +- interface/src/raypick/StylusPointer.h | 8 +- .../src/scripting/HMDScriptingInterface.h | 12 +- .../scripting/KeyboardScriptingInterface.cpp | 4 +- .../scripting/KeyboardScriptingInterface.h | 3 +- .../scripting/SelectionScriptingInterface.cpp | 47 +- .../scripting/SelectionScriptingInterface.h | 12 +- interface/src/ui/ApplicationOverlay.cpp | 4 +- interface/src/ui/Keyboard.cpp | 505 ++++++++---------- interface/src/ui/Keyboard.h | 38 +- interface/src/ui/LoginDialog.h | 2 +- .../ui/overlays/ContextOverlayInterface.cpp | 78 +-- .../src/ui/overlays/ContextOverlayInterface.h | 13 +- interface/src/ui/overlays/Overlay.cpp | 31 -- interface/src/ui/overlays/Overlay.h | 26 +- .../src/ui/overlays/OverlayTransformNode.cpp | 13 - .../src/ui/overlays/OverlayTransformNode.h | 21 - interface/src/ui/overlays/Overlays.h | 10 +- interface/src/ui/overlays/OverlaysPayload.cpp | 22 +- .../entities/src/EntityScriptingInterface.cpp | 9 + .../entities/src/EntityScriptingInterface.h | 29 +- libraries/entities/src/GrabPropertyGroup.h | 4 +- .../GraphicsScriptingInterface.cpp | 8 +- libraries/pointers/src/Pick.h | 2 +- libraries/pointers/src/PickCacheOptimizer.h | 23 +- libraries/pointers/src/Pointer.cpp | 20 +- libraries/pointers/src/Pointer.h | 2 +- libraries/pointers/src/PointerManager.cpp | 4 +- libraries/pointers/src/PointerManager.h | 2 +- .../render-utils/src/RenderCommonTask.cpp | 8 +- libraries/render-utils/src/RenderCommonTask.h | 10 +- .../render-utils/src/RenderDeferredTask.cpp | 52 +- .../render-utils/src/RenderForwardTask.cpp | 29 +- libraries/render/src/render/HighlightStage.h | 2 +- .../src/render/RenderFetchCullSortTask.cpp | 28 +- .../src/render/RenderFetchCullSortTask.h | 2 - libraries/render/src/render/Scene.h | 4 +- libraries/script-engine/src/ScriptUUID.h | 2 +- libraries/shared/src/PickFilter.h | 11 +- libraries/shared/src/PointerEvent.cpp | 4 +- libraries/shared/src/RegisteredMetaTypes.h | 4 +- 62 files changed, 611 insertions(+), 855 deletions(-) delete mode 100644 interface/src/ui/overlays/OverlayTransformNode.cpp delete mode 100644 interface/src/ui/overlays/OverlayTransformNode.h diff --git a/interface/resources/qml/+android/Web3DSurface.qml b/interface/resources/qml/+android/Web3DSurface.qml index d7b8306d6c..c4a613222e 100644 --- a/interface/resources/qml/+android/Web3DSurface.qml +++ b/interface/resources/qml/+android/Web3DSurface.qml @@ -1,5 +1,5 @@ // -// Web3DOverlay.qml +// Web3DSurface.qml // // Created by Gabriel Calero & Cristian Duarte on Jun 22, 2018 // Copyright 2016 High Fidelity, Inc. diff --git a/interface/resources/qml/Web3DSurface.qml b/interface/resources/qml/Web3DSurface.qml index fdd5d8a7c6..32c19daf14 100644 --- a/interface/resources/qml/Web3DSurface.qml +++ b/interface/resources/qml/Web3DSurface.qml @@ -1,5 +1,5 @@ // -// Web3DOverlay.qml +// Web3DSurface.qml // // Created by David Rowe on 16 Dec 2016. // Copyright 2016 High Fidelity, Inc. diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5dc283e8b4..f0b119b940 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -203,7 +203,6 @@ #include "ui/Stats.h" #include "ui/AnimStats.h" #include "ui/UpdateDialog.h" -#include "ui/overlays/Overlays.h" #include "ui/DomainConnectionModel.h" #include "ui/Keyboard.h" #include "Util.h" @@ -4900,7 +4899,7 @@ void Application::idle() { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); } else { - // update position of highlight overlay + // update position of highlight object if (!_keyboardFocusedEntity.get().isInvalidID()) { auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get()); if (entity && !_keyboardFocusHighlightID.isNull()) { diff --git a/interface/src/InterfaceParentFinder.cpp b/interface/src/InterfaceParentFinder.cpp index b9be58f04b..33328f54cc 100644 --- a/interface/src/InterfaceParentFinder.cpp +++ b/interface/src/InterfaceParentFinder.cpp @@ -50,15 +50,6 @@ SpatiallyNestableWeakPointer InterfaceParentFinder::find(QUuid parentID, bool& s return avatarManager->getMyAvatar(); } - // search overlays - auto& overlays = qApp->getOverlays(); - auto overlay = overlays.getOverlay(parentID); - parent = std::dynamic_pointer_cast(overlay); // this will return nullptr for non-3d overlays - if (!parent.expired()) { - success = true; - return parent; - } - success = false; return parent; } diff --git a/interface/src/LoginStateManager.cpp b/interface/src/LoginStateManager.cpp index 8811303f7d..0a09d33775 100644 --- a/interface/src/LoginStateManager.cpp +++ b/interface/src/LoginStateManager.cpp @@ -170,7 +170,7 @@ void LoginStateManager::setUp() { const unsigned int leftHand = 0; QVariantMap leftPointerProperties { { "joint", "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND" }, - { "filter", PickScriptingInterface::PICK_OVERLAYS() }, + { "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() }, { "triggers", leftPointerTriggerProperties }, { "posOffset", vec3toVariant(grabPointSphereOffsetLeft + malletOffset) }, { "hover", true }, @@ -197,7 +197,7 @@ void LoginStateManager::setUp() { rightPointerTriggerProperties = QList({rtClick1, rtClick2}); QVariantMap rightPointerProperties{ { "joint", "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" }, - { "filter", PickScriptingInterface::PICK_OVERLAYS() }, + { "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() }, { "triggers", rightPointerTriggerProperties }, { "posOffset", vec3toVariant(grabPointSphereOffsetRight + malletOffset) }, { "hover", true }, @@ -212,7 +212,7 @@ void LoginStateManager::setUp() { pointers->enablePointer(_rightLoginPointerID); } -void LoginStateManager::update(const QString dominantHand, const QUuid loginOverlayID) { +void LoginStateManager::update(const QString& dominantHand, const QUuid& loginEntityID) { if (!isSetUp()) { return; } @@ -224,8 +224,8 @@ void LoginStateManager::update(const QString dominantHand, const QUuid loginOver if (pointers && raypicks) { const auto rightObjectID = raypicks->getPrevRayPickResult(_rightLoginPointerID)["objectID"].toUuid(); const auto leftObjectID = raypicks->getPrevRayPickResult(_leftLoginPointerID)["objectID"].toUuid(); - const QString leftMode = (leftObjectID.isNull() || leftObjectID != loginOverlayID) ? "" : "full"; - const QString rightMode = (rightObjectID.isNull() || rightObjectID != loginOverlayID) ? "" : "full"; + const QString leftMode = (leftObjectID.isNull() || leftObjectID != loginEntityID) ? "" : "full"; + const QString rightMode = (rightObjectID.isNull() || rightObjectID != loginEntityID) ? "" : "full"; pointers->setRenderState(_leftLoginPointerID, leftMode); pointers->setRenderState(_rightLoginPointerID, rightMode); if (_dominantHand == "left" && !leftObjectID.isNull()) { diff --git a/interface/src/LoginStateManager.h b/interface/src/LoginStateManager.h index ad25e87ee6..b898303ba6 100644 --- a/interface/src/LoginStateManager.h +++ b/interface/src/LoginStateManager.h @@ -26,7 +26,7 @@ public: void setUp(); void tearDown(); - void update(const QString dominantHand, const QUuid loginOverlayID); + void update(const QString& dominantHand, const QUuid& loginObjectID); bool isSetUp() const { return (_leftLoginPointerID > PointerEvent::INVALID_POINTER_ID) && (_rightLoginPointerID > PointerEvent::INVALID_POINTER_ID); } diff --git a/interface/src/avatar/OtherAvatar.h b/interface/src/avatar/OtherAvatar.h index 8e31609e3e..d4628a0478 100644 --- a/interface/src/avatar/OtherAvatar.h +++ b/interface/src/avatar/OtherAvatar.h @@ -16,7 +16,6 @@ #include #include "InterfaceLogging.h" -#include "ui/overlays/Overlays.h" class AvatarManager; class AvatarMotionState; diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 3319f01b57..694c420426 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -247,6 +247,7 @@ PointerEvent LaserPointer::buildPointerEvent(const PickedObject& target, const P glm::vec3 LaserPointer::findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction) { switch (pickedObject.type) { case ENTITY: + case LOCAL_ENTITY: return RayPick::intersectRayWithEntityXYPlane(pickedObject.objectID, origin, direction); default: return glm::vec3(NAN); diff --git a/interface/src/raypick/ParabolaPick.cpp b/interface/src/raypick/ParabolaPick.cpp index 5349f8a113..7a0eed96a8 100644 --- a/interface/src/raypick/ParabolaPick.cpp +++ b/interface/src/raypick/ParabolaPick.cpp @@ -67,7 +67,15 @@ PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick) DependencyManager::get()->evalParabolaIntersectionVector(pick, searchFilter, getIncludeItemsAs(), getIgnoreItemsAs()); if (entityRes.intersects) { - return std::make_shared(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.parabolicDistance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo); + IntersectionType type = IntersectionType::ENTITY; + if (getFilter().doesPickLocalEntities()) { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_ENTITY_HOST_TYPE; + if (DependencyManager::get()->getEntityProperties(entityRes.entityID, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) { + type = IntersectionType::LOCAL_ENTITY; + } + } + return std::make_shared(type, entityRes.entityID, entityRes.distance, entityRes.parabolicDistance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo); } } return std::make_shared(pick.toVariantMap()); diff --git a/interface/src/raypick/ParabolaPointer.cpp b/interface/src/raypick/ParabolaPointer.cpp index 771d5c20de..389f6ed286 100644 --- a/interface/src/raypick/ParabolaPointer.cpp +++ b/interface/src/raypick/ParabolaPointer.cpp @@ -322,6 +322,7 @@ glm::vec3 ParabolaPointer::findIntersection(const PickedObject& pickedObject, co // TODO: implement switch (pickedObject.type) { case ENTITY: + case LOCAL_ENTITY: //return ParabolaPick::intersectParabolaWithEntityXYPlane(pickedObject.objectID, origin, velocity, acceleration); default: return glm::vec3(NAN); diff --git a/interface/src/raypick/PathPointer.cpp b/interface/src/raypick/PathPointer.cpp index 3cd444c0b3..6f94d25594 100644 --- a/interface/src/raypick/PathPointer.cpp +++ b/interface/src/raypick/PathPointer.cpp @@ -199,6 +199,7 @@ void PathPointer::editRenderState(const std::string& state, const QVariant& star } void PathPointer::updateRenderState(const QUuid& id, const QVariant& props) { + // FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers if (!id.isNull() && props.isValid()) { QVariantMap propMap = props.toMap(); propMap.remove("visible"); @@ -243,65 +244,79 @@ Pointer::Buttons PathPointer::getPressedButtons(const PickResultPointer& pickRes return toReturn; } -StartEndRenderState::StartEndRenderState(const OverlayID& startID, const OverlayID& endID) : +StartEndRenderState::StartEndRenderState(const QUuid& startID, const QUuid& endID) : _startID(startID), _endID(endID) { + auto entityScriptingInterface = DependencyManager::get(); if (!_startID.isNull()) { - _startDim = vec3FromVariant(qApp->getOverlays().getProperty(_startID, "dimensions").value); - _startIgnoreRays = qApp->getOverlays().getProperty(_startID, "ignorePickIntersection").value.toBool(); + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_DIMENSIONS; + desiredProperties += PROP_IGNORE_PICK_INTERSECTION; + auto properties = entityScriptingInterface->getEntityProperties(_startID, desiredProperties); + _startDim = properties.getDimensions(); + _startIgnorePicks = properties.getIgnorePickIntersection(); } if (!_endID.isNull()) { - _endDim = vec3FromVariant(qApp->getOverlays().getProperty(_endID, "dimensions").value); - _endRot = quatFromVariant(qApp->getOverlays().getProperty(_endID, "rotation").value); - _endIgnoreRays = qApp->getOverlays().getProperty(_endID, "ignorePickIntersection").value.toBool(); + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_DIMENSIONS; + desiredProperties += PROP_ROTATION; + desiredProperties += PROP_IGNORE_PICK_INTERSECTION; + auto properties = entityScriptingInterface->getEntityProperties(_endID, desiredProperties); + _endDim = properties.getDimensions(); + _endRot = properties.getRotation(); + _endIgnorePicks = properties.getIgnorePickIntersection(); } } void StartEndRenderState::cleanup() { + auto entityScriptingInterface = DependencyManager::get(); if (!_startID.isNull()) { - qApp->getOverlays().deleteOverlay(_startID); + entityScriptingInterface->deleteEntity(_startID); } if (!_endID.isNull()) { - qApp->getOverlays().deleteOverlay(_endID); + entityScriptingInterface->deleteEntity(_endID); } } void StartEndRenderState::disable() { + auto entityScriptingInterface = DependencyManager::get(); if (!getStartID().isNull()) { - QVariantMap startProps; - startProps.insert("visible", false); - startProps.insert("ignorePickIntersection", true); - qApp->getOverlays().editOverlay(getStartID(), startProps); + EntityItemProperties properties; + properties.setVisible(false); + properties.setIgnorePickIntersection(true); + entityScriptingInterface->editEntity(getStartID(), properties); } if (!getEndID().isNull()) { - QVariantMap endProps; - endProps.insert("visible", false); - endProps.insert("ignorePickIntersection", true); - qApp->getOverlays().editOverlay(getEndID(), endProps); + EntityItemProperties properties; + properties.setVisible(false); + properties.setIgnorePickIntersection(true); + entityScriptingInterface->editEntity(getEndID(), properties); } _enabled = false; } void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY, bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) { + auto entityScriptingInterface = DependencyManager::get(); if (!getStartID().isNull()) { - QVariantMap startProps; - startProps.insert("position", vec3toVariant(origin)); - startProps.insert("visible", true); - startProps.insert("dimensions", vec3toVariant(getStartDim() * parentScale)); - startProps.insert("ignorePickIntersection", doesStartIgnoreRays()); - qApp->getOverlays().editOverlay(getStartID(), startProps); + EntityItemProperties properties; + properties.setPosition(origin); + properties.setVisible(true); + properties.setDimensions(getStartDim() * parentScale); + properties.setIgnorePickIntersection(doesStartIgnorePicks()); + entityScriptingInterface->editEntity(getStartID(), properties); } if (!getEndID().isNull()) { - QVariantMap endProps; - glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(getEndID(), "dimensions").value); + EntityItemProperties properties; + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_DIMENSIONS; + glm::vec3 dim = entityScriptingInterface->getEntityProperties(getEndID(), desiredProperties).getDimensions(); if (distanceScaleEnd) { dim = getEndDim() * glm::distance(origin, end); - endProps.insert("dimensions", vec3toVariant(dim)); } else { dim = getEndDim() * parentScale; - endProps.insert("dimensions", vec3toVariant(dim)); } + properties.setDimensions(dim); glm::quat normalQuat = Quat().lookAtSimple(Vectors::ZERO, surfaceNormal); normalQuat = normalQuat * glm::quat(glm::vec3(-M_PI_2, 0, 0)); @@ -337,11 +352,11 @@ void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, _avgEndRot = rotation; } } - endProps.insert("position", vec3toVariant(position)); - endProps.insert("rotation", quatToVariant(rotation)); - endProps.insert("visible", true); - endProps.insert("ignorePickIntersection", doesEndIgnoreRays()); - qApp->getOverlays().editOverlay(getEndID(), endProps); + properties.setPosition(position); + properties.setRotation(rotation); + properties.setVisible(true); + properties.setIgnorePickIntersection(doesEndIgnorePicks()); + entityScriptingInterface->editEntity(getEndID(), properties); } _enabled = true; } @@ -349,9 +364,8 @@ void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, glm::vec2 PathPointer::findPos2D(const PickedObject& pickedObject, const glm::vec3& origin) { switch (pickedObject.type) { case ENTITY: + case LOCAL_ENTITY: return RayPick::projectOntoEntityXYPlane(pickedObject.objectID, origin); - case OVERLAY: - return RayPick::projectOntoOverlayXYPlane(pickedObject.objectID, origin); case HUD: return DependencyManager::get()->calculatePos2DFromHUD(origin); default: diff --git a/interface/src/raypick/PathPointer.h b/interface/src/raypick/PathPointer.h index 759d46842e..4b0625ef0f 100644 --- a/interface/src/raypick/PathPointer.h +++ b/interface/src/raypick/PathPointer.h @@ -12,8 +12,6 @@ #include #include -#include "ui/overlays/Overlay.h" - #include #include @@ -78,7 +76,7 @@ public: virtual ~PathPointer(); void setRenderState(const std::string& state) override; - // You cannot use editRenderState to change the type of any part of the pointer. You can only edit the properties of the existing overlays. + // You cannot use editRenderState to change the type of any part of the pointer. You can only edit the properties of the existing parts. void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) override; void setLength(float length) override; @@ -119,7 +117,7 @@ protected: bool shouldHover(const PickResultPointer& pickResult) override { return _currentRenderState != ""; } bool shouldTrigger(const PickResultPointer& pickResult) override { return _currentRenderState != ""; } - void updateRenderStateOverlay(const OverlayID& id, const QVariant& props); + void updateRenderState(const QUuid& id, const QVariant& props); virtual void editRenderStatePath(const std::string& state, const QVariant& pathProps) = 0; PickedObject getHoveredObject(const PickResultPointer& pickResult) override; diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index e8f84e63fe..ce01db3a56 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -26,7 +26,6 @@ #include "avatar/AvatarManager.h" #include "NestableTransformNode.h" #include "avatars-renderer/AvatarTransformNode.h" -#include "ui/overlays/OverlayTransformNode.h" #include "EntityTransformNode.h" #include @@ -61,7 +60,7 @@ PickFilter getPickFilter(unsigned int filter) { * @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results. * @property {number} [filter=0] The filter for this Pick to use, constructed using filter flags combined using bitwise OR. * @property {number} [maxDistance=0.0] The max distance at which this Pick will intersect. 0.0 = no max. < 0.0 is invalid. - * @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick. + * @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or a pick. * @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint) * @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar. * @property {Vec3} [posOffset=Vec3.ZERO] Only for Joint Ray Picks. A local joint position offset, in meters. x = upward, y = forward, z = lateral @@ -161,7 +160,7 @@ unsigned int PickScriptingInterface::createStylusPick(const QVariant& properties * @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results. * @property {number} [filter=0] The filter for this Pick to use, constructed using filter flags combined using bitwise OR. * @property {number} [maxDistance=0.0] The max distance at which this Pick will intersect. 0.0 = no max. < 0.0 is invalid. - * @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick. + * @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or a pick. * @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint) * @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar. * @property {Vec3} [posOffset=Vec3.ZERO] Only for Joint Parabola Picks. A local joint position offset, in meters. x = upward, y = forward, z = lateral @@ -264,7 +263,7 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti * The depth is measured in world space, but will scale with the parent if defined. * @property {CollisionMask} [collisionGroup=8] - The type of object this collision pick collides as. Objects whose collision masks overlap with the pick's collision group * will be considered colliding with the pick. -* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick. +* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or a pick. * @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint) * @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar. * @property {boolean} [scaleWithParent=true] If true, the collision pick's dimensions and threshold will adjust according to the scale of the parent. @@ -415,8 +414,6 @@ void PickScriptingInterface::setParentTransform(std::shared_ptr pick, NestableType nestableType = sharedNestablePointer->getNestableType(); if (nestableType == NestableType::Avatar) { pick->parentTransform = std::make_shared(std::static_pointer_cast(sharedNestablePointer), parentJointIndex); - } else if (nestableType == NestableType::Overlay) { - pick->parentTransform = std::make_shared(std::static_pointer_cast(sharedNestablePointer), parentJointIndex); } else if (nestableType == NestableType::Entity) { pick->parentTransform = std::make_shared(std::static_pointer_cast(sharedNestablePointer), parentJointIndex); } else { diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index e795068cd3..80cf238010 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -46,7 +46,8 @@ * * @property {number} INTERSECTED_NONE An intersection type. Intersected nothing with the given filter flags. Read-only. * @property {number} INTERSECTED_ENTITY An intersection type. Intersected an entity. Read-only. - * @property {number} INTERSECTED_OVERLAY An intersection type. Intersected an overlay. Read-only. + * @property {number} INTERSECTED_LOCAL_ENTITY An intersection type. Intersected a local entity. + * @property {number} INTERSECTED_OVERLAY An intersection type. Intersected an entity (3D Overlays no longer exist). Read-only. * @property {number} INTERSECTED_AVATAR An intersection type. Intersected an avatar. Read-only. * @property {number} INTERSECTED_HUD An intersection type. Intersected the HUD sphere. Read-only. * @property {number} perFrameTimeBudget - The max number of usec to spend per frame updating Pick results. @@ -76,6 +77,7 @@ class PickScriptingInterface : public QObject, public Dependency { Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_LOCAL_ENTITY READ INTERSECTED_LOCAL_ENTITY CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT) @@ -211,7 +213,7 @@ public: Q_INVOKABLE void setPrecisionPicking(unsigned int uid, bool precisionPicking); /**jsdoc - * Sets a list of Entity IDs, Overlay IDs, and/or Avatar IDs to ignore during intersection. Not used by Stylus Picks. + * Sets a list of Entity IDs and/or Avatar IDs to ignore during intersection. Not used by Stylus Picks. * @function Picks.setIgnoreItems * @param {number} uid The ID of the Pick, as returned by {@link Picks.createPick}. * @param {Uuid[]} ignoreItems A list of IDs to ignore. @@ -219,7 +221,7 @@ public: Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreItems); /**jsdoc - * Sets a list of Entity IDs, Overlay IDs, and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus + * Sets a list of Entity IDs and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus * Picks only intersect with objects in their include list. * @function Picks.setIncludeItems * @param {number} uid The ID of the Pick, as returned by {@link Picks.createPick}. @@ -348,7 +350,13 @@ public slots: * @function Picks.INTERSECTED_OVERLAY * @returns {number} */ - static constexpr unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } + static constexpr unsigned int INTERSECTED_LOCAL_ENTITY() { return IntersectionType::LOCAL_ENTITY; } + + /**jsdoc + * @function Picks.INTERSECTED_OVERLAY + * @returns {number} + */ + static constexpr unsigned int INTERSECTED_OVERLAY() { return INTERSECTED_LOCAL_ENTITY(); } /**jsdoc * @function Picks.INTERSECTED_AVATAR diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp index 0009536479..19c20f0c06 100644 --- a/interface/src/raypick/PointerScriptingInterface.cpp +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -99,7 +99,7 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties) } } - return DependencyManager::get()->addPointer(std::make_shared(properties, StylusPointer::buildStylusOverlay(propertyMap), hover, enabled, modelPositionOffset, + return DependencyManager::get()->addPointer(std::make_shared(properties, StylusPointer::buildStylus(propertyMap), hover, enabled, modelPositionOffset, modelRotationOffset, modelDimensions)); } @@ -116,15 +116,15 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties) * * @typedef {object} Pointers.RayPointerRenderState * @property {string} name When using {@link Pointers.createPointer}, the name of this render state, used by {@link Pointers.setRenderState} and {@link Pointers.editRenderState} - * @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the beginning of the Ray Pointer, + * @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined object to represent the beginning of the Ray Pointer, * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). - * When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise. - * @property {Overlays.OverlayProperties|QUuid} [path] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the path of the Ray Pointer, + * When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. + * @property {Overlays.OverlayProperties|QUuid} [path] When using {@link Pointers.createPointer}, an optionally defined object to represent the path of the Ray Pointer, * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field), which must be "line3d". - * When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise. - * @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the end of the Ray Pointer, + * When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. + * @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined object to represent the end of the Ray Pointer, * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). - * When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise. + * When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. */ /**jsdoc * A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick. @@ -271,14 +271,14 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope * * @typedef {object} Pointers.ParabolaPointerRenderState * @property {string} name When using {@link Pointers.createPointer}, the name of this render state, used by {@link Pointers.setRenderState} and {@link Pointers.editRenderState} -* @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the beginning of the Parabola Pointer, +* @property {Overlays.OverlayProperties|QUuid} [start] When using {@link Pointers.createPointer}, an optionally defined object to represent the beginning of the Parabola Pointer, * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). -* When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise. +* When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. * @property {Pointers.ParabolaProperties} [path] When using {@link Pointers.createPointer}, the optionally defined rendering properties of the parabolic path defined by the Parabola Pointer. * Not defined in {@link Pointers.getPointerProperties}. -* @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined overlay to represent the end of the Parabola Pointer, +* @property {Overlays.OverlayProperties|QUuid} [end] When using {@link Pointers.createPointer}, an optionally defined object to represent the end of the Parabola Pointer, * using the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a type field). -* When returned from {@link Pointers.getPointerProperties}, the ID of the created overlay if it exists, or a null ID otherwise. +* When returned from {@link Pointers.getPointerProperties}, the ID of the created object if it exists, or a null ID otherwise. */ /**jsdoc * A set of properties that can be passed to {@link Pointers.createPointer} to create a new Pointer. Contains the relevant {@link Picks.PickProperties} to define the underlying Pick. diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h index a21c1f2470..1ccc8893a2 100644 --- a/interface/src/raypick/PointerScriptingInterface.h +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -16,7 +16,7 @@ /**jsdoc * The Pointers API lets you create and manage objects for repeatedly calculating intersections in different ways, as well as the visual representation of those objects. - * Pointers can also be configured to automatically generate {@link PointerEvent}s on {@link Entities} and {@link Overlays}. + * Pointers can also be configured to automatically generate {@link PointerEvent}s on {@link Entities}. * * @namespace Pointers * @@ -39,7 +39,7 @@ public: * @typedef {object} Pointers.Trigger * @property {Controller.Standard|Controller.Actions|function} action This can be a built-in Controller action, like Controller.Standard.LTClick, or a function that evaluates to >= 1.0 when you want to trigger button. * @property {string} button Which button to trigger. "Primary", "Secondary", "Tertiary", and "Focus" are currently supported. Only "Primary" will trigger clicks on web surfaces. If "Focus" is triggered, - * it will try to set the entity or overlay focus to the object at which the Pointer is aimed. Buttons besides the first three will still trigger events, but event.button will be "None". + * it will try to set the entity focus to the object at which the Pointer is aimed. Buttons besides the first three will still trigger events, but event.button will be "None". */ /**jsdoc @@ -153,7 +153,7 @@ public: Q_INVOKABLE void setLength(unsigned int uid, float length) const { DependencyManager::get()->setLength(uid, length); } /**jsdoc - * Sets a list of Entity IDs, Overlay IDs, and/or Avatar IDs to ignore during intersection. Not used by Stylus Pointers. + * Sets a list of Entity IDs and/or Avatar IDs to ignore during intersection. Not used by Stylus Pointers. * @function Pointers.setIgnoreItems * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @param {Uuid[]} ignoreItems A list of IDs to ignore. @@ -161,7 +161,7 @@ public: Q_INVOKABLE void setIgnoreItems(unsigned int uid, const QScriptValue& ignoreEntities) const; /**jsdoc - * Sets a list of Entity IDs, Overlay IDs, and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus + * Sets a list of Entity IDs and/or Avatar IDs to include during intersection, instead of intersecting with everything. Stylus * Pointers only intersect with objects in their include list. * @function Pointers.setIncludeItems * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. @@ -171,15 +171,15 @@ public: /**jsdoc - * Lock a Pointer onto a specific object (overlay, entity, or avatar). Optionally, provide an offset in object-space, otherwise the Pointer will lock on to the center of the object. + * Lock a Pointer onto a specific object (entity or avatar). Optionally, provide an offset in object-space, otherwise the Pointer will lock on to the center of the object. * Not used by Stylus Pointers. * @function Pointers.setLockEndUUID * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @param {Uuid} objectID The ID of the object to which to lock on. - * @param {boolean} isOverlay False for entities or avatars, true for overlays + * @param {boolean} isAvatar False for entities, true for avatars * @param {Mat4} [offsetMat] The offset matrix to use if you do not want to lock on to the center of the object. */ - Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay, offsetMat); } + Q_INVOKABLE void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isAvatar, offsetMat); } /**jsdoc @@ -211,7 +211,7 @@ public: * @function Pointers.getPointerProperties * @param {number} uid The ID of the Pointer, as returned by {@link Pointers.createPointer}. * @returns {Pointers.LaserPointerProperties|Pointers.StylusPointerProperties|Pointers.ParabolaPointerProperties} The information about the Pointer. - * Currently only includes renderStates and defaultRenderStates with associated overlay IDs. + * Currently only includes renderStates and defaultRenderStates with associated entity IDs. */ Q_INVOKABLE QVariantMap getPointerProperties(unsigned int uid) const; }; diff --git a/interface/src/raypick/RayPick.cpp b/interface/src/raypick/RayPick.cpp index 507e45b470..e35f4584a6 100644 --- a/interface/src/raypick/RayPick.cpp +++ b/interface/src/raypick/RayPick.cpp @@ -9,7 +9,6 @@ #include "Application.h" #include "EntityScriptingInterface.h" -#include "ui/overlays/Overlays.h" #include "avatar/AvatarManager.h" #include "scripting/HMDScriptingInterface.h" #include "DependencyManager.h" @@ -37,19 +36,15 @@ PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) { DependencyManager::get()->evalRayIntersectionVector(pick, searchFilter, getIncludeItemsAs(), getIgnoreItemsAs()); if (entityRes.intersects) { - return std::make_shared(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo); - } else { - return std::make_shared(pick.toVariantMap()); - } -} - -PickResultPointer RayPick::getOverlayIntersection(const PickRay& pick) { - bool precisionPicking = !(getFilter().isCoarse() || DependencyManager::get()->getForceCoarsePicking()); - RayToOverlayIntersectionResult overlayRes = - qApp->getOverlays().findRayIntersectionVector(pick, precisionPicking, - getIncludeItemsAs(), getIgnoreItemsAs(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable()); - if (overlayRes.intersects) { - return std::make_shared(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, pick, overlayRes.surfaceNormal, overlayRes.extraInfo); + IntersectionType type = IntersectionType::ENTITY; + if (getFilter().doesPickLocalEntities()) { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_ENTITY_HOST_TYPE; + if (DependencyManager::get()->getEntityProperties(entityRes.entityID, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) { + type = IntersectionType::LOCAL_ENTITY; + } + } + return std::make_shared(type, entityRes.entityID, entityRes.distance, entityRes.intersection, pick, entityRes.surfaceNormal, entityRes.extraInfo); } else { return std::make_shared(pick.toVariantMap()); } @@ -88,12 +83,6 @@ glm::vec3 RayPick::intersectRayWithXYPlane(const glm::vec3& origin, const glm::v return origin + t * direction; } -glm::vec3 RayPick::intersectRayWithOverlayXYPlane(const QUuid& overlayID, const glm::vec3& origin, const glm::vec3& direction) { - glm::vec3 position = vec3FromVariant(qApp->getOverlays().getProperty(overlayID, "position").value); - glm::quat rotation = quatFromVariant(qApp->getOverlays().getProperty(overlayID, "rotation").value); - return intersectRayWithXYPlane(origin, direction, position, rotation, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT); -} - glm::vec3 RayPick::intersectRayWithEntityXYPlane(const QUuid& entityID, const glm::vec3& origin, const glm::vec3& direction) { auto props = DependencyManager::get()->getEntityProperties(entityID); return intersectRayWithXYPlane(origin, direction, props.getPosition(), props.getRotation(), props.getRegistrationPoint()); @@ -112,14 +101,6 @@ glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3 return pos2D; } -glm::vec2 RayPick::projectOntoOverlayXYPlane(const QUuid& overlayID, const glm::vec3& worldPos, bool unNormalized) { - glm::vec3 position = vec3FromVariant(qApp->getOverlays().getProperty(overlayID, "position").value); - glm::quat rotation = quatFromVariant(qApp->getOverlays().getProperty(overlayID, "rotation").value); - glm::vec3 dimensions = glm::vec3(vec2FromVariant(qApp->getOverlays().getProperty(overlayID, "dimensions").value), 0.01f); - - return projectOntoXYPlane(worldPos, position, rotation, dimensions, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT, unNormalized); -} - glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized) { auto props = DependencyManager::get()->getEntityProperties(entityID); return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint(), unNormalized); diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index ba67ceebb1..a781795e55 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -12,7 +12,6 @@ #include class EntityItemID; -class OverlayID; class RayPickResult : public PickResult { public: @@ -78,16 +77,13 @@ public: PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared(pickVariant); } PickResultPointer getEntityIntersection(const PickRay& pick) override; - PickResultPointer getOverlayIntersection(const PickRay& pick) override; PickResultPointer getAvatarIntersection(const PickRay& pick) override; PickResultPointer getHUDIntersection(const PickRay& pick) override; Transform getResultTransform() const override; // These are helper functions for projecting and intersecting rays static glm::vec3 intersectRayWithEntityXYPlane(const QUuid& entityID, const glm::vec3& origin, const glm::vec3& direction); - static glm::vec3 intersectRayWithOverlayXYPlane(const QUuid& overlayID, const glm::vec3& origin, const glm::vec3& direction); static glm::vec2 projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized = true); - static glm::vec2 projectOntoOverlayXYPlane(const QUuid& overlayID, const glm::vec3& worldPos, bool unNormalized = true); private: static glm::vec3 intersectRayWithXYPlane(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& point, const glm::quat& rotation, const glm::vec3& registration); diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index 3ad0efd439..f8c47ba4cf 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -53,6 +53,7 @@ class RayPickScriptingInterface : public QObject, public Dependency { Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_LOCAL_ENTITY READ INTERSECTED_LOCAL_ENTITY CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT) Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT) @@ -202,7 +203,13 @@ public slots: * @function RayPick.INTERSECTED_OVERLAY * @returns {number} */ - static unsigned int INTERSECTED_OVERLAY() { return PickScriptingInterface::INTERSECTED_OVERLAY(); } + static unsigned int INTERSECTED_LOCAL_ENTITY() { return PickScriptingInterface::INTERSECTED_LOCAL_ENTITY(); } + + /**jsdoc + * @function RayPick.INTERSECTED_OVERLAY + * @returns {number} + */ + static unsigned int INTERSECTED_OVERLAY() { return PickScriptingInterface::INTERSECTED_LOCAL_ENTITY(); } /**jsdoc * @function RayPick.INTERSECTED_AVATAR diff --git a/interface/src/raypick/StylusPick.cpp b/interface/src/raypick/StylusPick.cpp index 0a76180be8..a9dbf9b950 100644 --- a/interface/src/raypick/StylusPick.cpp +++ b/interface/src/raypick/StylusPick.cpp @@ -11,8 +11,6 @@ #include -#include "ui/overlays/Base3DOverlay.h" - #include "Application.h" #include #include "avatar/AvatarManager.h" @@ -148,7 +146,13 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) { continue; } - if (!entity->getVisible() && !getFilter().doesPickInvisible()) { + bool visible = entity->getVisible(); + bool collisionless = entity->getCollisionless(); + if ((!visible && !getFilter().doesPickInvisible()) || (visible && !getFilter().doesPickVisible()) || + (!collisionless && !getFilter().doesPickCollidable()) || (collisionless && !getFilter().doesPickNonCollidable()) || + (entity->isLocalEntity() && !getFilter().doesPickLocalEntities()) || + (entity->isAvatarEntity() && !getFilter().doesPickAvatarEntities()) || + (entity->isDomainEntity() && !getFilter().doesPickDomainEntities())) { continue; } @@ -161,47 +165,15 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) { glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(target, intersection, false); if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) { - results.push_back(StylusPickResult(IntersectionType::ENTITY, target, distance, intersection, pick, normal)); - } - } - - StylusPickResult nearestTarget(pick.toVariantMap()); - for (const auto& result : results) { - if (result.distance < nearestTarget.distance) { - nearestTarget = result; - } - } - return std::make_shared(nearestTarget); -} - -PickResultPointer StylusPick::getOverlayIntersection(const StylusTip& pick) { - std::vector results; - for (const auto& target : getIncludeItems()) { - if (target.isNull()) { - continue; - } - - auto overlay = qApp->getOverlays().getOverlay(target); - // Don't interact with non-3D or invalid overlays - if (!overlay || !overlay->is3D()) { - continue; - } - - if (!overlay->getVisible() && !getFilter().doesPickInvisible()) { - continue; - } - - auto overlay3D = std::static_pointer_cast(overlay); - const auto overlayRotation = overlay3D->getWorldOrientation(); - const auto overlayPosition = overlay3D->getWorldPosition(); - - glm::vec3 normal = overlayRotation * Vectors::UNIT_Z; - float distance = glm::dot(pick.position - overlayPosition, normal); - glm::vec3 intersection = pick.position - (normal * distance); - - glm::vec2 pos2D = RayPick::projectOntoOverlayXYPlane(target, intersection, false); - if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) { - results.push_back(StylusPickResult(IntersectionType::OVERLAY, target, distance, intersection, pick, normal)); + IntersectionType type = IntersectionType::ENTITY; + if (getFilter().doesPickLocalEntities()) { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_ENTITY_HOST_TYPE; + if (DependencyManager::get()->getEntityProperties(target, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) { + type = IntersectionType::LOCAL_ENTITY; + } + } + results.push_back(StylusPickResult(type, target, distance, intersection, pick, normal)); } } diff --git a/interface/src/raypick/StylusPick.h b/interface/src/raypick/StylusPick.h index 14821c0ce5..9d5dc10b67 100644 --- a/interface/src/raypick/StylusPick.h +++ b/interface/src/raypick/StylusPick.h @@ -63,7 +63,6 @@ public: StylusTip getMathematicalPick() const override; PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override; PickResultPointer getEntityIntersection(const StylusTip& pick) override; - PickResultPointer getOverlayIntersection(const StylusTip& pick) override; PickResultPointer getAvatarIntersection(const StylusTip& pick) override; PickResultPointer getHUDIntersection(const StylusTip& pick) override; Transform getResultTransform() const override; diff --git a/interface/src/raypick/StylusPointer.cpp b/interface/src/raypick/StylusPointer.cpp index 867f896763..3cdcb9c3a5 100644 --- a/interface/src/raypick/StylusPointer.cpp +++ b/interface/src/raypick/StylusPointer.cpp @@ -27,10 +27,10 @@ static const float TOUCH_HYSTERESIS = 0.001f; static const QString DEFAULT_STYLUS_MODEL_URL = PathUtils::resourcesUrl() + "/meshes/tablet-stylus-fat.fbx"; -StylusPointer::StylusPointer(const QVariant& props, const OverlayID& stylusOverlay, bool hover, bool enabled, +StylusPointer::StylusPointer(const QVariant& props, const QUuid& stylus, bool hover, bool enabled, const glm::vec3& modelPositionOffset, const glm::quat& modelRotationOffset, const glm::vec3& modelDimensions) : Pointer(DependencyManager::get()->createStylusPick(props), enabled, hover), - _stylusOverlay(stylusOverlay), + _stylus(stylus), _modelPositionOffset(modelPositionOffset), _modelDimensions(modelDimensions), _modelRotationOffset(modelRotationOffset) @@ -38,13 +38,14 @@ StylusPointer::StylusPointer(const QVariant& props, const OverlayID& stylusOverl } StylusPointer::~StylusPointer() { - if (!_stylusOverlay.isNull()) { - qApp->getOverlays().deleteOverlay(_stylusOverlay); + if (!_stylus.isNull()) { + DependencyManager::get()->deleteEntity(_stylus); } } -OverlayID StylusPointer::buildStylusOverlay(const QVariantMap& properties) { - QVariantMap overlayProperties; +QUuid StylusPointer::buildStylus(const QVariantMap& properties) { + // FIXME: we have to keep using the Overlays interface here, because existing scripts use overlay properties to define pointers + QVariantMap propertiesMap; QString modelUrl = DEFAULT_STYLUS_MODEL_URL; @@ -56,15 +57,15 @@ OverlayID StylusPointer::buildStylusOverlay(const QVariantMap& properties) { } } // TODO: make these configurable per pointer - overlayProperties["name"] = "stylus"; - overlayProperties["url"] = modelUrl; - overlayProperties["loadPriority"] = 10.0f; - overlayProperties["solid"] = true; - overlayProperties["visible"] = false; - overlayProperties["ignorePickIntersection"] = true; - overlayProperties["drawInFront"] = false; + propertiesMap["name"] = "stylus"; + propertiesMap["url"] = modelUrl; + propertiesMap["loadPriority"] = 10.0f; + propertiesMap["solid"] = true; + propertiesMap["visible"] = false; + propertiesMap["ignorePickIntersection"] = true; + propertiesMap["drawInFront"] = false; - return qApp->getOverlays().addOverlay("model", overlayProperties); + return qApp->getOverlays().addOverlay("model", propertiesMap); } void StylusPointer::updateVisuals(const PickResultPointer& pickResult) { @@ -83,25 +84,25 @@ void StylusPointer::updateVisuals(const PickResultPointer& pickResult) { } void StylusPointer::show(const StylusTip& tip) { - if (!_stylusOverlay.isNull()) { - QVariantMap props; + if (!_stylus.isNull()) { auto modelOrientation = tip.orientation * _modelRotationOffset; auto sensorToWorldScale = DependencyManager::get()->getMyAvatar()->getSensorToWorldScale(); auto modelPositionOffset = modelOrientation * (_modelPositionOffset * sensorToWorldScale); - props["position"] = vec3toVariant(tip.position + modelPositionOffset); - props["rotation"] = quatToVariant(modelOrientation); - props["dimensions"] = vec3toVariant(sensorToWorldScale * _modelDimensions); - props["visible"] = true; - qApp->getOverlays().editOverlay(_stylusOverlay, props); + EntityItemProperties properties; + properties.setPosition(tip.position + modelPositionOffset); + properties.setRotation(modelOrientation); + properties.setDimensions(sensorToWorldScale * _modelDimensions); + properties.setVisible(true); + DependencyManager::get()->editEntity(_stylus, properties); } _showing = true; } void StylusPointer::hide() { - if (!_stylusOverlay.isNull()) { - QVariantMap props; - props.insert("visible", false); - qApp->getOverlays().editOverlay(_stylusOverlay, props); + if (!_stylus.isNull()) { + EntityItemProperties properties; + properties.setVisible(false); + DependencyManager::get()->editEntity(_stylus, properties); } _showing = false; } @@ -234,9 +235,8 @@ QVariantMap StylusPointer::toVariantMap() const { glm::vec3 StylusPointer::findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction) { switch (pickedObject.type) { case ENTITY: + case LOCAL_ENTITY: return RayPick::intersectRayWithEntityXYPlane(pickedObject.objectID, origin, direction); - case OVERLAY: - return RayPick::intersectRayWithOverlayXYPlane(pickedObject.objectID, origin, direction); default: return glm::vec3(NAN); } @@ -245,9 +245,8 @@ glm::vec3 StylusPointer::findIntersection(const PickedObject& pickedObject, cons glm::vec2 StylusPointer::findPos2D(const PickedObject& pickedObject, const glm::vec3& origin) { switch (pickedObject.type) { case ENTITY: + case LOCAL_ENTITY: return RayPick::projectOntoEntityXYPlane(pickedObject.objectID, origin); - case OVERLAY: - return RayPick::projectOntoOverlayXYPlane(pickedObject.objectID, origin); case HUD: return DependencyManager::get()->calculatePos2DFromHUD(origin); default: diff --git a/interface/src/raypick/StylusPointer.h b/interface/src/raypick/StylusPointer.h index 64e2a38bed..7d43df2379 100644 --- a/interface/src/raypick/StylusPointer.h +++ b/interface/src/raypick/StylusPointer.h @@ -12,8 +12,6 @@ #include #include -#include "ui/overlays/Overlay.h" - #include "StylusPick.h" class StylusPointer : public Pointer { @@ -21,7 +19,7 @@ class StylusPointer : public Pointer { using Ptr = std::shared_ptr; public: - StylusPointer(const QVariant& props, const OverlayID& stylusOverlay, bool hover, bool enabled, + StylusPointer(const QVariant& props, const QUuid& stylus, bool hover, bool enabled, const glm::vec3& modelPositionOffset, const glm::quat& modelRotationOffset, const glm::vec3& modelDimensions); ~StylusPointer(); @@ -36,7 +34,7 @@ public: QVariantMap toVariantMap() const override; - static OverlayID buildStylusOverlay(const QVariantMap& properties); + static QUuid buildStylus(const QVariantMap& properties); protected: PickedObject getHoveredObject(const PickResultPointer& pickResult) override; @@ -74,7 +72,7 @@ private: RenderState _renderState { EVENTS_ON }; - const OverlayID _stylusOverlay; + QUuid _stylus; static bool isWithinBounds(float distance, float min, float max, float hysteresis); static glm::vec3 findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction); diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 81f85409cc..11b1c50073 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -53,12 +53,12 @@ class QScriptEngine; * @property {boolean} tabletContextualMode - true if the tablet has been opened in contextual mode, otherwise * false. In contextual mode, the tablet has been opened at a specific world position and orientation rather * than at a position and orientation relative to the user. Read-only. - * @property {Uuid} tabletID - The UUID of the tablet body model overlay. - * @property {Uuid} tabletScreenID - The UUID of the tablet's screen overlay. - * @property {Uuid} homeButtonID - The UUID of the tablet's "home" button overlay. - * @property {Uuid} homeButtonHighlightID - The UUID of the tablet's "home" button highlight overlay. - * @property {Uuid} miniTabletID - The UUID of the mini tablet's body model overlay. null if not in HMD mode. - * @property {Uuid} miniTabletScreenID - The UUID of the mini tablet's screen overlay. null if not in HMD mode. + * @property {Uuid} tabletID - The UUID of the tablet body model entity. + * @property {Uuid} tabletScreenID - The UUID of the tablet's screen entity. + * @property {Uuid} homeButtonID - The UUID of the tablet's "home" button entity. + * @property {Uuid} homeButtonHighlightID - The UUID of the tablet's "home" button highlight entity. + * @property {Uuid} miniTabletID - The UUID of the mini tablet's body model entity. null if not in HMD mode. + * @property {Uuid} miniTabletScreenID - The UUID of the mini tablet's screen entity. null if not in HMD mode. * @property {number} miniTabletHand - The hand that the mini tablet is displayed on: 0 for left hand, * 1 for right hand, -1 if not in HMD mode. * @property {bool} miniTabletEnabled=true - true if the mini tablet is enabled to be displayed, otherwise diff --git a/interface/src/scripting/KeyboardScriptingInterface.cpp b/interface/src/scripting/KeyboardScriptingInterface.cpp index ccf123efed..b031f2d749 100644 --- a/interface/src/scripting/KeyboardScriptingInterface.cpp +++ b/interface/src/scripting/KeyboardScriptingInterface.cpp @@ -64,6 +64,6 @@ bool KeyboardScriptingInterface::getPreferMalletsOverLasers() const { return DependencyManager::get()->getPreferMalletsOverLasers(); } -bool KeyboardScriptingInterface::containsID(OverlayID overlayID) const { - return DependencyManager::get()->containsID(overlayID); +bool KeyboardScriptingInterface::containsID(const QUuid& id) const { + return DependencyManager::get()->containsID(id); } diff --git a/interface/src/scripting/KeyboardScriptingInterface.h b/interface/src/scripting/KeyboardScriptingInterface.h index acee10669e..bc8f2f60bd 100644 --- a/interface/src/scripting/KeyboardScriptingInterface.h +++ b/interface/src/scripting/KeyboardScriptingInterface.h @@ -16,7 +16,6 @@ #include #include "DependencyManager.h" -#include "ui/overlays/Overlay.h" /**jsdoc * The Keyboard API provides facilities to use 3D Physical keyboard. @@ -46,7 +45,7 @@ public: Q_INVOKABLE void disableRightMallet(); Q_INVOKABLE void setLeftHandLaser(unsigned int leftHandLaser); Q_INVOKABLE void setRightHandLaser(unsigned int rightHandLaser); - Q_INVOKABLE bool containsID(OverlayID overlayID) const; + Q_INVOKABLE bool containsID(const QUuid& overlayID) const; private: bool getPreferMalletsOverLasers() const; bool isRaised() const; diff --git a/interface/src/scripting/SelectionScriptingInterface.cpp b/interface/src/scripting/SelectionScriptingInterface.cpp index 4a8a72b16d..c15b5cde11 100644 --- a/interface/src/scripting/SelectionScriptingInterface.cpp +++ b/interface/src/scripting/SelectionScriptingInterface.cpp @@ -40,19 +40,6 @@ bool GameplayObjects::removeFromGameplayObjects(const EntityItemID& entityID) { return true; } -bool GameplayObjects::addToGameplayObjects(const OverlayID& overlayID) { - containsData = true; - if (std::find(_overlayIDs.begin(), _overlayIDs.end(), overlayID) == _overlayIDs.end()) { - _overlayIDs.push_back(overlayID); - } - return true; -} -bool GameplayObjects::removeFromGameplayObjects(const OverlayID& overlayID) { - _overlayIDs.erase(std::remove(_overlayIDs.begin(), _overlayIDs.end(), overlayID), _overlayIDs.end()); - return true; -} - - SelectionScriptingInterface::SelectionScriptingInterface() { } @@ -64,7 +51,6 @@ SelectionScriptingInterface::SelectionScriptingInterface() { * * "avatar" * "entity" - * "overlay" * * * @typedef {string} Selection.ItemType @@ -72,20 +58,16 @@ SelectionScriptingInterface::SelectionScriptingInterface() { bool SelectionScriptingInterface::addToSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id) { if (itemType == "avatar") { return addToGameplayObjects(listName, (QUuid)id); - } else if (itemType == "entity") { + } else if (itemType == "entity" || itemType == "overlay") { return addToGameplayObjects(listName, (EntityItemID)id); - } else if (itemType == "overlay") { - return addToGameplayObjects(listName, (OverlayID)id); } return false; } bool SelectionScriptingInterface::removeFromSelectedItemsList(const QString& listName, const QString& itemType, const QUuid& id) { if (itemType == "avatar") { return removeFromGameplayObjects(listName, (QUuid)id); - } else if (itemType == "entity") { + } else if (itemType == "entity" || itemType == "overlay") { return removeFromGameplayObjects(listName, (EntityItemID)id); - } else if (itemType == "overlay") { - return removeFromGameplayObjects(listName, (OverlayID)id); } return false; } @@ -253,12 +235,6 @@ void SelectionScriptingInterface::printList(const QString& listName) { qDebug() << j << ';'; } qDebug() << ""; - - qDebug() << "Overlay IDs:"; - for (auto k : (*currentList).getOverlayIDs()) { - qDebug() << k << ';'; - } - qDebug() << ""; } else { qDebug() << "List named " << listName << " empty"; @@ -272,7 +248,6 @@ void SelectionScriptingInterface::printList(const QString& listName) { * @typedef {object} Selection.SelectedItemsList * @property {Uuid[]} avatars - The IDs of the avatars in the selection. * @property {Uuid[]} entities - The IDs of the entities in the selection. - * @property {Uuid[]} overlays - The IDs of the overlays in the selection. */ QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& listName) const { QReadLocker lock(&_selectionListsLock); @@ -281,7 +256,6 @@ QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& lis if (currentList != _selectedItemsListMap.end()) { QList avatarIDs; QList entityIDs; - QList overlayIDs; if ((*currentList).getContainsData()) { if (!(*currentList).getAvatarIDs().empty()) { @@ -294,15 +268,9 @@ QVariantMap SelectionScriptingInterface::getSelectedItemsList(const QString& lis entityIDs.push_back((QUuid)j ); } } - if (!(*currentList).getOverlayIDs().empty()) { - for (auto j : (*currentList).getOverlayIDs()) { - overlayIDs.push_back((QUuid)j); - } - } } list["avatars"] = (avatarIDs); list["entities"] = (entityIDs); - list["overlays"] = (overlayIDs); return list; } @@ -379,7 +347,6 @@ void SelectionToSceneHandler::updateSceneFromSelectedList() { render::ItemIDs finalList; render::ItemID currentID; auto entityTreeRenderer = DependencyManager::get(); - auto& overlays = qApp->getOverlays(); for (QUuid& currentAvatarID : thisList.getAvatarIDs()) { auto avatar = std::static_pointer_cast(DependencyManager::get()->getAvatarBySessionID(currentAvatarID)); @@ -398,16 +365,6 @@ void SelectionToSceneHandler::updateSceneFromSelectedList() { } } - for (OverlayID& currentOverlayID : thisList.getOverlayIDs()) { - auto overlay = overlays.getOverlay(currentOverlayID); - if (overlay != NULL) { - currentID = overlay->getRenderItemID(); - if (currentID != render::Item::INVALID_ITEM_ID) { - finalList.push_back(currentID); - } - } - } - render::Selection selection(_listName.toStdString(), finalList); transaction.resetSelection(selection); diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index 83aec63ee2..dc95b1ea24 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -19,7 +19,6 @@ #include #include "RenderableEntityItem.h" -#include "ui/overlays/Overlay.h" #include #include @@ -37,15 +36,10 @@ public: bool addToGameplayObjects(const EntityItemID& entityID); bool removeFromGameplayObjects(const EntityItemID& entityID); - std::vector getOverlayIDs() const { return _overlayIDs; } - bool addToGameplayObjects(const OverlayID& overlayID); - bool removeFromGameplayObjects(const OverlayID& overlayID); - private: bool containsData { false }; std::vector _avatarIDs; std::vector _entityIDs; - std::vector _overlayIDs; }; @@ -83,7 +77,7 @@ protected: }; /**jsdoc - * The Selection API provides a means of grouping together avatars, entities, and overlays in named lists. + * The Selection API provides a means of grouping together avatars and entities in named lists. * @namespace Selection * * @hifi-interface @@ -174,14 +168,14 @@ public: Q_INVOKABLE bool clearSelectedItemsList(const QString& listName); /**jsdoc - * Print out the list of avatars, entities, and overlays in a selection to the debug log (not the script log). + * Print out the list of avatars and entities in a selection to the debug log (not the script log). * @function Selection.printList * @param {string} listName - The name of the selection list. */ Q_INVOKABLE void printList(const QString& listName); /**jsdoc - * Get the list of avatars, entities, and overlays stored in a selection list. + * Get the list of avatars and entities stored in a selection list. * @function Selection.getSelectedItemsList * @param {string} listName - The name of the selection list. * @returns {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 3579776213..8f21965c56 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -134,9 +134,7 @@ void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { batch.resetViewTransform(); // Render all of the Script based "HUD" aka 2D overlays. - // note: we call them HUD, as opposed to 2D, only because there are some cases of 3D HUD overlays, like the - // cameral controls for the edit.js - qApp->getOverlays().renderHUD(renderArgs); + qApp->getOverlays().render(renderArgs); } void ApplicationOverlay::renderDomainConnectionStatusBorder(RenderArgs* renderArgs) { diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 9e9a319802..01d21a211a 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -33,11 +33,6 @@ #include #include -#include "ui/overlays/Overlays.h" -#include "ui/overlays/Overlay.h" -#include "ui/overlays/ModelOverlay.h" -#include "ui/overlays/Cube3DOverlay.h" -#include "ui/overlays/Text3DOverlay.h" #include "avatar/AvatarManager.h" #include "avatar/MyAvatar.h" #include "avatar/AvatarManager.h" @@ -120,21 +115,21 @@ std::pair calculateKeyboardPositionAndOrientation() { float sensorToWorldScale = myAvatar->getSensorToWorldScale(); QUuid tabletID = hmd->getCurrentTabletFrameID(); if (!tabletID.isNull() && hmd->getShouldShowTablet()) { - Overlays& overlays = qApp->getOverlays(); - auto tabletOverlay = std::dynamic_pointer_cast(overlays.getOverlay(tabletID)); - if (tabletOverlay) { - auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); - bool landscapeMode = tablet->getLandscape(); - glm::vec3 keyboardOffset = landscapeMode ? KEYBOARD_TABLET_LANDSCAPE_OFFSET : KEYBOARD_TABLET_OFFSET; - glm::vec3 keyboardDegreesOffset = landscapeMode ? KEYBOARD_TABLET_LANDSCAPE_DEGREES_OFFSET : KEYBOARD_TABLET_DEGREES_OFFSET; - glm::vec3 tabletWorldPosition = tabletOverlay->getWorldPosition(); - glm::quat tabletWorldOrientation = tabletOverlay->getWorldOrientation(); - glm::vec3 scaledKeyboardTabletOffset = keyboardOffset * sensorToWorldScale; + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_POSITION; + desiredProperties += PROP_ROTATION; + auto properties = DependencyManager::get()->getEntityProperties(tabletID, desiredProperties); - keyboardLocation.first = tabletWorldPosition + (tabletWorldOrientation * scaledKeyboardTabletOffset); - keyboardLocation.second = tabletWorldOrientation * glm::quat(glm::radians(keyboardDegreesOffset)); - } + auto tablet = DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system"); + bool landscapeMode = tablet->getLandscape(); + glm::vec3 keyboardOffset = landscapeMode ? KEYBOARD_TABLET_LANDSCAPE_OFFSET : KEYBOARD_TABLET_OFFSET; + glm::vec3 keyboardDegreesOffset = landscapeMode ? KEYBOARD_TABLET_LANDSCAPE_DEGREES_OFFSET : KEYBOARD_TABLET_DEGREES_OFFSET; + glm::vec3 tabletWorldPosition = properties.getPosition(); + glm::quat tabletWorldOrientation = properties.getRotation(); + glm::vec3 scaledKeyboardTabletOffset = keyboardOffset * sensorToWorldScale; + keyboardLocation.first = tabletWorldPosition + (tabletWorldOrientation * scaledKeyboardTabletOffset); + keyboardLocation.second = tabletWorldOrientation * glm::quat(glm::radians(keyboardDegreesOffset)); } else { glm::vec3 avatarWorldPosition = myAvatar->getWorldPosition(); glm::quat avatarWorldOrientation = myAvatar->getWorldOrientation(); @@ -148,32 +143,25 @@ std::pair calculateKeyboardPositionAndOrientation() { } void Key::saveDimensionsAndLocalPosition() { - Overlays& overlays = qApp->getOverlays(); - auto model3DOverlay = std::dynamic_pointer_cast(overlays.getOverlay(_keyID)); + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_LOCAL_POSITION; + desiredProperties += PROP_DIMENSIONS; + auto properties = DependencyManager::get()->getEntityProperties(_keyID, desiredProperties); - if (model3DOverlay) { - _originalLocalPosition = model3DOverlay->getLocalPosition(); - _originalDimensions = model3DOverlay->getDimensions(); - _currentLocalPosition = _originalLocalPosition; - } + _originalLocalPosition = properties.getLocalPosition(); + _originalDimensions = properties.getDimensions(); + _currentLocalPosition = _originalLocalPosition; } void Key::scaleKey(float sensorToWorldScale) { - Overlays& overlays = qApp->getOverlays(); - auto model3DOverlay = std::dynamic_pointer_cast(overlays.getOverlay(_keyID)); + glm::vec3 scaledLocalPosition = _originalLocalPosition * sensorToWorldScale; + glm::vec3 scaledDimensions = _originalDimensions * sensorToWorldScale; + _currentLocalPosition = scaledLocalPosition; - if (model3DOverlay) { - glm::vec3 scaledLocalPosition = _originalLocalPosition * sensorToWorldScale; - glm::vec3 scaledDimensions = _originalDimensions * sensorToWorldScale; - _currentLocalPosition = scaledLocalPosition; - - QVariantMap properties { - { "dimensions", vec3toVariant(scaledDimensions) }, - { "localPosition", vec3toVariant(scaledLocalPosition) } - }; - - overlays.editOverlay(_keyID, properties); - } + EntityItemProperties properties; + properties.setDimensions(scaledDimensions); + properties.setLocalPosition(scaledLocalPosition); + DependencyManager::get()->editEntity(_keyID, properties); } void Key::startTimer(int time) { @@ -262,21 +250,21 @@ void Keyboard::createKeyboard() { QVariantMap leftStylusProperties { { "hand", LEFT_HAND_CONTROLLER_INDEX }, - { "filter", PickScriptingInterface::PICK_OVERLAYS() }, + { "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() }, { "model", modelProperties }, { "tipOffset", vec3toVariant(MALLET_TIP_OFFSET) } }; QVariantMap rightStylusProperties { { "hand", RIGHT_HAND_CONTROLLER_INDEX }, - { "filter", PickScriptingInterface::PICK_OVERLAYS() }, + { "filter", PickScriptingInterface::PICK_LOCAL_ENTITIES() }, { "model", modelProperties }, { "tipOffset", vec3toVariant(MALLET_TIP_OFFSET) } }; - _leftHandStylus = pointerManager->addPointer(std::make_shared(leftStylusProperties, StylusPointer::buildStylusOverlay(leftStylusProperties), true, true, + _leftHandStylus = pointerManager->addPointer(std::make_shared(leftStylusProperties, StylusPointer::buildStylus(leftStylusProperties), true, true, MALLET_POSITION_OFFSET, MALLET_ROTATION_OFFSET, MALLET_MODEL_DIMENSIONS)); - _rightHandStylus = pointerManager->addPointer(std::make_shared(rightStylusProperties, StylusPointer::buildStylusOverlay(rightStylusProperties), true, true, + _rightHandStylus = pointerManager->addPointer(std::make_shared(rightStylusProperties, StylusPointer::buildStylus(rightStylusProperties), true, true, MALLET_POSITION_OFFSET, MALLET_ROTATION_OFFSET, MALLET_MODEL_DIMENSIONS)); pointerManager->disablePointer(_rightHandStylus); @@ -312,93 +300,70 @@ void Keyboard::setRaised(bool raised) { } void Keyboard::updateTextDisplay() { - Overlays& overlays = qApp->getOverlays(); - auto myAvatar = DependencyManager::get()->getMyAvatar(); + auto entityScriptingInterface = DependencyManager::get(); float sensorToWorldScale = myAvatar->getSensorToWorldScale(); - float textWidth = (float) overlays.textSize(_textDisplay.overlayID, _typedCharacters).width(); + float textWidth = (float)entityScriptingInterface->textSize(_textDisplay.entityID, _typedCharacters).width(); glm::vec3 scaledDimensions = _textDisplay.dimensions; scaledDimensions *= sensorToWorldScale; float leftMargin = (scaledDimensions.x / 2); scaledDimensions.x += textWidth; - - QVariantMap textDisplayProperties { - { "dimensions", vec3toVariant(scaledDimensions) }, - { "leftMargin", leftMargin }, - { "text", _typedCharacters }, - { "lineHeight", (_textDisplay.lineHeight * sensorToWorldScale) } - }; - - overlays.editOverlay(_textDisplay.overlayID, textDisplayProperties); + EntityItemProperties properties; + properties.setDimensions(scaledDimensions); + properties.setLeftMargin(leftMargin); + properties.setText(_typedCharacters); + properties.setLineHeight(_textDisplay.lineHeight * sensorToWorldScale); + entityScriptingInterface->editEntity(_textDisplay.entityID, properties); } void Keyboard::raiseKeyboardAnchor(bool raise) const { - Overlays& overlays = qApp->getOverlays(); - OverlayID anchorOverlayID = _anchor.overlayID; - auto anchorOverlay = std::dynamic_pointer_cast(overlays.getOverlay(anchorOverlayID)); - if (anchorOverlay) { + auto entityScriptingInterface = DependencyManager::get(); + + EntityItemProperties properties; + properties.setVisible(raise); + + entityScriptingInterface->editEntity(_textDisplay.entityID, properties); + entityScriptingInterface->editEntity(_backPlate.entityID, properties); + + if (_resetKeyboardPositionOnRaise) { std::pair keyboardLocation = calculateKeyboardPositionAndOrientation(); - if (_resetKeyboardPositionOnRaise) { - anchorOverlay->setWorldPosition(keyboardLocation.first); - anchorOverlay->setWorldOrientation(keyboardLocation.second); - } - anchorOverlay->setVisible(raise); - - QVariantMap textDisplayProperties { - { "visible", raise } - }; - - overlays.editOverlay(_textDisplay.overlayID, textDisplayProperties); - - auto backPlateOverlay = std::dynamic_pointer_cast(overlays.getOverlay(_backPlate.overlayID)); - - if (backPlateOverlay) { - backPlateOverlay->setVisible(raise); - } + properties.setPosition(keyboardLocation.first); + properties.setRotation(keyboardLocation.second); } + entityScriptingInterface->editEntity(_anchor.entityID, properties); } void Keyboard::scaleKeyboard(float sensorToWorldScale) { - Overlays& overlays = qApp->getOverlays(); + auto entityScriptingInterface = DependencyManager::get(); - glm::vec3 scaledDimensions = _anchor.originalDimensions * sensorToWorldScale; - auto volume3DOverlay = std::dynamic_pointer_cast(overlays.getOverlay(_anchor.overlayID)); - - if (volume3DOverlay) { - volume3DOverlay->setDimensions(scaledDimensions); + { + EntityItemProperties properties; + properties.setDimensions(_anchor.originalDimensions * sensorToWorldScale); + entityScriptingInterface->editEntity(_anchor.entityID, properties); } - for (auto& keyboardLayer: _keyboardLayers) { + for (auto& keyboardLayer : _keyboardLayers) { for (auto iter = keyboardLayer.begin(); iter != keyboardLayer.end(); iter++) { iter.value().scaleKey(sensorToWorldScale); } } + { + EntityItemProperties properties; + properties.setLocalPosition(_textDisplay.localPosition * sensorToWorldScale); + properties.setDimensions(_textDisplay.dimensions * sensorToWorldScale); + properties.setLineHeight(_textDisplay.lineHeight * sensorToWorldScale); + entityScriptingInterface->editEntity(_textDisplay.entityID, properties); + } - - glm::vec3 scaledLocalPosition = _textDisplay.localPosition * sensorToWorldScale; - glm::vec3 textDisplayScaledDimensions = _textDisplay.dimensions * sensorToWorldScale; - - QVariantMap textDisplayProperties { - { "localPosition", vec3toVariant(scaledLocalPosition) }, - { "dimensions", vec3toVariant(textDisplayScaledDimensions) }, - { "lineHeight", (_textDisplay.lineHeight * sensorToWorldScale) } - }; - - overlays.editOverlay(_textDisplay.overlayID, textDisplayProperties); - - - glm::vec3 backPlateScaledDimensions = _backPlate.dimensions * sensorToWorldScale; - glm::vec3 backPlateScaledLocalPosition = _backPlate.localPosition * sensorToWorldScale; - - QVariantMap backPlateProperties { - { "localPosition", vec3toVariant(backPlateScaledLocalPosition) }, - { "dimensions", vec3toVariant(backPlateScaledDimensions) } - }; - - overlays.editOverlay(_backPlate.overlayID, backPlateProperties); + { + EntityItemProperties properties; + properties.setLocalPosition(_backPlate.localPosition * sensorToWorldScale); + properties.setDimensions(_backPlate.dimensions * sensorToWorldScale); + entityScriptingInterface->editEntity(_backPlate.entityID, properties); + } } void Keyboard::startLayerSwitchTimer() { @@ -419,13 +384,12 @@ void Keyboard::raiseKeyboard(bool raise) const { if (_keyboardLayers.empty()) { return; } - Overlays& overlays = qApp->getOverlays(); + const auto& keyboardLayer = _keyboardLayers[_layerIndex]; + EntityItemProperties properties; + properties.setVisible(raise); for (auto iter = keyboardLayer.begin(); iter != keyboardLayer.end(); iter++) { - auto base3DOverlay = std::dynamic_pointer_cast(overlays.getOverlay(iter.key())); - if (base3DOverlay) { - base3DOverlay->setVisible(raise); - } + DependencyManager::get()->editEntity(iter.key(), properties); } } @@ -465,19 +429,15 @@ bool Keyboard::getPreferMalletsOverLasers() const { } void Keyboard::switchToLayer(int layerIndex) { + auto entityScriptingInterface = DependencyManager::get(); if (layerIndex >= 0 && layerIndex < (int)_keyboardLayers.size()) { - Overlays& overlays = qApp->getOverlays(); + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_POSITION; + desiredProperties += PROP_ROTATION; + auto oldProperties = entityScriptingInterface->getEntityProperties(_anchor.entityID, desiredProperties); - OverlayID currentAnchorOverlayID = _anchor.overlayID; - - glm::vec3 currentOverlayPosition; - glm::quat currentOverlayOrientation; - - auto currentAnchorOverlay = std::dynamic_pointer_cast(overlays.getOverlay(currentAnchorOverlayID)); - if (currentAnchorOverlay) { - currentOverlayPosition = currentAnchorOverlay->getWorldPosition(); - currentOverlayOrientation = currentAnchorOverlay->getWorldOrientation(); - } + glm::vec3 currentPosition = oldProperties.getPosition(); + glm::quat currentOrientation = oldProperties.getRotation(); raiseKeyboardAnchor(false); raiseKeyboard(false); @@ -487,19 +447,17 @@ void Keyboard::switchToLayer(int layerIndex) { raiseKeyboardAnchor(true); raiseKeyboard(true); - OverlayID newAnchorOverlayID = _anchor.overlayID; - auto newAnchorOverlay = std::dynamic_pointer_cast(overlays.getOverlay(newAnchorOverlayID)); - if (newAnchorOverlay) { - newAnchorOverlay->setWorldPosition(currentOverlayPosition); - newAnchorOverlay->setWorldOrientation(currentOverlayOrientation); - } + EntityItemProperties properties; + properties.setPosition(currentPosition); + properties.setRotation(currentOrientation); + entityScriptingInterface->editEntity(_anchor.entityID, properties); startLayerSwitchTimer(); } } -bool Keyboard::shouldProcessOverlayAndPointerEvent(const PointerEvent& event, const OverlayID& overlayID) const { - return (shouldProcessPointerEvent(event) && shouldProcessOverlay(overlayID)); +bool Keyboard::shouldProcessEntityAndPointerEvent(const PointerEvent& event, const QUuid& id) const { + return (shouldProcessPointerEvent(event) && shouldProcessEntity(id)); } bool Keyboard::shouldProcessPointerEvent(const PointerEvent& event) const { @@ -510,14 +468,14 @@ bool Keyboard::shouldProcessPointerEvent(const PointerEvent& event) const { return ((isStylusEvent && preferMalletsOverLasers) || (isLaserEvent && !preferMalletsOverLasers)); } -void Keyboard::handleTriggerBegin(const OverlayID& overlayID, const PointerEvent& event) { +void Keyboard::handleTriggerBegin(const QUuid& id, const PointerEvent& event) { auto buttonType = event.getButton(); - if (!shouldProcessOverlayAndPointerEvent(event, overlayID) || buttonType != PointerEvent::PrimaryButton) { + if (!shouldProcessEntityAndPointerEvent(event, id) || buttonType != PointerEvent::PrimaryButton) { return; } auto& keyboardLayer = _keyboardLayers[_layerIndex]; - auto search = keyboardLayer.find(overlayID); + auto search = keyboardLayer.find(id); if (search == keyboardLayer.end()) { return; @@ -533,13 +491,9 @@ void Keyboard::handleTriggerBegin(const OverlayID& overlayID, const PointerEvent auto userInputMapper = DependencyManager::get(); userInputMapper->triggerHapticPulse(PULSE_STRENGTH, PULSE_DURATION, handIndex); - Overlays& overlays = qApp->getOverlays(); - auto base3DOverlay = std::dynamic_pointer_cast(overlays.getOverlay(overlayID)); - - glm::vec3 keyWorldPosition; - if (base3DOverlay) { - keyWorldPosition = base3DOverlay->getWorldPosition(); - } + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_POSITION; + glm::vec3 keyWorldPosition = DependencyManager::get()->getEntityProperties(id, desiredProperties).getPosition(); AudioInjectorOptions audioOptions; audioOptions.localOnly = true; @@ -601,7 +555,7 @@ void Keyboard::handleTriggerBegin(const OverlayID& overlayID, const PointerEvent key.startTimer(KEY_PRESS_TIMEOUT_MS); } auto selection = DependencyManager::get(); - selection->addToSelectedItemsList(KEY_PRESSED_HIGHLIGHT, "overlay", overlayID); + selection->addToSelectedItemsList(KEY_PRESSED_HIGHLIGHT, "entity", id); } } @@ -617,25 +571,23 @@ void Keyboard::setRightHandLaser(unsigned int rightHandLaser) { }); } -void Keyboard::handleTriggerEnd(const OverlayID& overlayID, const PointerEvent& event) { - if (!shouldProcessOverlayAndPointerEvent(event, overlayID)) { +void Keyboard::handleTriggerEnd(const QUuid& id, const PointerEvent& event) { + if (!shouldProcessEntityAndPointerEvent(event, id)) { return; } auto& keyboardLayer = _keyboardLayers[_layerIndex]; - auto search = keyboardLayer.find(overlayID); + auto search = keyboardLayer.find(id); if (search == keyboardLayer.end()) { return; } - Key& key = search.value();; - Overlays& overlays = qApp->getOverlays(); - auto base3DOverlay = std::dynamic_pointer_cast(overlays.getOverlay(overlayID)); + Key& key = search.value(); - if (base3DOverlay) { - base3DOverlay->setLocalPosition(key.getCurrentLocalPosition()); - } + EntityItemProperties properties; + properties.setLocalPosition(key.getCurrentLocalPosition()); + DependencyManager::get()->editEntity(id, properties); key.setIsPressed(false); if (key.timerFinished() && getPreferMalletsOverLasers()) { @@ -643,78 +595,79 @@ void Keyboard::handleTriggerEnd(const OverlayID& overlayID, const PointerEvent& } auto selection = DependencyManager::get(); - selection->removeFromSelectedItemsList(KEY_PRESSED_HIGHLIGHT, "overlay", overlayID); + selection->removeFromSelectedItemsList(KEY_PRESSED_HIGHLIGHT, "entity", id); } -void Keyboard::handleTriggerContinue(const OverlayID& overlayID, const PointerEvent& event) { - if (!shouldProcessOverlayAndPointerEvent(event, overlayID)) { +void Keyboard::handleTriggerContinue(const QUuid& id, const PointerEvent& event) { + if (!shouldProcessEntityAndPointerEvent(event, id)) { return; } auto& keyboardLayer = _keyboardLayers[_layerIndex]; - auto search = keyboardLayer.find(overlayID); + auto search = keyboardLayer.find(id); if (search == keyboardLayer.end()) { return; } Key& key = search.value(); - Overlays& overlays = qApp->getOverlays(); - if (!key.isPressed() && getPreferMalletsOverLasers()) { - auto base3DOverlay = std::dynamic_pointer_cast(overlays.getOverlay(overlayID)); + unsigned int pointerID = event.getID(); + auto pointerManager = DependencyManager::get(); + auto pickResult = pointerManager->getPrevPickResult(pointerID); + auto stylusPickResult = std::dynamic_pointer_cast(pickResult); + float distance = stylusPickResult->distance; - if (base3DOverlay) { - unsigned int pointerID = event.getID(); - auto pointerManager = DependencyManager::get(); - auto pickResult = pointerManager->getPrevPickResult(pointerID); - auto stylusPickResult = std::dynamic_pointer_cast(pickResult); - float distance = stylusPickResult->distance; + static const float PENATRATION_THRESHOLD = 0.025f; + if (distance < PENATRATION_THRESHOLD) { + static const float Z_OFFSET = 0.002f; - static const float PENATRATION_THRESHOLD = 0.025f; - if (distance < PENATRATION_THRESHOLD) { - static const float Z_OFFSET = 0.002f; - glm::quat overlayOrientation = base3DOverlay->getWorldOrientation(); - glm::vec3 overlayYAxis = overlayOrientation * Z_AXIS; - glm::vec3 overlayYOffset = overlayYAxis * Z_OFFSET; - glm::vec3 localPosition = key.getCurrentLocalPosition() - overlayYOffset; - base3DOverlay->setLocalPosition(localPosition); - key.setIsPressed(true); - } + auto entityScriptingInterface = DependencyManager::get(); + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_ROTATION; + glm::quat orientation = entityScriptingInterface->getEntityProperties(id, desiredProperties).getRotation(); + glm::vec3 yAxis = orientation * Z_AXIS; + glm::vec3 yOffset = yAxis * Z_OFFSET; + glm::vec3 localPosition = key.getCurrentLocalPosition() - yOffset; + + EntityItemProperties properties; + properties.setLocalPosition(localPosition); + entityScriptingInterface->editEntity(id, properties); + key.setIsPressed(true); } } } -void Keyboard::handleHoverBegin(const OverlayID& overlayID, const PointerEvent& event) { - if (!shouldProcessOverlayAndPointerEvent(event, overlayID)) { +void Keyboard::handleHoverBegin(const QUuid& id, const PointerEvent& event) { + if (!shouldProcessEntityAndPointerEvent(event, id)) { return; } auto& keyboardLayer = _keyboardLayers[_layerIndex]; - auto search = keyboardLayer.find(overlayID); + auto search = keyboardLayer.find(id); if (search == keyboardLayer.end()) { return; } auto selection = DependencyManager::get(); - selection->addToSelectedItemsList(KEY_HOVER_HIGHLIGHT, "overlay", overlayID); + selection->addToSelectedItemsList(KEY_HOVER_HIGHLIGHT, "entity", id); } -void Keyboard::handleHoverEnd(const OverlayID& overlayID, const PointerEvent& event) { - if (!shouldProcessOverlayAndPointerEvent(event, overlayID)) { +void Keyboard::handleHoverEnd(const QUuid& id, const PointerEvent& event) { + if (!shouldProcessEntityAndPointerEvent(event, id)) { return; } auto& keyboardLayer = _keyboardLayers[_layerIndex]; - auto search = keyboardLayer.find(overlayID); + auto search = keyboardLayer.find(id); if (search == keyboardLayer.end()) { return; } auto selection = DependencyManager::get(); - selection->removeFromSelectedItemsList(KEY_HOVER_HIGHLIGHT, "overlay", overlayID); + selection->removeFromSelectedItemsList(KEY_HOVER_HIGHLIGHT, "entity", id); } void Keyboard::disableStylus() { @@ -752,7 +705,6 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { } clearKeyboardKeys(); - Overlays& overlays = qApp->getOverlays(); auto requestData = request->getData(); QVector includeItems; @@ -776,54 +728,58 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { return; } - QVariantMap anchorProperties { - { "name", "KeyboardAnchor"}, - { "isSolid", true }, - { "visible", false }, - { "grabbable", true }, - { "ignorePickIntersection", false }, - { "dimensions", anchorObject["dimensions"].toVariant() }, - { "position", anchorObject["position"].toVariant() }, - { "orientation", anchorObject["rotation"].toVariant() } - }; + auto entityScriptingInterface = DependencyManager::get(); + { + glm::vec3 dimensions = vec3FromVariant(anchorObject["dimensions"].toVariant()); - glm::vec3 dimensions = vec3FromVariant(anchorObject["dimensions"].toVariant()); + EntityItemProperties properties; + properties.setType(EntityTypes::Box); + properties.setName("KeyboardAnchor"); + properties.setVisible(false); + properties.getGrab().setGrabbable(true); + properties.setIgnorePickIntersection(false); + properties.setDimensions(dimensions); + properties.setPosition(vec3FromVariant(anchorObject["position"].toVariant())); + properties.setRotation(quatFromVariant(anchorObject["rotation"].toVariant())); - Anchor anchor; - anchor.overlayID = overlays.addOverlay("cube", anchorProperties); - anchor.originalDimensions = dimensions; - _anchor = anchor; + Anchor anchor; + anchor.entityID = entityScriptingInterface->addEntity(properties, "local"); + anchor.originalDimensions = dimensions; + _anchor = anchor; + } - QJsonObject backPlateObject = jsonObject["backPlate"].toObject(); + { + QJsonObject backPlateObject = jsonObject["backPlate"].toObject(); + glm::vec3 dimensions = vec3FromVariant(backPlateObject["dimensions"].toVariant()); - QVariantMap backPlateProperties { - { "name", "backPlate"}, - { "isSolid", true }, - { "visible", true }, - { "grabbable", false }, - { "alpha", 0.0 }, - { "ignoreRayIntersection", false}, - { "dimensions", backPlateObject["dimensions"].toVariant() }, - { "position", backPlateObject["position"].toVariant() }, - { "orientation", backPlateObject["rotation"].toVariant() }, - { "parentID", _anchor.overlayID } - }; + EntityItemProperties properties; + properties.setType(EntityTypes::Box); + properties.setName("BackPlate"); + properties.setVisible(true); + properties.getGrab().setGrabbable(false); + properties.setAlpha(0.0f); + properties.setIgnorePickIntersection(false); + properties.setDimensions(dimensions); + properties.setPosition(vec3FromVariant(backPlateObject["position"].toVariant())); + properties.setRotation(quatFromVariant(backPlateObject["rotation"].toVariant())); + properties.setParentID(_anchor.entityID); - BackPlate backPlate; - backPlate.overlayID = overlays.addOverlay("cube", backPlateProperties); - backPlate.dimensions = vec3FromVariant(backPlateObject["dimensions"].toVariant()); - backPlate.localPosition = vec3FromVariant(overlays.getProperty(backPlate.overlayID, "localPosition").value); - _backPlate = backPlate; + BackPlate backPlate; + backPlate.entityID = entityScriptingInterface->addEntity(properties, "local"); + backPlate.dimensions = dimensions; + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_LOCAL_POSITION; + backPlate.localPosition = entityScriptingInterface->getEntityProperties(backPlate.entityID, desiredProperties).getLocalPosition(); + _backPlate = backPlate; + } const QJsonArray& keyboardLayers = jsonObject["layers"].toArray(); int keyboardLayerCount = keyboardLayers.size(); _keyboardLayers.reserve(keyboardLayerCount); - - for (int keyboardLayerIndex = 0; keyboardLayerIndex < keyboardLayerCount; keyboardLayerIndex++) { const QJsonValue& keyboardLayer = keyboardLayers[keyboardLayerIndex].toArray(); - QHash keyboardLayerKeys; + QHash keyboardLayerKeys; foreach (const QJsonValue& keyboardKeyValue, keyboardLayer.toArray()) { QVariantMap textureMap; @@ -841,21 +797,6 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { QString modelUrl = keyboardKeyValue["modelURL"].toString(); QString url = (useResourcePath ? (resourcePath + modelUrl) : modelUrl); - QVariantMap properties { - { "dimensions", keyboardKeyValue["dimensions"].toVariant() }, - { "position", keyboardKeyValue["position"].toVariant() }, - { "visible", false }, - { "isSolid", true }, - { "emissive", true }, - { "parentID", _anchor.overlayID }, - { "url", url }, - { "textures", textureMap }, - { "grabbable", false }, - { "localOrientation", keyboardKeyValue["localOrientation"].toVariant() } - }; - - OverlayID overlayID = overlays.addOverlay("model", properties); - QString keyType = keyboardKeyValue["type"].toString(); QString keyString = keyboardKeyValue["key"].toString(); @@ -869,48 +810,65 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { key.setSwitchToLayerIndex(switchToLayer); } } - key.setID(overlayID); + + EntityItemProperties properties; + properties.setType(EntityTypes::Model); + properties.setDimensions(vec3FromVariant(keyboardKeyValue["dimensions"].toVariant())); + properties.setPosition(vec3FromVariant(keyboardKeyValue["position"].toVariant())); + properties.setVisible(false); + properties.setEmissive(true); + properties.setParentID(_anchor.entityID); + properties.setModelURL(url); + properties.setTextures(QVariant(textureMap).toString()); + properties.getGrab().setGrabbable(false); + properties.setLocalRotation(quatFromVariant(keyboardKeyValue["localOrientation"].toVariant())); + QUuid id = entityScriptingInterface->addEntity(properties, "local"); + key.setID(id); key.setKeyString(keyString); key.saveDimensionsAndLocalPosition(); includeItems.append(key.getID()); _itemsToIgnore.append(key.getID()); - keyboardLayerKeys.insert(overlayID, key); + keyboardLayerKeys.insert(id, key); } _keyboardLayers.push_back(keyboardLayerKeys); } - TextDisplay textDisplay; - QJsonObject displayTextObject = jsonObject["textDisplay"].toObject(); + { + QJsonObject displayTextObject = jsonObject["textDisplay"].toObject(); + glm::vec3 dimensions = vec3FromVariant(displayTextObject["dimensions"].toVariant()); + glm::vec3 localPosition = vec3FromVariant(displayTextObject["localPosition"].toVariant()); + float lineHeight = (float)displayTextObject["lineHeight"].toDouble(); - QVariantMap displayTextProperties { - { "dimensions", displayTextObject["dimensions"].toVariant() }, - { "localPosition", displayTextObject["localPosition"].toVariant() }, - { "localOrientation", displayTextObject["localOrientation"].toVariant() }, - { "leftMargin", displayTextObject["leftMargin"].toVariant() }, - { "rightMargin", displayTextObject["rightMargin"].toVariant() }, - { "topMargin", displayTextObject["topMargin"].toVariant() }, - { "bottomMargin", displayTextObject["bottomMargin"].toVariant() }, - { "lineHeight", displayTextObject["lineHeight"].toVariant() }, - { "visible", false }, - { "emissive", true }, - { "grabbable", false }, - { "text", ""}, - { "parentID", _anchor.overlayID } - }; + EntityItemProperties properties; + properties.setType(EntityTypes::Text); + properties.setDimensions(dimensions); + properties.setLocalPosition(localPosition); + properties.setLocalRotation(quatFromVariant(displayTextObject["localOrientation"].toVariant())); + properties.setLeftMargin((float)displayTextObject["leftMargin"].toDouble()); + properties.setRightMargin((float)displayTextObject["rightMargin"].toDouble()); + properties.setTopMargin((float)displayTextObject["topMargin"].toDouble()); + properties.setBottomMargin((float)displayTextObject["bottomMargin"].toDouble()); + properties.setLineHeight((float)displayTextObject["lineHeight"].toDouble()); + properties.setVisible(false); + properties.setEmissive(true); + properties.getGrab().setGrabbable(false); + properties.setText(""); + properties.setParentID(_anchor.entityID); - textDisplay.overlayID = overlays.addOverlay("text3d", displayTextProperties); - textDisplay.localPosition = vec3FromVariant(displayTextObject["localPosition"].toVariant()); - textDisplay.dimensions = vec3FromVariant(displayTextObject["dimensions"].toVariant()); - textDisplay.lineHeight = (float) displayTextObject["lineHeight"].toDouble(); - - _textDisplay = textDisplay; + TextDisplay textDisplay; + textDisplay.entityID = entityScriptingInterface->addEntity(properties, "local"); + textDisplay.localPosition = localPosition; + textDisplay.dimensions = dimensions; + textDisplay.lineHeight = lineHeight; + _textDisplay = textDisplay; + } _ignoreItemsLock.withWriteLock([&] { - _itemsToIgnore.append(_textDisplay.overlayID); - _itemsToIgnore.append(_anchor.overlayID); + _itemsToIgnore.append(_textDisplay.entityID); + _itemsToIgnore.append(_anchor.entityID); }); _layerIndex = 0; auto pointerManager = DependencyManager::get(); @@ -922,34 +880,33 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { } -OverlayID Keyboard::getAnchorID() { - return _ignoreItemsLock.resultWithReadLock([&] { - return _anchor.overlayID; +QUuid Keyboard::getAnchorID() { + return _ignoreItemsLock.resultWithReadLock([&] { + return _anchor.entityID; }); } -bool Keyboard::shouldProcessOverlay(const OverlayID& overlayID) const { - return (!_keyboardLayers.empty() && isLayerSwitchTimerFinished() && overlayID != _backPlate.overlayID); +bool Keyboard::shouldProcessEntity(const QUuid& id) const { + return (!_keyboardLayers.empty() && isLayerSwitchTimerFinished() && id != _backPlate.entityID); } -QVector Keyboard::getKeysID() { - return _ignoreItemsLock.resultWithReadLock>([&] { +QVector Keyboard::getKeysID() { + return _ignoreItemsLock.resultWithReadLock>([&] { return _itemsToIgnore; }); } void Keyboard::clearKeyboardKeys() { - Overlays& overlays = qApp->getOverlays(); - + auto entityScriptingInterface = DependencyManager::get(); for (const auto& keyboardLayer: _keyboardLayers) { for (auto iter = keyboardLayer.begin(); iter != keyboardLayer.end(); iter++) { - overlays.deleteOverlay(iter.key()); + entityScriptingInterface->deleteEntity(iter.key()); } } - overlays.deleteOverlay(_anchor.overlayID); - overlays.deleteOverlay(_textDisplay.overlayID); - overlays.deleteOverlay(_backPlate.overlayID); + entityScriptingInterface->deleteEntity(_anchor.entityID); + entityScriptingInterface->deleteEntity(_textDisplay.entityID); + entityScriptingInterface->deleteEntity(_backPlate.entityID); _keyboardLayers.clear(); @@ -989,8 +946,8 @@ void Keyboard::disableRightMallet() { pointerManager->disablePointer(_rightHandStylus); } -bool Keyboard::containsID(OverlayID overlayID) const { +bool Keyboard::containsID(const QUuid& id) const { return resultWithReadLock([&] { - return _itemsToIgnore.contains(overlayID) || _backPlate.overlayID == overlayID; + return _itemsToIgnore.contains(id) || _backPlate.entityID == id; }); } diff --git a/interface/src/ui/Keyboard.h b/interface/src/ui/Keyboard.h index bcb6ef1a22..dcb9deac4e 100644 --- a/interface/src/ui/Keyboard.h +++ b/interface/src/ui/Keyboard.h @@ -25,8 +25,6 @@ #include #include -#include "ui/overlays/Overlay.h" - class PointerEvent; @@ -47,8 +45,8 @@ public: static Key::Type getKeyTypeFromString(const QString& keyTypeString); - OverlayID getID() const { return _keyID; } - void setID(OverlayID overlayID) { _keyID = overlayID; } + QUuid getID() const { return _keyID; } + void setID(const QUuid& id) { _keyID = id; } void startTimer(int time); bool timerFinished(); @@ -77,7 +75,7 @@ private: int _switchToLayer { 0 }; bool _pressed { false }; - OverlayID _keyID; + QUuid _keyID; QString _keyString; glm::vec3 _originalLocalPosition; @@ -111,35 +109,35 @@ public: bool getUse3DKeyboard() const; void setUse3DKeyboard(bool use); - bool containsID(OverlayID overlayID) const; + bool containsID(const QUuid& id) const; void loadKeyboardFile(const QString& keyboardFile); - QVector getKeysID(); - OverlayID getAnchorID(); + QVector getKeysID(); + QUuid getAnchorID(); public slots: - void handleTriggerBegin(const OverlayID& overlayID, const PointerEvent& event); - void handleTriggerEnd(const OverlayID& overlayID, const PointerEvent& event); - void handleTriggerContinue(const OverlayID& overlayID, const PointerEvent& event); - void handleHoverBegin(const OverlayID& overlayID, const PointerEvent& event); - void handleHoverEnd(const OverlayID& overlayID, const PointerEvent& event); + void handleTriggerBegin(const QUuid& id, const PointerEvent& event); + void handleTriggerEnd(const QUuid& id, const PointerEvent& event); + void handleTriggerContinue(const QUuid& id, const PointerEvent& event); + void handleHoverBegin(const QUuid& id, const PointerEvent& event); + void handleHoverEnd(const QUuid& id, const PointerEvent& event); void scaleKeyboard(float sensorToWorldScale); private: struct Anchor { - OverlayID overlayID; + QUuid entityID; glm::vec3 originalDimensions; }; struct BackPlate { - OverlayID overlayID; + QUuid entityID; glm::vec3 dimensions; glm::vec3 localPosition; }; struct TextDisplay { float lineHeight; - OverlayID overlayID; + QUuid entityID; glm::vec3 localPosition; glm::vec3 dimensions; }; @@ -153,9 +151,9 @@ private: void clearKeyboardKeys(); void switchToLayer(int layerIndex); void updateTextDisplay(); - bool shouldProcessOverlayAndPointerEvent(const PointerEvent& event, const OverlayID& overlayID) const; + bool shouldProcessEntityAndPointerEvent(const PointerEvent& event, const QUuid& id) const; bool shouldProcessPointerEvent(const PointerEvent& event) const; - bool shouldProcessOverlay(const OverlayID& overlayID) const; + bool shouldProcessEntity(const QUuid& id) const; void startLayerSwitchTimer(); bool isLayerSwitchTimerFinished() const; @@ -184,8 +182,8 @@ private: Anchor _anchor; BackPlate _backPlate; - QVector _itemsToIgnore; - std::vector> _keyboardLayers; + QVector _itemsToIgnore; + std::vector> _keyboardLayers; }; #endif diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 2714d654bf..66773b638b 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -18,7 +18,7 @@ class QNetworkReply; -extern const QUrl OVERLAY_LOGIN_DIALOG; +extern const QUrl LOGIN_DIALOG; class LoginDialog : public OffscreenQmlDialog { Q_OBJECT diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index aecfdba3b8..5e6a9b116b 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -60,11 +60,12 @@ ContextOverlayInterface::ContextOverlayInterface() { QUuid tabletFrameID = _hmdScriptingInterface->getCurrentTabletFrameID(); auto myAvatar = DependencyManager::get()->getMyAvatar(); glm::quat cameraOrientation = qApp->getCamera().getOrientation(); - QVariantMap props; + + EntityItemProperties properties; float sensorToWorldScale = myAvatar->getSensorToWorldScale(); - props.insert("position", vec3toVariant(myAvatar->getEyePosition() + glm::quat(glm::radians(glm::vec3(0.0f, CONTEXT_OVERLAY_TABLET_OFFSET, 0.0f))) * ((CONTEXT_OVERLAY_TABLET_DISTANCE * sensorToWorldScale) * (cameraOrientation * Vectors::FRONT)))); - props.insert("orientation", quatToVariant(cameraOrientation * glm::quat(glm::radians(glm::vec3(0.0f, CONTEXT_OVERLAY_TABLET_ORIENTATION, 0.0f))))); - qApp->getOverlays().editOverlay(tabletFrameID, props); + properties.setPosition(myAvatar->getEyePosition() + glm::quat(glm::radians(glm::vec3(0.0f, CONTEXT_OVERLAY_TABLET_OFFSET, 0.0f))) * ((CONTEXT_OVERLAY_TABLET_DISTANCE * sensorToWorldScale) * (cameraOrientation * Vectors::FRONT))); + properties.setRotation(cameraOrientation * glm::quat(glm::radians(glm::vec3(0.0f, CONTEXT_OVERLAY_TABLET_ORIENTATION, 0.0f)))); + DependencyManager::get()->editEntity(tabletFrameID, properties); _contextOverlayJustClicked = false; } }); @@ -93,7 +94,6 @@ static const float CONTEXT_OVERLAY_HOVERED_ALPHA = 1.0f; static const float CONTEXT_OVERLAY_UNHOVERED_PULSEMIN = 0.6f; static const float CONTEXT_OVERLAY_UNHOVERED_PULSEMAX = 1.0f; static const float CONTEXT_OVERLAY_UNHOVERED_PULSEPERIOD = 1.0f; -static const float CONTEXT_OVERLAY_UNHOVERED_COLORPULSE = 1.0f; void ContextOverlayInterface::setEnabled(bool enabled) { _enabled = enabled; @@ -192,22 +192,28 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID& } // Finally, setup and draw the Context Overlay - if (_contextOverlayID == UNKNOWN_OVERLAY_ID || !qApp->getOverlays().isAddedOverlay(_contextOverlayID)) { - _contextOverlay = std::make_shared(); - _contextOverlay->setAlpha(CONTEXT_OVERLAY_UNHOVERED_ALPHA); - _contextOverlay->setPulseMin(CONTEXT_OVERLAY_UNHOVERED_PULSEMIN); - _contextOverlay->setPulseMax(CONTEXT_OVERLAY_UNHOVERED_PULSEMAX); - _contextOverlay->setColorPulse(CONTEXT_OVERLAY_UNHOVERED_COLORPULSE); - _contextOverlay->setIgnorePickIntersection(false); - _contextOverlay->setDrawInFront(true); - _contextOverlay->setURL(PathUtils::resourcesUrl() + "images/inspect-icon.png"); - _contextOverlay->setIsFacingAvatar(true); - _contextOverlayID = qApp->getOverlays().addOverlay(_contextOverlay); + auto entityScriptingInterface = DependencyManager::get(); + if (_contextOverlayID == UNKNOWN_ENTITY_ID || !entityScriptingInterface->isAddedEntity(_contextOverlayID)) { + EntityItemProperties properties; + properties.setType(EntityTypes::Image); + properties.setAlpha(CONTEXT_OVERLAY_UNHOVERED_ALPHA); + properties.getPulse().setMin(CONTEXT_OVERLAY_UNHOVERED_PULSEMIN); + properties.getPulse().setMax(CONTEXT_OVERLAY_UNHOVERED_PULSEMAX); + properties.getPulse().setColorMode(PulseMode::IN_PHASE); + properties.setIgnorePickIntersection(false); + properties.setRenderLayer(RenderLayer::FRONT); + properties.setImageURL(PathUtils::resourcesUrl() + "images/inspect-icon.png"); + properties.setBillboardMode(BillboardMode::FULL); + + _contextOverlayID = entityScriptingInterface->addEntity(properties, "local"); } - _contextOverlay->setWorldPosition(contextOverlayPosition); - _contextOverlay->setDimensions(contextOverlayDimensions); - _contextOverlay->setWorldOrientation(entityProperties.getRotation()); - _contextOverlay->setVisible(true); + + EntityItemProperties properties; + properties.setPosition(contextOverlayPosition); + properties.setDimensions(glm::vec3(contextOverlayDimensions, 0.01f)); + properties.setRotation(entityProperties.getRotation()); + properties.setVisible(true); + entityScriptingInterface->editEntity(_contextOverlayID, properties); return true; } @@ -227,15 +233,13 @@ bool ContextOverlayInterface::contextOverlayFilterPassed(const EntityItemID& ent } bool ContextOverlayInterface::destroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event) { - if (_contextOverlayID != UNKNOWN_OVERLAY_ID) { + if (_contextOverlayID != UNKNOWN_ENTITY_ID) { qCDebug(context_overlay) << "Destroying Context Overlay on top of entity with ID: " << entityItemID; disableEntityHighlight(entityItemID); setCurrentEntityWithContextOverlay(QUuid()); _entityMarketplaceID.clear(); - // Destroy the Context Overlay - qApp->getOverlays().deleteOverlay(_contextOverlayID); - _contextOverlay = NULL; - _contextOverlayID = UNKNOWN_OVERLAY_ID; + DependencyManager::get()->deleteEntity(_contextOverlayID); + _contextOverlayID = UNKNOWN_ENTITY_ID; return true; } return false; @@ -254,22 +258,26 @@ void ContextOverlayInterface::contextOverlays_mousePressOnOverlay(const OverlayI } void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event) { - if (_contextOverlayID != UNKNOWN_OVERLAY_ID && _contextOverlay) { + if (_contextOverlayID != UNKNOWN_ENTITY_ID) { qCDebug(context_overlay) << "Started hovering over Context Overlay. Overlay ID:" << overlayID; - _contextOverlay->setColor(CONTEXT_OVERLAY_COLOR); - _contextOverlay->setColorPulse(0.0f); // pulse off - _contextOverlay->setPulsePeriod(0.0f); // pulse off - _contextOverlay->setAlpha(CONTEXT_OVERLAY_HOVERED_ALPHA); + EntityItemProperties properties; + properties.setColor(CONTEXT_OVERLAY_COLOR); + properties.getPulse().setColorMode(PulseMode::NONE); + properties.getPulse().setPeriod(0.0f); + properties.setAlpha(CONTEXT_OVERLAY_HOVERED_ALPHA); + DependencyManager::get()->editEntity(_contextOverlayID, properties); } } void ContextOverlayInterface::contextOverlays_hoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event) { - if (_contextOverlayID != UNKNOWN_OVERLAY_ID && _contextOverlay) { + if (_contextOverlayID != UNKNOWN_ENTITY_ID) { qCDebug(context_overlay) << "Stopped hovering over Context Overlay. Overlay ID:" << overlayID; - _contextOverlay->setColor(CONTEXT_OVERLAY_COLOR); - _contextOverlay->setColorPulse(CONTEXT_OVERLAY_UNHOVERED_COLORPULSE); - _contextOverlay->setPulsePeriod(CONTEXT_OVERLAY_UNHOVERED_PULSEPERIOD); - _contextOverlay->setAlpha(CONTEXT_OVERLAY_UNHOVERED_ALPHA); + EntityItemProperties properties; + properties.setColor(CONTEXT_OVERLAY_COLOR); + properties.getPulse().setColorMode(PulseMode::IN_PHASE); + properties.getPulse().setPeriod(CONTEXT_OVERLAY_UNHOVERED_PULSEPERIOD); + properties.setAlpha(CONTEXT_OVERLAY_UNHOVERED_ALPHA); + DependencyManager::get()->editEntity(_contextOverlayID, properties); } } diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index 48b14e1a91..2c6607a664 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -22,8 +22,6 @@ #include "avatar/AvatarManager.h" #include "EntityScriptingInterface.h" -#include "ui/overlays/Image3DOverlay.h" -#include "ui/overlays/Overlays.h" #include "scripting/HMDScriptingInterface.h" #include "scripting/SelectionScriptingInterface.h" #include "scripting/WalletScriptingInterface.h" @@ -43,8 +41,7 @@ class ContextOverlayInterface : public QObject, public Dependency { QSharedPointer _hmdScriptingInterface; QSharedPointer _tabletScriptingInterface; QSharedPointer _selectionScriptingInterface; - OverlayID _contextOverlayID { UNKNOWN_OVERLAY_ID }; - std::shared_ptr _contextOverlay { nullptr }; + QUuid _contextOverlayID { UNKNOWN_ENTITY_ID }; public: ContextOverlayInterface(); Q_INVOKABLE QUuid getCurrentEntityWithContextOverlay() { return _currentEntityWithContextOverlay; } @@ -83,12 +80,12 @@ private: enum { MAX_SELECTION_COUNT = 16 }; - bool _verboseLogging{ true }; + bool _verboseLogging { true }; bool _enabled { true }; - EntityItemID _mouseDownEntity{}; + EntityItemID _mouseDownEntity; quint64 _mouseDownEntityTimestamp; - EntityItemID _currentEntityWithContextOverlay{}; - EntityItemID _lastInspectedEntity{}; + EntityItemID _currentEntityWithContextOverlay; + EntityItemID _lastInspectedEntity; QString _entityMarketplaceID; bool _contextOverlayJustClicked { false }; diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 1bf94adfa0..cf55c87114 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -215,37 +215,6 @@ void Overlay::removeFromScene(Overlay::Pointer overlay, const render::ScenePoint render::Item::clearID(_renderItemID); } -QScriptValue OverlayIDtoScriptValue(QScriptEngine* engine, const OverlayID& id) { - return quuidToScriptValue(engine, id); -} - -void OverlayIDfromScriptValue(const QScriptValue &object, OverlayID& id) { - quuidFromScriptValue(object, id); -} - -QVector qVectorOverlayIDFromScriptValue(const QScriptValue& array) { - if (!array.isArray()) { - return QVector(); - } - QVector newVector; - int length = array.property("length").toInteger(); - newVector.reserve(length); - for (int i = 0; i < length; i++) { - newVector << OverlayID(array.property(i).toString()); - } - return newVector; -} - -void Overlay::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) { - std::lock_guard lock(_materialsLock); - _materials[parentMaterialName].push(material); -} - -void Overlay::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) { - std::lock_guard lock(_materialsLock); - _materials[parentMaterialName].remove(material); -} - render::ItemKey Overlay::getKey() { auto builder = render::ItemKey::Builder().withTypeShape().withTypeMeta(); diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 8e430f7e85..068e1b7641 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -13,13 +13,6 @@ #include -class OverlayID : public QUuid { -public: - OverlayID() : QUuid() {} - OverlayID(QString v) : QUuid(v) {} - OverlayID(QUuid v) : QUuid(v) {} -}; - class Overlay : public QObject { Q_OBJECT @@ -32,8 +25,8 @@ public: Overlay(const Overlay* overlay); ~Overlay(); - virtual OverlayID getOverlayID() const { return _overlayID; } - virtual void setOverlayID(OverlayID overlayID) { _overlayID = overlayID; } + virtual QUuid getID() const { return _id; } + virtual void setID(const QUuid& id) { _id = id; } virtual void update(float deltatime) {} virtual void render(RenderArgs* args) = 0; @@ -51,7 +44,6 @@ public: // getters virtual QString getType() const = 0; - virtual bool is3D() const = 0; bool isLoaded() { return _isLoaded; } bool getVisible() const { return _visible; } virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; }; @@ -92,9 +84,6 @@ public: unsigned int getStackOrder() const { return _stackOrder; } void setStackOrder(unsigned int stackOrder) { _stackOrder = stackOrder; } - virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); - virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); - protected: float updatePulse(); @@ -121,11 +110,8 @@ protected: static const glm::u8vec3 DEFAULT_OVERLAY_COLOR; static const float DEFAULT_ALPHA; - std::unordered_map _materials; - std::mutex _materialsLock; - private: - OverlayID _overlayID; // only used for non-3d overlays + QUuid _id; }; namespace render { @@ -136,10 +122,4 @@ namespace render { template <> uint32_t metaFetchMetaSubItems(const Overlay::Pointer& overlay, ItemIDs& subItems); } -Q_DECLARE_METATYPE(OverlayID); -Q_DECLARE_METATYPE(QVector); -QScriptValue OverlayIDtoScriptValue(QScriptEngine* engine, const OverlayID& id); -void OverlayIDfromScriptValue(const QScriptValue& object, OverlayID& id); -QVector qVectorOverlayIDFromScriptValue(const QScriptValue& array); - #endif // hifi_Overlay_h diff --git a/interface/src/ui/overlays/OverlayTransformNode.cpp b/interface/src/ui/overlays/OverlayTransformNode.cpp deleted file mode 100644 index 817b6af305..0000000000 --- a/interface/src/ui/overlays/OverlayTransformNode.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// -// Created by Sabrina Shanman 9/5/2018 -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -#include "OverlayTransformNode.h" - -template<> -glm::vec3 BaseNestableTransformNode::getActualScale(const std::shared_ptr& nestablePointer) const { - return nestablePointer->getBounds().getScale(); -} \ No newline at end of file diff --git a/interface/src/ui/overlays/OverlayTransformNode.h b/interface/src/ui/overlays/OverlayTransformNode.h deleted file mode 100644 index 11c3415828..0000000000 --- a/interface/src/ui/overlays/OverlayTransformNode.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by Sabrina Shanman 9/5/2018 -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -#ifndef hifi_OverlayTransformNode_h -#define hifi_OverlayTransformNode_h - -#include "NestableTransformNode.h" - -#include "Base3DOverlay.h" - -// For 3D overlays only -class OverlayTransformNode : public BaseNestableTransformNode { -public: - OverlayTransformNode(std::weak_ptr spatiallyNestable, int jointIndex) : BaseNestableTransformNode(spatiallyNestable, jointIndex) {}; -}; - -#endif // hifi_OverlayTransformNode_h \ No newline at end of file diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index d39c847457..2a8812f69e 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -37,7 +37,7 @@ class PickRay; * @typedef {object} Overlays.RayToOverlayIntersectionResult * @property {boolean} intersects - true if the {@link PickRay} intersected with a 3D overlay, otherwise * false. - * @property {Uuid} overlayID - The UUID of the overlay that was intersected. + * @property {Uuid} overlayID - The UUID of the local entity that was intersected. * @property {number} distance - The distance from the {@link PickRay} origin to the intersection point. * @property {Vec3} surfaceNormal - The normal of the overlay surface at the intersection point. * @property {Vec3} intersection - The position of the intersection point. @@ -46,7 +46,7 @@ class PickRay; class RayToOverlayIntersectionResult { public: bool intersects { false }; - QUuid overlayID { UNKNOWN_OVERLAY_ID }; + QUuid overlayID; float distance { 0.0f }; BoxFace face { UNKNOWN_FACE }; glm::vec3 surfaceNormal; @@ -60,7 +60,7 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R class ParabolaToOverlayIntersectionResult { public: bool intersects { false }; - QUuid overlayID { UNKNOWN_OVERLAY_ID }; + QUuid overlayID; float distance { 0.0f }; float parabolicDistance { 0.0f }; BoxFace face { UNKNOWN_FACE }; @@ -715,8 +715,8 @@ private: PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, PointerEvent::EventType eventType); - QUuid _currentClickingOnOverlayID { UNKNOWN_OVERLAY_ID }; - QUuid _currentHoverOverOverlayID { UNKNOWN_OVERLAY_ID }; + QUuid _currentClickingOnOverlayID; + QUuid _currentHoverOverOverlayID; private slots: void mousePressPointerEvent(const QUuid& id, const PointerEvent& event); diff --git a/interface/src/ui/overlays/OverlaysPayload.cpp b/interface/src/ui/overlays/OverlaysPayload.cpp index 37fadef0b4..0d1bcdd071 100644 --- a/interface/src/ui/overlays/OverlaysPayload.cpp +++ b/interface/src/ui/overlays/OverlaysPayload.cpp @@ -8,27 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include - -#include -#include -#include -#include - -#include "Image3DOverlay.h" -#include "Circle3DOverlay.h" -#include "Cube3DOverlay.h" -#include "ImageOverlay.h" -#include "Line3DOverlay.h" -#include "ModelOverlay.h" -#include "Overlays.h" -#include "Rectangle3DOverlay.h" -#include "Sphere3DOverlay.h" -#include "Grid3DOverlay.h" -#include "TextOverlay.h" -#include "Text3DOverlay.h" - +#include "Overlay.h" namespace render { template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) { diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 17fed5ff54..20af206162 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1038,6 +1038,15 @@ bool EntityScriptingInterface::isLoaded(const QUuid& id) { return toReturn; } +bool EntityScriptingInterface::isAddedEntity(const QUuid& id) { + bool toReturn = false; + _entityTree->withReadLock([&] { + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(id); + toReturn = (bool)entity; + }); + return toReturn; +} + QSizeF EntityScriptingInterface::textSize(const QUuid& id, const QString& text) { return EntityTree::textSize(id, text); } diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 7b6a191e1e..0cdc71c8ff 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -1306,11 +1306,11 @@ public slots: /**jsdoc - * Get the IDs of entities, overlays, and avatars that are directly parented to an entity, overlay, or avatar model. Recurse on the IDs returned by the function to get all descendants of an entity, overlay, or avatar. + * Get the IDs of entities and avatars that are directly parented to an entity or avatar model. Recurse on the IDs returned by the function to get all descendants of an entity or avatar. * @function Entities.getChildrenIDs - * @param {Uuid} parentID - The ID of the entity, overlay, or avatar to get the children IDs of. - * @returns {Uuid[]} An array of entity, overlay, and avatar IDs that are parented directly to the parentID - * entity, overlay, or avatar. Does not include children's children, etc. The array is empty if no children can be found or + * @param {Uuid} parentID - The ID of the entity or avatar to get the children IDs of. + * @returns {Uuid[]} An array of entity and avatar IDs that are parented directly to the parentID + * entity or avatar. Does not include children's children, etc. The array is empty if no children can be found or * parentID cannot be found. * @example Report the children of an entity. * function createEntity(description, position, parent) { @@ -1336,12 +1336,12 @@ public slots: Q_INVOKABLE QVector getChildrenIDs(const QUuid& parentID); /**jsdoc - * Get the IDs of entities, overlays, and avatars that are directly parented to an entity, overlay, or avatar model's joint. + * Get the IDs of entities and avatars that are directly parented to an entity or avatar model's joint. * @function Entities.getChildrenIDsOfJoint - * @param {Uuid} parentID - The ID of the entity, overlay, or avatar to get the children IDs of. + * @param {Uuid} parentID - The ID of the entity or avatar to get the children IDs of. * @param {number} jointIndex - Integer number of the model joint to get the children IDs of. - * @returns {Uuid[]} An array of entity, overlay, and avatar IDs that are parented directly to the parentID - * entity, overlay, or avatar at the jointIndex joint. Does not include children's children, etc. The + * @returns {Uuid[]} An array of entity and avatar IDs that are parented directly to the parentID + * entity or avatar at the jointIndex joint. Does not include children's children, etc. The * array is empty if no children can be found or parentID cannot be found. * @example Report the children of your avatar's right hand. * function createEntity(description, position, parent) { @@ -1371,11 +1371,11 @@ public slots: Q_INVOKABLE QVector getChildrenIDsOfJoint(const QUuid& parentID, int jointIndex); /**jsdoc - * Check whether an entity or overlay has an entity as an ancestor (parent, parent's parent, etc.). + * Check whether an entity has an entity as an ancestor (parent, parent's parent, etc.). * @function Entities.isChildOfParent - * @param {Uuid} childID - The ID of the child entity or overlay to test for being a child, grandchild, etc. + * @param {Uuid} childID - The ID of the child entity to test for being a child, grandchild, etc. * @param {Uuid} parentID - The ID of the parent entity to test for being a parent, grandparent, etc. - * @returns {boolean} true if the childID entity or overlay has the parentID entity + * @returns {boolean} true if the childID entity has the parentID entity * as a parent or grandparent etc., otherwise false. * @example Check that a grandchild entity is a child of its grandparent. * function createEntity(description, position, parent) { @@ -1400,12 +1400,11 @@ public slots: Q_INVOKABLE bool isChildOfParent(const QUuid& childID, const QUuid& parentID); /**jsdoc - * Get the type — entity, overlay, or avatar — of an in-world item. + * Get the type — entity or avatar — of an in-world item. * @function Entities.getNestableType * @param {Uuid} entityID - The ID of the item to get the type of. - * @returns {string} The type of the item: "entity" if the item is an entity, "overlay" if the - * the item is an overlay, "avatar" if the item is an avatar; otherwise "unknown" if the item - * cannot be found. + * @returns {string} The type of the item: "entity" if the item is an entity, "avatar" + * if the item is an avatar; otherwise "unknown" if the item cannot be found. * @example Print some nestable types. * var entity = Entities.addEntity({ * type: "Sphere", diff --git a/libraries/entities/src/GrabPropertyGroup.h b/libraries/entities/src/GrabPropertyGroup.h index 33550fef3d..d76ac46a81 100644 --- a/libraries/entities/src/GrabPropertyGroup.h +++ b/libraries/entities/src/GrabPropertyGroup.h @@ -64,9 +64,9 @@ static const glm::vec3 INITIAL_EQUIPPABLE_INDICATOR_OFFSET { glm::vec3(0.0f) }; * @property {string} equippableIndicatorURL="" - If non-empty, this model will be used to indicate that an * entity is equippable, rather than the default. * @property {Vec3} equippableIndicatorScale=1,1,1 - If equippableIndicatorURL is non-empty, this controls the - scale of the displayed overlay. + scale of the displayed indicator. * @property {Vec3} equippableIndicatorOffset=0,0,0 - If equippableIndicatorURL is non-empty, this controls the - relative offset of the displayed overlay from the equippable entity. + relative offset of the displayed object from the equippable entity. */ diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index 67f79db6b7..aa8e954e0a 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -36,12 +36,12 @@ void GraphicsScriptingInterface::jsThrowError(const QString& error) { } } -bool GraphicsScriptingInterface::canUpdateModel(QUuid uuid, int meshIndex, int partNumber) { +bool GraphicsScriptingInterface::canUpdateModel(const QUuid& uuid, int meshIndex, int partNumber) { auto provider = getModelProvider(uuid); return provider && provider->canReplaceModelMeshPart(meshIndex, partNumber); } -bool GraphicsScriptingInterface::updateModel(QUuid uuid, const scriptable::ScriptableModelPointer& model) { +bool GraphicsScriptingInterface::updateModel(const QUuid& uuid, const scriptable::ScriptableModelPointer& model) { if (!model) { jsThrowError("null model argument"); } @@ -69,7 +69,7 @@ bool GraphicsScriptingInterface::updateModel(QUuid uuid, const scriptable::Scrip return provider->replaceScriptableModelMeshPart(base, -1, -1); } -scriptable::ModelProviderPointer GraphicsScriptingInterface::getModelProvider(QUuid uuid) { +scriptable::ModelProviderPointer GraphicsScriptingInterface::getModelProvider(const QUuid& uuid) { QString error; if (auto appProvider = DependencyManager::get()) { if (auto provider = appProvider->lookupModelProvider(uuid)) { @@ -107,7 +107,7 @@ scriptable::ScriptableModelPointer GraphicsScriptingInterface::newModel(const sc return modelWrapper; } -scriptable::ScriptableModelPointer GraphicsScriptingInterface::getModel(QUuid uuid) { +scriptable::ScriptableModelPointer GraphicsScriptingInterface::getModel(const QUuid& uuid) { QString error; bool success; QString providerType = "unknown"; diff --git a/libraries/pointers/src/Pick.h b/libraries/pointers/src/Pick.h index 2db8aa95f5..ecb6188a9a 100644 --- a/libraries/pointers/src/Pick.h +++ b/libraries/pointers/src/Pick.h @@ -23,6 +23,7 @@ enum IntersectionType { NONE = 0, ENTITY, + LOCAL_ENTITY, AVATAR, HUD }; @@ -175,7 +176,6 @@ public: virtual T getMathematicalPick() const = 0; virtual PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const = 0; virtual PickResultPointer getEntityIntersection(const T& pick) = 0; - virtual PickResultPointer getOverlayIntersection(const T& pick) = 0; virtual PickResultPointer getAvatarIntersection(const T& pick) = 0; virtual PickResultPointer getHUDIntersection(const T& pick) = 0; diff --git a/libraries/pointers/src/PickCacheOptimizer.h b/libraries/pointers/src/PickCacheOptimizer.h index e91283f02c..0bbdfea8e4 100644 --- a/libraries/pointers/src/PickCacheOptimizer.h +++ b/libraries/pointers/src/PickCacheOptimizer.h @@ -37,7 +37,7 @@ template class PickCacheOptimizer { public: - QVector4D update(std::unordered_map>& picks, uint32_t& nextToUpdate, uint64_t expiry, bool shouldPickHUD); + QVector3D update(std::unordered_map>& picks, uint32_t& nextToUpdate, uint64_t expiry, bool shouldPickHUD); protected: typedef std::unordered_map> PickCache; @@ -67,9 +67,9 @@ void PickCacheOptimizer::cacheResult(const bool needToCompareResults, const P } template -QVector4D PickCacheOptimizer::update(std::unordered_map>& picks, +QVector3D PickCacheOptimizer::update(std::unordered_map>& picks, uint32_t& nextToUpdate, uint64_t expiry, bool shouldPickHUD) { - QVector4D numIntersectionsComputed; + QVector3D numIntersectionsComputed; PickCache results; const uint32_t INVALID_PICK_ID = 0; auto itr = picks.begin(); @@ -88,7 +88,7 @@ QVector4D PickCacheOptimizer::update(std::unordered_mapisEnabled() || pick->getMaxDistance() < 0.0f || !mathematicalPick) { pick->setPickResult(res); } else { - if (pick->getFilter().doesPickDomainEntities() || pick->getFilter().doesPickAvatarEntities()) { + if (pick->getFilter().doesPickDomainEntities() || pick->getFilter().doesPickAvatarEntities() || pick->getFilter().doesPickLocalEntities()) { PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) { PickResultPointer entityRes = pick->getEntityIntersection(mathematicalPick); @@ -99,22 +99,11 @@ QVector4D PickCacheOptimizer::update(std::unordered_mapgetFilter().doesPickLocalEntities()) { - PickCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; - if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) { - PickResultPointer overlayRes = pick->getOverlayIntersection(mathematicalPick); - numIntersectionsComputed[1]++; - if (overlayRes) { - cacheResult(overlayRes->doesIntersect(), overlayRes, overlayKey, res, mathematicalPick, results, pick); - } - } - } - if (pick->getFilter().doesPickAvatars()) { PickCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) { PickResultPointer avatarRes = pick->getAvatarIntersection(mathematicalPick); - numIntersectionsComputed[2]++; + numIntersectionsComputed[1]++; if (avatarRes) { cacheResult(avatarRes->doesIntersect(), avatarRes, avatarKey, res, mathematicalPick, results, pick); } @@ -126,7 +115,7 @@ QVector4D PickCacheOptimizer::update(std::unordered_mapgetFilter().getHUDFlags(), QVector(), QVector() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) { PickResultPointer hudRes = pick->getHUDIntersection(mathematicalPick); - numIntersectionsComputed[3]++; + numIntersectionsComputed[2]++; if (hudRes) { cacheResult(true, hudRes, hudKey, res, mathematicalPick, results, pick); } diff --git a/libraries/pointers/src/Pointer.cpp b/libraries/pointers/src/Pointer.cpp index 26460cbdd7..c08a3c2be6 100644 --- a/libraries/pointers/src/Pointer.cpp +++ b/libraries/pointers/src/Pointer.cpp @@ -109,14 +109,14 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin if (_enabled && _hover && doHover && !_prevDoHover) { if (hoveredObject.type == ENTITY) { emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent); - } else if (hoveredObject.type == OVERLAY) { + } else if (hoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent); } else if (hoveredObject.type == HUD) { emit pointerManager->hoverBeginHUD(hoveredEvent); } } else if (_enabled && _hover && doHover) { - if (hoveredObject.type == OVERLAY) { - if (_prevHoveredObject.type == OVERLAY) { + if (hoveredObject.type == LOCAL_ENTITY) { + if (_prevHoveredObject.type == LOCAL_ENTITY) { if (hoveredObject.objectID == _prevHoveredObject.objectID) { emit pointerManager->hoverContinueOverlay(hoveredObject.objectID, hoveredEvent); } else { @@ -150,7 +150,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin } } else { emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent); - if (_prevHoveredObject.type == OVERLAY) { + if (_prevHoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == HUD) { emit pointerManager->hoverEndHUD(hoveredEvent); @@ -166,7 +166,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin emit pointerManager->hoverBeginHUD(hoveredEvent); if (_prevHoveredObject.type == ENTITY) { emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent); - } else if (_prevHoveredObject.type == OVERLAY) { + } else if (_prevHoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent); } } @@ -175,7 +175,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin if (hoveredObject.type == NONE) { if (_prevHoveredObject.type == ENTITY) { emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent); - } else if (_prevHoveredObject.type == OVERLAY) { + } else if (_prevHoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == HUD) { emit pointerManager->hoverEndHUD(hoveredEvent); @@ -191,7 +191,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin hoveredEvent.setShouldFocus(button == SHOULD_FOCUS_BUTTON); if (hoveredObject.type == ENTITY) { emit pointerManager->triggerBeginEntity(hoveredObject.objectID, hoveredEvent); - } else if (hoveredObject.type == OVERLAY) { + } else if (hoveredObject.type == LOCAL_ENTITY) { emit pointerManager->triggerBeginOverlay(hoveredObject.objectID, hoveredEvent); } else if (hoveredObject.type == HUD) { emit pointerManager->triggerBeginHUD(hoveredEvent); @@ -207,7 +207,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin triggeredEvent.setButton(chooseButton(button)); if (_triggeredObjects[button].type == ENTITY) { emit pointerManager->triggerContinueEntity(_triggeredObjects[button].objectID, triggeredEvent); - } else if (_triggeredObjects[button].type == OVERLAY) { + } else if (_triggeredObjects[button].type == LOCAL_ENTITY) { emit pointerManager->triggerContinueOverlay(_triggeredObjects[button].objectID, triggeredEvent); } else if (_triggeredObjects[button].type == HUD) { emit pointerManager->triggerContinueHUD(triggeredEvent); @@ -222,7 +222,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin triggeredEvent.setButton(chooseButton(button)); if (_triggeredObjects[button].type == ENTITY) { emit pointerManager->triggerEndEntity(_triggeredObjects[button].objectID, triggeredEvent); - } else if (_triggeredObjects[button].type == OVERLAY) { + } else if (_triggeredObjects[button].type == LOCAL_ENTITY) { emit pointerManager->triggerEndOverlay(_triggeredObjects[button].objectID, triggeredEvent); } else if (_triggeredObjects[button].type == HUD) { emit pointerManager->triggerEndHUD(triggeredEvent); @@ -234,7 +234,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin if (_hover && ((!_enabled && _prevEnabled) || (!doHover && _prevDoHover))) { if (_prevHoveredObject.type == ENTITY) { emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent); - } else if (_prevHoveredObject.type == OVERLAY) { + } else if (_prevHoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == HUD) { emit pointerManager->hoverEndHUD(hoveredEvent); diff --git a/libraries/pointers/src/Pointer.h b/libraries/pointers/src/Pointer.h index 173163374f..28d7e42e8f 100644 --- a/libraries/pointers/src/Pointer.h +++ b/libraries/pointers/src/Pointer.h @@ -62,7 +62,7 @@ public: // Pointers can choose to implement these virtual void setLength(float length) {} - virtual void setLockEndUUID(const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) {} + virtual void setLockEndUUID(const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) {} void update(unsigned int pointerID); virtual void updateVisuals(const PickResultPointer& pickResult) = 0; diff --git a/libraries/pointers/src/PointerManager.cpp b/libraries/pointers/src/PointerManager.cpp index 72e4b417cd..ca8dfb3f26 100644 --- a/libraries/pointers/src/PointerManager.cpp +++ b/libraries/pointers/src/PointerManager.cpp @@ -124,10 +124,10 @@ void PointerManager::setLength(unsigned int uid, float length) const { } } -void PointerManager::setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat) const { +void PointerManager::setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat) const { auto pointer = find(uid); if (pointer) { - pointer->setLockEndUUID(objectID, isOverlay, offsetMat); + pointer->setLockEndUUID(objectID, isAvatar, offsetMat); } } diff --git a/libraries/pointers/src/PointerManager.h b/libraries/pointers/src/PointerManager.h index 2d0b2a107e..6c1581b09b 100644 --- a/libraries/pointers/src/PointerManager.h +++ b/libraries/pointers/src/PointerManager.h @@ -37,7 +37,7 @@ public: void setIncludeItems(unsigned int uid, const QVector& includeEntities) const; void setLength(unsigned int uid, float length) const; - void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const; + void setLockEndUUID(unsigned int uid, const QUuid& objectID, bool isAvatar, const glm::mat4& offsetMat = glm::mat4()) const; void update(); diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 40724cbf5a..64037d64b6 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -45,13 +45,13 @@ void EndGPURangeTimer::run(const render::RenderContextPointer& renderContext, co config->setGPUBatchRunTime(timer->getGPUAverage(), timer->getBatchAverage()); } -DrawOverlay3D::DrawOverlay3D(bool opaque) : +DrawLayered3D::DrawLayered3D(bool opaque) : _shapePlumber(std::make_shared()), _opaquePass(opaque) { initForwardPipelines(*_shapePlumber); } -void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs& inputs) { +void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& inputs) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); @@ -70,7 +70,7 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs& // Needs to be distinct from the other batch because using the clear call // while stereo is enabled triggers a warning if (_opaquePass) { - gpu::doInBatch("DrawOverlay3D::run::clear", args->_context, [&](gpu::Batch& batch) { + gpu::doInBatch("DrawLayered3D::run::clear", args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); batch.clearFramebuffer(gpu::Framebuffer::BUFFER_DEPTH, glm::vec4(), 1.f, 0, false); }); @@ -78,7 +78,7 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs& if (!inItems.empty()) { // Render the items - gpu::doInBatch("DrawOverlay3D::main", args->_context, [&](gpu::Batch& batch) { + gpu::doInBatch("DrawLayered3D::main", args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index 29f195ffff..4f8f53257d 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -40,7 +40,7 @@ public: protected: }; -class DrawOverlay3DConfig : public render::Job::Config { +class DrawLayered3DConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) @@ -58,13 +58,13 @@ protected: int numDrawn{ 0 }; }; -class DrawOverlay3D { +class DrawLayered3D { public: using Inputs = render::VaryingSet3; - using Config = DrawOverlay3DConfig; - using JobModel = render::Job::ModelI; + using Config = DrawLayered3DConfig; + using JobModel = render::Job::ModelI; - DrawOverlay3D(bool opaque); + DrawLayered3D(bool opaque); void configure(const Config& config) { _maxDrawn = config.maxDrawn; } void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index a685f3998e..673a165105 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -116,13 +116,13 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto& items = fetchedItems.get0(); - // Extract opaques / transparents / lights / metas / overlays / background + // Extract opaques / transparents / lights / metas / layered / background const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; - const auto& overlaysInFrontOpaque = items[RenderFetchCullSortTask::LAYER_FRONT_OPAQUE_SHAPE]; - const auto& overlaysInFrontTransparent = items[RenderFetchCullSortTask::LAYER_FRONT_TRANSPARENT_SHAPE]; - const auto& overlaysHUDOpaque = items[RenderFetchCullSortTask::LAYER_HUD_OPAQUE_SHAPE]; - const auto& overlaysHUDTransparent = items[RenderFetchCullSortTask::LAYER_HUD_TRANSPARENT_SHAPE]; + const auto& inFrontOpaque = items[RenderFetchCullSortTask::LAYER_FRONT_OPAQUE_SHAPE]; + const auto& inFrontTransparent = items[RenderFetchCullSortTask::LAYER_FRONT_TRANSPARENT_SHAPE]; + const auto& hudOpaque = items[RenderFetchCullSortTask::LAYER_HUD_OPAQUE_SHAPE]; + const auto& hudTransparent = items[RenderFetchCullSortTask::LAYER_HUD_TRANSPARENT_SHAPE]; // Lighting model comes next, the big configuration of the view const auto& lightingModel = inputs[1]; @@ -227,12 +227,12 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("HighlightRangeTimer", outlineRangeTimer); // Layered Over (in front) - const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel, jitter).asVarying(); - const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel, jitter).asVarying(); - task.addJob("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true); - task.addJob("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false); + const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, jitter).asVarying(); + const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, jitter).asVarying(); + task.addJob("DrawInFrontOpaque", inFrontOpaquesInputs, true); + task.addJob("DrawInFrontTransparent", inFrontTransparentsInputs, false); - const auto toneAndPostRangeTimer = task.addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); + const auto toneAndPostRangeTimer = task.addJob("BeginToneAndPostRangeTimer", "PostToneLayeredAntialiasing"); // AA job before bloom to limit flickering const auto antialiasingInputs = Antialiasing::Inputs(deferredFrameTransform, lightingFramebuffer, linearDepthTarget, velocityBuffer).asVarying(); @@ -257,14 +257,14 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Upscale to finale resolution const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", scaledPrimaryFramebuffer); - // Composite the HUD and HUD overlays + // Composite the HUD and HUD layered objects task.addJob("HUD"); const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); - const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel, nullJitter).asVarying(); - const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel, nullJitter).asVarying(); - task.addJob("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true); - task.addJob("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false); + const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); + const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying(); + task.addJob("DrawHUDOpaque", hudOpaquesInputs, true); + task.addJob("DrawHUDTransparent", hudTransparentsInputs, false); task.addJob("ToneAndPostRangeTimer", toneAndPostRangeTimer); @@ -283,15 +283,15 @@ void RenderDeferredTaskDebug::build(JobModel& task, const render::Varying& input const auto& fetchCullSortTaskOut = inputs.get0(); const auto& items = fetchCullSortTaskOut.get0(); - // Extract opaques / transparents / lights / metas / overlays InFront and HUD / background + // Extract opaques / transparents / lights / metas / layered / background const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; const auto& lights = items[RenderFetchCullSortTask::LIGHT]; const auto& metas = items[RenderFetchCullSortTask::META]; - const auto& overlaysInFrontOpaque = items[RenderFetchCullSortTask::LAYER_FRONT_OPAQUE_SHAPE]; - const auto& overlaysInFrontTransparent = items[RenderFetchCullSortTask::LAYER_FRONT_TRANSPARENT_SHAPE]; - const auto& overlaysHUDOpaque = items[RenderFetchCullSortTask::LAYER_HUD_OPAQUE_SHAPE]; - const auto& overlaysHUDTransparent = items[RenderFetchCullSortTask::LAYER_HUD_TRANSPARENT_SHAPE]; + const auto& inFrontOpaque = items[RenderFetchCullSortTask::LAYER_FRONT_OPAQUE_SHAPE]; + const auto& inFrontTransparent = items[RenderFetchCullSortTask::LAYER_FRONT_TRANSPARENT_SHAPE]; + const auto& hudOpaque = items[RenderFetchCullSortTask::LAYER_HUD_OPAQUE_SHAPE]; + const auto& hudTransparent = items[RenderFetchCullSortTask::LAYER_HUD_TRANSPARENT_SHAPE]; const auto& spatialSelection = fetchCullSortTaskOut[1]; @@ -388,14 +388,14 @@ void RenderDeferredTaskDebug::build(JobModel& task, const render::Varying& input task.addJob("DrawSelectionBounds", selectedItems); } - { // Debug the bounds of the rendered Overlay items that are marked drawInFront, still look at the zbuffer - task.addJob("DrawOverlayInFrontOpaqueBounds", overlaysInFrontOpaque); - task.addJob("DrawOverlayInFrontTransparentBounds", overlaysInFrontTransparent); + { // Debug the bounds of the layered objects, still look at the zbuffer + task.addJob("DrawInFrontOpaqueBounds", inFrontOpaque); + task.addJob("DrawInFrontTransparentBounds", inFrontTransparent); } - { // Debug the bounds of the rendered Overlay items that are marked drawHUDLayer, still look at the zbuffer - task.addJob("DrawOverlayHUDOpaqueBounds", overlaysHUDOpaque); - task.addJob("DrawOverlayHUDTransparentBounds", overlaysHUDTransparent); + { // Debug the bounds of the layered objects, still look at the zbuffer + task.addJob("DrawHUDOpaqueBounds", hudOpaque); + task.addJob("DrawHUDTransparentBounds", hudTransparent); } // Debugging stages diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index ffdbc1c4b1..92db4ec1e0 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -65,11 +65,10 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; const auto& metas = items[RenderFetchCullSortTask::META]; - const auto& overlaysInFrontOpaque = items[RenderFetchCullSortTask::LAYER_FRONT_OPAQUE_SHAPE]; - const auto& overlaysInFrontTransparent = items[RenderFetchCullSortTask::LAYER_FRONT_TRANSPARENT_SHAPE]; - // TODO: Re enable the rendering of the HUD overlayes - // const auto& overlaysHUDOpaque = items[RenderFetchCullSortTask::LAYER_HUD_OPAQUE_SHAPE]; - // const auto& overlaysHUDTransparent = items[RenderFetchCullSortTask::LAYER_HUD_TRANSPARENT_SHAPE]; + const auto& inFrontOpaque = items[RenderFetchCullSortTask::LAYER_FRONT_OPAQUE_SHAPE]; + const auto& inFrontTransparent = items[RenderFetchCullSortTask::LAYER_FRONT_TRANSPARENT_SHAPE]; + const auto& hudOpaque = items[RenderFetchCullSortTask::LAYER_HUD_OPAQUE_SHAPE]; + const auto& hudTransparent = items[RenderFetchCullSortTask::LAYER_HUD_TRANSPARENT_SHAPE]; // Lighting model comes next, the big configuration of the view const auto& lightingModel = inputs[1]; @@ -97,14 +96,12 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // draw a stencil mask in hidden regions of the framebuffer. task.addJob("PrepareStencil", framebuffer); - // Layered Overlays + // Layered const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); - - // Layered Over (in front) - const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel, nullJitter).asVarying(); - const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel, nullJitter).asVarying(); - task.addJob("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true); - task.addJob("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false); + const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, nullJitter).asVarying(); + const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, nullJitter).asVarying(); + task.addJob("DrawInFrontOpaque", inFrontOpaquesInputs, true); + task.addJob("DrawInFrontTransparent", inFrontTransparentsInputs, false); // Draw opaques forward const auto opaqueInputs = DrawForward::Inputs(opaques, lightingModel).asVarying(); @@ -135,10 +132,14 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto toneMappingInputs = ToneMappingDeferred::Inputs(framebuffer, static_cast(nullptr) ).asVarying(); task.addJob("ToneMapping", toneMappingInputs); - // Layered Overlays - // Composite the HUD and HUD overlays + // Composite the HUD and HUD layered objects task.addJob("HUD"); + const auto hudOpaquesInputs = DrawLayered3D::Inputs(hudOpaque, lightingModel, nullJitter).asVarying(); + const auto hudTransparentsInputs = DrawLayered3D::Inputs(hudTransparent, lightingModel, nullJitter).asVarying(); + task.addJob("DrawHUDOpaque", hudOpaquesInputs, true); + task.addJob("DrawHUDTransparent", hudTransparentsInputs, false); + // Disable blit because we do tonemapping and compositing directly to the blit FBO // Blit! // task.addJob("Blit", framebuffer); diff --git a/libraries/render/src/render/HighlightStage.h b/libraries/render/src/render/HighlightStage.h index 5e6574840f..91d8cc3f81 100644 --- a/libraries/render/src/render/HighlightStage.h +++ b/libraries/render/src/render/HighlightStage.h @@ -107,7 +107,7 @@ namespace render { float getOccludedFillOpacity() const { return getStyle()._fillOccluded.alpha; } void setOccludedFillOpacity(float value); - std::string _selectionName{ "contextOverlayHighlightList" }; + std::string _selectionName { "contextOverlayHighlightList" }; mutable SelectionStyles _styles; const HighlightStyle& getStyle() const; diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index 324f1d879f..d82fdef258 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -29,10 +29,10 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying(); const auto culledSpatialSelection = task.addJob("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM); - // Overlays are not culled - const ItemFilter overlayfilter = ItemFilter::Builder().withVisible().withoutSubMetaCulled().withTagBits(tagBits, tagMask); - const auto nonspatialFilter = render::Varying(overlayfilter); - const auto nonspatialSelection = task.addJob("FetchOverlaySelection", nonspatialFilter); + // Layered objects are not culled + const ItemFilter layeredFilter = ItemFilter::Builder().withVisible().withoutSubMetaCulled().withTagBits(tagBits, tagMask); + const auto nonspatialFilter = render::Varying(layeredFilter); + const auto nonspatialSelection = task.addJob("FetchLayeredSelection", nonspatialFilter); // Multi filter visible items into different buckets const int NUM_SPATIAL_FILTERS = 4; @@ -57,26 +57,26 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin task.addJob>("FilterSceneSelection", culledSpatialSelection, spatialFilters) .get::ItemBoundsArray>(); const auto filteredNonspatialBuckets = - task.addJob>("FilterOverlaySelection", nonspatialSelection, nonspatialFilters) + task.addJob>("FilterLayeredSelection", nonspatialSelection, nonspatialFilters) .get::ItemBoundsArray>(); - // Extract opaques / transparents / lights / overlays + // Extract opaques / transparents / lights / layered const auto opaques = task.addJob("DepthSortOpaque", filteredSpatialBuckets[OPAQUE_SHAPE_BUCKET]); const auto transparents = task.addJob("DepthSortTransparent", filteredSpatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); const auto lights = filteredSpatialBuckets[LIGHT_BUCKET]; const auto metas = filteredSpatialBuckets[META_BUCKET]; - const auto overlayOpaques = task.addJob("DepthSortOverlayOpaque", filteredNonspatialBuckets[OPAQUE_SHAPE_BUCKET]); - const auto overlayTransparents = task.addJob("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET]; - // split up the overlays into 3D front, hud - const auto filteredOverlaysOpaque = task.addJob("FilterOverlaysLayeredOpaque", overlayOpaques, ItemKey::Layer::LAYER_1); - const auto filteredOverlaysTransparent = task.addJob("FilterOverlaysLayeredTransparent", overlayTransparents, ItemKey::Layer::LAYER_1); + // split up the layered objects into 3D front, hud + const auto layeredOpaques = task.addJob("DepthSortLayaredOpaque", filteredNonspatialBuckets[OPAQUE_SHAPE_BUCKET]); + const auto layeredTransparents = task.addJob("DepthSortLayeredTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); + const auto filteredLayeredOpaque = task.addJob("FilterLayeredOpaque", layeredOpaques, ItemKey::Layer::LAYER_1); + const auto filteredLayeredTransparent = task.addJob("FilterLayeredTransparent", layeredTransparents, ItemKey::Layer::LAYER_1); - output = Output(BucketList{ opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, - filteredOverlaysOpaque.getN(0), filteredOverlaysTransparent.getN(0), - filteredOverlaysOpaque.getN(1), filteredOverlaysTransparent.getN(1), + output = Output(BucketList{ opaques, transparents, lights, metas, + filteredLayeredOpaque.getN(0), filteredLayeredTransparent.getN(0), + filteredLayeredOpaque.getN(1), filteredLayeredTransparent.getN(1), background }, spatialSelection); } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.h b/libraries/render/src/render/RenderFetchCullSortTask.h index a75c814d91..1b1e4a5d8f 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.h +++ b/libraries/render/src/render/RenderFetchCullSortTask.h @@ -23,8 +23,6 @@ public: TRANSPARENT_SHAPE, LIGHT, META, - OVERLAY_OPAQUE_SHAPE, - OVERLAY_TRANSPARENT_SHAPE, LAYER_FRONT_OPAQUE_SHAPE, LAYER_FRONT_TRANSPARENT_SHAPE, LAYER_HUD_OPAQUE_SHAPE, diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index e05cb04532..f00c74775d 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -167,11 +167,9 @@ public: // Access the spatialized items const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; } - // Access non-spatialized items (overlays, backgrounds) + // Access non-spatialized items (layered objects, backgrounds) const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; } - - // Access a particular Stage (empty if doesn't exist) // Thread safe StagePointer getStage(const Stage::Name& name) const; diff --git a/libraries/script-engine/src/ScriptUUID.h b/libraries/script-engine/src/ScriptUUID.h index 45e6ec0ad1..48514968e8 100644 --- a/libraries/script-engine/src/ScriptUUID.h +++ b/libraries/script-engine/src/ScriptUUID.h @@ -19,7 +19,7 @@ #include /**jsdoc - * A UUID (Universally Unique IDentifier) is used to uniquely identify entities, overlays, avatars, and the like. It is + * A UUID (Universally Unique IDentifier) is used to uniquely identify entities, avatars, and the like. It is * represented in JavaScript as a string in the format, {nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn}, where the "n"s are * hexadecimal digits. * diff --git a/libraries/shared/src/PickFilter.h b/libraries/shared/src/PickFilter.h index 2efd408e4f..33f6e7278a 100644 --- a/libraries/shared/src/PickFilter.h +++ b/libraries/shared/src/PickFilter.h @@ -68,7 +68,7 @@ public: // Helpers for RayPickManager Flags getEntityFlags() const { unsigned int toReturn = 0; - for (int i = DOMAIN_ENTITIES; i < LOCAL_ENTITIES; i++) { + for (int i = DOMAIN_ENTITIES; i <= LOCAL_ENTITIES; i++) { if (_flags[i]) { toReturn |= getBitMask(FlagBit(i)); } @@ -80,15 +80,6 @@ public: } return Flags(toReturn); } - Flags getOverlayFlags() const { - unsigned int toReturn = getBitMask(LOCAL_ENTITIES); - for (int i = HUD + 1; i < NUM_FLAGS; i++) { - if (_flags[i]) { - toReturn |= getBitMask(FlagBit(i)); - } - } - return Flags(toReturn); - } Flags getAvatarFlags() const { return Flags(getBitMask(AVATARS)); } Flags getHUDFlags() const { return Flags(getBitMask(HUD)); } diff --git a/libraries/shared/src/PointerEvent.cpp b/libraries/shared/src/PointerEvent.cpp index 422f2dfb20..69d3f28d80 100644 --- a/libraries/shared/src/PointerEvent.cpp +++ b/libraries/shared/src/PointerEvent.cpp @@ -72,8 +72,8 @@ void PointerEvent::setButton(Button button) { * "Move". * @property {number} id - Integer number used to identify the pointer: 0 = hardware mouse, 1 = left * controller, 2 = right controller. - * @property {Vec2} pos2D - The 2D position of the event on the intersected overlay or entity XY plane, where applicable. - * @property {Vec3} pos3D - The 3D position of the event on the intersected overlay or entity, where applicable. + * @property {Vec2} pos2D - The 2D position of the event on the intersected object XY plane, where applicable. + * @property {Vec3} pos3D - The 3D position of the event on the intersected object, where applicable. * @property {Vec3} normal - The surface normal at the intersection point. * @property {Vec3} direction - The direction of the intersection ray. * @property {string} button - The name of the button pressed: None, Primary, Secondary, diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 9d5bca6b9f..134eae41e9 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -232,7 +232,7 @@ public: }; /**jsdoc - * A PickRay defines a vector with a starting point. It is used, for example, when finding entities or overlays that lie under a + * A PickRay defines a vector with a starting point. It is used, for example, when finding entities or avatars that lie under a * mouse click or intersect a laser beam. * * @typedef {object} PickRay @@ -351,7 +351,7 @@ public: * The depth is measured in world space, but will scale with the parent if defined. * @property {CollisionMask} [collisionGroup=8] - The type of object this collision pick collides as. Objects whose collision masks overlap with the pick's collision group * will be considered colliding with the pick. -* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or an overlay. +* @property {Uuid} parentID - The ID of the parent, either an avatar or an entity. * @property {number} parentJointIndex - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint) * @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar. */ From a2083d949ea32626014a9f790df60b0677f1b48c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 25 Jan 2019 14:04:52 -0800 Subject: [PATCH 007/139] IT'S BUILDING (but still wip) --- interface/src/Application.cpp | 2 +- interface/src/avatar/OtherAvatar.h | 2 +- interface/src/raypick/ParabolaPointer.h | 2 + interface/src/raypick/RayPick.cpp | 7 +- interface/src/ui/DialogsManager.cpp | 2 +- interface/src/ui/overlays/Base3DOverlay.cpp | 2 +- interface/src/ui/overlays/Base3DOverlay.h | 6 - .../ui/overlays/ContextOverlayInterface.cpp | 34 +- .../src/ui/overlays/ContextOverlayInterface.h | 6 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/ModelOverlay.cpp | 42 +- interface/src/ui/overlays/ModelOverlay.h | 5 - interface/src/ui/overlays/Overlay2D.h | 2 - interface/src/ui/overlays/Overlays.cpp | 486 ++++++++---------- interface/src/ui/overlays/Overlays.h | 25 +- interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- 17 files changed, 269 insertions(+), 360 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f0b119b940..285b9f140b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -8748,7 +8748,7 @@ void Application::createLoginDialog() { EntityItemProperties properties; properties.setType(EntityTypes::Web); properties.setName("LoginDialogEntity"); - properties.setSourceUrl(LOGIN_DIALOG); + properties.setSourceUrl(LOGIN_DIALOG.toString()); properties.setPosition(position); properties.setRotation(cameraOrientation); properties.setDimensions(LOGIN_DIMENSIONS); diff --git a/interface/src/avatar/OtherAvatar.h b/interface/src/avatar/OtherAvatar.h index d4628a0478..bf22da4d5e 100644 --- a/interface/src/avatar/OtherAvatar.h +++ b/interface/src/avatar/OtherAvatar.h @@ -57,7 +57,7 @@ protected: void onRemoveAttachedAvatarEntity(const QUuid& id); std::vector _attachedAvatarEntities; - QUuid _otherAvatarOrbMeshPlaceholderID { UNKNOWN_ENTITY_ID }; + QUuid _otherAvatarOrbMeshPlaceholderID; AvatarMotionState* _motionState { nullptr }; int32_t _spaceIndex { -1 }; uint8_t _workloadRegion { workload::Region::INVALID }; diff --git a/interface/src/raypick/ParabolaPointer.h b/interface/src/raypick/ParabolaPointer.h index 5594f101d0..d4b705a7d2 100644 --- a/interface/src/raypick/ParabolaPointer.h +++ b/interface/src/raypick/ParabolaPointer.h @@ -10,6 +10,8 @@ #include "PathPointer.h" +#include + class ParabolaPointer : public PathPointer { using Parent = PathPointer; public: diff --git a/interface/src/raypick/RayPick.cpp b/interface/src/raypick/RayPick.cpp index e35f4584a6..5b45d5efe9 100644 --- a/interface/src/raypick/RayPick.cpp +++ b/interface/src/raypick/RayPick.cpp @@ -102,6 +102,11 @@ glm::vec2 RayPick::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3 } glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized) { - auto props = DependencyManager::get()->getEntityProperties(entityID); + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_POSITION; + desiredProperties += PROP_ROTATION; + desiredProperties += PROP_DIMENSIONS; + desiredProperties += PROP_REGISTRATION_POINT; + auto props = DependencyManager::get()->getEntityProperties(entityID, desiredProperties); return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint(), unNormalized); } diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 435cd66bf7..27e55a8586 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -70,7 +70,7 @@ void DialogsManager::hideAddressBar() { tablet->gotoHomeScreen(); hmd->closeTablet(); } - qApp->setKeyboardFocusLocalEntity(UNKNOWN_OVERLAY_ID); + qApp->setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); setAddressBarVisible(false); } diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index eb43e8cf45..ad38d91ceb 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -302,7 +302,7 @@ void Base3DOverlay::locationChanged(bool tellPhysics) { // FIXME: Overlays shouldn't be deleted when their parents are void Base3DOverlay::parentDeleted() { - qApp->getOverlays().deleteOverlay(getOverlayID()); + qApp->getOverlays().deleteOverlay(Overlay::getID()); } void Base3DOverlay::update(float duration) { diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index daf15e676f..b72ef73104 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -27,15 +27,9 @@ public: void setVisible(bool visible) override; bool queryAACubeNeedsUpdate() const override { return false; } // HACK: queryAACube not relevant for Overlays - virtual OverlayID getOverlayID() const override { return OverlayID(getID().toString()); } - void setOverlayID(OverlayID overlayID) override { setID(overlayID); } - virtual QString getName() const override; void setName(QString name); - // getters - virtual bool is3D() const override { return true; } - virtual render::ItemKey getKey() override; virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return (uint32_t) subItems.size(); } virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); } diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 5e6a9b116b..9eb9a75432 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -249,17 +249,17 @@ bool ContextOverlayInterface::destroyContextOverlay(const EntityItemID& entityIt return ContextOverlayInterface::destroyContextOverlay(entityItemID, PointerEvent()); } -void ContextOverlayInterface::contextOverlays_mousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { - if (overlayID == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) { - qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "Overlay ID:" << overlayID; +void ContextOverlayInterface::contextOverlays_mousePressOnOverlay(const QUuid& id, const PointerEvent& event) { + if (id == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) { + qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "ID:" << id; emit contextOverlayClicked(_currentEntityWithContextOverlay); _contextOverlayJustClicked = true; } } -void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event) { +void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const QUuid& id, const PointerEvent& event) { if (_contextOverlayID != UNKNOWN_ENTITY_ID) { - qCDebug(context_overlay) << "Started hovering over Context Overlay. Overlay ID:" << overlayID; + qCDebug(context_overlay) << "Started hovering over Context Overlay. ID:" << id; EntityItemProperties properties; properties.setColor(CONTEXT_OVERLAY_COLOR); properties.getPulse().setColorMode(PulseMode::NONE); @@ -269,9 +269,9 @@ void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const OverlayID& } } -void ContextOverlayInterface::contextOverlays_hoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event) { +void ContextOverlayInterface::contextOverlays_hoverLeaveOverlay(const QUuid& id, const PointerEvent& event) { if (_contextOverlayID != UNKNOWN_ENTITY_ID) { - qCDebug(context_overlay) << "Stopped hovering over Context Overlay. Overlay ID:" << overlayID; + qCDebug(context_overlay) << "Stopped hovering over Context Overlay. ID:" << id; EntityItemProperties properties; properties.setColor(CONTEXT_OVERLAY_COLOR); properties.getPulse().setColorMode(PulseMode::IN_PHASE); @@ -281,17 +281,17 @@ void ContextOverlayInterface::contextOverlays_hoverLeaveOverlay(const OverlayID& } } -void ContextOverlayInterface::contextOverlays_hoverEnterEntity(const EntityItemID& entityID, const PointerEvent& event) { +void ContextOverlayInterface::contextOverlays_hoverEnterEntity(const EntityItemID& id, const PointerEvent& event) { bool isMouse = event.getID() == PointerManager::MOUSE_POINTER_ID || DependencyManager::get()->isMouse(event.getID()); - if (contextOverlayFilterPassed(entityID) && _enabled && !isMouse) { - enableEntityHighlight(entityID); + if (contextOverlayFilterPassed(id) && _enabled && !isMouse) { + enableEntityHighlight(id); } } -void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemID& entityID, const PointerEvent& event) { +void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemID& id, const PointerEvent& event) { bool isMouse = event.getID() == PointerManager::MOUSE_POINTER_ID || DependencyManager::get()->isMouse(event.getID()); - if (_currentEntityWithContextOverlay != entityID && _enabled && !isMouse) { - disableEntityHighlight(entityID); + if (_currentEntityWithContextOverlay != id && _enabled && !isMouse) { + disableEntityHighlight(id); } } @@ -388,12 +388,12 @@ void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID } } -void ContextOverlayInterface::enableEntityHighlight(const EntityItemID& entityItemID) { - _selectionScriptingInterface->addToSelectedItemsList("contextOverlayHighlightList", "entity", entityItemID); +void ContextOverlayInterface::enableEntityHighlight(const EntityItemID& entityID) { + _selectionScriptingInterface->addToSelectedItemsList("contextOverlayHighlightList", "entity", entityID); } -void ContextOverlayInterface::disableEntityHighlight(const EntityItemID& entityItemID) { - _selectionScriptingInterface->removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityItemID); +void ContextOverlayInterface::disableEntityHighlight(const EntityItemID& entityID) { + _selectionScriptingInterface->removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityID); } void ContextOverlayInterface::deletingEntity(const EntityItemID& entityID) { diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index 2c6607a664..b87535acf2 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -65,9 +65,9 @@ public slots: bool createOrDestroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event); bool destroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event); bool destroyContextOverlay(const EntityItemID& entityItemID); - void contextOverlays_mousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event); - void contextOverlays_hoverEnterOverlay(const OverlayID& overlayID, const PointerEvent& event); - void contextOverlays_hoverLeaveOverlay(const OverlayID& overlayID, const PointerEvent& event); + void contextOverlays_mousePressOnOverlay(const QUuid& id, const PointerEvent& event); + void contextOverlays_hoverEnterOverlay(const QUuid& id, const PointerEvent& event); + void contextOverlays_hoverLeaveOverlay(const QUuid& id, const PointerEvent& event); void contextOverlays_hoverEnterEntity(const EntityItemID& entityID, const PointerEvent& event); void contextOverlays_hoverLeaveEntity(const EntityItemID& entityID, const PointerEvent& event); bool contextOverlayFilterPassed(const EntityItemID& entityItemID); diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 9888d696cf..128281faee 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -189,7 +189,7 @@ scriptable::ScriptableModelBase Cube3DOverlay::getScriptableModel() { auto vertexColor = ColorUtils::toVec3(_color); scriptable::ScriptableModelBase result; if (auto mesh = geometryCache->meshFromShape(GeometryCache::Cube, vertexColor)) { - result.objectID = getID(); + result.objectID = Overlay::getID(); result.append(mesh); } return result; diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 14e5cdc7f5..92a316690a 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -92,7 +92,7 @@ void ModelOverlay::update(float deltatime) { render::ScenePointer scene = qApp->getMain3DScene(); render::Transaction transaction; if (_model->needsFixupInScene()) { - emit DependencyManager::get()->modelRemovedFromScene(getID(), NestableType::Overlay, _model); + emit DependencyManager::get()->modelRemovedFromScene(Overlay::getID(), NestableType::Overlay, _model); _model->removeFromScene(scene, transaction); _model->addToScene(scene, transaction); @@ -101,8 +101,7 @@ void ModelOverlay::update(float deltatime) { auto modelOverlay = static_cast(&data); modelOverlay->setSubRenderItemIDs(newRenderItemIDs); }); - processMaterials(); - emit DependencyManager::get()->modelAddedToScene(getID(), NestableType::Overlay, _model); + emit DependencyManager::get()->modelAddedToScene(Overlay::getID(), NestableType::Overlay, _model); } bool metaDirty = false; if (_visibleDirty && _texturesLoaded) { @@ -145,15 +144,14 @@ void ModelOverlay::update(float deltatime) { bool ModelOverlay::addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) { Volume3DOverlay::addToScene(overlay, scene, transaction); _model->addToScene(scene, transaction); - processMaterials(); - emit DependencyManager::get()->modelAddedToScene(getID(), NestableType::Overlay, _model); + emit DependencyManager::get()->modelAddedToScene(Overlay::getID(), NestableType::Overlay, _model); return true; } void ModelOverlay::removeFromScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) { Volume3DOverlay::removeFromScene(overlay, scene, transaction); _model->removeFromScene(scene, transaction); - emit DependencyManager::get()->modelRemovedFromScene(getID(), NestableType::Overlay, _model); + emit DependencyManager::get()->modelRemovedFromScene(Overlay::getID(), NestableType::Overlay, _model); transaction.updateItem(getRenderItemID(), [](Overlay& data) { auto modelOverlay = static_cast(&data); modelOverlay->clearSubRenderItemIDs(); @@ -709,32 +707,6 @@ uint32_t ModelOverlay::fetchMetaSubItems(render::ItemIDs& subItems) const { return 0; } -void ModelOverlay::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) { - Overlay::addMaterial(material, parentMaterialName); - if (_model && _model->fetchRenderItemIDs().size() > 0) { - _model->addMaterial(material, parentMaterialName); - } -} - -void ModelOverlay::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) { - Overlay::removeMaterial(material, parentMaterialName); - if (_model && _model->fetchRenderItemIDs().size() > 0) { - _model->removeMaterial(material, parentMaterialName); - } -} - -void ModelOverlay::processMaterials() { - assert(_model); - std::lock_guard lock(_materialsLock); - for (auto& shapeMaterialPair : _materials) { - auto material = shapeMaterialPair.second; - while (!material.empty()) { - _model->addMaterial(material.top(), shapeMaterialPair.first); - material.pop(); - } - } -} - bool ModelOverlay::canReplaceModelMeshPart(int meshIndex, int partIndex) { // TODO: bounds checking; for now just used to indicate provider generally supports mesh updates return _model && _model->isLoaded(); @@ -750,11 +722,7 @@ scriptable::ScriptableModelBase ModelOverlay::getScriptableModel() { return Base3DOverlay::getScriptableModel(); } auto result = _model->getScriptableModel(); - result.objectID = getID(); - { - std::lock_guard lock(_materialsLock); - result.appendMaterials(_materials); - } + result.objectID = Overlay::getID(); return result; } diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 17a2327d02..63ffeaaafe 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -70,9 +70,6 @@ public: void setDrawHUDLayer(bool drawHUDLayer) override; void setGroupCulled(bool groupCulled); - void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) override; - void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) override; - virtual scriptable::ScriptableModelBase getScriptableModel() override; virtual bool canReplaceModelMeshPart(int meshIndex, int partIndex) override; virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, int meshIndex, int partIndex) override; @@ -130,8 +127,6 @@ private: bool _isGroupCulled { false }; bool _groupCulledDirty { false }; - void processMaterials(); - }; #endif // hifi_ModelOverlay_h diff --git a/interface/src/ui/overlays/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h index 3175df92f1..5417dbd9e0 100644 --- a/interface/src/ui/overlays/Overlay2D.h +++ b/interface/src/ui/overlays/Overlay2D.h @@ -23,8 +23,6 @@ public: Overlay2D(const Overlay2D* overlay2D); virtual AABox getBounds() const override; - - virtual bool is3D() const override { return false; } virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return 1; } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index df65b26a3f..69d3883de7 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -21,20 +21,15 @@ #include "Application.h" #include "InterfaceLogging.h" -#include "Image3DOverlay.h" -#include "Circle3DOverlay.h" -#include "Cube3DOverlay.h" -#include "Shape3DOverlay.h" + #include "ImageOverlay.h" -#include "Line3DOverlay.h" -#include "ModelOverlay.h" -#include "Rectangle3DOverlay.h" -#include "Sphere3DOverlay.h" -#include "Grid3DOverlay.h" #include "TextOverlay.h" #include "RectangleOverlay.h" -#include "Text3DOverlay.h" -#include "Web3DOverlay.h" + +#include + +#include + #include "ui/Keyboard.h" #include @@ -42,6 +37,9 @@ Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") +std::unordered_map Overlays::_entityToOverlayTypes; +std::unordered_map Overlays::_overlayToEntityTypes; + Overlays::Overlays() { auto pointerManager = DependencyManager::get(); connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, this, &Overlays::hoverEnterPointerEvent); @@ -50,6 +48,17 @@ Overlays::Overlays() { connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, this, &Overlays::mousePressPointerEvent); connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, this, &Overlays::mouseMovePointerEvent); connect(pointerManager.data(), &PointerManager::triggerEndOverlay, this, &Overlays::mouseReleasePointerEvent); + + ADD_TYPE_MAP(Box, cube); + ADD_TYPE_MAP(Sphere, sphere); + ADD_TYPE_MAP(Shape, shape); + ADD_TYPE_MAP(Model, model); + ADD_TYPE_MAP(Text, text3d); + ADD_TYPE_MAP(Image, image3d); + ADD_TYPE_MAP(Web, web3d); + ADD_TYPE_MAP(PolyLine, line3d); + ADD_TYPE_MAP(Grid, grid); + ADD_TYPE_MAP(Gizmo, circle3d); } void Overlays::cleanupAllOverlays() { @@ -151,9 +160,39 @@ Overlay::Pointer Overlays::get2DOverlay(const QUuid& id) const { return nullptr; } +QString Overlays::entityToOverlayType(const QString& type) { + auto iter = _entityToOverlayTypes.find(type); + if (iter != _entityToOverlayTypes.end()) { + return iter->second; + } + return "unknown"; +} + +QString Overlays::overlayToEntityType(const QString& type) { + auto iter = _overlayToEntityTypes.find(type); + if (iter != _overlayToEntityTypes.end()) { + return iter->second; + } else if (type == "billboard") { + return "Image"; + } + return "Unknown"; +} + +EntityItemProperties convertOverlayToEntityProperties(const QVariantMap& overlayProps) { + EntityItemProperties props; + + return props; +} + +QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps) { + QVariantMap props; + + return props; +} + QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { if (_shuttingDown) { - return UNKNOWN_OVERLAY_ID; + return UNKNOWN_ENTITY_ID; } if (QThread::currentThread() != thread()) { @@ -163,8 +202,6 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { return result; } - Overlay::Pointer thisOverlay = nullptr; - /**jsdoc *

An overlay may be one of the following types:

* @@ -172,26 +209,26 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { * * * + * + * + * * * * - * * * * - * * * * - * * * * *
Value2D/3DDescription
image2DAn image. Synonym: billboard.
rectangle2DA rectangle.
text2DText.
circle3d3DA circle.
cube3DA cube. Can also use a shape overlay to create a * cube.
grid3DA grid of lines in a plane.
image2DAn image. Synonym: billboard.
image3d3DAn image.
line3d3DA line.
model3DA model.
rectangle2DA rectangle.
rectangle3d3DA rectangle.
shape3DA geometric shape, such as a cube, sphere, or cylinder.
sphere3DA sphere. Can also use a shape overlay to create a * sphere.
text2DText.
text3d3DText.
web3d3DWeb content.
*

2D overlays are rendered on the display surface in desktop mode and on the HUD surface in HMD mode. 3D overlays are - * rendered at a position and orientation in-world.

+ * rendered at a position and orientation in-world, but are deprecated (use local entities instead).

*

Each overlay type has different {@link Overlays.OverlayProperties|OverlayProperties}.

* @typedef {string} Overlays.OverlayType */ @@ -203,18 +240,18 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { * {@link Overlays.OverlayType|OverlayType}Overlay Properties * * + * image{@link Overlays.ImageProperties|ImageProperties} + * rectangle{@link Overlays.RectangleProperties|RectangleProperties} + * text{@link Overlays.TextProperties|TextProperties} * circle3d{@link Overlays.Circle3DProperties|Circle3DProperties} * cube{@link Overlays.CubeProperties|CubeProperties} * grid{@link Overlays.GridProperties|GridProperties} - * image{@link Overlays.ImageProperties|ImageProperties} * image3d{@link Overlays.Image3DProperties|Image3DProperties} * line3d{@link Overlays.Line3DProperties|Line3DProperties} * model{@link Overlays.ModelProperties|ModelProperties} - * rectangle{@link Overlays.RectangleProperties|RectangleProperties} * rectangle3d{@link Overlays.Rectangle3DProperties|Rectangle3DProperties} * shape{@link Overlays.ShapeProperties|ShapeProperties} * sphere{@link Overlays.SphereProperties|SphereProperties} - * text{@link Overlays.TextProperties|TextProperties} * text3d{@link Overlays.Text3DProperties|Text3DProperties} * web3d{@link Overlays.Web3DProperties|Web3DProperties} * @@ -222,54 +259,42 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { * @typedef {object} Overlays.OverlayProperties */ + Overlay::Pointer overlay; if (type == ImageOverlay::TYPE) { #if !defined(DISABLE_QML) - thisOverlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); + overlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); #endif - } else if (type == Image3DOverlay::TYPE || type == "billboard") { // "billboard" for backwards compatibility - thisOverlay = Overlay::Pointer(new Image3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); } else if (type == TextOverlay::TYPE) { #if !defined(DISABLE_QML) - thisOverlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); + overlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); #endif - } else if (type == Text3DOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new Text3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); - } else if (type == Shape3DOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new Shape3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); - } else if (type == Cube3DOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new Cube3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); - } else if (type == Sphere3DOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new Sphere3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); - } else if (type == Circle3DOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new Circle3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); - } else if (type == Rectangle3DOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new Rectangle3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); - } else if (type == Line3DOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new Line3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); - } else if (type == Grid3DOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new Grid3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); - } else if (type == ModelOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new ModelOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); - } else if (type == Web3DOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new Web3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); } else if (type == RectangleOverlay::TYPE) { - thisOverlay = Overlay::Pointer(new RectangleOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); + overlay = Overlay::Pointer(new RectangleOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); } - if (thisOverlay) { - thisOverlay->setProperties(properties.toMap()); - return add2DOverlay(thisOverlay); + if (overlay) { + overlay->setProperties(properties.toMap()); + return add2DOverlay(overlay); } - return UNKNOWN_OVERLAY_ID; + + QString entityType = overlayToEntityType(type); + + if (entityType == "Unknown") { + return UNKNOWN_ENTITY_ID; + } + + QVariantMap propertyMap = properties.toMap(); + propertyMap["type"] = entityType; + return DependencyManager::get()->addEntity(convertOverlayToEntityProperties(propertyMap), "local"); } QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) { if (_shuttingDown) { - return UNKNOWN_OVERLAY_ID; + return UNKNOWN_ENTITY_ID; } QUuid thisID = QUuid::createUuid(); - overlay->setOverlayID(thisID); + overlay->setID(thisID); overlay->setStackOrder(_stackOrder++); { QMutexLocker locker(&_mutex); @@ -281,7 +306,7 @@ QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) { QUuid Overlays::cloneOverlay(const QUuid& id) { if (_shuttingDown) { - return UNKNOWN_OVERLAY_ID; + return UNKNOWN_ENTITY_ID; } if (QThread::currentThread() != thread()) { @@ -486,111 +511,70 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray, const QScriptValue& overlayIDsToInclude, const QScriptValue& overlayIDsToDiscard, bool visibleOnly, bool collidableOnly) { - const QVector overlaysToInclude = qVectorQUuidFromScriptValue(overlayIDsToInclude); - const QVector overlaysToDiscard = qVectorQUuidFromScriptValue(overlayIDsToDiscard); + const QVector include = qVectorEntityItemIDFromScriptValue(overlayIDsToInclude); + const QVector discard = qVectorEntityItemIDFromScriptValue(overlayIDsToDiscard); - return findRayIntersectionVector(ray, precisionPicking, - overlaysToInclude, overlaysToDiscard, visibleOnly, collidableOnly); + return findRayIntersectionVector(ray, precisionPicking, include, discard, visibleOnly, collidableOnly); } - RayToOverlayIntersectionResult Overlays::findRayIntersectionVector(const PickRay& ray, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, + const QVector& include, + const QVector& discard, bool visibleOnly, bool collidableOnly) { - float bestDistance = std::numeric_limits::max(); - bool bestIsFront = false; - bool bestIsTablet = false; - auto tabletIDs = qApp->getTabletIDs(); + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); - QMutexLocker locker(&_mutex); - RayToOverlayIntersectionResult result; - QMapIterator i(_overlaysWorld); - while (i.hasNext()) { - i.next(); - OverlayID thisID = i.key(); - auto thisOverlay = std::dynamic_pointer_cast(i.value()); - - if ((overlaysToDiscard.size() > 0 && overlaysToDiscard.contains(thisID)) || - (overlaysToInclude.size() > 0 && !overlaysToInclude.contains(thisID))) { - continue; - } - - if (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnorePickIntersection() && thisOverlay->isLoaded()) { - float thisDistance; - BoxFace thisFace; - glm::vec3 thisSurfaceNormal; - QVariantMap thisExtraInfo; - if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, - thisFace, thisSurfaceNormal, thisExtraInfo, precisionPicking)) { - bool isDrawInFront = thisOverlay->getDrawInFront(); - bool isTablet = tabletIDs.contains(thisID); - if ((isDrawInFront && !bestIsFront && !bestIsTablet) - || ((isTablet || isDrawInFront || !bestIsFront) && thisDistance < bestDistance)) { - bestIsFront = isDrawInFront; - bestIsTablet = isTablet; - bestDistance = thisDistance; - result.intersects = true; - result.distance = thisDistance; - result.face = thisFace; - result.surfaceNormal = thisSurfaceNormal; - result.overlayID = thisID; - result.intersection = ray.origin + (ray.direction * thisDistance); - result.extraInfo = thisExtraInfo; - } - } - } + if (!precisionPicking) { + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE); } - return result; + + if (visibleOnly) { + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE); + } + + if (collidableOnly) { + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE); + } + auto result = DependencyManager::get()->evalRayIntersectionVector(ray, PickFilter(searchFilter), include, discard); + + RayToOverlayIntersectionResult overlayResult; + overlayResult.overlayID = result.entityID; + overlayResult.intersects = result.intersects; + overlayResult.intersection = result.intersection; + overlayResult.distance = result.distance; + overlayResult.surfaceNormal = result.surfaceNormal; + overlayResult.face = result.face; + overlayResult.extraInfo = result.extraInfo; + return overlayResult; } ParabolaToOverlayIntersectionResult Overlays::findParabolaIntersectionVector(const PickParabola& parabola, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, + const QVector& include, + const QVector& discard, bool visibleOnly, bool collidableOnly) { - float bestDistance = std::numeric_limits::max(); - bool bestIsFront = false; - const QVector keyboardKeysToDiscard = DependencyManager::get()->getKeysID(); - QMutexLocker locker(&_mutex); - ParabolaToOverlayIntersectionResult result; - QMapIterator i(_overlaysWorld); - while (i.hasNext()) { - i.next(); - OverlayID thisID = i.key(); - auto thisOverlay = std::dynamic_pointer_cast(i.value()); + unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); - if ((overlaysToDiscard.size() > 0 && overlaysToDiscard.contains(thisID)) || - (overlaysToInclude.size() > 0 && !overlaysToInclude.contains(thisID)) || - (keyboardKeysToDiscard.size() > 0 && keyboardKeysToDiscard.contains(thisID))) { - continue; - } - - if (thisOverlay && thisOverlay->getVisible() && !thisOverlay->getIgnorePickIntersection() && thisOverlay->isLoaded()) { - float thisDistance; - BoxFace thisFace; - glm::vec3 thisSurfaceNormal; - QVariantMap thisExtraInfo; - if (thisOverlay->findParabolaIntersectionExtraInfo(parabola.origin, parabola.velocity, parabola.acceleration, thisDistance, - thisFace, thisSurfaceNormal, thisExtraInfo, precisionPicking)) { - bool isDrawInFront = thisOverlay->getDrawInFront(); - if ((bestIsFront && isDrawInFront && thisDistance < bestDistance) - || (!bestIsFront && (isDrawInFront || thisDistance < bestDistance))) { - - bestIsFront = isDrawInFront; - bestDistance = thisDistance; - result.intersects = true; - result.parabolicDistance = thisDistance; - result.face = thisFace; - result.surfaceNormal = thisSurfaceNormal; - result.overlayID = thisID; - result.intersection = parabola.origin + parabola.velocity * thisDistance + 0.5f * parabola.acceleration * thisDistance * thisDistance; - result.distance = glm::distance(result.intersection, parabola.origin); - result.extraInfo = thisExtraInfo; - } - } - } + if (!precisionPicking) { + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COARSE); } - return result; + + if (visibleOnly) { + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE); + } + + if (collidableOnly) { + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::COLLIDABLE); + } + auto result = DependencyManager::get()->evalParabolaIntersectionVector(parabola, PickFilter(searchFilter), include, discard); + + ParabolaToOverlayIntersectionResult overlayResult; + overlayResult.overlayID = result.entityID; + overlayResult.intersects = result.intersects; + overlayResult.intersection = result.intersection; + overlayResult.parabolicDistance = result.parabolicDistance; + overlayResult.surfaceNormal = result.surfaceNormal; + overlayResult.face = result.face; + overlayResult.extraInfo = result.extraInfo; + return overlayResult; } QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value) { @@ -671,28 +655,28 @@ bool Overlays::isAddedOverlay(const QUuid& id) { return DependencyManager::get()->isAddedEntity(id); } -void Overlays::sendMousePressOnOverlay(const QUuid& overlayID, const PointerEvent& event) { - mousePressPointerEvent(overlayID, event); +void Overlays::sendMousePressOnOverlay(const QUuid& id, const PointerEvent& event) { + mousePressPointerEvent(id, event); } -void Overlays::sendMouseReleaseOnOverlay(const QUuid& overlayID, const PointerEvent& event) { - mouseReleasePointerEvent(overlayID, event); +void Overlays::sendMouseReleaseOnOverlay(const QUuid& id, const PointerEvent& event) { + mouseReleasePointerEvent(id, event); } -void Overlays::sendMouseMoveOnOverlay(const QUuid& overlayID, const PointerEvent& event) { - mouseMovePointerEvent(overlayID, event); +void Overlays::sendMouseMoveOnOverlay(const QUuid& id, const PointerEvent& event) { + mouseMovePointerEvent(id, event); } -void Overlays::sendHoverEnterOverlay(const QUuid& overlayID, const PointerEvent& event) { - hoverEnterPointerEvent(overlayID, event); +void Overlays::sendHoverEnterOverlay(const QUuid& id, const PointerEvent& event) { + hoverEnterPointerEvent(id, event); } -void Overlays::sendHoverOverOverlay(const QUuid& overlayID, const PointerEvent& event) { - hoverOverPointerEvent(overlayID, event); +void Overlays::sendHoverOverOverlay(const QUuid& id, const PointerEvent& event) { + hoverOverPointerEvent(id, event); } -void Overlays::sendHoverLeaveOverlay(const QUuid& overlayID, const PointerEvent& event) { - hoverLeavePointerEvent(overlayID, event); +void Overlays::sendHoverLeaveOverlay(const QUuid& id, const PointerEvent& event) { + hoverLeavePointerEvent(id, event); } float Overlays::width() { @@ -719,28 +703,6 @@ float Overlays::height() { return offscreenUi->getWindow()->size().height(); } -static glm::vec2 projectOntoOverlayXYPlane(glm::vec3 position, glm::quat rotation, glm::vec2 dimensions, const PickRay& pickRay, - const RayToOverlayIntersectionResult& rayPickResult) { - - // Project the intersection point onto the local xy plane of the overlay. - float distance; - glm::vec3 planePosition = position; - glm::vec3 planeNormal = rotation * Vectors::UNIT_Z; - glm::vec3 overlayDimensions = glm::vec3(dimensions.x, dimensions.y, 0.0f); - glm::vec3 rayDirection = pickRay.direction; - glm::vec3 rayStart = pickRay.origin; - glm::vec3 p; - if (rayPlaneIntersection(planePosition, planeNormal, rayStart, rayDirection, distance)) { - p = rayStart + rayDirection * distance; - } else { - p = rayPickResult.intersection; - } - glm::vec3 localP = glm::inverse(rotation) * (p - position); - glm::vec3 normalizedP = (localP / overlayDimensions) + glm::vec3(0.5f); - return glm::vec2(normalizedP.x * overlayDimensions.x, - (1.0f - normalizedP.y) * overlayDimensions.y); // flip y-axis -} - static uint32_t toPointerButtons(const QMouseEvent& event) { uint32_t buttons = 0; buttons |= event.buttons().testFlag(Qt::LeftButton) ? PointerEvent::PrimaryButton : 0; @@ -765,32 +727,18 @@ static PointerEvent::Button toPointerButton(const QMouseEvent& event) { PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, PointerEvent::EventType eventType) { - auto overlay = std::dynamic_pointer_cast(getOverlay(id)); - if (getOverlayType(overlayID) == "web3d") { - overlay = std::dynamic_pointer_cast(getOverlay(overlayID)); - } - if (!overlay) { - return PointerEvent(); - } - glm::vec3 position = overlay->getWorldPosition(); - glm::quat rotation = overlay->getWorldOrientation(); - glm::vec2 dimensions = overlay->getSize(); - - - glm::vec2 pos2D = projectOntoOverlayXYPlane(position, rotation, dimensions, ray, rayPickResult); - + glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(id, rayPickResult.intersection); PointerEvent pointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers()); return pointerEvent; } - bool Overlays::mousePressEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mousePressEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); + RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); if (rayPickResult.intersects) { _currentClickingOnOverlayID = rayPickResult.overlayID; @@ -799,35 +747,33 @@ bool Overlays::mousePressEvent(QMouseEvent* event) { return true; } // if we didn't press on an overlay, disable overlay keyboard focus - setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); + setKeyboardFocusOverlay(UNKNOWN_ENTITY_ID); // emit to scripts emit mousePressOffOverlay(); return false; } -void Overlays::mousePressPointerEvent(const OverlayID& overlayID, const PointerEvent& event) { - // TODO: generalize this to allow any overlay to recieve events - std::shared_ptr thisOverlay; - if (getOverlayType(overlayID) == "web3d") { - thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); - } - if (thisOverlay) { - if (event.shouldFocus()) { - // Focus keyboard on web overlays - DependencyManager::get()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); - setKeyboardFocusOverlay(overlayID); +void Overlays::mousePressPointerEvent(const QUuid& id, const PointerEvent& event) { + // TODO: generalize this to allow any object to recieve events + auto renderable = qApp->getEntities()->renderableForEntityId(id); + if (renderable) { + auto web = std::dynamic_pointer_cast(renderable); + if (web) { + if (event.shouldFocus()) { + // Focus keyboard on web overlays + DependencyManager::get()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); + setKeyboardFocusOverlay(id); + } + + web->handlePointerEvent(event); } - - // Send to web overlay - QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event)); } - auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(overlayID)) { + if (!keyboard->getKeysID().contains(id)) { // emit to scripts - emit mousePressOnOverlay(overlayID, event); + emit mousePressOnOverlay(id, event); } } @@ -835,7 +781,7 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); + RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); if (rayPickResult.intersects) { _currentClickingOnOverlayID = rayPickResult.overlayID; @@ -849,60 +795,57 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) { return false; } -void Overlays::hoverEnterPointerEvent(const OverlayID& overlayID, const PointerEvent& event) { - // TODO: generalize this to allow any overlay to recieve events - std::shared_ptr thisOverlay; - if (getOverlayType(overlayID) == "web3d") { - thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); - } - if (thisOverlay) { - // Send to web overlay - QMetaObject::invokeMethod(thisOverlay.get(), "hoverEnterOverlay", Q_ARG(PointerEvent, event)); +void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) { + // TODO: generalize this to allow any object to recieve events + auto renderable = qApp->getEntities()->renderableForEntityId(id); + if (renderable) { + auto web = std::dynamic_pointer_cast(renderable); + if (web) { + web->hoverEnterEntity(event); + } } auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(overlayID)) { + if (!keyboard->getKeysID().contains(id)) { // emit to scripts - emit hoverEnterOverlay(overlayID, event); + emit hoverEnterOverlay(id, event); } } -void Overlays::hoverOverPointerEvent(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::hoverOverPointerEvent(const QUuid& id, const PointerEvent& event) { // TODO: generalize this to allow any overlay to recieve events - std::shared_ptr thisOverlay; - if (getOverlayType(overlayID) == "web3d") { - thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); - } - if (thisOverlay) { - // Send to web overlay - QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event)); + auto renderable = qApp->getEntities()->renderableForEntityId(id); + if (renderable) { + auto web = std::dynamic_pointer_cast(renderable); + if (web) { + web->handlePointerEvent(event); + } } auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(overlayID)) { + if (!keyboard->getKeysID().contains(id)) { // emit to scripts - emit hoverOverOverlay(overlayID, event); + emit hoverOverOverlay(id, event); } } -void Overlays::hoverLeavePointerEvent(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event) { // TODO: generalize this to allow any overlay to recieve events - std::shared_ptr thisOverlay; - if (getOverlayType(overlayID) == "web3d") { - thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); - } - if (thisOverlay) { - // Send to web overlay - QMetaObject::invokeMethod(thisOverlay.get(), "hoverLeaveOverlay", Q_ARG(PointerEvent, event)); + auto renderable = qApp->getEntities()->renderableForEntityId(id); + if (renderable) { + auto web = std::dynamic_pointer_cast(renderable); + if (web) { + web->hoverLeaveEntity(event); + } } auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(overlayID)) { + if (!keyboard->getKeysID().contains(id)) { // emit to scripts - emit hoverLeaveOverlay(overlayID, event); + emit hoverLeaveOverlay(id, event); } } @@ -910,33 +853,31 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseReleaseEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), - QVector()); + RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); if (rayPickResult.intersects) { auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release); mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent); } - _currentClickingOnOverlayID = UNKNOWN_OVERLAY_ID; + _currentClickingOnOverlayID = UNKNOWN_ENTITY_ID; return false; } -void Overlays::mouseReleasePointerEvent(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event) { // TODO: generalize this to allow any overlay to recieve events - std::shared_ptr thisOverlay; - if (getOverlayType(overlayID) == "web3d") { - thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); - } - if (thisOverlay) { - // Send to web overlay - QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event)); + auto renderable = qApp->getEntities()->renderableForEntityId(id); + if (renderable) { + auto web = std::dynamic_pointer_cast(renderable); + if (web) { + web->handlePointerEvent(event); + } } auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(overlayID)) { + if (!keyboard->getKeysID().contains(id)) { // emit to scripts - emit mouseReleaseOnOverlay(overlayID, event); + emit mouseReleaseOnOverlay(id, event); } } @@ -944,14 +885,13 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseMoveEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), - QVector()); + RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); if (rayPickResult.intersects) { auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move); mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent); // If previously hovering over a different overlay then leave hover on that overlay. - if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID && rayPickResult.overlayID != _currentHoverOverOverlayID) { + if (_currentHoverOverOverlayID != UNKNOWN_ENTITY_ID && rayPickResult.overlayID != _currentHoverOverOverlayID) { auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move); hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent); } @@ -967,33 +907,31 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { _currentHoverOverOverlayID = rayPickResult.overlayID; } else { // If previously hovering an overlay then leave hover. - if (_currentHoverOverOverlayID != UNKNOWN_OVERLAY_ID) { + if (_currentHoverOverOverlayID != UNKNOWN_ENTITY_ID) { auto pointerEvent = calculateOverlayPointerEvent(_currentHoverOverOverlayID, ray, rayPickResult, event, PointerEvent::Move); hoverLeavePointerEvent(_currentHoverOverOverlayID, pointerEvent); - _currentHoverOverOverlayID = UNKNOWN_OVERLAY_ID; + _currentHoverOverOverlayID = UNKNOWN_ENTITY_ID; } } return false; } -void Overlays::mouseMovePointerEvent(const OverlayID& overlayID, const PointerEvent& event) { +void Overlays::mouseMovePointerEvent(const QUuid& id, const PointerEvent& event) { // TODO: generalize this to allow any overlay to recieve events - std::shared_ptr thisOverlay; - if (getOverlayType(overlayID) == "web3d") { - thisOverlay = std::static_pointer_cast(getOverlay(overlayID)); - } - if (thisOverlay) { - // Send to web overlay - QMetaObject::invokeMethod(thisOverlay.get(), "handlePointerEvent", Q_ARG(PointerEvent, event)); + auto renderable = qApp->getEntities()->renderableForEntityId(id); + if (renderable) { + auto web = std::dynamic_pointer_cast(renderable); + if (web) { + web->handlePointerEvent(event); + } } auto keyboard = DependencyManager::get(); - // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(overlayID)) { + if (!keyboard->getKeysID().contains(id)) { // emit to scripts - emit mouseMoveOnOverlay(overlayID, event); + emit mouseMoveOnOverlay(id, event); } } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 2a8812f69e..a9d3cffe41 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -103,13 +103,13 @@ public: QUuid add2DOverlay(const Overlay::Pointer& overlay); RayToOverlayIntersectionResult findRayIntersectionVector(const PickRay& ray, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, + const QVector& include, + const QVector& discard, bool visibleOnly = false, bool collidableOnly = false); ParabolaToOverlayIntersectionResult findParabolaIntersectionVector(const PickParabola& parabola, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToDiscard, + const QVector& include, + const QVector& discard, bool visibleOnly = false, bool collidableOnly = false); bool mousePressEvent(QMouseEvent* event); @@ -356,8 +356,8 @@ public slots: * @function Overlays.findRayIntersection * @param {PickRay} pickRay - The PickRay to use for finding overlays. * @param {boolean} [precisionPicking=false] - Unused; exists to match Entity API. - * @param {Array.} [overlayIDsToInclude=[]] - If not empty then the search is restricted to these overlays. - * @param {Array.} [overlayIDsToExclude=[]] - Overlays to ignore during the search. + * @param {Array.} [include=[]] - If not empty then the search is restricted to these overlays. + * @param {Array.} [discard=[]] - Overlays to ignore during the search. * @param {boolean} [visibleOnly=false] - Unused; exists to match Entity API. * @param {boolean} [collidableOnly=false] - Unused; exists to match Entity API. * @returns {Overlays.RayToOverlayIntersectionResult} The closest 3D overlay intersected by pickRay, taking @@ -379,8 +379,8 @@ public slots: */ RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray, bool precisionPicking = false, - const QScriptValue& overlayIDsToInclude = QScriptValue(), - const QScriptValue& overlayIDsToDiscard = QScriptValue(), + const QScriptValue& include = QScriptValue(), + const QScriptValue& discard = QScriptValue(), bool visibleOnly = false, bool collidableOnly = false); @@ -718,6 +718,11 @@ private: QUuid _currentClickingOnOverlayID; QUuid _currentHoverOverOverlayID; + static QString entityToOverlayType(const QString& type); + static QString overlayToEntityType(const QString& type); + static std::unordered_map _entityToOverlayTypes; + static std::unordered_map _overlayToEntityTypes; + private slots: void mousePressPointerEvent(const QUuid& id, const PointerEvent& event); void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event); @@ -727,4 +732,8 @@ private slots: void hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event); }; +#define ADD_TYPE_MAP(entity, overlay) \ + _entityToOverlayTypes[#entity] = #overlay; \ + _overlayToEntityTypes[#overlay] = #entity; + #endif // hifi_Overlays_h diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index 4adbbf3792..b7bbc76ffb 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -196,7 +196,7 @@ scriptable::ScriptableModelBase Shape3DOverlay::getScriptableModel() { auto geometryCache = DependencyManager::get(); auto vertexColor = ColorUtils::toVec3(_color); scriptable::ScriptableModelBase result; - result.objectID = getID(); + result.objectID = Overlay::getID(); if (auto mesh = geometryCache->meshFromShape(_shape, vertexColor)) { result.append(mesh); } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index b1d5c878c4..385fea768c 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -128,7 +128,7 @@ scriptable::ScriptableModelBase Sphere3DOverlay::getScriptableModel() { auto vertexColor = ColorUtils::toVec3(_color); scriptable::ScriptableModelBase result; if (auto mesh = geometryCache->meshFromShape(GeometryCache::Sphere, vertexColor)) { - result.objectID = getID(); + result.objectID = Overlay::getID(); result.append(mesh); } return result; From becc9f4f8d70461f6e9777dc968a4bc4baeed6eb Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 25 Jan 2019 16:06:59 -0800 Subject: [PATCH 008/139] DELETE IT ALL --- interface/src/ui/overlays/Base3DOverlay.cpp | 392 ---------- interface/src/ui/overlays/Base3DOverlay.h | 106 --- .../src/ui/overlays/Billboard3DOverlay.cpp | 65 -- .../src/ui/overlays/Billboard3DOverlay.h | 38 - interface/src/ui/overlays/Billboardable.cpp | 56 -- interface/src/ui/overlays/Billboardable.h | 36 - interface/src/ui/overlays/Circle3DOverlay.cpp | 589 -------------- interface/src/ui/overlays/Circle3DOverlay.h | 96 --- interface/src/ui/overlays/Cube3DOverlay.cpp | 196 ----- interface/src/ui/overlays/Cube3DOverlay.h | 45 -- interface/src/ui/overlays/Grid3DOverlay.cpp | 200 ----- interface/src/ui/overlays/Grid3DOverlay.h | 61 -- interface/src/ui/overlays/Image3DOverlay.cpp | 341 -------- interface/src/ui/overlays/Image3DOverlay.h | 67 -- interface/src/ui/overlays/ImageOverlay.cpp | 26 +- interface/src/ui/overlays/Line3DOverlay.cpp | 366 --------- interface/src/ui/overlays/Line3DOverlay.h | 79 -- interface/src/ui/overlays/ModelOverlay.cpp | 735 ------------------ interface/src/ui/overlays/ModelOverlay.h | 132 ---- interface/src/ui/overlays/Overlay.cpp | 163 +--- interface/src/ui/overlays/Overlay.h | 57 +- interface/src/ui/overlays/Overlay2D.h | 7 +- interface/src/ui/overlays/Overlays.cpp | 593 +++++++++++++- interface/src/ui/overlays/PanelAttachable.cpp | 62 -- interface/src/ui/overlays/PanelAttachable.h | 69 -- interface/src/ui/overlays/Planar3DOverlay.cpp | 126 --- interface/src/ui/overlays/Planar3DOverlay.h | 45 -- interface/src/ui/overlays/QmlOverlay.h | 1 - .../src/ui/overlays/Rectangle3DOverlay.cpp | 158 ---- .../src/ui/overlays/Rectangle3DOverlay.h | 39 - .../src/ui/overlays/RectangleOverlay.cpp | 23 - interface/src/ui/overlays/Shape3DOverlay.cpp | 204 ----- interface/src/ui/overlays/Shape3DOverlay.h | 45 -- interface/src/ui/overlays/Sphere3DOverlay.cpp | 135 ---- interface/src/ui/overlays/Sphere3DOverlay.h | 37 - interface/src/ui/overlays/Text3DOverlay.cpp | 295 ------- interface/src/ui/overlays/Text3DOverlay.h | 78 -- interface/src/ui/overlays/TextOverlay.cpp | 39 +- interface/src/ui/overlays/TextOverlay.h | 8 - interface/src/ui/overlays/Volume3DOverlay.cpp | 117 --- interface/src/ui/overlays/Volume3DOverlay.h | 45 -- interface/src/ui/overlays/Web3DOverlay.cpp | 490 ------------ interface/src/ui/overlays/Web3DOverlay.h | 99 --- .../render-utils/src/RenderForwardTask.cpp | 2 +- 44 files changed, 600 insertions(+), 5963 deletions(-) delete mode 100644 interface/src/ui/overlays/Base3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Base3DOverlay.h delete mode 100644 interface/src/ui/overlays/Billboard3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Billboard3DOverlay.h delete mode 100644 interface/src/ui/overlays/Billboardable.cpp delete mode 100644 interface/src/ui/overlays/Billboardable.h delete mode 100644 interface/src/ui/overlays/Circle3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Circle3DOverlay.h delete mode 100644 interface/src/ui/overlays/Cube3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Cube3DOverlay.h delete mode 100644 interface/src/ui/overlays/Grid3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Grid3DOverlay.h delete mode 100644 interface/src/ui/overlays/Image3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Image3DOverlay.h delete mode 100644 interface/src/ui/overlays/Line3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Line3DOverlay.h delete mode 100644 interface/src/ui/overlays/ModelOverlay.cpp delete mode 100644 interface/src/ui/overlays/ModelOverlay.h delete mode 100644 interface/src/ui/overlays/PanelAttachable.cpp delete mode 100644 interface/src/ui/overlays/PanelAttachable.h delete mode 100644 interface/src/ui/overlays/Planar3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Planar3DOverlay.h delete mode 100644 interface/src/ui/overlays/Rectangle3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Rectangle3DOverlay.h delete mode 100644 interface/src/ui/overlays/Shape3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Shape3DOverlay.h delete mode 100644 interface/src/ui/overlays/Sphere3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Sphere3DOverlay.h delete mode 100644 interface/src/ui/overlays/Text3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Text3DOverlay.h delete mode 100644 interface/src/ui/overlays/Volume3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Volume3DOverlay.h delete mode 100644 interface/src/ui/overlays/Web3DOverlay.cpp delete mode 100644 interface/src/ui/overlays/Web3DOverlay.h diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp deleted file mode 100644 index ad38d91ceb..0000000000 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ /dev/null @@ -1,392 +0,0 @@ -// -// Base3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - - -#include "Base3DOverlay.h" - -#include -#include -#include "Application.h" - - -const bool DEFAULT_IS_SOLID = false; -const bool DEFAULT_IS_DASHED_LINE = false; - -Base3DOverlay::Base3DOverlay() : - SpatiallyNestable(NestableType::Overlay, QUuid::createUuid()), - _isSolid(DEFAULT_IS_SOLID), - _isDashedLine(DEFAULT_IS_DASHED_LINE), - _ignorePickIntersection(false), - _drawInFront(false), - _drawHUDLayer(false) -{ - // HACK: queryAACube stuff not actually relevant for 3DOverlays, and by setting _queryAACubeSet true here - // we can avoid incorrect evaluation for sending updates for entities with 3DOverlays children. - _queryAACubeSet = true; -} - -Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : - Overlay(base3DOverlay), - SpatiallyNestable(NestableType::Overlay, QUuid::createUuid()), - _isSolid(base3DOverlay->_isSolid), - _isDashedLine(base3DOverlay->_isDashedLine), - _ignorePickIntersection(base3DOverlay->_ignorePickIntersection), - _drawInFront(base3DOverlay->_drawInFront), - _drawHUDLayer(base3DOverlay->_drawHUDLayer), - _isGrabbable(base3DOverlay->_isGrabbable), - _isVisibleInSecondaryCamera(base3DOverlay->_isVisibleInSecondaryCamera) -{ - setTransform(base3DOverlay->getTransform()); - // HACK: queryAACube stuff not actually relevant for 3DOverlays, and by setting _queryAACubeSet true here - // we can avoid incorrect evaluation for sending updates for entities with 3DOverlays children. - _queryAACubeSet = true; -} - -QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& properties, bool scalesWithParent) { - // the position and rotation in _transform are relative to the parent (aka local). The versions coming from - // scripts are in world-frame, unless localPosition or localRotation are used. Patch up the properties - // so that "position" and "rotation" are relative-to-parent values. - QVariantMap result = properties; - QUuid parentID = result["parentID"].isValid() ? QUuid(result["parentID"].toString()) : QUuid(); - int parentJointIndex = result["parentJointIndex"].isValid() ? result["parentJointIndex"].toInt() : -1; - bool success; - - // make "position" and "orientation" be relative-to-parent - if (result["localPosition"].isValid()) { - result["position"] = result["localPosition"]; - } else if (result["position"].isValid()) { - glm::vec3 localPosition = SpatiallyNestable::worldToLocal(vec3FromVariant(result["position"]), - parentID, parentJointIndex, scalesWithParent, success); - if (success) { - result["position"] = vec3toVariant(localPosition); - } - } - - if (result["localOrientation"].isValid()) { - result["orientation"] = result["localOrientation"]; - } else if (result["orientation"].isValid()) { - glm::quat localOrientation = SpatiallyNestable::worldToLocal(quatFromVariant(result["orientation"]), - parentID, parentJointIndex, scalesWithParent, success); - if (success) { - result["orientation"] = quatToVariant(localOrientation); - } - } - - return result; -} - -void Base3DOverlay::setProperties(const QVariantMap& originalProperties) { - QVariantMap properties = originalProperties; - - if (properties["name"].isValid()) { - setName(properties["name"].toString()); - } - - // carry over some legacy keys - if (!properties["position"].isValid() && !properties["localPosition"].isValid()) { - if (properties["p1"].isValid()) { - properties["position"] = properties["p1"]; - } else if (properties["point"].isValid()) { - properties["position"] = properties["point"]; - } else if (properties["start"].isValid()) { - properties["position"] = properties["start"]; - } - } - if (!properties["orientation"].isValid() && properties["rotation"].isValid()) { - properties["orientation"] = properties["rotation"]; - } - if (!properties["localOrientation"].isValid() && properties["localRotation"].isValid()) { - properties["localOrientation"] = properties["localRotation"]; - } - - // All of parentID, parentJointIndex, position, orientation are needed to make sense of any of them. - // If any of these changed, pull any missing properties from the overlay. - if (properties["parentID"].isValid() || properties["parentJointIndex"].isValid() || - properties["position"].isValid() || properties["localPosition"].isValid() || - properties["orientation"].isValid() || properties["localOrientation"].isValid()) { - if (!properties["parentID"].isValid()) { - properties["parentID"] = getParentID(); - } - if (!properties["parentJointIndex"].isValid()) { - properties["parentJointIndex"] = getParentJointIndex(); - } - if (!properties["position"].isValid() && !properties["localPosition"].isValid()) { - properties["position"] = vec3toVariant(getWorldPosition()); - } - if (!properties["orientation"].isValid() && !properties["localOrientation"].isValid()) { - properties["orientation"] = quatToVariant(getWorldOrientation()); - } - } - - properties = convertOverlayLocationFromScriptSemantics(properties, getScalesWithParent()); - Overlay::setProperties(properties); - - bool needRenderItemUpdate = false; - - auto drawInFront = properties["drawInFront"]; - if (drawInFront.isValid()) { - bool value = drawInFront.toBool(); - setDrawInFront(value); - needRenderItemUpdate = true; - } - - auto drawHUDLayer = properties["drawHUDLayer"]; - if (drawHUDLayer.isValid()) { - bool value = drawHUDLayer.toBool(); - setDrawHUDLayer(value); - needRenderItemUpdate = true; - } - - auto isGrabbable = properties["grabbable"]; - if (isGrabbable.isValid()) { - setIsGrabbable(isGrabbable.toBool()); - } - - auto isVisibleInSecondaryCamera = properties["isVisibleInSecondaryCamera"]; - if (isVisibleInSecondaryCamera.isValid()) { - bool value = isVisibleInSecondaryCamera.toBool(); - setIsVisibleInSecondaryCamera(value); - needRenderItemUpdate = true; - } - - if (properties["position"].isValid()) { - setLocalPosition(vec3FromVariant(properties["position"])); - needRenderItemUpdate = true; - } - if (properties["orientation"].isValid()) { - setLocalOrientation(quatFromVariant(properties["orientation"])); - needRenderItemUpdate = true; - } - if (properties["isSolid"].isValid()) { - setIsSolid(properties["isSolid"].toBool()); - } - if (properties["isFilled"].isValid()) { - setIsSolid(properties["isSolid"].toBool()); - } - if (properties["isWire"].isValid()) { - setIsSolid(!properties["isWire"].toBool()); - } - if (properties["solid"].isValid()) { - setIsSolid(properties["solid"].toBool()); - } - if (properties["filled"].isValid()) { - setIsSolid(properties["filled"].toBool()); - } - if (properties["wire"].isValid()) { - setIsSolid(!properties["wire"].toBool()); - } - - if (properties["isDashedLine"].isValid()) { - qDebug() << "isDashed is deprecated and will be removed in RC79!"; - setIsDashedLine(properties["isDashedLine"].toBool()); - } - if (properties["dashed"].isValid()) { - qDebug() << "dashed is deprecated and will be removed in RC79!"; - setIsDashedLine(properties["dashed"].toBool()); - } - if (properties["ignorePickIntersection"].isValid()) { - setIgnorePickIntersection(properties["ignorePickIntersection"].toBool()); - } else if (properties["ignoreRayIntersection"].isValid()) { - setIgnorePickIntersection(properties["ignoreRayIntersection"].toBool()); - } - - if (properties["parentID"].isValid()) { - setParentID(QUuid(properties["parentID"].toString())); - needRenderItemUpdate = true; - } - if (properties["parentJointIndex"].isValid()) { - setParentJointIndex(properties["parentJointIndex"].toInt()); - needRenderItemUpdate = true; - } - - // Communicate changes to the renderItem if needed - if (needRenderItemUpdate) { - auto itemID = getRenderItemID(); - if (render::Item::isValidID(itemID)) { - render::ScenePointer scene = qApp->getMain3DScene(); - render::Transaction transaction; - transaction.updateItem(itemID); - scene->enqueueTransaction(transaction); - } - _queryAACubeSet = true; // HACK: just in case some SpatiallyNestable code accidentally set it false - } -} - -// JSDoc for copying to @typedefs of overlay types that inherit Base3DOverlay. -/**jsdoc - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {boolean} isVisibleInSecondaryCamera=false - If true, the overlay is rendered in secondary - * camera views. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - */ -QVariant Base3DOverlay::getProperty(const QString& property) { - if (property == "name") { - return _nameLock.resultWithReadLock([&] { - return _name; - }); - } - if (property == "position" || property == "start" || property == "p1" || property == "point") { - return vec3toVariant(getWorldPosition()); - } - if (property == "localPosition") { - return vec3toVariant(getLocalPosition()); - } - if (property == "rotation" || property == "orientation") { - return quatToVariant(getWorldOrientation()); - } - if (property == "localRotation" || property == "localOrientation") { - return quatToVariant(getLocalOrientation()); - } - if (property == "isSolid" || property == "isFilled" || property == "solid" || property == "filled") { - return _isSolid; - } - if (property == "isWire" || property == "wire") { - return !_isSolid; - } - if (property == "isDashedLine" || property == "dashed") { - qDebug() << "isDashedLine/dashed are deprecated and will be removed in RC79!"; - return _isDashedLine; - } - if (property == "ignorePickIntersection" || property == "ignoreRayIntersection") { - return _ignorePickIntersection; - } - if (property == "drawInFront") { - return _drawInFront; - } - if (property == "grabbable") { - return _isGrabbable; - } - if (property == "isVisibleInSecondaryCamera") { - return _isVisibleInSecondaryCamera; - } - if (property == "parentID") { - return getParentID(); - } - if (property == "parentJointIndex") { - return getParentJointIndex(); - } - - return Overlay::getProperty(property); -} - -void Base3DOverlay::locationChanged(bool tellPhysics) { - SpatiallyNestable::locationChanged(tellPhysics); - - // Force the actual update of the render transform through the notify call - notifyRenderVariableChange(); -} - -// FIXME: Overlays shouldn't be deleted when their parents are -void Base3DOverlay::parentDeleted() { - qApp->getOverlays().deleteOverlay(Overlay::getID()); -} - -void Base3DOverlay::update(float duration) { - // In Base3DOverlay, if its location or bound changed, the renderTrasnformDirty flag is true. - // then the correct transform used for rendering is computed in the update transaction and assigned. - if (_renderVariableDirty) { - auto itemID = getRenderItemID(); - if (render::Item::isValidID(itemID)) { - // Capture the render transform value in game loop before - auto latestTransform = evalRenderTransform(); - bool latestVisible = getVisible(); - _renderVariableDirty = false; - render::ScenePointer scene = qApp->getMain3DScene(); - render::Transaction transaction; - transaction.updateItem(itemID, [latestTransform, latestVisible](Overlay& data) { - auto overlay3D = dynamic_cast(&data); - if (overlay3D) { - // TODO: overlays need to communicate all relavent render properties through transactions - overlay3D->setRenderTransform(latestTransform); - overlay3D->setRenderVisible(latestVisible); - } - }); - scene->enqueueTransaction(transaction); - } - } -} - -void Base3DOverlay::notifyRenderVariableChange() const { - _renderVariableDirty = true; -} - -Transform Base3DOverlay::evalRenderTransform() { - return getTransform(); -} - -void Base3DOverlay::setRenderTransform(const Transform& transform) { - _renderTransform = transform; -} - -void Base3DOverlay::setRenderVisible(bool visible) { - _renderVisible = visible; -} - -SpatialParentTree* Base3DOverlay::getParentTree() const { - auto entityTreeRenderer = qApp->getEntities(); - EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; - return entityTree.get(); -} - -void Base3DOverlay::setVisible(bool visible) { - Parent::setVisible(visible); - notifyRenderVariableChange(); -} - -QString Base3DOverlay::getName() const { - return _nameLock.resultWithReadLock([&] { - return QString("Overlay:") + _name; - }); -} - -void Base3DOverlay::setName(QString name) { - _nameLock.withWriteLock([&] { - _name = name; - }); -} - - - -render::ItemKey Base3DOverlay::getKey() { - auto builder = render::ItemKey::Builder(Overlay::getKey()); - - if (getDrawInFront()) { - builder.withLayer(render::hifi::LAYER_3D_FRONT); - } else if (getDrawHUDLayer()) { - builder.withLayer(render::hifi::LAYER_3D_HUD); - } else { - builder.withoutLayer(); - } - - builder.withoutViewSpace(); - - if (isTransparent()) { - builder.withTransparent(); - } - - return builder.build(); -} diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h deleted file mode 100644 index b72ef73104..0000000000 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ /dev/null @@ -1,106 +0,0 @@ -// -// Base3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Base3DOverlay_h -#define hifi_Base3DOverlay_h - -#include -#include -#include -#include "Overlay.h" - -class Base3DOverlay : public Overlay, public SpatiallyNestable, public scriptable::ModelProvider { - Q_OBJECT - using Parent = Overlay; - -public: - Base3DOverlay(); - Base3DOverlay(const Base3DOverlay* base3DOverlay); - - void setVisible(bool visible) override; - bool queryAACubeNeedsUpdate() const override { return false; } // HACK: queryAACube not relevant for Overlays - - virtual QString getName() const override; - void setName(QString name); - - virtual render::ItemKey getKey() override; - virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return (uint32_t) subItems.size(); } - virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); } - - // TODO: consider implementing registration points in this class - glm::vec3 getCenter() const { return getWorldPosition(); } - - bool getIsSolid() const { return _isSolid; } - bool getIsDashedLine() const { return _isDashedLine; } - bool getIsSolidLine() const { return !_isDashedLine; } - bool getIgnorePickIntersection() const { return _ignorePickIntersection; } - bool getDrawInFront() const { return _drawInFront; } - bool getDrawHUDLayer() const { return _drawHUDLayer; } - bool getIsGrabbable() const { return _isGrabbable; } - virtual bool getIsVisibleInSecondaryCamera() const override { return _isVisibleInSecondaryCamera; } - - void setIsSolid(bool isSolid) { _isSolid = isSolid; } - void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } - void setIgnorePickIntersection(bool value) { _ignorePickIntersection = value; } - virtual void setDrawInFront(bool value) { _drawInFront = value; } - virtual void setDrawHUDLayer(bool value) { _drawHUDLayer = value; } - void setIsGrabbable(bool value) { _isGrabbable = value; } - virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; } - - void update(float deltatime) override; - - void notifyRenderVariableChange() const; - - virtual void setProperties(const QVariantMap& properties) override; - virtual QVariant getProperty(const QString& property) override; - - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) { return false; } - - virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) { - return findRayIntersection(origin, direction, distance, face, surfaceNormal, precisionPicking); - } - - virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) { return false; } - - virtual bool findParabolaIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) { - return findParabolaIntersection(origin, velocity, acceleration, parabolicDistance, face, surfaceNormal, precisionPicking); - } - - virtual SpatialParentTree* getParentTree() const override; - -protected: - virtual void locationChanged(bool tellPhysics = true) override; - virtual void parentDeleted() override; - - mutable Transform _renderTransform; - mutable bool _renderVisible; - virtual Transform evalRenderTransform(); - virtual void setRenderTransform(const Transform& transform); - void setRenderVisible(bool visible); - const Transform& getRenderTransform() const { return _renderTransform; } - - bool _isSolid; - bool _isDashedLine; - bool _ignorePickIntersection; - bool _drawInFront; - bool _drawHUDLayer; - bool _isGrabbable { false }; - bool _isVisibleInSecondaryCamera { false }; - mutable bool _renderVariableDirty { true }; - - QString _name; - mutable ReadWriteLockable _nameLock; -}; - -#endif // hifi_Base3DOverlay_h diff --git a/interface/src/ui/overlays/Billboard3DOverlay.cpp b/interface/src/ui/overlays/Billboard3DOverlay.cpp deleted file mode 100644 index ecade70ef8..0000000000 --- a/interface/src/ui/overlays/Billboard3DOverlay.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// Billboard3DOverlay.cpp -// hifi/interface/src/ui/overlays -// -// Created by Zander Otavka on 8/4/15. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Billboard3DOverlay.h" - -Billboard3DOverlay::Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay) : - Planar3DOverlay(billboard3DOverlay), - PanelAttachable(*billboard3DOverlay), - Billboardable(*billboard3DOverlay) -{ -} - -void Billboard3DOverlay::setProperties(const QVariantMap& properties) { - Planar3DOverlay::setProperties(properties); - PanelAttachable::setProperties(properties); - Billboardable::setProperties(properties); -} - -QVariant Billboard3DOverlay::getProperty(const QString &property) { - QVariant value; - value = Billboardable::getProperty(property); - if (value.isValid()) { - return value; - } - value = PanelAttachable::getProperty(property); - if (value.isValid()) { - return value; - } - return Planar3DOverlay::getProperty(property); -} - -bool Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) { - bool transformChanged = false; - if (force || usecTimestampNow() > _transformExpiry) { - transformChanged = PanelAttachable::applyTransformTo(transform, true); - transformChanged |= pointTransformAtCamera(transform, getOffsetRotation()); - } - return transformChanged; -} - -void Billboard3DOverlay::update(float duration) { - if (isFacingAvatar()) { - _renderVariableDirty = true; - } - Parent::update(duration); -} - -Transform Billboard3DOverlay::evalRenderTransform() { - Transform transform = getTransform(); - bool transformChanged = applyTransformTo(transform, true); - // If the transform is not modified, setting the transform to - // itself will cause drift over time due to floating point errors. - if (transformChanged) { - setTransform(transform); - } - return transform; -} \ No newline at end of file diff --git a/interface/src/ui/overlays/Billboard3DOverlay.h b/interface/src/ui/overlays/Billboard3DOverlay.h deleted file mode 100644 index 174bc23bc8..0000000000 --- a/interface/src/ui/overlays/Billboard3DOverlay.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Billboard3DOverlay.h -// hifi/interface/src/ui/overlays -// -// Created by Zander Otavka on 8/4/15. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Billboard3DOverlay_h -#define hifi_Billboard3DOverlay_h - -#include "Planar3DOverlay.h" -#include "PanelAttachable.h" -#include "Billboardable.h" - -class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable, public Billboardable { - Q_OBJECT - using Parent = Planar3DOverlay; - -public: - Billboard3DOverlay() {} - Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay); - - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - - void update(float duration) override; - -protected: - virtual bool applyTransformTo(Transform& transform, bool force = false) override; - - Transform evalRenderTransform() override; -}; - -#endif // hifi_Billboard3DOverlay_h diff --git a/interface/src/ui/overlays/Billboardable.cpp b/interface/src/ui/overlays/Billboardable.cpp deleted file mode 100644 index a125956b5a..0000000000 --- a/interface/src/ui/overlays/Billboardable.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// Billboardable.cpp -// interface/src/ui/overlays -// -// Created by Zander Otavka on 8/7/15. -// Modified by Daniela Fontes on 24/10/17. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Billboardable.h" - -#include -#include -#include "avatar/AvatarManager.h" - -void Billboardable::setProperties(const QVariantMap& properties) { - auto isFacingAvatar = properties["isFacingAvatar"]; - if (isFacingAvatar.isValid()) { - setIsFacingAvatar(isFacingAvatar.toBool()); - } -} - -// JSDoc for copying to @typedefs of overlay types that inherit Billboardable. -/**jsdoc - * @property {boolean} isFacingAvatar - If true, the overlay is rotated to face the user's camera about an axis - * parallel to the user's avatar's "up" direction. - */ -QVariant Billboardable::getProperty(const QString &property) { - if (property == "isFacingAvatar") { - return isFacingAvatar(); - } - return QVariant(); -} - -bool Billboardable::pointTransformAtCamera(Transform& transform, glm::quat offsetRotation) { - if (isFacingAvatar()) { - glm::vec3 billboardPos = transform.getTranslation(); - glm::vec3 cameraPos = qApp->getCamera().getPosition(); - // use the referencial from the avatar, y isn't always up - glm::vec3 avatarUP = DependencyManager::get()->getMyAvatar()->getWorldOrientation()*Vectors::UP; - // check to see if glm::lookAt will work / using glm::lookAt variable name - glm::highp_vec3 s(glm::cross(billboardPos - cameraPos, avatarUP)); - - // make sure s is not NaN for any component - if(glm::length2(s) > 0.0f) { - glm::quat rotation(conjugate(toQuat(glm::lookAt(cameraPos, billboardPos, avatarUP)))); - transform.setRotation(rotation); - transform.postRotate(offsetRotation); - return true; - } - } - return false; -} diff --git a/interface/src/ui/overlays/Billboardable.h b/interface/src/ui/overlays/Billboardable.h deleted file mode 100644 index 46d9ac6479..0000000000 --- a/interface/src/ui/overlays/Billboardable.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Billboardable.h -// interface/src/ui/overlays -// -// Created by Zander Otavka on 8/7/15. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Billboardable_h -#define hifi_Billboardable_h - -#include -#include - -class QString; -class Transform; - -class Billboardable { -public: - bool isFacingAvatar() const { return _isFacingAvatar; } - void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; } - -protected: - void setProperties(const QVariantMap& properties); - QVariant getProperty(const QString& property); - - bool pointTransformAtCamera(Transform& transform, glm::quat offsetRotation = {1, 0, 0, 0}); - -private: - bool _isFacingAvatar = false; -}; - -#endif // hifi_Billboardable_h diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp deleted file mode 100644 index 1a7d3228c7..0000000000 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ /dev/null @@ -1,589 +0,0 @@ -// -// Circle3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Circle3DOverlay.h" - -#include -#include -#include - -QString const Circle3DOverlay::TYPE = "circle3d"; - -Circle3DOverlay::Circle3DOverlay() {} - -Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) : - Planar3DOverlay(circle3DOverlay), - _startAt(circle3DOverlay->_startAt), - _endAt(circle3DOverlay->_endAt), - _outerRadius(circle3DOverlay->_outerRadius), - _innerRadius(circle3DOverlay->_innerRadius), - _innerStartColor(circle3DOverlay->_innerStartColor), - _innerEndColor(circle3DOverlay->_innerEndColor), - _outerStartColor(circle3DOverlay->_outerStartColor), - _outerEndColor(circle3DOverlay->_outerEndColor), - _innerStartAlpha(circle3DOverlay->_innerStartAlpha), - _innerEndAlpha(circle3DOverlay->_innerEndAlpha), - _outerStartAlpha(circle3DOverlay->_outerStartAlpha), - _outerEndAlpha(circle3DOverlay->_outerEndAlpha), - _hasTickMarks(circle3DOverlay->_hasTickMarks), - _majorTickMarksAngle(circle3DOverlay->_majorTickMarksAngle), - _minorTickMarksAngle(circle3DOverlay->_minorTickMarksAngle), - _majorTickMarksLength(circle3DOverlay->_majorTickMarksLength), - _minorTickMarksLength(circle3DOverlay->_minorTickMarksLength), - _majorTickMarksColor(circle3DOverlay->_majorTickMarksColor), - _minorTickMarksColor(circle3DOverlay->_minorTickMarksColor) -{ -} - -Circle3DOverlay::~Circle3DOverlay() { - auto geometryCache = DependencyManager::get(); - if (geometryCache) { - if (_quadVerticesID) { - geometryCache->releaseID(_quadVerticesID); - } - if (_lineVerticesID) { - geometryCache->releaseID(_lineVerticesID); - } - if (_majorTicksVerticesID) { - geometryCache->releaseID(_majorTicksVerticesID); - } - if (_minorTicksVerticesID) { - geometryCache->releaseID(_minorTicksVerticesID); - } - } -} -void Circle3DOverlay::render(RenderArgs* args) { - if (!_renderVisible) { - return; // do nothing if we're not visible - } - - float alpha = getAlpha(); - if (alpha == 0.0f) { - return; // do nothing if our alpha is 0, we're not visible - } - - bool geometryChanged = _dirty; - _dirty = false; - - const float FULL_CIRCLE = 360.0f; - const float SLICES = 180.0f; // The amount of segment to create the circle - const float SLICE_ANGLE_RADIANS = glm::radians(FULL_CIRCLE / SLICES); - - auto geometryCache = DependencyManager::get(); - - Q_ASSERT(args->_batch); - auto& batch = *args->_batch; - - DependencyManager::get()->bindSimpleProgram(batch, false, isTransparent(), false, !getIsSolid(), true); - - batch.setModelTransform(getRenderTransform()); - - // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise - // we just draw a line... - if (getIsSolid()) { - if (!_quadVerticesID) { - _quadVerticesID = geometryCache->allocateID(); - } - - if (geometryChanged) { - QVector points; - QVector colors; - - float pulseLevel = updatePulse(); - vec4 pulseModifier = vec4(1); - if (_alphaPulse != 0.0f) { - pulseModifier.a = (_alphaPulse >= 0.0f) ? pulseLevel : (1.0f - pulseLevel); - } - if (_colorPulse != 0.0f) { - float pulseValue = (_colorPulse >= 0.0f) ? pulseLevel : (1.0f - pulseLevel); - pulseModifier = vec4(vec3(pulseValue), pulseModifier.a); - } - vec4 innerStartColor = vec4(toGlm(_innerStartColor), _innerStartAlpha) * pulseModifier; - vec4 outerStartColor = vec4(toGlm(_outerStartColor), _outerStartAlpha) * pulseModifier; - vec4 innerEndColor = vec4(toGlm(_innerEndColor), _innerEndAlpha) * pulseModifier; - vec4 outerEndColor = vec4(toGlm(_outerEndColor), _outerEndAlpha) * pulseModifier; - - const auto startAtRadians = glm::radians(_startAt); - const auto endAtRadians = glm::radians(_endAt); - - const auto totalRange = _endAt - _startAt; - if (_innerRadius <= 0) { - _solidPrimitive = gpu::TRIANGLE_FAN; - points << vec2(); - colors << innerStartColor; - for (float angleRadians = startAtRadians; angleRadians < endAtRadians; angleRadians += SLICE_ANGLE_RADIANS) { - float range = (angleRadians - startAtRadians) / totalRange; - points << glm::vec2(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius); - colors << glm::mix(outerStartColor, outerEndColor, range); - } - points << glm::vec2(cosf(endAtRadians) * _outerRadius, sinf(endAtRadians) * _outerRadius); - colors << outerEndColor; - - } else { - _solidPrimitive = gpu::TRIANGLE_STRIP; - for (float angleRadians = startAtRadians; angleRadians < endAtRadians; angleRadians += SLICE_ANGLE_RADIANS) { - float range = (angleRadians - startAtRadians) / totalRange; - - points << glm::vec2(cosf(angleRadians) * _innerRadius, sinf(angleRadians) * _innerRadius); - colors << glm::mix(innerStartColor, innerEndColor, range); - - points << glm::vec2(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius); - colors << glm::mix(outerStartColor, outerEndColor, range); - } - points << glm::vec2(cosf(endAtRadians) * _innerRadius, sinf(endAtRadians) * _innerRadius); - colors << innerEndColor; - - points << glm::vec2(cosf(endAtRadians) * _outerRadius, sinf(endAtRadians) * _outerRadius); - colors << outerEndColor; - } - geometryCache->updateVertices(_quadVerticesID, points, colors); - } - - geometryCache->renderVertices(batch, _solidPrimitive, _quadVerticesID); - - } else { - if (!_lineVerticesID) { - _lineVerticesID = geometryCache->allocateID(); - } - - if (geometryChanged) { - QVector points; - - const auto startAtRadians = glm::radians(_startAt); - const auto endAtRadians = glm::radians(_endAt); - - float angleRadians = startAtRadians; - glm::vec2 firstPoint(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius); - points << firstPoint; - - while (angleRadians < endAtRadians) { - angleRadians += SLICE_ANGLE_RADIANS; - glm::vec2 thisPoint(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius); - points << thisPoint; - - if (getIsDashedLine()) { - angleRadians += SLICE_ANGLE_RADIANS / 2.0f; // short gap - glm::vec2 dashStartPoint(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius); - points << dashStartPoint; - } - } - - // get the last slice portion.... - angleRadians = endAtRadians; - glm::vec2 lastPoint(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius); - points << lastPoint; - geometryCache->updateVertices(_lineVerticesID, points, vec4(toGlm(getColor()), getAlpha())); - } - - if (getIsDashedLine()) { - geometryCache->renderVertices(batch, gpu::LINES, _lineVerticesID); - } else { - geometryCache->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID); - } - } - - // draw our tick marks - // for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise - // we just draw a line... - if (getHasTickMarks()) { - if (!_majorTicksVerticesID) { - _majorTicksVerticesID = geometryCache->allocateID(); - } - if (!_minorTicksVerticesID) { - _minorTicksVerticesID = geometryCache->allocateID(); - } - - if (geometryChanged) { - QVector majorPoints; - QVector minorPoints; - - // draw our major tick marks - if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) { - - float tickMarkAngle = getMajorTickMarksAngle(); - float angle = _startAt - fmodf(_startAt, tickMarkAngle) + tickMarkAngle; - float tickMarkLength = getMajorTickMarksLength(); - float startRadius = (tickMarkLength > 0.0f) ? _innerRadius : _outerRadius; - float endRadius = startRadius + tickMarkLength; - - while (angle <= _endAt) { - float angleInRadians = glm::radians(angle); - - glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius); - glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius); - - majorPoints << thisPointA << thisPointB; - - angle += tickMarkAngle; - } - } - - // draw our minor tick marks - if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) { - - float tickMarkAngle = getMinorTickMarksAngle(); - float angle = _startAt - fmodf(_startAt, tickMarkAngle) + tickMarkAngle; - float tickMarkLength = getMinorTickMarksLength(); - float startRadius = (tickMarkLength > 0.0f) ? _innerRadius : _outerRadius; - float endRadius = startRadius + tickMarkLength; - - while (angle <= _endAt) { - float angleInRadians = glm::radians(angle); - - glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius); - glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius); - - minorPoints << thisPointA << thisPointB; - - angle += tickMarkAngle; - } - } - - glm::vec4 majorColor(toGlm(getMajorTickMarksColor()), alpha); - geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor); - glm::vec4 minorColor(toGlm(getMinorTickMarksColor()), alpha); - geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor); - } - - geometryCache->renderVertices(batch, gpu::LINES, _majorTicksVerticesID); - - geometryCache->renderVertices(batch, gpu::LINES, _minorTicksVerticesID); - } -} - -const render::ShapeKey Circle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace(); - if (isTransparent()) { - builder.withTranslucent(); - } - if (!getIsSolid()) { - builder.withUnlit().withDepthBias(); - } - return builder.build(); -} - -template T fromVariant(const QVariant& v, bool& valid) { - valid = v.isValid(); - return qvariant_cast(v); -} - -template<> glm::u8vec3 fromVariant(const QVariant& v, bool& valid) { - return u8vec3FromVariant(v, valid); -} - -template -bool updateIfValid(const QVariantMap& properties, const char* key, T& output) { - bool valid; - T result = fromVariant(properties[key], valid); - if (!valid) { - return false; - } - - // Don't signal updates if the value was already set - if (result == output) { - return false; - } - - output = result; - return true; -} - -// Multicast, many outputs -template -bool updateIfValid(const QVariantMap& properties, const char* key, std::initializer_list> outputs) { - bool valid; - T value = fromVariant(properties[key], valid); - if (!valid) { - return false; - } - bool updated = false; - for (T& output : outputs) { - if (output != value) { - output = value; - updated = true; - } - } - return updated; -} - -// Multicast, multiple possible inputs, in order of preference -template -bool updateIfValid(const QVariantMap& properties, const std::initializer_list keys, T& output) { - for (const char* key : keys) { - if (updateIfValid(properties, key, output)) { - return true; - } - } - return false; -} - - -void Circle3DOverlay::setProperties(const QVariantMap& properties) { - Planar3DOverlay::setProperties(properties); - _dirty |= updateIfValid(properties, "alpha", { _innerStartAlpha, _innerEndAlpha, _outerStartAlpha, _outerEndAlpha }); - _dirty |= updateIfValid(properties, "Alpha", { _innerStartAlpha, _innerEndAlpha, _outerStartAlpha, _outerEndAlpha }); - _dirty |= updateIfValid(properties, "startAlpha", { _innerStartAlpha, _outerStartAlpha }); - _dirty |= updateIfValid(properties, "endAlpha", { _innerEndAlpha, _outerEndAlpha }); - _dirty |= updateIfValid(properties, "innerAlpha", { _innerStartAlpha, _innerEndAlpha }); - _dirty |= updateIfValid(properties, "outerAlpha", { _outerStartAlpha, _outerEndAlpha }); - _dirty |= updateIfValid(properties, "innerStartAlpha", _innerStartAlpha); - _dirty |= updateIfValid(properties, "innerEndAlpha", _innerEndAlpha); - _dirty |= updateIfValid(properties, "outerStartAlpha", _outerStartAlpha); - _dirty |= updateIfValid(properties, "outerEndAlpha", _outerEndAlpha); - - _dirty |= updateIfValid(properties, "color", { _innerStartColor, _innerEndColor, _outerStartColor, _outerEndColor }); - _dirty |= updateIfValid(properties, "startColor", { _innerStartColor, _outerStartColor } ); - _dirty |= updateIfValid(properties, "endColor", { _innerEndColor, _outerEndColor } ); - _dirty |= updateIfValid(properties, "innerColor", { _innerStartColor, _innerEndColor } ); - _dirty |= updateIfValid(properties, "outerColor", { _outerStartColor, _outerEndColor } ); - _dirty |= updateIfValid(properties, "innerStartColor", _innerStartColor); - _dirty |= updateIfValid(properties, "innerEndColor", _innerEndColor); - _dirty |= updateIfValid(properties, "outerStartColor", _outerStartColor); - _dirty |= updateIfValid(properties, "outerEndColor", _outerEndColor); - - _dirty |= updateIfValid(properties, "startAt", _startAt); - _dirty |= updateIfValid(properties, "endAt", _endAt); - - _dirty |= updateIfValid(properties, { "radius", "outerRadius" }, _outerRadius); - _dirty |= updateIfValid(properties, "innerRadius", _innerRadius); - _dirty |= updateIfValid(properties, "hasTickMarks", _hasTickMarks); - _dirty |= updateIfValid(properties, "majorTickMarksAngle", _majorTickMarksAngle); - _dirty |= updateIfValid(properties, "minorTickMarksAngle", _minorTickMarksAngle); - _dirty |= updateIfValid(properties, "majorTickMarksLength", _majorTickMarksLength); - _dirty |= updateIfValid(properties, "minorTickMarksLength", _minorTickMarksLength); - _dirty |= updateIfValid(properties, "majorTickMarksColor", _majorTickMarksColor); - _dirty |= updateIfValid(properties, "minorTickMarksColor", _minorTickMarksColor); - - if (_innerStartAlpha < 1.0f || _innerEndAlpha < 1.0f || _outerStartAlpha < 1.0f || _outerEndAlpha < 1.0f) { - // Force the alpha to 0.5, since we'll ignore it in the presence of these other values, but we need - // it to be non-1 in order to get the right pipeline and non-0 in order to render at all. - _alpha = 0.5f; - } -} - -// Overlay's color and alpha properties are overridden. And the dimensions property is not used. -/**jsdoc - * These are the properties of a circle3d {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.Circle3DProperties - * - * @property {string} type=circle3d - Has the value "circle3d". Read-only. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: scale, size. - * Not used. - * - * @property {number} startAt=0 - The counter-clockwise angle from the overlay's x-axis that drawing starts at, in degrees. - * @property {number} endAt=360 - The counter-clockwise angle from the overlay's x-axis that drawing ends at, in degrees. - * @property {number} outerRadius=1 - The outer radius of the overlay, in meters. Synonym: radius. - * @property {number} innerRadius=0 - The inner radius of the overlay, in meters. - * @property {Color} color=255,255,255 - The color of the overlay. Setting this value also sets the values of - * innerStartColor, innerEndColor, outerStartColor, and outerEndColor. - * @property {Color} startColor - Sets the values of innerStartColor and outerStartColor. - * Write-only. - * @property {Color} endColor - Sets the values of innerEndColor and outerEndColor. - * Write-only. - * @property {Color} innerColor - Sets the values of innerStartColor and innerEndColor. - * Write-only. - * @property {Color} outerColor - Sets the values of outerStartColor and outerEndColor. - * Write-only. - * @property {Color} innerStartcolor - The color at the inner start point of the overlay. - * @property {Color} innerEndColor - The color at the inner end point of the overlay. - * @property {Color} outerStartColor - The color at the outer start point of the overlay. - * @property {Color} outerEndColor - The color at the outer end point of the overlay. - * @property {number} alpha=0.5 - The opacity of the overlay, 0.0 - 1.0. Setting this value also sets - * the values of innerStartAlpha, innerEndAlpha, outerStartAlpha, and - * outerEndAlpha. Synonym: Alpha; write-only. - * @property {number} startAlpha - Sets the values of innerStartAlpha and outerStartAlpha. - * Write-only. - * @property {number} endAlpha - Sets the values of innerEndAlpha and outerEndAlpha. - * Write-only. - * @property {number} innerAlpha - Sets the values of innerStartAlpha and innerEndAlpha. - * Write-only. - * @property {number} outerAlpha - Sets the values of outerStartAlpha and outerEndAlpha. - * Write-only. - * @property {number} innerStartAlpha=0 - The alpha at the inner start point of the overlay. - * @property {number} innerEndAlpha=0 - The alpha at the inner end point of the overlay. - * @property {number} outerStartAlpha=0 - The alpha at the outer start point of the overlay. - * @property {number} outerEndAlpha=0 - The alpha at the outer end point of the overlay. - - * @property {boolean} hasTickMarks=false - If true, tick marks are drawn. - * @property {number} majorTickMarksAngle=0 - The angle between major tick marks, in degrees. - * @property {number} minorTickMarksAngle=0 - The angle between minor tick marks, in degrees. - * @property {number} majorTickMarksLength=0 - The length of the major tick marks, in meters. A positive value draws tick marks - * outwards from the inner radius; a negative value draws tick marks inwards from the outer radius. - * @property {number} minorTickMarksLength=0 - The length of the minor tick marks, in meters. A positive value draws tick marks - * outwards from the inner radius; a negative value draws tick marks inwards from the outer radius. - * @property {Color} majorTickMarksColor=0,0,0 - The color of the major tick marks. - * @property {Color} minorTickMarksColor=0,0,0 - The color of the minor tick marks. - */ -QVariant Circle3DOverlay::getProperty(const QString& property) { - if (property == "startAt") { - return _startAt; - } - if (property == "endAt") { - return _endAt; - } - if (property == "radius") { - return _outerRadius; - } - if (property == "outerRadius") { - return _outerRadius; - } - if (property == "innerRadius") { - return _innerRadius; - } - if (property == "innerStartColor") { - return u8vec3ColortoVariant(_innerStartColor); - } - if (property == "innerEndColor") { - return u8vec3ColortoVariant(_innerEndColor); - } - if (property == "outerStartColor") { - return u8vec3ColortoVariant(_outerStartColor); - } - if (property == "outerEndColor") { - return u8vec3ColortoVariant(_outerEndColor); - } - if (property == "innerStartAlpha") { - return _innerStartAlpha; - } - if (property == "innerEndAlpha") { - return _innerEndAlpha; - } - if (property == "outerStartAlpha") { - return _outerStartAlpha; - } - if (property == "outerEndAlpha") { - return _outerEndAlpha; - } - if (property == "hasTickMarks") { - return _hasTickMarks; - } - if (property == "majorTickMarksAngle") { - return _majorTickMarksAngle; - } - if (property == "minorTickMarksAngle") { - return _minorTickMarksAngle; - } - if (property == "majorTickMarksLength") { - return _majorTickMarksLength; - } - if (property == "minorTickMarksLength") { - return _minorTickMarksLength; - } - if (property == "majorTickMarksColor") { - return u8vec3ColortoVariant(_majorTickMarksColor); - } - if (property == "minorTickMarksColor") { - return u8vec3ColortoVariant(_minorTickMarksColor); - } - - return Planar3DOverlay::getProperty(property); -} - -bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - // Scale the dimensions by the diameter - glm::vec2 dimensions = getOuterRadius() * 2.0f * getDimensions(); - glm::quat rotation = getWorldOrientation(); - - if (findRayRectangleIntersection(origin, direction, rotation, getWorldPosition(), dimensions, distance)) { - glm::vec3 hitPosition = origin + (distance * direction); - glm::vec3 localHitPosition = glm::inverse(getWorldOrientation()) * (hitPosition - getWorldPosition()); - localHitPosition.x /= getDimensions().x; - localHitPosition.y /= getDimensions().y; - float distanceToHit = glm::length(localHitPosition); - - if (getInnerRadius() <= distanceToHit && distanceToHit <= getOuterRadius()) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } - } - - return false; -} - -bool Circle3DOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - // Scale the dimensions by the diameter - glm::vec2 xyDimensions = getOuterRadius() * 2.0f * getDimensions(); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition(); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - glm::vec3 localHitPosition = localOrigin + localVelocity * parabolicDistance + 0.5f * localAcceleration * parabolicDistance * parabolicDistance; - localHitPosition.x /= getDimensions().x; - localHitPosition.y /= getDimensions().y; - float distanceToHit = glm::length(localHitPosition); - - if (getInnerRadius() <= distanceToHit && distanceToHit <= getOuterRadius()) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } - } - - return false; -} - -Circle3DOverlay* Circle3DOverlay::createClone() const { - return new Circle3DOverlay(this); -} diff --git a/interface/src/ui/overlays/Circle3DOverlay.h b/interface/src/ui/overlays/Circle3DOverlay.h deleted file mode 100644 index ca5e05a53b..0000000000 --- a/interface/src/ui/overlays/Circle3DOverlay.h +++ /dev/null @@ -1,96 +0,0 @@ -// -// Circle3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Circle3DOverlay_h -#define hifi_Circle3DOverlay_h - -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "Planar3DOverlay.h" - -class Circle3DOverlay : public Planar3DOverlay { - Q_OBJECT - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Circle3DOverlay(); - Circle3DOverlay(const Circle3DOverlay* circle3DOverlay); - ~Circle3DOverlay(); - - virtual void render(RenderArgs* args) override; - virtual const render::ShapeKey getShapeKey() override; - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - - float getStartAt() const { return _startAt; } - float getEndAt() const { return _endAt; } - float getOuterRadius() const { return _outerRadius; } - float getInnerRadius() const { return _innerRadius; } - bool getHasTickMarks() const { return _hasTickMarks; } - float getMajorTickMarksAngle() const { return _majorTickMarksAngle; } - float getMinorTickMarksAngle() const { return _minorTickMarksAngle; } - float getMajorTickMarksLength() const { return _majorTickMarksLength; } - float getMinorTickMarksLength() const { return _minorTickMarksLength; } - glm::u8vec3 getMajorTickMarksColor() const { return _majorTickMarksColor; } - glm::u8vec3 getMinorTickMarksColor() const { return _minorTickMarksColor; } - - void setStartAt(float value) { _startAt = value; } - void setEndAt(float value) { _endAt = value; } - void setOuterRadius(float value) { _outerRadius = value; } - void setInnerRadius(float value) { _innerRadius = value; } - void setHasTickMarks(bool value) { _hasTickMarks = value; } - void setMajorTickMarksAngle(float value) { _majorTickMarksAngle = value; } - void setMinorTickMarksAngle(float value) { _minorTickMarksAngle = value; } - void setMajorTickMarksLength(float value) { _majorTickMarksLength = value; } - void setMinorTickMarksLength(float value) { _minorTickMarksLength = value; } - void setMajorTickMarksColor(const glm::u8vec3& value) { _majorTickMarksColor = value; } - void setMinorTickMarksColor(const glm::u8vec3& value) { _minorTickMarksColor = value; } - - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - - virtual Circle3DOverlay* createClone() const override; - -protected: - float _startAt { 0 }; - float _endAt { 360 }; - float _outerRadius { 1 }; - float _innerRadius { 0 }; - - glm::u8vec3 _innerStartColor { DEFAULT_OVERLAY_COLOR }; - glm::u8vec3 _innerEndColor { DEFAULT_OVERLAY_COLOR }; - glm::u8vec3 _outerStartColor { DEFAULT_OVERLAY_COLOR }; - glm::u8vec3 _outerEndColor { DEFAULT_OVERLAY_COLOR }; - float _innerStartAlpha { DEFAULT_ALPHA }; - float _innerEndAlpha { DEFAULT_ALPHA }; - float _outerStartAlpha { DEFAULT_ALPHA }; - float _outerEndAlpha { DEFAULT_ALPHA }; - - bool _hasTickMarks { false }; - float _majorTickMarksAngle { 0 }; - float _minorTickMarksAngle { 0 }; - float _majorTickMarksLength { 0 }; - float _minorTickMarksLength { 0 }; - glm::u8vec3 _majorTickMarksColor { DEFAULT_OVERLAY_COLOR }; - glm::u8vec3 _minorTickMarksColor { DEFAULT_OVERLAY_COLOR }; - gpu::Primitive _solidPrimitive { gpu::TRIANGLE_FAN }; - int _quadVerticesID { 0 }; - int _lineVerticesID { 0 }; - int _majorTicksVerticesID { 0 }; - int _minorTicksVerticesID { 0 }; - - bool _dirty { true }; -}; - - -#endif // hifi_Circle3DOverlay_h diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp deleted file mode 100644 index 128281faee..0000000000 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ /dev/null @@ -1,196 +0,0 @@ -// -// Cube3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "Cube3DOverlay.h" - -#include -#include -#include -#include - -QString const Cube3DOverlay::TYPE = "cube"; - -Cube3DOverlay::Cube3DOverlay() { - auto geometryCache = DependencyManager::get(); - for (size_t i = 0; i < _geometryIds.size(); ++i) { - _geometryIds[i] = geometryCache->allocateID(); - } -} - -Cube3DOverlay::Cube3DOverlay(const Cube3DOverlay* cube3DOverlay) : - Volume3DOverlay(cube3DOverlay) -{ - auto geometryCache = DependencyManager::get(); - for (size_t i = 0; i < _geometryIds.size(); ++i) { - _geometryIds[i] = geometryCache->allocateID(); - } -} - -Cube3DOverlay::~Cube3DOverlay() { - auto geometryCache = DependencyManager::get(); - if (geometryCache) { - for (size_t i = 0; i < _geometryIds.size(); ++i) { - geometryCache->releaseID(_geometryIds[i]); - } - } -} - -void Cube3DOverlay::render(RenderArgs* args) { - if (!_renderVisible) { - return; // do nothing if we're not visible - } - - float alpha = getAlpha(); - glm::u8vec3 color = getColor(); - glm::vec4 cubeColor(toGlm(color), alpha); - - auto batch = args->_batch; - if (batch) { - Transform transform = getRenderTransform(); - auto geometryCache = DependencyManager::get(); - auto shapePipeline = args->_shapePipeline; - if (!shapePipeline) { - shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); - } - - if (_isSolid) { - batch->setModelTransform(transform); - geometryCache->renderSolidCubeInstance(args, *batch, cubeColor, shapePipeline); - } else { - geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); - if (getIsDashedLine()) { - auto dimensions = transform.getScale(); - transform.setScale(1.0f); - batch->setModelTransform(transform); - - glm::vec3 halfDimensions = dimensions / 2.0f; - glm::vec3 bottomLeftNear(-halfDimensions.x, -halfDimensions.y, -halfDimensions.z); - glm::vec3 bottomRightNear(halfDimensions.x, -halfDimensions.y, -halfDimensions.z); - glm::vec3 topLeftNear(-halfDimensions.x, halfDimensions.y, -halfDimensions.z); - glm::vec3 topRightNear(halfDimensions.x, halfDimensions.y, -halfDimensions.z); - - glm::vec3 bottomLeftFar(-halfDimensions.x, -halfDimensions.y, halfDimensions.z); - glm::vec3 bottomRightFar(halfDimensions.x, -halfDimensions.y, halfDimensions.z); - glm::vec3 topLeftFar(-halfDimensions.x, halfDimensions.y, halfDimensions.z); - glm::vec3 topRightFar(halfDimensions.x, halfDimensions.y, halfDimensions.z); - - geometryCache->renderDashedLine(*batch, bottomLeftNear, bottomRightNear, cubeColor, _geometryIds[0]); - geometryCache->renderDashedLine(*batch, bottomRightNear, bottomRightFar, cubeColor, _geometryIds[1]); - geometryCache->renderDashedLine(*batch, bottomRightFar, bottomLeftFar, cubeColor, _geometryIds[2]); - geometryCache->renderDashedLine(*batch, bottomLeftFar, bottomLeftNear, cubeColor, _geometryIds[3]); - - geometryCache->renderDashedLine(*batch, topLeftNear, topRightNear, cubeColor, _geometryIds[4]); - geometryCache->renderDashedLine(*batch, topRightNear, topRightFar, cubeColor, _geometryIds[5]); - geometryCache->renderDashedLine(*batch, topRightFar, topLeftFar, cubeColor, _geometryIds[6]); - geometryCache->renderDashedLine(*batch, topLeftFar, topLeftNear, cubeColor, _geometryIds[7]); - - geometryCache->renderDashedLine(*batch, bottomLeftNear, topLeftNear, cubeColor, _geometryIds[8]); - geometryCache->renderDashedLine(*batch, bottomRightNear, topRightNear, cubeColor, _geometryIds[9]); - geometryCache->renderDashedLine(*batch, bottomLeftFar, topLeftFar, cubeColor, _geometryIds[10]); - geometryCache->renderDashedLine(*batch, bottomRightFar, topRightFar, cubeColor, _geometryIds[11]); - - } else { - batch->setModelTransform(transform); - geometryCache->renderWireCubeInstance(args, *batch, cubeColor, shapePipeline); - } - } - } -} - -const render::ShapeKey Cube3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); - if (isTransparent()) { - builder.withTranslucent(); - } - if (!getIsSolid()) { - builder.withUnlit().withDepthBias(); - } - return builder.build(); -} - -Cube3DOverlay* Cube3DOverlay::createClone() const { - return new Cube3DOverlay(this); -} - -void Cube3DOverlay::setProperties(const QVariantMap& properties) { - Volume3DOverlay::setProperties(properties); -} - -/**jsdoc - * These are the properties of a cube {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.CubeProperties - * - * @property {string} type=cube - Has the value "cube". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. - */ -QVariant Cube3DOverlay::getProperty(const QString& property) { - return Volume3DOverlay::getProperty(property); -} - -Transform Cube3DOverlay::evalRenderTransform() { - // TODO: handle registration point?? - glm::vec3 position = getWorldPosition(); - glm::vec3 dimensions = getDimensions(); - glm::quat rotation = getWorldOrientation(); - - Transform transform; - transform.setScale(dimensions); - transform.setTranslation(position); - transform.setRotation(rotation); - return transform; -} - -scriptable::ScriptableModelBase Cube3DOverlay::getScriptableModel() { - auto geometryCache = DependencyManager::get(); - auto vertexColor = ColorUtils::toVec3(_color); - scriptable::ScriptableModelBase result; - if (auto mesh = geometryCache->meshFromShape(GeometryCache::Cube, vertexColor)) { - result.objectID = Overlay::getID(); - result.append(mesh); - } - return result; -} diff --git a/interface/src/ui/overlays/Cube3DOverlay.h b/interface/src/ui/overlays/Cube3DOverlay.h deleted file mode 100644 index d28d11920a..0000000000 --- a/interface/src/ui/overlays/Cube3DOverlay.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Cube3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Cube3DOverlay_h -#define hifi_Cube3DOverlay_h - -#include "Volume3DOverlay.h" - -class Cube3DOverlay : public Volume3DOverlay { - Q_OBJECT - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Cube3DOverlay(); - Cube3DOverlay(const Cube3DOverlay* cube3DOverlay); - ~Cube3DOverlay(); - - virtual void render(RenderArgs* args) override; - virtual const render::ShapeKey getShapeKey() override; - - virtual Cube3DOverlay* createClone() const override; - - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - - virtual scriptable::ScriptableModelBase getScriptableModel() override; -protected: - Transform evalRenderTransform() override; - -private: - // edges on a cube - std::array _geometryIds; -}; - - -#endif // hifi_Cube3DOverlay_h diff --git a/interface/src/ui/overlays/Grid3DOverlay.cpp b/interface/src/ui/overlays/Grid3DOverlay.cpp deleted file mode 100644 index 92481b8116..0000000000 --- a/interface/src/ui/overlays/Grid3DOverlay.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// -// Grid3DOverlay.cpp -// interface/src/ui/overlays -// -// Created by Ryan Huffman on 11/06/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Grid3DOverlay.h" - -#include -#include -#include -#include -#include - - -QString const Grid3DOverlay::TYPE = "grid"; -const float DEFAULT_SCALE = 100.0f; - -Grid3DOverlay::Grid3DOverlay() { - setDimensions(DEFAULT_SCALE); - updateGrid(); - _geometryId = DependencyManager::get()->allocateID(); -} - -Grid3DOverlay::Grid3DOverlay(const Grid3DOverlay* grid3DOverlay) : - Planar3DOverlay(grid3DOverlay), - _majorGridEvery(grid3DOverlay->_majorGridEvery), - _minorGridEvery(grid3DOverlay->_minorGridEvery) -{ - updateGrid(); - _geometryId = DependencyManager::get()->allocateID(); -} - -Grid3DOverlay::~Grid3DOverlay() { - auto geometryCache = DependencyManager::get(); - if (geometryCache) { - geometryCache->releaseID(_geometryId); - } -} - -AABox Grid3DOverlay::getBounds() const { - if (_followCamera) { - // This is a UI element that should always be in view, lie to the octree to avoid culling - const AABox DOMAIN_BOX = AABox(glm::vec3(-TREE_SCALE / 2), TREE_SCALE); - return DOMAIN_BOX; - } - return Planar3DOverlay::getBounds(); -} - -void Grid3DOverlay::render(RenderArgs* args) { - if (!_renderVisible) { - return; // do nothing if we're not visible - } - - float alpha = getAlpha(); - glm::u8vec3 color = getColor(); - glm::vec4 gridColor(toGlm(color), alpha); - - auto batch = args->_batch; - - if (batch) { - auto minCorner = glm::vec2(-0.5f, -0.5f); - auto maxCorner = glm::vec2(0.5f, 0.5f); - - auto position = getWorldPosition(); - if (_followCamera) { - // Get the camera position rounded to the nearest major grid line - // This grid is for UI and should lie on worldlines - auto cameraPosition = - (float)_majorGridEvery * glm::round(args->getViewFrustum().getPosition() / (float)_majorGridEvery); - - position += glm::vec3(cameraPosition.x, 0.0f, cameraPosition.z); - } - - Transform transform = getRenderTransform(); - transform.setTranslation(position); - batch->setModelTransform(transform); - const float MINOR_GRID_EDGE = 0.0025f; - const float MAJOR_GRID_EDGE = 0.005f; - DependencyManager::get()->renderGrid(*batch, minCorner, maxCorner, - _minorGridRowDivisions, _minorGridColDivisions, MINOR_GRID_EDGE, - _majorGridRowDivisions, _majorGridColDivisions, MAJOR_GRID_EDGE, - gridColor, _geometryId); - } -} - -const render::ShapeKey Grid3DOverlay::getShapeKey() { - return render::ShapeKey::Builder().withOwnPipeline().withUnlit().withDepthBias(); -} - -void Grid3DOverlay::setProperties(const QVariantMap& properties) { - Planar3DOverlay::setProperties(properties); - if (properties["followCamera"].isValid()) { - _followCamera = properties["followCamera"].toBool(); - } - - if (properties["majorGridEvery"].isValid()) { - _majorGridEvery = properties["majorGridEvery"].toInt(); - } - - if (properties["minorGridEvery"].isValid()) { - _minorGridEvery = properties["minorGridEvery"].toFloat(); - } - - updateGrid(); -} - -/**jsdoc - * These are the properties of a grid {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.GridProperties - * - * @property {string} type=grid - Has the value "grid". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: scale, size. - * - * @property {boolean} followCamera=true - If true, the grid is always visible even as the camera moves to another - * position. - * @property {number} majorGridEvery=5 - Integer number of minorGridEvery intervals at which to draw a thick grid - * line. Minimum value = 1. - * @property {number} minorGridEvery=1 - Real number of meters at which to draw thin grid lines. Minimum value = - * 0.001. - */ -QVariant Grid3DOverlay::getProperty(const QString& property) { - if (property == "followCamera") { - return _followCamera; - } - if (property == "majorGridEvery") { - return _majorGridEvery; - } - if (property == "minorGridEvery") { - return _minorGridEvery; - } - - return Planar3DOverlay::getProperty(property); -} - -Grid3DOverlay* Grid3DOverlay::createClone() const { - return new Grid3DOverlay(this); -} - -void Grid3DOverlay::updateGrid() { - const int MAJOR_GRID_EVERY_MIN = 1; - const float MINOR_GRID_EVERY_MIN = 0.01f; - - _majorGridEvery = std::max(_majorGridEvery, MAJOR_GRID_EVERY_MIN); - _minorGridEvery = std::max(_minorGridEvery, MINOR_GRID_EVERY_MIN); - - _majorGridRowDivisions = getDimensions().x / _majorGridEvery; - _majorGridColDivisions = getDimensions().y / _majorGridEvery; - - _minorGridRowDivisions = getDimensions().x / _minorGridEvery; - _minorGridColDivisions = getDimensions().y / _minorGridEvery; -} - -Transform Grid3DOverlay::evalRenderTransform() { - Transform transform; - transform.setRotation(getWorldOrientation()); - transform.setScale(glm::vec3(getDimensions(), 1.0f)); - return transform; -} diff --git a/interface/src/ui/overlays/Grid3DOverlay.h b/interface/src/ui/overlays/Grid3DOverlay.h deleted file mode 100644 index 64b65b3178..0000000000 --- a/interface/src/ui/overlays/Grid3DOverlay.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// Grid3DOverlay.h -// interface/src/ui/overlays -// -// Created by Ryan Huffman on 11/06/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Grid3DOverlay_h -#define hifi_Grid3DOverlay_h - -#include "Planar3DOverlay.h" - -class Grid3DOverlay : public Planar3DOverlay { - Q_OBJECT - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Grid3DOverlay(); - Grid3DOverlay(const Grid3DOverlay* grid3DOverlay); - ~Grid3DOverlay(); - - virtual AABox getBounds() const override; - - virtual void render(RenderArgs* args) override; - virtual const render::ShapeKey getShapeKey() override; - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - - virtual Grid3DOverlay* createClone() const override; - - // Grids are UI tools, and may not be intersected (pickable) - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, - glm::vec3& surfaceNormal, bool precisionPicking = false) override { return false; } - virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override { return false; } - -protected: - Transform evalRenderTransform() override; - -private: - void updateGrid(); - - bool _followCamera { true }; - - int _majorGridEvery { 5 }; - float _majorGridRowDivisions; - float _majorGridColDivisions; - - float _minorGridEvery { 1.0f }; - float _minorGridRowDivisions; - float _minorGridColDivisions; - int _geometryId { 0 }; -}; - -#endif // hifi_Grid3DOverlay_h diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp deleted file mode 100644 index dcf3ca2285..0000000000 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ /dev/null @@ -1,341 +0,0 @@ -// -// Image3DOverlay.cpp -// -// -// Created by Clement on 7/1/14. -// Modified and renamed by Zander Otavka on 8/4/15 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Image3DOverlay.h" - -#include -#include -#include -#include - -#include "GeometryUtil.h" - -#include "AbstractViewStateInterface.h" - -QString const Image3DOverlay::TYPE = "image3d"; - -Image3DOverlay::Image3DOverlay() { - _isLoaded = false; - _geometryId = DependencyManager::get()->allocateID(); -} - -Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) : - Billboard3DOverlay(image3DOverlay), - _url(image3DOverlay->_url), - _texture(image3DOverlay->_texture), - _emissive(image3DOverlay->_emissive), - _fromImage(image3DOverlay->_fromImage) -{ - _geometryId = DependencyManager::get()->allocateID(); -} - -Image3DOverlay::~Image3DOverlay() { - auto geometryCache = DependencyManager::get(); - if (geometryCache) { - geometryCache->releaseID(_geometryId); - } -} - -void Image3DOverlay::update(float deltatime) { - if (!_isLoaded) { - _isLoaded = true; - _texture = DependencyManager::get()->getTexture(_url); - _textureIsLoaded = false; - } - Parent::update(deltatime); -} - -void Image3DOverlay::render(RenderArgs* args) { - if (!_renderVisible || !getParentVisible() || !_texture || !_texture->isLoaded()) { - return; - } - - // Once the texture has loaded, check if we need to update the render item because of transparency - if (!_textureIsLoaded && _texture && _texture->getGPUTexture()) { - _textureIsLoaded = true; - bool prevAlphaTexture = _alphaTexture; - _alphaTexture = _texture->getGPUTexture()->getUsage().isAlpha(); - if (_alphaTexture != prevAlphaTexture) { - auto itemID = getRenderItemID(); - if (render::Item::isValidID(itemID)) { - render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - render::Transaction transaction; - transaction.updateItem(itemID); - scene->enqueueTransaction(transaction); - } - } - } - - Q_ASSERT(args->_batch); - gpu::Batch* batch = args->_batch; - - float imageWidth = _texture->getWidth(); - float imageHeight = _texture->getHeight(); - - QRect fromImage; - if (_fromImage.width() <= 0) { - fromImage.setX(0); - fromImage.setWidth(imageWidth); - } else { - float scaleX = imageWidth / _texture->getOriginalWidth(); - fromImage.setX(scaleX * _fromImage.x()); - fromImage.setWidth(scaleX * _fromImage.width()); - } - - if (_fromImage.height() <= 0) { - fromImage.setY(0); - fromImage.setHeight(imageHeight); - } else { - float scaleY = imageHeight / _texture->getOriginalHeight(); - fromImage.setY(scaleY * _fromImage.y()); - fromImage.setHeight(scaleY * _fromImage.height()); - } - - float maxSize = glm::max(fromImage.width(), fromImage.height()); - float x = _keepAspectRatio ? fromImage.width() / (2.0f * maxSize) : 0.5f; - float y = _keepAspectRatio ? -fromImage.height() / (2.0f * maxSize) : -0.5f; - - glm::vec2 topLeft(-x, -y); - glm::vec2 bottomRight(x, y); - glm::vec2 texCoordTopLeft((fromImage.x() + 0.5f) / imageWidth, (fromImage.y() + 0.5f) / imageHeight); - glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth, - (fromImage.y() + fromImage.height() - 0.5f) / imageHeight); - - float alpha = getAlpha(); - glm::u8vec3 color = getColor(); - glm::vec4 imageColor(toGlm(color), alpha); - - batch->setModelTransform(getRenderTransform()); - batch->setResourceTexture(0, _texture->getGPUTexture()); - - DependencyManager::get()->renderQuad( - *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, - imageColor, _geometryId - ); - - batch->setResourceTexture(0, nullptr); // restore default white color after me -} - -const render::ShapeKey Image3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); - if (_emissive) { - builder.withUnlit(); - } - if (isTransparent()) { - builder.withTranslucent(); - } - return builder.build(); -} - -void Image3DOverlay::setProperties(const QVariantMap& properties) { - Billboard3DOverlay::setProperties(properties); - - auto urlValue = properties["url"]; - if (urlValue.isValid()) { - QString newURL = urlValue.toString(); - if (newURL != _url) { - setURL(newURL); - } - } - - auto subImageBoundsVar = properties["subImage"]; - if (subImageBoundsVar.isValid()) { - if (subImageBoundsVar.isNull()) { - _fromImage = QRect(); - } else { - QRect oldSubImageRect = _fromImage; - QRect subImageRect = _fromImage; - auto subImageBounds = subImageBoundsVar.toMap(); - if (subImageBounds["x"].isValid()) { - subImageRect.setX(subImageBounds["x"].toInt()); - } else { - subImageRect.setX(oldSubImageRect.x()); - } - if (subImageBounds["y"].isValid()) { - subImageRect.setY(subImageBounds["y"].toInt()); - } else { - subImageRect.setY(oldSubImageRect.y()); - } - if (subImageBounds["width"].isValid()) { - subImageRect.setWidth(subImageBounds["width"].toInt()); - } else { - subImageRect.setWidth(oldSubImageRect.width()); - } - if (subImageBounds["height"].isValid()) { - subImageRect.setHeight(subImageBounds["height"].toInt()); - } else { - subImageRect.setHeight(oldSubImageRect.height()); - } - setClipFromSource(subImageRect); - } - } - - auto keepAspectRatioValue = properties["keepAspectRatio"]; - if (keepAspectRatioValue.isValid()) { - _keepAspectRatio = keepAspectRatioValue.toBool(); - } - - auto emissiveValue = properties["emissive"]; - if (emissiveValue.isValid()) { - _emissive = emissiveValue.toBool(); - } -} - -/**jsdoc - * These are the properties of an image3d {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.Image3DProperties - * - * @property {string} type=image3d - Has the value "image3d". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: scale, size. - * - * @property {bool} keepAspectRatio=true - overlays will maintain the aspect ratio when the subImage is applied. - * - * @property {boolean} isFacingAvatar - If true, the overlay is rotated to face the user's camera about an axis - * parallel to the user's avatar's "up" direction. - * - * @property {string} url - The URL of the PNG or JPG image to display. - * @property {Rect} subImage - The portion of the image to display. Defaults to the full image. - * @property {boolean} emissive - If true, the overlay is displayed at full brightness, otherwise it is rendered - * with scene lighting. - */ -QVariant Image3DOverlay::getProperty(const QString& property) { - if (property == "url") { - return _url; - } - if (property == "subImage") { - return _fromImage; - } - if (property == "emissive") { - return _emissive; - } - if (property == "keepAspectRatio") { - return _keepAspectRatio; - } - - return Billboard3DOverlay::getProperty(property); -} - -void Image3DOverlay::setURL(const QString& url) { - _url = url; - _isLoaded = false; -} - -bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - if (_texture && _texture->isLoaded()) { - Transform transform = getTransform(); - - // Produce the dimensions of the overlay based on the image's aspect ratio and the overlay's scale. - bool isNull = _fromImage.isNull(); - float width = isNull ? _texture->getWidth() : _fromImage.width(); - float height = isNull ? _texture->getHeight() : _fromImage.height(); - float maxSize = glm::max(width, height); - glm::vec2 dimensions = _dimensions * glm::vec2(width / maxSize, height / maxSize); - glm::quat rotation = transform.getRotation(); - - if (findRayRectangleIntersection(origin, direction, rotation, transform.getTranslation(), dimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } - } - - return false; -} - -bool Image3DOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - if (_texture && _texture->isLoaded()) { - Transform transform = getTransform(); - - // Produce the dimensions of the overlay based on the image's aspect ratio and the overlay's scale. - bool isNull = _fromImage.isNull(); - float width = isNull ? _texture->getWidth() : _fromImage.width(); - float height = isNull ? _texture->getHeight() : _fromImage.height(); - float maxSize = glm::max(width, height); - glm::vec2 dimensions = _dimensions * glm::vec2(width / maxSize, height / maxSize); - glm::quat rotation = transform.getRotation(); - glm::vec3 position = getWorldPosition(); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, dimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } - } - - return false; -} - -Image3DOverlay* Image3DOverlay::createClone() const { - return new Image3DOverlay(this); -} - -Transform Image3DOverlay::evalRenderTransform() { - auto transform = Parent::evalRenderTransform(); - transform.postScale(glm::vec3(getDimensions(), 1.0f)); - return transform; -} diff --git a/interface/src/ui/overlays/Image3DOverlay.h b/interface/src/ui/overlays/Image3DOverlay.h deleted file mode 100644 index 1000401abb..0000000000 --- a/interface/src/ui/overlays/Image3DOverlay.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Image3DOverlay.h -// -// -// Created by Clement on 7/1/14. -// Modified and renamed by Zander Otavka on 8/4/15 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Image3DOverlay_h -#define hifi_Image3DOverlay_h - -#include - -#include "Billboard3DOverlay.h" - -class Image3DOverlay : public Billboard3DOverlay { - Q_OBJECT - using Parent = Billboard3DOverlay; - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Image3DOverlay(); - Image3DOverlay(const Image3DOverlay* image3DOverlay); - ~Image3DOverlay(); - virtual void render(RenderArgs* args) override; - - virtual void update(float deltatime) override; - - virtual const render::ShapeKey getShapeKey() override; - - // setters - void setURL(const QString& url); - void setClipFromSource(const QRect& bounds) { _fromImage = bounds; } - - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - bool isTransparent() override { return Base3DOverlay::isTransparent() || _alphaTexture; } - - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - - virtual Image3DOverlay* createClone() const override; - -protected: - Transform evalRenderTransform() override; - -private: - QString _url; - NetworkTexturePointer _texture; - bool _textureIsLoaded { false }; - bool _alphaTexture { false }; - bool _emissive { false }; - bool _keepAspectRatio { true }; - - QRect _fromImage; // where from in the image to sample - int _geometryId { 0 }; -}; - -#endif // hifi_Image3DOverlay_h diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index 19f32511f6..228c904026 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -19,29 +19,6 @@ QString const ImageOverlay::TYPE = "image"; QUrl const ImageOverlay::URL(QString("hifi/overlays/ImageOverlay.qml")); -// ImageOverlay's properties are defined in the QML file specified above. -/**jsdoc - * These are the properties of an image {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.ImageProperties - * - * @property {Rect} bounds - The position and size of the image display area, in pixels. Write-only. - * @property {number} x - Integer left, x-coordinate value of the image display area = bounds.x. - * Write-only. - * @property {number} y - Integer top, y-coordinate value of the image display area = bounds.y. - * Write-only. - * @property {number} width - Integer width of the image display area = bounds.width. Write-only. - * @property {number} height - Integer height of the image display area = bounds.height. Write-only. - * @property {string} imageURL - The URL of the image file to display. The image is scaled to fit to the bounds. - * Write-only. - * @property {Vec2} subImage=0,0 - Integer coordinates of the top left pixel to start using image content from. - * Write-only. - * @property {Color} color=0,0,0 - The color to apply over the top of the image to colorize it. Write-only. - * @property {number} alpha=0.0 - The opacity of the color applied over the top of the image, 0.0 - - * 1.0. Write-only. - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * Write-only. - */ - ImageOverlay::ImageOverlay() : QmlOverlay(URL) { } @@ -50,5 +27,4 @@ ImageOverlay::ImageOverlay(const ImageOverlay* imageOverlay) : ImageOverlay* ImageOverlay::createClone() const { return new ImageOverlay(this); -} - +} \ No newline at end of file diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp deleted file mode 100644 index b1c316c6af..0000000000 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ /dev/null @@ -1,366 +0,0 @@ -// -// Line3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Line3DOverlay.h" - -#include -#include - -#include "AbstractViewStateInterface.h" - -QString const Line3DOverlay::TYPE = "line3d"; - -Line3DOverlay::Line3DOverlay() : - _geometryCacheID(DependencyManager::get()->allocateID()) -{ -} - -Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) : - Base3DOverlay(line3DOverlay), - _geometryCacheID(DependencyManager::get()->allocateID()) -{ - setParentID(line3DOverlay->getParentID()); - setParentJointIndex(line3DOverlay->getParentJointIndex()); - setLocalTransform(line3DOverlay->getLocalTransform()); - _direction = line3DOverlay->getDirection(); - _length = line3DOverlay->getLength(); - _endParentID = line3DOverlay->getEndParentID(); - _endParentJointIndex = line3DOverlay->getEndJointIndex(); - _lineWidth = line3DOverlay->getLineWidth(); - _glow = line3DOverlay->getGlow(); -} - -Line3DOverlay::~Line3DOverlay() { - auto geometryCache = DependencyManager::get(); - if (_geometryCacheID && geometryCache) { - geometryCache->releaseID(_geometryCacheID); - } -} - -glm::vec3 Line3DOverlay::getStart() const { - return getWorldPosition(); -} - -glm::vec3 Line3DOverlay::getEnd() const { - bool success; - glm::vec3 localEnd; - glm::vec3 worldEnd; - - if (_endParentID != QUuid()) { - glm::vec3 localOffset = _direction * _length; - bool success; - worldEnd = localToWorld(localOffset, _endParentID, _endParentJointIndex, getScalesWithParent(), success); - return worldEnd; - } - - localEnd = getLocalEnd(); - worldEnd = localToWorld(localEnd, getParentID(), getParentJointIndex(), getScalesWithParent(), success); - if (!success) { - qDebug() << "Line3DOverlay::getEnd failed, parentID = " << getParentID(); - } - return worldEnd; -} - -void Line3DOverlay::setStart(const glm::vec3& start) { - setWorldPosition(start); -} - -void Line3DOverlay::setEnd(const glm::vec3& end) { - bool success; - glm::vec3 localStart; - glm::vec3 localEnd; - glm::vec3 offset; - - if (_endParentID != QUuid()) { - offset = worldToLocal(end, _endParentID, _endParentJointIndex, getScalesWithParent(), success); - } else { - localStart = getLocalStart(); - localEnd = worldToLocal(end, getParentID(), getParentJointIndex(), getScalesWithParent(), success); - offset = localEnd - localStart; - } - if (!success) { - qDebug() << "Line3DOverlay::setEnd failed"; - return; - } - - _length = glm::length(offset); - if (_length > 0.0f) { - _direction = glm::normalize(offset); - } else { - _direction = glm::vec3(0.0f); - } - notifyRenderVariableChange(); -} - -void Line3DOverlay::setLocalEnd(const glm::vec3& localEnd) { - glm::vec3 offset; - if (_endParentID != QUuid()) { - offset = localEnd; - } else { - glm::vec3 localStart = getLocalStart(); - offset = localEnd - localStart; - } - _length = glm::length(offset); - if (_length > 0.0f) { - _direction = glm::normalize(offset); - } else { - _direction = glm::vec3(0.0f); - } -} - -AABox Line3DOverlay::getBounds() const { - auto extents = Extents{}; - extents.addPoint(getStart()); - extents.addPoint(getEnd()); - return AABox(extents); -} - -void Line3DOverlay::render(RenderArgs* args) { - if (!_renderVisible) { - return; // do nothing if we're not visible - } - - float alpha = getAlpha(); - glm::u8vec3 color = getColor(); - glm::vec4 colorv4(toGlm(color), alpha); - auto batch = args->_batch; - if (batch) { - batch->setModelTransform(Transform()); - auto& renderTransform = getRenderTransform(); - glm::vec3 start = renderTransform.getTranslation(); - glm::vec3 end = renderTransform.transform(vec3(0.0, 0.0, -1.0)); - - auto geometryCache = DependencyManager::get(); - if (getIsDashedLine()) { - // TODO: add support for color to renderDashedLine() - geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); - geometryCache->renderDashedLine(*batch, start, end, colorv4, _geometryCacheID); - } else { - // renderGlowLine handles both glow = 0 and glow > 0 cases - geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _lineWidth, _geometryCacheID); - } - } -} - -const render::ShapeKey Line3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); - if (isTransparent()) { - builder.withTranslucent(); - } - return builder.build(); -} - -void Line3DOverlay::setProperties(const QVariantMap& originalProperties) { - QVariantMap properties = originalProperties; - glm::vec3 newStart(0.0f); - bool newStartSet { false }; - glm::vec3 newEnd(0.0f); - bool newEndSet { false }; - - auto start = properties["start"]; - // If "start" property was not there, check to see if they included aliases: startPoint, p1 - if (!start.isValid()) { - start = properties["startPoint"]; - } - if (!start.isValid()) { - start = properties["p1"]; - } - if (start.isValid()) { - newStart = vec3FromVariant(start); - newStartSet = true; - } - properties.remove("start"); // so that Base3DOverlay doesn't respond to it - properties.remove("startPoint"); - properties.remove("p1"); - - auto end = properties["end"]; - // If "end" property was not there, check to see if they included aliases: endPoint, p2 - if (!end.isValid()) { - end = properties["endPoint"]; - } - if (!end.isValid()) { - end = properties["p2"]; - } - if (end.isValid()) { - newEnd = vec3FromVariant(end); - newEndSet = true; - } - properties.remove("end"); // so that Base3DOverlay doesn't respond to it - properties.remove("endPoint"); - properties.remove("p2"); - - auto length = properties["length"]; - if (length.isValid()) { - _length = length.toFloat(); - } - - Base3DOverlay::setProperties(properties); - - auto endParentIDProp = properties["endParentID"]; - if (endParentIDProp.isValid()) { - _endParentID = QUuid(endParentIDProp.toString()); - } - auto endParentJointIndexProp = properties["endParentJointIndex"]; - if (endParentJointIndexProp.isValid()) { - _endParentJointIndex = endParentJointIndexProp.toInt(); - } - - auto localStart = properties["localStart"]; - if (localStart.isValid()) { - glm::vec3 tmpLocalEnd = getLocalEnd(); - setLocalStart(vec3FromVariant(localStart)); - setLocalEnd(tmpLocalEnd); - } - - auto localEnd = properties["localEnd"]; - if (localEnd.isValid()) { - setLocalEnd(vec3FromVariant(localEnd)); - } - - // these are saved until after Base3DOverlay::setProperties so parenting infomation can be set, first - if (newStartSet) { - setStart(newStart); - } - if (newEndSet) { - setEnd(newEnd); - } - - auto glow = properties["glow"]; - if (glow.isValid()) { - float prevGlow = _glow; - setGlow(glow.toFloat()); - // Update our payload key if necessary to handle transparency - if ((prevGlow <= 0.0f && _glow > 0.0f) || (prevGlow > 0.0f && _glow <= 0.0f)) { - auto itemID = getRenderItemID(); - if (render::Item::isValidID(itemID)) { - render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - render::Transaction transaction; - transaction.updateItem(itemID); - scene->enqueueTransaction(transaction); - } - } - } - - auto lineWidth = properties["lineWidth"]; - if (lineWidth.isValid()) { - setLineWidth(lineWidth.toFloat()); - } -} - -/**jsdoc - * These are the properties of a line3d {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.Line3DProperties - * - * @property {string} type=line3d - Has the value "line3d". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {Uuid} endParentID=null - The avatar, entity, or overlay that the end point of the line is parented to. - * @property {number} endParentJointIndex=65535 - Integer value specifying the skeleton joint that the end point of the line is - * attached to if parentID is an avatar skeleton. A value of 65535 means "no joint". - * @property {Vec3} start - The start point of the line. Synonyms: startPoint, p1, and - * position. - * @property {Vec3} end - The end point of the line. Synonyms: endPoint and p2. - * @property {Vec3} localStart - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as start. Synonym: localPosition. - * @property {Vec3} localEnd - The local position of the overlay relative to its parent if the overlay has a - * endParentID set, otherwise the same value as end. - * @property {number} length - The length of the line, in meters. This can be set after creating a line with start and end - * points. - * @property {number} glow=0 - If glow > 0, the line is rendered with a glow. - * @property {number} lineWidth=0.02 - If glow > 0, this is the width of the glow, in meters. - */ -QVariant Line3DOverlay::getProperty(const QString& property) { - if (property == "start" || property == "startPoint" || property == "p1") { - return vec3toVariant(getStart()); - } - if (property == "end" || property == "endPoint" || property == "p2") { - return vec3toVariant(getEnd()); - } - if (property == "length") { - return QVariant(getLength()); - } - if (property == "endParentID") { - return _endParentID; - } - if (property == "endParentJointIndex") { - return _endParentJointIndex; - } - if (property == "localStart") { - return vec3toVariant(getLocalStart()); - } - if (property == "localEnd") { - return vec3toVariant(getLocalEnd()); - } - if (property == "glow") { - return getGlow(); - } - if (property == "lineWidth") { - return _lineWidth; - } - - return Base3DOverlay::getProperty(property); -} - -Line3DOverlay* Line3DOverlay::createClone() const { - return new Line3DOverlay(this); -} - -Transform Line3DOverlay::evalRenderTransform() { - // Capture start and endin the renderTransform: - // start is the origin - // end is at the tip of the front axis aka -Z - Transform transform; - transform.setTranslation( getStart()); - auto endPos = getEnd(); - - auto vec = endPos - transform.getTranslation(); - const float MIN_LINE_LENGTH = 0.0001f; - auto scale = glm::max(glm::length(vec), MIN_LINE_LENGTH); - auto dir = vec / scale; - auto orientation = glm::rotation(glm::vec3(0.0f, 0.0f, -1.0f), dir); - transform.setRotation(orientation); - transform.setScale(scale); - - return transform; -} diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h deleted file mode 100644 index 79af937f23..0000000000 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Line3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Line3DOverlay_h -#define hifi_Line3DOverlay_h - -#include "Base3DOverlay.h" - -class Line3DOverlay : public Base3DOverlay { - Q_OBJECT - using Parent = Base3DOverlay; - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Line3DOverlay(); - Line3DOverlay(const Line3DOverlay* line3DOverlay); - ~Line3DOverlay(); - virtual void render(RenderArgs* args) override; - virtual const render::ShapeKey getShapeKey() override; - virtual AABox getBounds() const override; - - // getters - glm::vec3 getStart() const; - glm::vec3 getEnd() const; - const float& getLineWidth() const { return _lineWidth; } - const float& getGlow() const { return _glow; } - - // setters - void setStart(const glm::vec3& start); - void setEnd(const glm::vec3& end); - - void setLocalStart(const glm::vec3& localStart) { setLocalPosition(localStart); } - void setLocalEnd(const glm::vec3& localEnd); - - void setLineWidth(const float& lineWidth) { _lineWidth = lineWidth; } - void setGlow(const float& glow) { _glow = glow; } - - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - bool isTransparent() override { return Base3DOverlay::isTransparent() || _glow > 0.0f; } - - virtual Line3DOverlay* createClone() const override; - - glm::vec3 getDirection() const { return _direction; } - float getLength() const { return _length; } - glm::vec3 getLocalStart() const { return getLocalPosition(); } - glm::vec3 getLocalEnd() const { return getLocalStart() + _direction * _length; } - QUuid getEndParentID() const { return _endParentID; } - quint16 getEndJointIndex() const { return _endParentJointIndex; } - -protected: - Transform evalRenderTransform() override; - -private: - QUuid _endParentID; - quint16 _endParentJointIndex { INVALID_JOINT_INDEX }; - - // _direction and _length are in the parent's frame. If _endParentID is set, they are - // relative to that. Otherwise, they are relative to the local-start-position (which is the - // same as localPosition) - glm::vec3 _direction; // in parent frame - float _length { 1.0 }; // in parent frame - - const float DEFAULT_LINE_WIDTH = 0.02f; - float _lineWidth { DEFAULT_LINE_WIDTH }; - float _glow { 0.0 }; - int _geometryCacheID; -}; - -#endif // hifi_Line3DOverlay_h diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp deleted file mode 100644 index 92a316690a..0000000000 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ /dev/null @@ -1,735 +0,0 @@ -// -// ModelOverlay.cpp -// -// -// Created by Clement on 6/30/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "ModelOverlay.h" - -#include -#include - -#include - -#include "Application.h" - - -QString const ModelOverlay::TYPE = "model"; - -ModelOverlay::ModelOverlay() - : _model(std::make_shared(nullptr, this)), - _modelTextures(QVariantMap()) -{ - _model->setLoadingPriority(_loadPriority); - _isLoaded = false; - render::ScenePointer scene = qApp->getMain3DScene(); - _model->setVisibleInScene(false, scene); -} - -ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) : - Volume3DOverlay(modelOverlay), - _model(std::make_shared(nullptr, this)), - _modelTextures(QVariantMap()), - _url(modelOverlay->_url), - _updateModel(false), - _scaleToFit(modelOverlay->_scaleToFit), - _loadPriority(modelOverlay->_loadPriority), - - _animationURL(modelOverlay->_animationURL), - _animationFPS(modelOverlay->_animationFPS), - _animationCurrentFrame(modelOverlay->_animationCurrentFrame), - _animationRunning(modelOverlay->_animationRunning), - _animationLoop(modelOverlay->_animationLoop), - _animationFirstFrame(modelOverlay->_animationFirstFrame), - _animationLastFrame(modelOverlay->_animationLastFrame), - _animationHold(modelOverlay->_animationHold), - _animationAllowTranslation(modelOverlay->_animationAllowTranslation) - - // Joint translations and rotations aren't copied because the model needs to load before they can be applied. -{ - _model->setLoadingPriority(_loadPriority); - if (_url.isValid()) { - _updateModel = true; - _isLoaded = false; - } -} - -void ModelOverlay::update(float deltatime) { - Base3DOverlay::update(deltatime); - - if (_updateModel) { - _updateModel = false; - _model->setSnapModelToCenter(true); - Transform transform = evalRenderTransform(); - if (_scaleToFit) { - _model->setScaleToFit(true, transform.getScale() * getDimensions()); - } else { - _model->setScale(transform.getScale()); - } - _model->setRotation(transform.getRotation()); - _model->setTranslation(transform.getTranslation()); - _model->setURL(_url); - _model->simulate(deltatime, true); - } else { - _model->simulate(deltatime); - } - _isLoaded = _model->isActive(); - - if (isAnimatingSomething()) { - if (!jointsMapped()) { - mapAnimationJoints(_model->getJointNames()); - } - animate(); - } - - // check to see if when we added our model to the scene they were ready, if they were not ready, then - // fix them up in the scene - render::ScenePointer scene = qApp->getMain3DScene(); - render::Transaction transaction; - if (_model->needsFixupInScene()) { - emit DependencyManager::get()->modelRemovedFromScene(Overlay::getID(), NestableType::Overlay, _model); - _model->removeFromScene(scene, transaction); - _model->addToScene(scene, transaction); - - auto newRenderItemIDs{ _model->fetchRenderItemIDs() }; - transaction.updateItem(getRenderItemID(), [newRenderItemIDs](Overlay& data) { - auto modelOverlay = static_cast(&data); - modelOverlay->setSubRenderItemIDs(newRenderItemIDs); - }); - emit DependencyManager::get()->modelAddedToScene(Overlay::getID(), NestableType::Overlay, _model); - } - bool metaDirty = false; - if (_visibleDirty && _texturesLoaded) { - _visibleDirty = false; - // don't show overlays in mirrors or spectator-cam unless _isVisibleInSecondaryCamera is true - uint8_t modelRenderTagMask = (_isVisibleInSecondaryCamera ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW); - - _model->setTagMask(modelRenderTagMask, scene); - _model->setVisibleInScene(getVisible(), scene); - metaDirty = true; - } - if (_renderLayerDirty) { - _renderLayerDirty = false; - _model->setHifiRenderLayer(_drawHUDLayer ? render::hifi::LAYER_3D_HUD : (_drawInFront ? render::hifi::LAYER_3D_FRONT : render::hifi::LAYER_3D), scene); - metaDirty = true; - } - if (_groupCulledDirty) { - _groupCulledDirty = false; - _model->setGroupCulled(_isGroupCulled, scene); - metaDirty = true; - } - if (metaDirty) { - transaction.updateItem(getRenderItemID(), [](Overlay& data) {}); - } - scene->enqueueTransaction(transaction); - - if (_texturesDirty && !_modelTextures.isEmpty()) { - _texturesDirty = false; - _model->setTextures(_modelTextures); - } - - if (!_texturesLoaded && _model->getGeometry() && _model->getGeometry()->areTexturesLoaded()) { - _texturesLoaded = true; - - _model->setVisibleInScene(getVisible(), scene); - _model->updateRenderItems(); - } -} - -bool ModelOverlay::addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) { - Volume3DOverlay::addToScene(overlay, scene, transaction); - _model->addToScene(scene, transaction); - emit DependencyManager::get()->modelAddedToScene(Overlay::getID(), NestableType::Overlay, _model); - return true; -} - -void ModelOverlay::removeFromScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) { - Volume3DOverlay::removeFromScene(overlay, scene, transaction); - _model->removeFromScene(scene, transaction); - emit DependencyManager::get()->modelRemovedFromScene(Overlay::getID(), NestableType::Overlay, _model); - transaction.updateItem(getRenderItemID(), [](Overlay& data) { - auto modelOverlay = static_cast(&data); - modelOverlay->clearSubRenderItemIDs(); - }); -} - -void ModelOverlay::setVisible(bool visible) { - if (visible != getVisible()) { - Overlay::setVisible(visible); - _visibleDirty = true; - } -} - -void ModelOverlay::setDrawInFront(bool drawInFront) { - if (drawInFront != getDrawInFront()) { - Base3DOverlay::setDrawInFront(drawInFront); - _renderLayerDirty = true; - } -} - -void ModelOverlay::setDrawHUDLayer(bool drawHUDLayer) { - if (drawHUDLayer != getDrawHUDLayer()) { - Base3DOverlay::setDrawHUDLayer(drawHUDLayer); - _renderLayerDirty = true; - } -} - -void ModelOverlay::setGroupCulled(bool groupCulled) { - if (groupCulled != _isGroupCulled) { - _isGroupCulled = groupCulled; - _groupCulledDirty = true; - } -} - -void ModelOverlay::setProperties(const QVariantMap& properties) { - auto origPosition = getWorldPosition(); - auto origRotation = getWorldOrientation(); - auto origDimensions = getDimensions(); - auto origScale = getSNScale(); - - Base3DOverlay::setProperties(properties); - - auto scale = properties["scale"]; - if (scale.isValid()) { - setSNScale(vec3FromVariant(scale)); - } - - auto dimensions = properties["dimensions"]; - if (!dimensions.isValid()) { - dimensions = properties["size"]; - } - if (dimensions.isValid()) { - _scaleToFit = true; - setDimensions(vec3FromVariant(dimensions)); - } else if (scale.isValid()) { - // if "scale" property is set but "dimensions" is not. - // do NOT scale to fit. - _scaleToFit = false; - } - - if (origPosition != getWorldPosition() || origRotation != getWorldOrientation() || origDimensions != getDimensions() || origScale != getSNScale()) { - _updateModel = true; - } - - auto loadPriorityProperty = properties["loadPriority"]; - if (loadPriorityProperty.isValid()) { - _loadPriority = loadPriorityProperty.toFloat(); - _model->setLoadingPriority(_loadPriority); - } - - auto urlValue = properties["url"]; - if (urlValue.isValid() && urlValue.canConvert()) { - _url = urlValue.toString(); - _updateModel = true; - _isLoaded = false; - _texturesLoaded = false; - } - - auto texturesValue = properties["textures"]; - if (texturesValue.isValid() && texturesValue.canConvert(QVariant::Map)) { - _texturesLoaded = false; - QVariantMap textureMap = texturesValue.toMap(); - _modelTextures = textureMap; - _texturesDirty = true; - } - - auto groupCulledValue = properties["isGroupCulled"]; - if (groupCulledValue.isValid() && groupCulledValue.canConvert(QVariant::Bool)) { - setGroupCulled(groupCulledValue.toBool()); - } - - // jointNames is read-only. - // jointPositions is read-only. - // jointOrientations is read-only. - - // relative - auto jointTranslationsValue = properties["jointTranslations"]; - if (jointTranslationsValue.canConvert(QVariant::List)) { - const QVariantList& jointTranslations = jointTranslationsValue.toList(); - int translationCount = jointTranslations.size(); - int jointCount = _model->getJointStateCount(); - if (translationCount < jointCount) { - jointCount = translationCount; - } - for (int i=0; i < jointCount; i++) { - const auto& translationValue = jointTranslations[i]; - if (translationValue.isValid()) { - _model->setJointTranslation(i, true, vec3FromVariant(translationValue), 1.0f); - } - } - _updateModel = true; - } - - // relative - auto jointRotationsValue = properties["jointRotations"]; - if (jointRotationsValue.canConvert(QVariant::List)) { - const QVariantList& jointRotations = jointRotationsValue.toList(); - int rotationCount = jointRotations.size(); - int jointCount = _model->getJointStateCount(); - if (rotationCount < jointCount) { - jointCount = rotationCount; - } - for (int i=0; i < jointCount; i++) { - const auto& rotationValue = jointRotations[i]; - if (rotationValue.isValid()) { - _model->setJointRotation(i, true, quatFromVariant(rotationValue), 1.0f); - } - } - _updateModel = true; - } - - auto animationSettings = properties["animationSettings"]; - if (animationSettings.canConvert(QVariant::Map)) { - QVariantMap animationSettingsMap = animationSettings.toMap(); - - auto animationURL = animationSettingsMap["url"]; - auto animationFPS = animationSettingsMap["fps"]; - auto animationCurrentFrame = animationSettingsMap["currentFrame"]; - auto animationFirstFrame = animationSettingsMap["firstFrame"]; - auto animationLastFrame = animationSettingsMap["lastFrame"]; - auto animationRunning = animationSettingsMap["running"]; - auto animationLoop = animationSettingsMap["loop"]; - auto animationHold = animationSettingsMap["hold"]; - auto animationAllowTranslation = animationSettingsMap["allowTranslation"]; - - if (animationURL.canConvert(QVariant::Url)) { - _animationURL = animationURL.toUrl(); - } - if (animationFPS.isValid()) { - _animationFPS = animationFPS.toFloat(); - } - if (animationCurrentFrame.isValid()) { - _animationCurrentFrame = animationCurrentFrame.toFloat(); - } - if (animationFirstFrame.isValid()) { - _animationFirstFrame = animationFirstFrame.toFloat(); - } - if (animationLastFrame.isValid()) { - _animationLastFrame = animationLastFrame.toFloat(); - } - - if (animationRunning.canConvert(QVariant::Bool)) { - _animationRunning = animationRunning.toBool(); - } - if (animationLoop.canConvert(QVariant::Bool)) { - _animationLoop = animationLoop.toBool(); - } - if (animationHold.canConvert(QVariant::Bool)) { - _animationHold = animationHold.toBool(); - } - if (animationAllowTranslation.canConvert(QVariant::Bool)) { - _animationAllowTranslation = animationAllowTranslation.toBool(); - } - - } -} - -template -vectorType ModelOverlay::mapJoints(mapFunction function) const { - vectorType result; - if (_model && _model->isActive()) { - const int jointCount = _model->getJointStateCount(); - result.reserve(jointCount); - for (int i = 0; i < jointCount; i++) { - result << function(i); - } - } - return result; -} - -// Note: ModelOverlay overrides Volume3DOverlay's "dimensions" and "scale" properties. -/**jsdoc - * These are the properties of a model {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.ModelProperties - * - * @property {string} type=sphere - Has the value "model". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} isGroupCulled=false - If true, the mesh parts of the model are LOD culled as a group. - * If false, separate mesh parts will be LOD culled individually. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {string} url - The URL of the FBX or OBJ model used for the overlay. - * @property {number} loadPriority=0.0 - The priority for loading and displaying the overlay. Overlays with higher values load - * first. - * @property {Vec3} dimensions - The dimensions of the overlay. Synonym: size. - * @property {Vec3} scale - The scale factor applied to the model's dimensions. - * @property {object.} textures - Maps the named textures in the model to the JPG or PNG images in the urls. - * @property {Array.} jointNames - The names of the joints - if any - in the model. Read-only. - * @property {Array.} jointRotations - The relative rotations of the model's joints. Not copied if overlay is - * cloned. - * @property {Array.} jointTranslations - The relative translations of the model's joints. Not copied if overlay is - * cloned. - * @property {Array.} jointOrientations - The absolute orientations of the model's joints, in world coordinates. - * Read-only. - * @property {Array.} jointPositions - The absolute positions of the model's joints, in world coordinates. - * Read-only. - * @property {string} animationSettings.url="" - The URL of an FBX file containing an animation to play. - * @property {number} animationSettings.fps=0 - The frame rate (frames/sec) to play the animation at. - * @property {number} animationSettings.firstFrame=0 - The frame to start playing at. - * @property {number} animationSettings.lastFrame=0 - The frame to finish playing at. - * @property {number} animationSettings.currentFrame=0 - The current frame being played. - * @property {boolean} animationSettings.running=false - Whether or not the animation is playing. - * @property {boolean} animationSettings.loop=false - Whether or not the animation should repeat in a loop. - * @property {boolean} animationSettings.hold=false - Whether or not when the animation finishes, the rotations and - * translations of the last frame played should be maintained. - * @property {boolean} animationSettings.allowTranslation=false - Whether or not translations contained in the animation should - * be played. - */ -QVariant ModelOverlay::getProperty(const QString& property) { - if (property == "url") { - return _url.toString(); - } - if (property == "dimensions" || property == "size") { - return vec3toVariant(getDimensions()); - } - if (property == "scale") { - return vec3toVariant(getSNScale()); - } - if (property == "textures") { - if (_modelTextures.size() > 0) { - QVariantMap textures; - foreach(const QString& key, _modelTextures.keys()) { - textures[key] = _modelTextures[key].toString(); - } - return textures; - } else { - return QVariant(); - } - } - - if (property == "loadPriority") { - return _loadPriority; - } - - if (property == "jointNames") { - if (_model && _model->isActive()) { - // note: going through Rig because Model::getJointNames() (which proxies to HFMModel) was always empty - const Rig* rig = &(_model->getRig()); - return mapJoints([rig](int jointIndex) -> QString { - return rig->nameOfJoint(jointIndex); - }); - } - } - - // relative - if (property == "jointRotations") { - return mapJoints( - [this](int jointIndex) -> QVariant { - glm::quat rotation; - _model->getJointRotation(jointIndex, rotation); - return quatToVariant(rotation); - }); - } - - // relative - if (property == "jointTranslations") { - return mapJoints( - [this](int jointIndex) -> QVariant { - glm::vec3 translation; - _model->getJointTranslation(jointIndex, translation); - return vec3toVariant(translation); - }); - } - - // absolute - if (property == "jointOrientations") { - return mapJoints( - [this](int jointIndex) -> QVariant { - glm::quat orientation; - _model->getJointRotationInWorldFrame(jointIndex, orientation); - return quatToVariant(orientation); - }); - } - - // absolute - if (property == "jointPositions") { - return mapJoints( - [this](int jointIndex) -> QVariant { - glm::vec3 position; - _model->getJointPositionInWorldFrame(jointIndex, position); - return vec3toVariant(position); - }); - } - - // animation properties - if (property == "animationSettings") { - QVariantMap animationSettingsMap; - - animationSettingsMap["url"] = _animationURL; - animationSettingsMap["fps"] = _animationFPS; - animationSettingsMap["currentFrame"] = _animationCurrentFrame; - animationSettingsMap["firstFrame"] = _animationFirstFrame; - animationSettingsMap["lastFrame"] = _animationLastFrame; - animationSettingsMap["running"] = _animationRunning; - animationSettingsMap["loop"] = _animationLoop; - animationSettingsMap["hold"]= _animationHold; - animationSettingsMap["allowTranslation"] = _animationAllowTranslation; - - return animationSettingsMap; - } - - - return Volume3DOverlay::getProperty(property); -} - -bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - QVariantMap extraInfo; - return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo, precisionPicking); -} - -bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) { - return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo, precisionPicking); -} - -bool ModelOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - QVariantMap extraInfo; - return _model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, parabolicDistance, face, surfaceNormal, extraInfo, precisionPicking); -} - -bool ModelOverlay::findParabolaIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) { - return _model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, parabolicDistance, face, surfaceNormal, extraInfo, precisionPicking); -} - -ModelOverlay* ModelOverlay::createClone() const { - return new ModelOverlay(this); -} - -Transform ModelOverlay::evalRenderTransform() { - Transform transform = getTransform(); - transform.setScale(1.0f); // disable inherited scale - return transform; -} - -void ModelOverlay::locationChanged(bool tellPhysics) { - Base3DOverlay::locationChanged(tellPhysics); - - // FIXME Start using the _renderTransform instead of calling for Transform and Dimensions from here, do the custom things needed in evalRenderTransform() - if (_model && _model->isActive()) { - _model->setRotation(getWorldOrientation()); - _model->setTranslation(getWorldPosition()); - _updateModel = true; - } -} - -QString ModelOverlay::getName() const { - if (_name != "") { - return QString("Overlay:") + getType() + ":" + _name; - } - return QString("Overlay:") + getType() + ":" + _url.toString(); -} - - -void ModelOverlay::animate() { - - if (!_animation || !_animation->isLoaded() || !_model || !_model->isLoaded()) { - return; - } - - - QVector jointsData; - - const QVector& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy - int frameCount = frames.size(); - if (frameCount <= 0) { - return; - } - - if (!_lastAnimated) { - _lastAnimated = usecTimestampNow(); - return; - } - - auto now = usecTimestampNow(); - auto interval = now - _lastAnimated; - _lastAnimated = now; - float deltaTime = (float)interval / (float)USECS_PER_SECOND; - _animationCurrentFrame += (deltaTime * _animationFPS); - - int animationCurrentFrame = (int)(glm::floor(_animationCurrentFrame)) % frameCount; - if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) { - animationCurrentFrame = 0; - } - - if (animationCurrentFrame == _lastKnownCurrentFrame) { - return; - } - _lastKnownCurrentFrame = animationCurrentFrame; - - if (_jointMapping.size() != _model->getJointStateCount()) { - return; - } - - QStringList animationJointNames = _animation->getHFMModel().getJointNames(); - auto& hfmJoints = _animation->getHFMModel().joints; - - auto& originalHFMJoints = _model->getHFMModel().joints; - auto& originalHFMIndices = _model->getHFMModel().jointIndices; - - const QVector& rotations = frames[_lastKnownCurrentFrame].rotations; - const QVector& translations = frames[_lastKnownCurrentFrame].translations; - - jointsData.resize(_jointMapping.size()); - for (int j = 0; j < _jointMapping.size(); j++) { - int index = _jointMapping[j]; - - if (index >= 0) { - glm::mat4 translationMat; - - if (_animationAllowTranslation) { - if (index < translations.size()) { - translationMat = glm::translate(translations[index]); - } - } else if (index < animationJointNames.size()) { - QString jointName = hfmJoints[index].name; - - if (originalHFMIndices.contains(jointName)) { - // Making sure the joint names exist in the original model the animation is trying to apply onto. If they do, then remap and get its translation. - int remappedIndex = originalHFMIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual. - translationMat = glm::translate(originalHFMJoints[remappedIndex].translation); - } - } - glm::mat4 rotationMat; - if (index < rotations.size()) { - rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * rotations[index] * hfmJoints[index].postRotation); - } else { - rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * hfmJoints[index].postRotation); - } - - glm::mat4 finalMat = (translationMat * hfmJoints[index].preTransform * - rotationMat * hfmJoints[index].postTransform); - auto& jointData = jointsData[j]; - jointData.translation = extractTranslation(finalMat); - jointData.translationIsDefaultPose = false; - jointData.rotation = glmExtractRotation(finalMat); - jointData.rotationIsDefaultPose = false; - } - } - // Set the data in the model - copyAnimationJointDataToModel(jointsData); -} - - -void ModelOverlay::mapAnimationJoints(const QStringList& modelJointNames) { - - // if we don't have animation, or we're already joint mapped then bail early - if (!hasAnimation() || jointsMapped()) { - return; - } - - if (!_animation || _animation->getURL() != _animationURL) { - _animation = DependencyManager::get()->getAnimation(_animationURL); - } - - if (_animation && _animation->isLoaded()) { - QStringList animationJointNames = _animation->getJointNames(); - - if (modelJointNames.size() > 0 && animationJointNames.size() > 0) { - _jointMapping.resize(modelJointNames.size()); - for (int i = 0; i < modelJointNames.size(); i++) { - _jointMapping[i] = animationJointNames.indexOf(modelJointNames[i]); - } - _jointMappingCompleted = true; - _jointMappingURL = _animationURL; - } - } -} - -void ModelOverlay::copyAnimationJointDataToModel(QVector jointsData) { - if (!_model || !_model->isLoaded()) { - return; - } - - // relay any inbound joint changes from scripts/animation/network to the model/rig - for (int index = 0; index < jointsData.size(); ++index) { - auto& jointData = jointsData[index]; - _model->setJointRotation(index, true, jointData.rotation, 1.0f); - _model->setJointTranslation(index, true, jointData.translation, 1.0f); - } - _updateModel = true; -} - -void ModelOverlay::clearSubRenderItemIDs() { - _subRenderItemIDs.clear(); -} - -void ModelOverlay::setSubRenderItemIDs(const render::ItemIDs& ids) { - _subRenderItemIDs = ids; -} - -uint32_t ModelOverlay::fetchMetaSubItems(render::ItemIDs& subItems) const { - if (_model) { - auto metaSubItems = _subRenderItemIDs; - subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end()); - return (uint32_t)metaSubItems.size(); - } - return 0; -} - -bool ModelOverlay::canReplaceModelMeshPart(int meshIndex, int partIndex) { - // TODO: bounds checking; for now just used to indicate provider generally supports mesh updates - return _model && _model->isLoaded(); -} - -bool ModelOverlay::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer newModel, int meshIndex, int partIndex) { - return canReplaceModelMeshPart(meshIndex, partIndex) && - _model->replaceScriptableModelMeshPart(newModel, meshIndex, partIndex); -} - -scriptable::ScriptableModelBase ModelOverlay::getScriptableModel() { - if (!_model || !_model->isLoaded()) { - return Base3DOverlay::getScriptableModel(); - } - auto result = _model->getScriptableModel(); - result.objectID = Overlay::getID(); - return result; -} - -render::ItemKey ModelOverlay::getKey() { - auto builder = render::ItemKey::Builder(Base3DOverlay::getKey()); - if (_isGroupCulled) { - builder.withMetaCullGroup(); - } - return builder.build(); -} diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h deleted file mode 100644 index 63ffeaaafe..0000000000 --- a/interface/src/ui/overlays/ModelOverlay.h +++ /dev/null @@ -1,132 +0,0 @@ -// -// ModelOverlay.h -// -// -// Created by Clement on 6/30/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_ModelOverlay_h -#define hifi_ModelOverlay_h - -#include -#include - -#include "Volume3DOverlay.h" - -class ModelOverlay : public Volume3DOverlay { - Q_OBJECT -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - virtual QString getName() const override; - - ModelOverlay(); - ModelOverlay(const ModelOverlay* modelOverlay); - - virtual void update(float deltatime) override; - virtual void render(RenderArgs* args) override {}; - - virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override; - - render::ItemKey getKey() override; - void clearSubRenderItemIDs(); - void setSubRenderItemIDs(const render::ItemIDs& ids); - - virtual void setIsVisibleInSecondaryCamera(bool value) override { - Base3DOverlay::setIsVisibleInSecondaryCamera(value); - _visibleDirty = true; - } - - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) override; - virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - virtual bool findParabolaIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) override; - - virtual ModelOverlay* createClone() const override; - - virtual bool addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) override; - virtual void removeFromScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) override; - - void locationChanged(bool tellPhysics) override; - - float getLoadPriority() const { return _loadPriority; } - - bool hasAnimation() const { return !_animationURL.isEmpty(); } - bool jointsMapped() const { return _jointMappingURL == _animationURL && _jointMappingCompleted; } - - void setVisible(bool visible) override; - void setDrawInFront(bool drawInFront) override; - void setDrawHUDLayer(bool drawHUDLayer) override; - void setGroupCulled(bool groupCulled); - - virtual scriptable::ScriptableModelBase getScriptableModel() override; - virtual bool canReplaceModelMeshPart(int meshIndex, int partIndex) override; - virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, int meshIndex, int partIndex) override; - -protected: - Transform evalRenderTransform() override; - - // helper to extract metadata from our Model's rigged joints - template using mapFunction = std::function; - template - vectorType mapJoints(mapFunction function) const; - - void animate(); - void mapAnimationJoints(const QStringList& modelJointNames); - bool isAnimatingSomething() const { - return !_animationURL.isEmpty() && _animationRunning && _animationFPS != 0.0f; - } - void copyAnimationJointDataToModel(QVector jointsData); - - -private: - - ModelPointer _model; - QVariantMap _modelTextures; - bool _texturesLoaded { false }; - bool _texturesDirty { false }; - - render::ItemIDs _subRenderItemIDs; - - QUrl _url; - bool _updateModel { false }; - bool _scaleToFit { false }; - float _loadPriority { 0.0f }; - - AnimationPointer _animation; - - QUrl _animationURL; - float _animationFPS { 0.0f }; - float _animationCurrentFrame { 0.0f }; - bool _animationRunning { false }; - bool _animationLoop { false }; - float _animationFirstFrame { 0.0f }; - float _animationLastFrame { 0.0f }; - bool _animationHold { false }; - bool _animationAllowTranslation { false }; - uint64_t _lastAnimated { 0 }; - int _lastKnownCurrentFrame { -1 }; - - QUrl _jointMappingURL; - bool _jointMappingCompleted { false }; - QVector _jointMapping; // domain is index into model-joints, range is index into animation-joints - - bool _visibleDirty { true }; - bool _renderLayerDirty { false }; - bool _isGroupCulled { false }; - bool _groupCulledDirty { false }; - -}; - -#endif // hifi_ModelOverlay_h diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index cf55c87114..714db97bc2 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -15,126 +15,31 @@ #include "Application.h" -const glm::u8vec3 Overlay::DEFAULT_OVERLAY_COLOR = { 255, 255, 255 }; -const float Overlay::DEFAULT_ALPHA = 0.7f; - Overlay::Overlay() : _renderItemID(render::Item::INVALID_ITEM_ID), - _isLoaded(true), - _alpha(DEFAULT_ALPHA), - _pulse(1.0f), - _pulseMax(0.0f), - _pulseMin(0.0f), - _pulsePeriod(1.0f), - _pulseDirection(1.0f), - _lastPulseUpdate(usecTimestampNow()), - _alphaPulse(0.0f), - _colorPulse(0.0f), - _color(DEFAULT_OVERLAY_COLOR), _visible(true) { } Overlay::Overlay(const Overlay* overlay) : _renderItemID(render::Item::INVALID_ITEM_ID), - _isLoaded(overlay->_isLoaded), - _alpha(overlay->_alpha), - _pulse(overlay->_pulse), - _pulseMax(overlay->_pulseMax), - _pulseMin(overlay->_pulseMin), - _pulsePeriod(overlay->_pulsePeriod), - _pulseDirection(overlay->_pulseDirection), - _lastPulseUpdate(usecTimestampNow()), - _alphaPulse(overlay->_alphaPulse), - _colorPulse(overlay->_colorPulse), - _color(overlay->_color), _visible(overlay->_visible) { } -Overlay::~Overlay() { -} - void Overlay::setProperties(const QVariantMap& properties) { - bool valid; - auto color = u8vec3FromVariant(properties["color"], valid); - if (valid) { - _color = color; - } - - if (properties["alpha"].isValid()) { - setAlpha(properties["alpha"].toFloat()); - } - - if (properties["pulseMax"].isValid()) { - setPulseMax(properties["pulseMax"].toFloat()); - } - - if (properties["pulseMin"].isValid()) { - setPulseMin(properties["pulseMin"].toFloat()); - } - - if (properties["pulsePeriod"].isValid()) { - setPulsePeriod(properties["pulsePeriod"].toFloat()); - } - - if (properties["alphaPulse"].isValid()) { - setAlphaPulse(properties["alphaPulse"].toFloat()); - } - - if (properties["colorPulse"].isValid()) { - setColorPulse(properties["colorPulse"].toFloat()); - } - if (properties["visible"].isValid()) { bool visible = properties["visible"].toBool(); setVisible(visible); } } -// JSDoc for copying to @typedefs of overlay types that inherit Overlay. -/**jsdoc - * @property {string} type=TODO - Has the value "TODO". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - */ QVariant Overlay::getProperty(const QString& property) { if (property == "type") { return QVariant(getType()); } - if (property == "color") { - return u8vec3ColortoVariant(_color); - } - if (property == "alpha") { - return _alpha; - } - if (property == "pulseMax") { - return _pulseMax; - } - if (property == "pulseMin") { - return _pulseMin; - } - if (property == "pulsePeriod") { - return _pulsePeriod; - } - if (property == "alphaPulse") { - return _alphaPulse; - } - if (property == "colorPulse") { - return _colorPulse; + if (property == "id") { + return getID(); } if (property == "visible") { return _visible; @@ -143,67 +48,6 @@ QVariant Overlay::getProperty(const QString& property) { return QVariant(); } -glm::u8vec3 Overlay::getColor() { - if (_colorPulse == 0.0f) { - return _color; - } - - float pulseLevel = updatePulse(); - glm::u8vec3 result = _color; - if (_colorPulse < 0.0f) { - result.x *= (1.0f - pulseLevel); - result.y *= (1.0f - pulseLevel); - result.z *= (1.0f - pulseLevel); - } else { - result.x *= pulseLevel; - result.y *= pulseLevel; - result.z *= pulseLevel; - } - return result; -} - -float Overlay::getAlpha() { - if (_alphaPulse == 0.0f) { - return _alpha; - } - float pulseLevel = updatePulse(); - return (_alphaPulse >= 0.0f) ? _alpha * pulseLevel : _alpha * (1.0f - pulseLevel); -} - -// pulse travels from min to max, then max to min in one period. -float Overlay::updatePulse() { - if (_pulsePeriod <= 0.0f) { - return _pulse; - } - quint64 now = usecTimestampNow(); - quint64 elapsedUSecs = (now - _lastPulseUpdate); - float elapsedSeconds = (float)elapsedUSecs / (float)USECS_PER_SECOND; - float elapsedPeriods = elapsedSeconds / _pulsePeriod; - - // we can safely remove any "full" periods, since those just rotate us back - // to our final pulse level - elapsedPeriods = fmod(elapsedPeriods, 1.0f); - _lastPulseUpdate = now; - - float pulseDistance = (_pulseMax - _pulseMin); - float pulseDistancePerPeriod = pulseDistance * 2.0f; - - float pulseDelta = _pulseDirection * pulseDistancePerPeriod * elapsedPeriods; - float newPulse = _pulse + pulseDelta; - float limit = (_pulseDirection > 0.0f) ? _pulseMax : _pulseMin; - float passedLimit = (_pulseDirection > 0.0f) ? (newPulse >= limit) : (newPulse <= limit); - - if (passedLimit) { - float pulseDeltaToLimit = newPulse - limit; - float pulseDeltaFromLimitBack = pulseDelta - pulseDeltaToLimit; - pulseDelta = -pulseDeltaFromLimitBack; - _pulseDirection *= -1.0f; - } - _pulse += pulseDelta; - - return _pulse; -} - bool Overlay::addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) { _renderItemID = scene->allocateID(); transaction.resetItem(_renderItemID, std::make_shared(overlay)); @@ -225,8 +69,7 @@ render::ItemKey Overlay::getKey() { builder.withInvisible(); } - // always visible in primary view. if isVisibleInSecondaryCamera, also draw in secondary view - render::hifi::Tag viewTagBits = getIsVisibleInSecondaryCamera() ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW; + render::hifi::Tag viewTagBits = render::hifi::TAG_ALL_VIEWS; builder.withTagBits(viewTagBits); return builder.build(); diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 068e1b7641..ee6e281193 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -23,12 +23,10 @@ public: Overlay(); Overlay(const Overlay* overlay); - ~Overlay(); virtual QUuid getID() const { return _id; } virtual void setID(const QUuid& id) { _id = id; } - virtual void update(float deltatime) {} virtual void render(RenderArgs* args) = 0; virtual render::ItemKey getKey(); @@ -44,35 +42,13 @@ public: // getters virtual QString getType() const = 0; - bool isLoaded() { return _isLoaded; } + bool isLoaded() { return true; } bool getVisible() const { return _visible; } - virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; }; - virtual bool getIsVisibleInSecondaryCamera() const { return false; } - - glm::u8vec3 getColor(); - float getAlpha(); - - float getPulseMax() const { return _pulseMax; } - float getPulseMin() const { return _pulseMin; } - float getPulsePeriod() const { return _pulsePeriod; } - float getPulseDirection() const { return _pulseDirection; } - - float getColorPulse() const { return _colorPulse; } - float getAlphaPulse() const { return _alphaPulse; } // setters virtual void setVisible(bool visible) { _visible = visible; } - void setDrawHUDLayer(bool drawHUDLayer); - void setColor(const glm::u8vec3& color) { _color = color; } - void setAlpha(float alpha) { _alpha = alpha; } - - void setPulseMax(float value) { _pulseMax = value; } - void setPulseMin(float value) { _pulseMin = value; } - void setPulsePeriod(float value) { _pulsePeriod = value; } - void setPulseDirection(float value) { _pulseDirection = value; } - - void setColorPulse(float value) { _colorPulse = value; } - void setAlphaPulse(float value) { _alphaPulse = value; } + unsigned int getStackOrder() const { return _stackOrder; } + void setStackOrder(unsigned int stackOrder) { _stackOrder = stackOrder; } Q_INVOKABLE virtual void setProperties(const QVariantMap& properties); Q_INVOKABLE virtual Overlay* createClone() const = 0; @@ -81,35 +57,12 @@ public: render::ItemID getRenderItemID() const { return _renderItemID; } void setRenderItemID(render::ItemID renderItemID) { _renderItemID = renderItemID; } - unsigned int getStackOrder() const { return _stackOrder; } - void setStackOrder(unsigned int stackOrder) { _stackOrder = stackOrder; } - protected: - float updatePulse(); - - render::ItemID _renderItemID{ render::Item::INVALID_ITEM_ID }; - - bool _isLoaded; - float _alpha; - - float _pulse; - float _pulseMax; - float _pulseMin; - float _pulsePeriod; - float _pulseDirection; - quint64 _lastPulseUpdate; - - float _alphaPulse; // ratio of the pulse to the alpha - float _colorPulse; // ratio of the pulse to the color - - glm::u8vec3 _color; - bool _visible; // should the overlay be drawn at all + render::ItemID _renderItemID { render::Item::INVALID_ITEM_ID }; + bool _visible; unsigned int _stackOrder { 0 }; - static const glm::u8vec3 DEFAULT_OVERLAY_COLOR; - static const float DEFAULT_ALPHA; - private: QUuid _id; }; diff --git a/interface/src/ui/overlays/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h index 5417dbd9e0..54ab52b469 100644 --- a/interface/src/ui/overlays/Overlay2D.h +++ b/interface/src/ui/overlays/Overlay2D.h @@ -17,13 +17,12 @@ class Overlay2D : public Overlay { Q_OBJECT - + public: Overlay2D() {} Overlay2D(const Overlay2D* overlay2D); - - virtual AABox getBounds() const override; + virtual AABox getBounds() const override; virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return 1; } // getters @@ -32,7 +31,7 @@ public: int getWidth() const { return _bounds.width(); } int getHeight() const { return _bounds.height(); } const QRect& getBoundingRect() const { return _bounds; } - + // setters void setX(int x) { _bounds.setX(x); } void setY(int y) { _bounds.setY(y); } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 69d3883de7..14328a349a 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -79,13 +79,6 @@ void Overlays::init() { } void Overlays::update(float deltatime) { - { - QMutexLocker locker(&_mutex); - foreach(const auto& thisOverlay, _overlays) { - thisOverlay->update(deltatime); - } - } - cleanupOverlaysToDelete(); } @@ -948,3 +941,589 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { } return result; } + +/**jsdoc + * Different overlay types have different properties: some common to all overlays (listed below) and some specific to each + * {@link Overlays.OverlayType|OverlayType} (linked to below). The properties are accessed as an object of property names and + * values. + * + * @typedef {object} Overlays.OverlayProperties + * @property {Uuid} id - The ID of the overlay. Read-only. + * @property {string} type=TODO - Has the value "TODO". Read-only. + * @property {Overlays.OverlayType} type - The overlay type. Read-only. + * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. + * + * @see The different entity types have additional properties as follows: + * @see {@link Overlays.OverlayProperties-Image|OverlayProperties-Image} + * @see {@link Overlays.OverlayProperties-Text|OverlayProperties-Text} + * @see {@link Overlays.OverlayProperties-Rectangle|OverlayProperties-Rectangle} + * @see {@link Overlays.OverlayProperties-Cube|OverlayProperties-Cube} + * @see {@link Overlays.OverlayProperties-Sphere|OverlayProperties-Sphere} + * @see {@link Overlays.OverlayProperties-Shape|OverlayProperties-Shape} + * @see {@link Overlays.OverlayProperties-Model|OverlayProperties-Model} + * @see {@link Overlays.OverlayProperties-Text3D|OverlayProperties-Text3D} + * @see {@link Overlays.OverlayProperties-Image3D|OverlayProperties-Image3D} + * @see {@link Overlays.OverlayProperties-Web|OverlayProperties-Web} + * @see {@link Overlays.OverlayProperties-Line|OverlayProperties-Line} + * @see {@link Overlays.OverlayProperties-Grid|OverlayProperties-Grid} + * @see {@link Overlays.OverlayProperties-Circle|OverlayProperties-Circle} + */ + +/**jsdoc + * The "Image" {@link Overlays.OverlayType|OverlayType} is a 2D image. + * @typedef {object} Overlays.OverlayProperties-Image + * @property {Rect} bounds - The position and size of the image display area, in pixels. Write-only. + * @property {number} x - Integer left, x-coordinate value of the image display area = bounds.x. + * Write-only. + * @property {number} y - Integer top, y-coordinate value of the image display area = bounds.y. + * Write-only. + * @property {number} width - Integer width of the image display area = bounds.width. Write-only. + * @property {number} height - Integer height of the image display area = bounds.height. Write-only. + * @property {string} imageURL - The URL of the image file to display. The image is scaled to fit to the bounds. + * Write-only. + * @property {Vec2} subImage=0,0 - Integer coordinates of the top left pixel to start using image content from. + * Write-only. + * @property {Color} color=0,0,0 - The color to apply over the top of the image to colorize it. Write-only. + * @property {number} alpha=0.0 - The opacity of the color applied over the top of the image, 0.0 - + * 1.0. Write-only. + */ + +/**jsdoc + * The "Text" {@link Overlays.OverlayType|OverlayType} is for 2D text. + * @typedef {object} Overlays.OverlayProperties-Text + * @property {Rect} bounds - The position and size of the rectangle, in pixels. Write-only. + * @property {number} x - Integer left, x-coordinate value = bounds.x. Write-only. + * @property {number} y - Integer top, y-coordinate value = bounds.y. Write-only. + * @property {number} width - Integer width of the rectangle = bounds.width. Write-only. + * @property {number} height - Integer height of the rectangle = bounds.height. Write-only. + * + * @property {number} margin=0 - Sets the leftMargin and topMargin values, in pixels. + * Write-only. + * @property {number} leftMargin=0 - The left margin's size, in pixels. This value is also used for the right margin. + * Write-only. + * @property {number} topMargin=0 - The top margin's size, in pixels. This value is also used for the bottom margin. + * Write-only. + * @property {string} text="" - The text to display. Text does not automatically wrap; use \n for a line break. Text + * is clipped to the bounds. Write-only. + * @property {number} font.size=18 - The size of the text, in pixels. Write-only. + * @property {number} lineHeight=18 - The height of a line of text, in pixels. Write-only. + * @property {Color} color=255,255,255 - The color of the text. Synonym: textColor. Write-only. + * @property {number} alpha=1.0 - The opacity of the overlay, 0.0 - 1.0. Write-only. + * @property {Color} backgroundColor=0,0,0 - The color of the background rectangle. Write-only. + * @property {number} backgroundAlpha=0.7 - The opacity of the background rectangle. Write-only. + */ + +/**jsdoc + * The "Text" {@link Overlays.OverlayType|OverlayType} is for 2D rectangles. + * @typedef {object} Overlays.OverlayProperties-Rectangle + * @property {Rect} bounds - The position and size of the rectangle, in pixels. Write-only. + * @property {number} x - Integer left, x-coordinate value = bounds.x. Write-only. + * @property {number} y - Integer top, y-coordinate value = bounds.y. Write-only. + * @property {number} width - Integer width of the rectangle = bounds.width. Write-only. + * @property {number} height - Integer height of the rectangle = bounds.height. Write-only. + * + * @property {Color} color=0,0,0 - The color of the overlay. Write-only. + * @property {number} alpha=1.0 - The opacity of the overlay, 0.0 - 1.0. Write-only. + * @property {number} borderWidth=1 - Integer width of the border, in pixels. The border is drawn within the rectangle's bounds. + * It is not drawn unless either borderColor or borderAlpha are specified. Write-only. + * @property {number} radius=0 - Integer corner radius, in pixels. Write-only. + * @property {Color} borderColor=0,0,0 - The color of the border. Write-only. + * @property {number} borderAlpha=1.0 - The opacity of the border, 0.0 - 1.0. + * Write-only. + */ + +/**jsdoc + * The "Cube" {@link Overlays.OverlayType|OverlayType} is for 3D cubes. + * @typedef {object} Overlays.OverlayProperties-Cube + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. + * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. + * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * pulseMin to pulseMax, then pulseMax to pulseMin in one period. + * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + */ + +/**jsdoc + * The "Sphere" {@link Overlays.OverlayType|OverlayType} is for 3D spheres. + * @typedef {object} Overlays.OverlayProperties-Sphere + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. + * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. + * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * pulseMin to pulseMax, then pulseMax to pulseMin in one period. + * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + */ + +/**jsdoc + *

A shape {@link Overlays.OverlayType|OverlayType} may display as one of the following geometrical shapes:

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
ValueDimensionsDescription
"Circle"2DA circle oriented in 3D.
"Cone"3D
"Cube"3D
"Cylinder"3D
"Dodecahedron"3D
"Hexagon"3DA hexagonal prism.
"Icosahedron"3D
"Line"1DA line oriented in 3D.
"Octagon"3DAn octagonal prism.
"Octahedron"3D
"Quad"2DA square oriented in 3D.
"Sphere"3D
"Tetrahedron"3D
"Torus"3DNot implemented.
"Triangle"3DA triangular prism.
+ * @typedef {string} Overlays.Shape + */ + +/**jsdoc + * The "Shape" {@link Overlays.OverlayType|OverlayType} is for 3D shapes. + * @typedef {object} Overlays.OverlayProperties-Shape + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. + * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. + * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * pulseMin to pulseMax, then pulseMax to pulseMin in one period. + * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + * @property {Overlays.Shape} shape=Hexagon - The geometrical shape of the overlay. + */ + +/**jsdoc + * The "Model" {@link Overlays.OverlayType|OverlayType} is for 3D models. + * @typedef {object} Overlays.OverlayProperties-Model + * @property {string} name - The name of the overlay. + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + * @property {string} url - The URL of the FBX or OBJ model used for the overlay. + * @property {number} loadPriority=0.0 - The priority for loading and displaying the overlay. Overlays with higher values load + * first. + * @property {object.} textures - Maps the named textures in the model to the JPG or PNG images in the urls. + * @property {string[]} jointNames - The names of the joints - if any - in the model. Read-only. + * @property {Quat[]} jointRotations - The relative rotations of the model's joints. + * @property {Vec3[]} jointTranslations - The relative translations of the model's joints. + * @property {Quat[]} jointOrientations - The absolute orientations of the model's joints, in world coordinates. Read-only. + * @property {Vec3[]} jointPositions - The absolute positions of the model's joints, in world coordinates. Read-only. + * @property {string} animationSettings.url="" - The URL of an FBX file containing an animation to play. + * @property {number} animationSettings.fps=0 - The frame rate (frames/sec) to play the animation at. + * @property {number} animationSettings.firstFrame=0 - The frame to start playing at. + * @property {number} animationSettings.lastFrame=0 - The frame to finish playing at. + * @property {number} animationSettings.currentFrame=0 - The current frame being played. + * @property {boolean} animationSettings.running=false - Whether or not the animation is playing. + * @property {boolean} animationSettings.loop=false - Whether or not the animation should repeat in a loop. + * @property {boolean} animationSettings.hold=false - Whether or not when the animation finishes, the rotations and + * translations of the last frame played should be maintained. + * @property {boolean} animationSettings.allowTranslation=false - Whether or not translations contained in the animation should + * be played. + */ + +/**jsdoc + * The "Text3D" {@link Overlays.OverlayType|OverlayType} is for 3D text. + * @typedef {object} Overlays.OverlayProperties-Text3D + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. + * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. + * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * pulseMin to pulseMax, then pulseMax to pulseMin in one period. + * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + * @property {boolean} isFacingAvatar - If true< / code>, the overlay is rotated to face the user's camera about an axis + * parallel to the user's avatar's "up" direction. + * @property {string} text="" - The text to display.Text does not automatically wrap; use \n< / code> for a line break. + * @property {number} textAlpha=1 - The text alpha value. + * @property {Color} backgroundColor=0,0,0 - The background color. + * @property {number} backgroundAlpha=0.7 - The background alpha value. + * @property {number} lineHeight=1 - The height of a line of text in meters. + * @property {number} leftMargin=0.1 - The left margin, in meters. + * @property {number} topMargin=0.1 - The top margin, in meters. + * @property {number} rightMargin=0.1 - The right margin, in meters. + * @property {number} bottomMargin=0.1 - The bottom margin, in meters. + */ + +/**jsdoc + * The "Image3D" {@link Overlays.OverlayType|OverlayType} is for 3D images. + * @typedef {object} Overlays.OverlayProperties-Image3D + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. + * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. + * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * pulseMin to pulseMax, then pulseMax to pulseMin in one period. + * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + * @property {boolean} isFacingAvatar - If true, the overlay is rotated to face the user's camera about an axis + * parallel to the user's avatar's "up" direction. + * @property {string} url - The URL of the PNG or JPG image to display. + * @property {Rect} subImage - The portion of the image to display. Defaults to the full image. + * @property {boolean} emissive - If true, the overlay is displayed at full brightness, otherwise it is rendered + * with scene lighting. + * @property {bool} keepAspectRatio=true - overlays will maintain the aspect ratio when the subImage is applied. + */ + +/**jsdoc + * The "Web" {@link Overlays.OverlayType|OverlayType} is for 3D web surfaces. + * @typedef {object} Overlays.OverlayProperties-Web + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. + * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. + * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * pulseMin to pulseMax, then pulseMax to pulseMin in one period. + * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + * @property {boolean} isFacingAvatar - If true, the overlay is rotated to face the user's camera about an axis + * parallel to the user's avatar's "up" direction. + * @property {string} url - The URL of the Web page to display. + * @property {string} scriptURL="" - The URL of a JavaScript file to inject into the Web page. + * @property {number} dpi=30 - The dots per inch to display the Web page at, on the overlay. + * @property {number} maxFPS=10 - The maximum update rate for the Web overlay content, in frames/second. + * @property {string} inputMode=Touch - The user input mode to use - either "Touch" or "Mouse". + */ + +/**jsdoc + * The "Line" {@link Overlays.OverlayType|OverlayType} is for 3D lines. + * @typedef {object} Overlays.OverlayProperties-Line + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + * @property {Uuid} endParentID=null - The avatar, entity, or overlay that the end point of the line is parented to. + * @property {number} endParentJointIndex=65535 - Integer value specifying the skeleton joint that the end point of the line is + * attached to if parentID is an avatar skeleton. A value of 65535 means "no joint". + * @property {Vec3} start - The start point of the line. Synonyms: startPoint and p1. + * @property {Vec3} end - The end point of the line. Synonyms: endPoint and p2. + * @property {Vec3} localStart - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as start. Synonym: localPosition. + * @property {Vec3} localEnd - The local position of the overlay relative to its parent if the overlay has a + * endParentID set, otherwise the same value as end. + * @property {number} length - The length of the line, in meters. This can be set after creating a line with start and end + * points. + * @property {number} glow=0 - If glow > 0, the line is rendered with a glow. + * @property {number} lineWidth=0.02 - Width of the line, in meters. + */ + +/**jsdoc + * The "Grid" {@link Overlays.OverlayType|OverlayType} is for 3D grid. + * @typedef {object} Overlays.OverlayProperties-Grid + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. + * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. + * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * pulseMin to pulseMax, then pulseMax to pulseMin in one period. + * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + * @property {boolean} followCamera=true - If true, the grid is always visible even as the camera moves to another position. + * @property {number} majorGridEvery=5 - Integer number of minorGridEvery intervals at which to draw a thick grid line. Minimum value = 1. + * @property {number} minorGridEvery=1 - Real number of meters at which to draw thin grid lines. Minimum value = 0.001. + */ + +/**jsdoc + * The "Circle" {@link Overlays.OverlayType|OverlayType} is for 3D circle. + * @typedef {object} Overlays.OverlayProperties-Circle + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. + * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. + * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * pulseMin to pulseMax, then pulseMax to pulseMin in one period. + * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + * @property {number} startAt = 0 - The counter - clockwise angle from the overlay's x-axis that drawing starts at, in degrees. + * @property {number} endAt = 360 - The counter - clockwise angle from the overlay's x-axis that drawing ends at, in degrees. + * @property {number} outerRadius = 1 - The outer radius of the overlay, in meters.Synonym: radius< / code>. + * @property {number} innerRadius = 0 - The inner radius of the overlay, in meters. + * @property {Color} color = 255, 255, 255 - The color of the overlay.Setting this value also sets the values of + * innerStartColor< / code>, innerEndColor< / code>, outerStartColor< / code>, and outerEndColor< / code>. + * @property {Color} startColor - Sets the values of innerStartColor< / code> and outerStartColor< / code>. + * Write - only.< / em> + * @property {Color} endColor - Sets the values of innerEndColor< / code> and outerEndColor< / code>. + * Write - only.< / em> + * @property {Color} innerColor - Sets the values of innerStartColor< / code> and innerEndColor< / code>. + * Write - only.< / em> + * @property {Color} outerColor - Sets the values of outerStartColor< / code> and outerEndColor< / code>. + * Write - only.< / em> + * @property {Color} innerStartcolor - The color at the inner start point of the overlay. + * @property {Color} innerEndColor - The color at the inner end point of the overlay. + * @property {Color} outerStartColor - The color at the outer start point of the overlay. + * @property {Color} outerEndColor - The color at the outer end point of the overlay. + * @property {number} alpha = 0.5 - The opacity of the overlay, 0.0< / code> -1.0< / code>.Setting this value also sets + * the values of innerStartAlpha< / code>, innerEndAlpha< / code>, outerStartAlpha< / code>, and + * outerEndAlpha< / code>.Synonym: Alpha< / code>; write - only< / em>. + * @property {number} startAlpha - Sets the values of innerStartAlpha< / code> and outerStartAlpha< / code>. + * Write - only.< / em> + * @property {number} endAlpha - Sets the values of innerEndAlpha< / code> and outerEndAlpha< / code>. + * Write - only.< / em> + * @property {number} innerAlpha - Sets the values of innerStartAlpha< / code> and innerEndAlpha< / code>. + * Write - only.< / em> + * @property {number} outerAlpha - Sets the values of outerStartAlpha< / code> and outerEndAlpha< / code>. + * Write - only.< / em> + * @property {number} innerStartAlpha = 0 - The alpha at the inner start point of the overlay. + * @property {number} innerEndAlpha = 0 - The alpha at the inner end point of the overlay. + * @property {number} outerStartAlpha = 0 - The alpha at the outer start point of the overlay. + * @property {number} outerEndAlpha = 0 - The alpha at the outer end point of the overlay. + * + * @property {boolean} hasTickMarks = false - If true< / code>, tick marks are drawn. + * @property {number} majorTickMarksAngle = 0 - The angle between major tick marks, in degrees. + * @property {number} minorTickMarksAngle = 0 - The angle between minor tick marks, in degrees. + * @property {number} majorTickMarksLength = 0 - The length of the major tick marks, in meters.A positive value draws tick marks + * outwards from the inner radius; a negative value draws tick marks inwards from the outer radius. + * @property {number} minorTickMarksLength = 0 - The length of the minor tick marks, in meters.A positive value draws tick marks + * outwards from the inner radius; a negative value draws tick marks inwards from the outer radius. + * @property {Color} majorTickMarksColor = 0, 0, 0 - The color of the major tick marks. + * @property {Color} minorTickMarksColor = 0, 0, 0 - The color of the minor tick marks. + */ \ No newline at end of file diff --git a/interface/src/ui/overlays/PanelAttachable.cpp b/interface/src/ui/overlays/PanelAttachable.cpp deleted file mode 100644 index b53474390c..0000000000 --- a/interface/src/ui/overlays/PanelAttachable.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// PanelAttachable.cpp -// interface/src/ui/overlays -// -// Created by Zander Otavka on 7/15/15. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "PanelAttachable.h" - -#include - -bool PanelAttachable::getParentVisible() const { - return true; -} - -// JSDoc for copying to @typedefs of overlay types that inherit PanelAttachable. -// No JSDoc because these properties are not actually used. -QVariant PanelAttachable::getProperty(const QString& property) { - if (property == "offsetPosition") { - return vec3toVariant(getOffsetPosition()); - } - if (property == "offsetRotation") { - return quatToVariant(getOffsetRotation()); - } - if (property == "offsetScale") { - return vec3toVariant(getOffsetScale()); - } - return QVariant(); -} - -void PanelAttachable::setProperties(const QVariantMap& properties) { - auto offsetPosition = properties["offsetPosition"]; - bool valid; - if (offsetPosition.isValid()) { - glm::vec3 newPosition = vec3FromVariant(offsetPosition, valid); - if (valid) { - setOffsetPosition(newPosition); - } - } - - auto offsetRotation = properties["offsetRotation"]; - if (offsetRotation.isValid()) { - setOffsetRotation(quatFromVariant(offsetRotation)); - } - - auto offsetScale = properties["offsetScale"]; - if (offsetScale.isValid()) { - setOffsetScale(vec3FromVariant(offsetScale)); - } -} - -bool PanelAttachable::applyTransformTo(Transform& transform, bool force) { - if (force || usecTimestampNow() > _transformExpiry) { - const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz - _transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD; - } - return false; -} diff --git a/interface/src/ui/overlays/PanelAttachable.h b/interface/src/ui/overlays/PanelAttachable.h deleted file mode 100644 index 95faf38cf2..0000000000 --- a/interface/src/ui/overlays/PanelAttachable.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// PanelAttachable.h -// interface/src/ui/overlays -// -// Created by Zander Otavka on 7/1/15. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -// Base class for anything that can attach itself to an `OverlayPanel` as a child. -// `PanelAttachable keeps an `std::shared_ptr` to it's parent panel, and sets its -// transformations and visibility based on the parent. -// -// When subclassing `PanelAttachable`, make sure `applyTransformTo`, `getProperty`, and -// `setProperties are all called in the appropriate places. Look through `Image3DOverlay` and -// `Billboard3DOverlay` for examples. Pay special attention to `applyTransformTo`; it should -// be called in three places for `Overlay`s: `render`, `update`, and `findRayIntersection`. -// -// When overriding `applyTransformTo`, make sure to wrap all of your code, including the call -// to the superclass method, with the following `if` block. Then call the superclass method -// with force = true. -// -// if (force || usecTimestampNow() > _transformExpiry) { -// PanelAttachable::applyTransformTo(transform, true); -// ... -// } -// - -#ifndef hifi_PanelAttachable_h -#define hifi_PanelAttachable_h - -#include - -#include -#include -#include -#include -#include - -class OverlayPanel; -class PanelAttachable { -public: - // getters - glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); } - glm::quat getOffsetRotation() const { return _offset.getRotation(); } - glm::vec3 getOffsetScale() const { return _offset.getScale(); } - bool getParentVisible() const; - - // setters - void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); } - void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); } - void setOffsetScale(float scale) { _offset.setScale(scale); } - void setOffsetScale(const glm::vec3& scale) { _offset.setScale(scale); } - -protected: - void setProperties(const QVariantMap& properties); - QVariant getProperty(const QString& property); - - /// set position, rotation and scale on transform based on offsets, and parent panel offsets - /// if force is false, only apply transform if it hasn't been applied in the last .1 seconds - virtual bool applyTransformTo(Transform& transform, bool force = false); - quint64 _transformExpiry = 0; - -private: - Transform _offset; -}; - -#endif // hifi_PanelAttachable_h diff --git a/interface/src/ui/overlays/Planar3DOverlay.cpp b/interface/src/ui/overlays/Planar3DOverlay.cpp deleted file mode 100644 index c33d3a0c39..0000000000 --- a/interface/src/ui/overlays/Planar3DOverlay.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// Planar3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Planar3DOverlay.h" - -#include -#include -#include - -Planar3DOverlay::Planar3DOverlay() : - Base3DOverlay(), - _dimensions{1.0f, 1.0f} -{ -} - -Planar3DOverlay::Planar3DOverlay(const Planar3DOverlay* planar3DOverlay) : - Base3DOverlay(planar3DOverlay), - _dimensions(planar3DOverlay->_dimensions) -{ -} - -AABox Planar3DOverlay::getBounds() const { - auto halfDimensions = glm::vec3{_dimensions / 2.0f, 0.01f}; - - auto extents = Extents{-halfDimensions, halfDimensions}; - extents.transform(getTransform()); - - return AABox(extents); -} - -void Planar3DOverlay::setDimensions(const glm::vec2& value) { - _dimensions = value; - notifyRenderVariableChange(); -} - -void Planar3DOverlay::setProperties(const QVariantMap& properties) { - Base3DOverlay::setProperties(properties); - - auto dimensions = properties["dimensions"]; - - // if "dimensions" property was not there, check to see if they included aliases: scale - if (!dimensions.isValid()) { - dimensions = properties["scale"]; - if (!dimensions.isValid()) { - dimensions = properties["size"]; - } - } - - if (dimensions.isValid()) { - setDimensions(vec2FromVariant(dimensions)); - } -} - -// JSDoc for copying to @typedefs of overlay types that inherit Planar3DOverlay. -/**jsdoc - * @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: scale, size. - */ -QVariant Planar3DOverlay::getProperty(const QString& property) { - if (property == "dimensions" || property == "scale" || property == "size") { - return vec2ToVariant(getDimensions()); - } - - return Base3DOverlay::getProperty(property); -} - -bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - glm::vec2 xyDimensions = getDimensions(); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition(); - - if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { - glm::vec3 forward = rotation * Vectors::FRONT; - if (glm::dot(forward, direction) > 0.0f) { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } else { - face = MIN_Z_FACE; - surfaceNormal = forward; - } - return true; - } - return false; -} - -bool Planar3DOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - glm::vec2 xyDimensions = getDimensions(); - glm::quat rotation = getWorldOrientation(); - glm::vec3 position = getWorldPosition(); - - glm::quat inverseRot = glm::inverse(rotation); - glm::vec3 localOrigin = inverseRot * (origin - position); - glm::vec3 localVelocity = inverseRot * velocity; - glm::vec3 localAcceleration = inverseRot * acceleration; - - if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) { - float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance; - glm::vec3 forward = rotation * Vectors::FRONT; - if (localIntersectionVelocityZ > 0.0f) { - face = MIN_Z_FACE; - surfaceNormal = forward; - } else { - face = MAX_Z_FACE; - surfaceNormal = -forward; - } - return true; - } - return false; -} - -Transform Planar3DOverlay::evalRenderTransform() { - auto transform = getTransform(); - transform.setScale(1.0f); // ignore inherited scale factor from parents - if (glm::length2(getDimensions()) != 1.0f) { - transform.postScale(vec3(getDimensions(), 1.0f)); - } - return transform; -} diff --git a/interface/src/ui/overlays/Planar3DOverlay.h b/interface/src/ui/overlays/Planar3DOverlay.h deleted file mode 100644 index 0054b0baf1..0000000000 --- a/interface/src/ui/overlays/Planar3DOverlay.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Planar3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Planar3DOverlay_h -#define hifi_Planar3DOverlay_h - -#include "Base3DOverlay.h" - -class Planar3DOverlay : public Base3DOverlay { - Q_OBJECT - -public: - Planar3DOverlay(); - Planar3DOverlay(const Planar3DOverlay* planar3DOverlay); - - virtual AABox getBounds() const override; - virtual glm::vec2 getSize() const { return _dimensions; }; - - glm::vec2 getDimensions() const { return _dimensions; } - void setDimensions(float value) { setDimensions(glm::vec2(value)); } - void setDimensions(const glm::vec2& value); - - virtual void setProperties(const QVariantMap& properties) override; - virtual QVariant getProperty(const QString& property) override; - - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - -protected: - glm::vec2 _dimensions; - - Transform evalRenderTransform() override; -}; - - -#endif // hifi_Planar3DOverlay_h diff --git a/interface/src/ui/overlays/QmlOverlay.h b/interface/src/ui/overlays/QmlOverlay.h index 7f2cf5a918..ce25ee75ba 100644 --- a/interface/src/ui/overlays/QmlOverlay.h +++ b/interface/src/ui/overlays/QmlOverlay.h @@ -25,7 +25,6 @@ public: QmlOverlay(const QUrl& url, const QmlOverlay* textOverlay); ~QmlOverlay(); - // Cannot fetch properties from QML based overlays due to race conditions bool supportsGetProperty() const override { return false; } void setProperties(const QVariantMap& properties) override; diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp deleted file mode 100644 index e30171bd50..0000000000 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// -// Rectangle3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Rectangle3DOverlay.h" - -#include -#include - - -QString const Rectangle3DOverlay::TYPE = "rectangle3d"; - -Rectangle3DOverlay::Rectangle3DOverlay() : - _geometryCacheID(DependencyManager::get()->allocateID()) -{ - auto geometryCache = DependencyManager::get(); - for (size_t i = 0; i < _rectGeometryIds.size(); ++i) { - _rectGeometryIds[i] = geometryCache->allocateID(); - } -} - -Rectangle3DOverlay::Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay) : - Planar3DOverlay(rectangle3DOverlay), - _geometryCacheID(DependencyManager::get()->allocateID()) -{ - auto geometryCache = DependencyManager::get(); - for (size_t i = 0; i < _rectGeometryIds.size(); ++i) { - _rectGeometryIds[i] = geometryCache->allocateID(); - } -} - -Rectangle3DOverlay::~Rectangle3DOverlay() { - auto geometryCache = DependencyManager::get(); - if (geometryCache) { - geometryCache->releaseID(_geometryCacheID); - for (size_t i = 0; i < _rectGeometryIds.size(); ++i) { - geometryCache->releaseID(_rectGeometryIds[i]); - } - } -} - -void Rectangle3DOverlay::render(RenderArgs* args) { - if (!_renderVisible) { - return; // do nothing if we're not visible - } - - float alpha = getAlpha(); - glm::u8vec3 color = getColor(); - glm::vec4 rectangleColor(toGlm(color), alpha); - - auto batch = args->_batch; - if (batch) { - Transform transform = getRenderTransform(); - glm::vec2 halfDimensions = transform.getScale() * 0.5f; - transform.setScale(1.0f); - - batch->setModelTransform(transform); - auto geometryCache = DependencyManager::get(); - - if (getIsSolid()) { - glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, 0.0f); - glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, 0.0f); - geometryCache->bindSimpleProgram(*batch); - geometryCache->renderQuad(*batch, topLeft, bottomRight, rectangleColor, _geometryCacheID); - } else { - geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); - if (getIsDashedLine()) { - glm::vec3 point1(-halfDimensions.x, -halfDimensions.y, 0.0f); - glm::vec3 point2(halfDimensions.x, -halfDimensions.y, 0.0f); - glm::vec3 point3(halfDimensions.x, halfDimensions.y, 0.0f); - glm::vec3 point4(-halfDimensions.x, halfDimensions.y, 0.0f); - - geometryCache->renderDashedLine(*batch, point1, point2, rectangleColor, _rectGeometryIds[0]); - geometryCache->renderDashedLine(*batch, point2, point3, rectangleColor, _rectGeometryIds[1]); - geometryCache->renderDashedLine(*batch, point3, point4, rectangleColor, _rectGeometryIds[2]); - geometryCache->renderDashedLine(*batch, point4, point1, rectangleColor, _rectGeometryIds[3]); - } else { - if (halfDimensions != _previousHalfDimensions) { - QVector border; - border << glm::vec3(-halfDimensions.x, -halfDimensions.y, 0.0f); - border << glm::vec3(halfDimensions.x, -halfDimensions.y, 0.0f); - border << glm::vec3(halfDimensions.x, halfDimensions.y, 0.0f); - border << glm::vec3(-halfDimensions.x, halfDimensions.y, 0.0f); - border << glm::vec3(-halfDimensions.x, -halfDimensions.y, 0.0f); - geometryCache->updateVertices(_geometryCacheID, border, rectangleColor); - - _previousHalfDimensions = halfDimensions; - } - geometryCache->renderVertices(*batch, gpu::LINE_STRIP, _geometryCacheID); - } - } - } -} - -const render::ShapeKey Rectangle3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withOwnPipeline(); - if (isTransparent()) { - builder.withTranslucent(); - } - return builder.build(); -} - -/**jsdoc - * These are the properties of a rectangle3d {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.Rectangle3DProperties - * - * @property {string} type=rectangle3d - Has the value "rectangle3d". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: scale, size. - */ -void Rectangle3DOverlay::setProperties(const QVariantMap& properties) { - Planar3DOverlay::setProperties(properties); -} - -Rectangle3DOverlay* Rectangle3DOverlay::createClone() const { - return new Rectangle3DOverlay(this); -} diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.h b/interface/src/ui/overlays/Rectangle3DOverlay.h deleted file mode 100644 index 645553ed38..0000000000 --- a/interface/src/ui/overlays/Rectangle3DOverlay.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Rectangle3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Rectangle3DOverlay_h -#define hifi_Rectangle3DOverlay_h - -#include "Planar3DOverlay.h" - -class Rectangle3DOverlay : public Planar3DOverlay { - Q_OBJECT - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Rectangle3DOverlay(); - Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay); - ~Rectangle3DOverlay(); - virtual void render(RenderArgs* args) override; - virtual const render::ShapeKey getShapeKey() override; - void setProperties(const QVariantMap& properties) override; - - virtual Rectangle3DOverlay* createClone() const override; - -private: - int _geometryCacheID; - std::array _rectGeometryIds; - glm::vec2 _previousHalfDimensions; -}; - - -#endif // hifi_Rectangle3DOverlay_h diff --git a/interface/src/ui/overlays/RectangleOverlay.cpp b/interface/src/ui/overlays/RectangleOverlay.cpp index af37a4ac02..1487a4cb63 100644 --- a/interface/src/ui/overlays/RectangleOverlay.cpp +++ b/interface/src/ui/overlays/RectangleOverlay.cpp @@ -11,29 +11,6 @@ QString const RectangleOverlay::TYPE = "rectangle"; QUrl const RectangleOverlay::URL(QString("hifi/overlays/RectangleOverlay.qml")); -// RectangleOverlay's properties are defined in the QML file specified above. -/**jsdoc - * These are the properties of a rectangle {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.RectangleProperties - * - * @property {Rect} bounds - The position and size of the rectangle, in pixels. Write-only. - * @property {number} x - Integer left, x-coordinate value = bounds.x. Write-only. - * @property {number} y - Integer top, y-coordinate value = bounds.y. Write-only. - * @property {number} width - Integer width of the rectangle = bounds.width. Write-only. - * @property {number} height - Integer height of the rectangle = bounds.height. Write-only. - * - * @property {Color} color=0,0,0 - The color of the overlay. Write-only. - * @property {number} alpha=1.0 - The opacity of the overlay, 0.0 - 1.0. Write-only. - * @property {number} borderWidth=1 - Integer width of the border, in pixels. The border is drawn within the rectangle's bounds. - * It is not drawn unless either borderColor or borderAlpha are specified. Write-only. - * @property {number} radius=0 - Integer corner radius, in pixels. Write-only. - * @property {Color} borderColor=0,0,0 - The color of the border. Write-only. - * @property {number} borderAlpha=1.0 - The opacity of the border, 0.0 - 1.0. - * Write-only. - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * Write-only. - */ - RectangleOverlay::RectangleOverlay() : QmlOverlay(URL) {} RectangleOverlay::RectangleOverlay(const RectangleOverlay* rectangleOverlay) diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp deleted file mode 100644 index b7bbc76ffb..0000000000 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// -// Shape3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -// include this before QGLWidget, which includes an earlier version of OpenGL -#include "Shape3DOverlay.h" - -#include -#include -#include -#include - -QString const Shape3DOverlay::TYPE = "shape"; - -Shape3DOverlay::Shape3DOverlay(const Shape3DOverlay* shape3DOverlay) : - Volume3DOverlay(shape3DOverlay), - _shape(shape3DOverlay->_shape) -{ -} - -void Shape3DOverlay::render(RenderArgs* args) { - if (!_renderVisible) { - return; // do nothing if we're not visible - } - - float alpha = getAlpha(); - glm::u8vec3 color = getColor(); - glm::vec4 shapeColor(toGlm(color), alpha); - - auto batch = args->_batch; - if (batch) { - auto geometryCache = DependencyManager::get(); - auto shapePipeline = args->_shapePipeline; - if (!shapePipeline) { - shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); - } - - batch->setModelTransform(getRenderTransform()); - if (_isSolid) { - geometryCache->renderSolidShapeInstance(args, *batch, _shape, shapeColor, shapePipeline); - } else { - geometryCache->renderWireShapeInstance(args, *batch, _shape, shapeColor, shapePipeline); - } - } -} - -const render::ShapeKey Shape3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); - if (isTransparent()) { - builder.withTranslucent(); - } - if (!getIsSolid()) { - builder.withUnlit().withDepthBias(); - } - return builder.build(); -} - -Shape3DOverlay* Shape3DOverlay::createClone() const { - return new Shape3DOverlay(this); -} - - -/**jsdoc - *

A shape {@link Overlays.OverlayType|OverlayType} may display as one of the following geometrical shapes:

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
ValueDimensionsDescription
"Circle"2DA circle oriented in 3D.
"Cone"3D
"Cube"3D
"Cylinder"3D
"Dodecahedron"3D
"Hexagon"3DA hexagonal prism.
"Icosahedron"3D
"Line"1DA line oriented in 3D.
"Octagon"3DAn octagonal prism.
"Octahedron"3D
"Quad"2DA square oriented in 3D.
"Sphere"3D
"Tetrahedron"3D
"Torus"3DNot implemented.
"Triangle"3DA triangular prism.
- * @typedef {string} Overlays.Shape - */ -static const std::array shapeStrings { { - "Line", - "Triangle", - "Quad", - "Hexagon", - "Octagon", - "Circle", - "Cube", - "Sphere", - "Tetrahedron", - "Octahedron", - "Dodecahedron", - "Icosahedron", - "Torus", // Not implemented yet. - "Cone", - "Cylinder" -} }; - - -void Shape3DOverlay::setProperties(const QVariantMap& properties) { - Volume3DOverlay::setProperties(properties); - - auto shape = properties["shape"]; - if (shape.isValid()) { - const QString shapeStr = shape.toString(); - for (size_t i = 0; i < shapeStrings.size(); ++i) { - if (shapeStr == shapeStrings[i]) { - this->_shape = static_cast(i); - break; - } - } - } -} - -/**jsdoc - * These are the properties of a shape {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.ShapeProperties - * - * @property {string} type=shape - Has the value "shape". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid
, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. - * - * @property {Overlays.Shape} shape=Hexagon - The geometrical shape of the overlay. - */ -QVariant Shape3DOverlay::getProperty(const QString& property) { - if (property == "shape") { - return shapeStrings[_shape]; - } - - return Volume3DOverlay::getProperty(property); -} - -Transform Shape3DOverlay::evalRenderTransform() { - // TODO: handle registration point?? - glm::vec3 position = getWorldPosition(); - glm::vec3 dimensions = getDimensions(); - glm::quat rotation = getWorldOrientation(); - - Transform transform; - transform.setScale(dimensions); - transform.setTranslation(position); - transform.setRotation(rotation); - return transform; -} - -scriptable::ScriptableModelBase Shape3DOverlay::getScriptableModel() { - auto geometryCache = DependencyManager::get(); - auto vertexColor = ColorUtils::toVec3(_color); - scriptable::ScriptableModelBase result; - result.objectID = Overlay::getID(); - if (auto mesh = geometryCache->meshFromShape(_shape, vertexColor)) { - result.append(mesh); - } - return result; -} diff --git a/interface/src/ui/overlays/Shape3DOverlay.h b/interface/src/ui/overlays/Shape3DOverlay.h deleted file mode 100644 index 60af287af0..0000000000 --- a/interface/src/ui/overlays/Shape3DOverlay.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Shape3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Shape3DOverlay_h -#define hifi_Shape3DOverlay_h - -#include "Volume3DOverlay.h" - -#include - -class Shape3DOverlay : public Volume3DOverlay { - Q_OBJECT - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Shape3DOverlay() {} - Shape3DOverlay(const Shape3DOverlay* shape3DOverlay); - - virtual void render(RenderArgs* args) override; - virtual const render::ShapeKey getShapeKey() override; - - virtual Shape3DOverlay* createClone() const override; - - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - - virtual scriptable::ScriptableModelBase getScriptableModel() override; -protected: - Transform evalRenderTransform() override; - -private: - GeometryCache::Shape _shape { GeometryCache::Hexagon }; -}; - - -#endif // hifi_Shape3DOverlay_h diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp deleted file mode 100644 index 385fea768c..0000000000 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Sphere3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Sphere3DOverlay.h" - -#include -#include -#include -#include - -QString const Sphere3DOverlay::TYPE = "sphere"; - -// Sphere overlays should fit inside a cube of the specified dimensions, hence it needs to be a half unit sphere. -// However, the geometry cache renders a UNIT sphere, so we need to scale down. -static const float SPHERE_OVERLAY_SCALE = 0.5f; - -Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) : - Volume3DOverlay(Sphere3DOverlay) -{ -} - -// If Sphere3DOverlay had a getProperty() method then it would go here; do JSDoc here. -/**jsdoc - * These are the properties of a sphere {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.SphereProperties - * - * @property {string} type=sphere - Has the value "sphere". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. - */ - -void Sphere3DOverlay::render(RenderArgs* args) { - if (!_renderVisible) { - return; // do nothing if we're not visible - } - - float alpha = getAlpha(); - glm::u8vec3 color = getColor(); - glm::vec4 sphereColor(toGlm(color), alpha); - - auto batch = args->_batch; - - if (batch) { - batch->setModelTransform(getRenderTransform()); - - auto geometryCache = DependencyManager::get(); - auto shapePipeline = args->_shapePipeline; - if (!shapePipeline) { - shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline(); - } - - if (_isSolid) { - geometryCache->renderSolidSphereInstance(args, *batch, sphereColor, shapePipeline); - } else { - geometryCache->renderWireSphereInstance(args, *batch, sphereColor, shapePipeline); - } - } -} - -const render::ShapeKey Sphere3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); - if (isTransparent()) { - builder.withTranslucent(); - } - if (!getIsSolid()) { - builder.withUnlit().withDepthBias(); - } - return builder.build(); -} - -Sphere3DOverlay* Sphere3DOverlay::createClone() const { - return new Sphere3DOverlay(this); -} - -Transform Sphere3DOverlay::evalRenderTransform() { - Transform transform = getTransform(); - transform.setScale(1.0f); // ignore inherited scale from SpatiallyNestable - transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE); - - return transform; -} - - -scriptable::ScriptableModelBase Sphere3DOverlay::getScriptableModel() { - auto geometryCache = DependencyManager::get(); - auto vertexColor = ColorUtils::toVec3(_color); - scriptable::ScriptableModelBase result; - if (auto mesh = geometryCache->meshFromShape(GeometryCache::Sphere, vertexColor)) { - result.objectID = Overlay::getID(); - result.append(mesh); - } - return result; -} diff --git a/interface/src/ui/overlays/Sphere3DOverlay.h b/interface/src/ui/overlays/Sphere3DOverlay.h deleted file mode 100644 index 9a434e7182..0000000000 --- a/interface/src/ui/overlays/Sphere3DOverlay.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Sphere3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Sphere3DOverlay_h -#define hifi_Sphere3DOverlay_h - -#include "Volume3DOverlay.h" - -class Sphere3DOverlay : public Volume3DOverlay { - Q_OBJECT - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Sphere3DOverlay() {} - Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay); - - virtual void render(RenderArgs* args) override; - virtual const render::ShapeKey getShapeKey() override; - - virtual Sphere3DOverlay* createClone() const override; - - virtual scriptable::ScriptableModelBase getScriptableModel() override; -protected: - Transform evalRenderTransform() override; -}; - - -#endif // hifi_Sphere3DOverlay_h diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp deleted file mode 100644 index 58ce16a9fc..0000000000 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ /dev/null @@ -1,295 +0,0 @@ -// -// Text3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - - -#include "Text3DOverlay.h" - -#include -#include -#include -#include -#include - -#include - -const int FIXED_FONT_POINT_SIZE = 40; -const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 92.0f; // Determined through experimentation to fit font to line - // height. -const float LINE_SCALE_RATIO = 1.2f; - -QString const Text3DOverlay::TYPE = "text3d"; - -Text3DOverlay::Text3DOverlay() { - _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); - _geometryId = DependencyManager::get()->allocateID(); -} - -Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) : - Billboard3DOverlay(text3DOverlay), - _text(text3DOverlay->_text), - _backgroundColor(text3DOverlay->_backgroundColor), - _textAlpha(text3DOverlay->_textAlpha), - _lineHeight(text3DOverlay->_lineHeight), - _leftMargin(text3DOverlay->_leftMargin), - _topMargin(text3DOverlay->_topMargin), - _rightMargin(text3DOverlay->_rightMargin), - _bottomMargin(text3DOverlay->_bottomMargin) -{ - _textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE); - _geometryId = DependencyManager::get()->allocateID(); -} - -Text3DOverlay::~Text3DOverlay() { - delete _textRenderer; - auto geometryCache = DependencyManager::get(); - if (geometryCache) { - geometryCache->releaseID(_geometryId); - } -} - -const QString Text3DOverlay::getText() const { - QMutexLocker lock(&_mutex); - return _text; -} - -void Text3DOverlay::setText(const QString& text) { - QMutexLocker lock(&_mutex); - _text = text; -} - -glm::u8vec3 Text3DOverlay::getBackgroundColor() { - if (_colorPulse == 0.0f) { - return _backgroundColor; - } - - float pulseLevel = updatePulse(); - glm::u8vec3 result = _backgroundColor; - if (_colorPulse < 0.0f) { - result.x *= (1.0f - pulseLevel); - result.y *= (1.0f - pulseLevel); - result.z *= (1.0f - pulseLevel); - } else { - result.x *= pulseLevel; - result.y *= pulseLevel; - result.z *= pulseLevel; - } - return result; -} - -void Text3DOverlay::render(RenderArgs* args) { - if (!_renderVisible || !getParentVisible()) { - return; // do nothing if we're not visible - } - - Q_ASSERT(args->_batch); - auto& batch = *args->_batch; - - auto transform = getRenderTransform(); - batch.setModelTransform(transform); - - glm::u8vec3 backgroundColor = getBackgroundColor(); - glm::vec4 quadColor(toGlm(backgroundColor), getBackgroundAlpha()); - - glm::vec2 dimensions = getDimensions(); - glm::vec2 halfDimensions = dimensions * 0.5f; - - const float SLIGHTLY_BEHIND = -0.001f; - - glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND); - glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND); - DependencyManager::get()->bindSimpleProgram(batch, false, quadColor.a < 1.0f, false, false, false); - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, quadColor, _geometryId); - - // Same font properties as textSize() - float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO; - - float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; - - glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor, - (dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor); - - transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin), - halfDimensions.y - _topMargin, 0.001f)); - transform.setScale(scaleFactor); - batch.setModelTransform(transform); - - glm::vec4 textColor = { toGlm(_color), getTextAlpha() }; - - // FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline for a gpu performance increase. - _textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f)); -} - -const render::ShapeKey Text3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder(); - if (isTransparent()) { - builder.withTranslucent(); - } - return builder.build(); -} - -void Text3DOverlay::setProperties(const QVariantMap& properties) { - Billboard3DOverlay::setProperties(properties); - - auto text = properties["text"]; - if (text.isValid()) { - setText(text.toString()); - } - - auto textAlpha = properties["textAlpha"]; - if (textAlpha.isValid()) { - float prevTextAlpha = getTextAlpha(); - setTextAlpha(textAlpha.toFloat()); - // Update our payload key if necessary to handle transparency - if ((prevTextAlpha < 1.0f && _textAlpha >= 1.0f) || (prevTextAlpha >= 1.0f && _textAlpha < 1.0f)) { - auto itemID = getRenderItemID(); - if (render::Item::isValidID(itemID)) { - render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); - render::Transaction transaction; - transaction.updateItem(itemID); - scene->enqueueTransaction(transaction); - } - } - } - - bool valid; - auto backgroundColor = properties["backgroundColor"]; - if (backgroundColor.isValid()) { - auto color = u8vec3FromVariant(backgroundColor, valid); - if (valid) { - _backgroundColor = color; - } - } - - if (properties["backgroundAlpha"].isValid()) { - setAlpha(properties["backgroundAlpha"].toFloat()); - } - - if (properties["lineHeight"].isValid()) { - setLineHeight(properties["lineHeight"].toFloat()); - } - - if (properties["leftMargin"].isValid()) { - setLeftMargin(properties["leftMargin"].toFloat()); - } - - if (properties["topMargin"].isValid()) { - setTopMargin(properties["topMargin"].toFloat()); - } - - if (properties["rightMargin"].isValid()) { - setRightMargin(properties["rightMargin"].toFloat()); - } - - if (properties["bottomMargin"].isValid()) { - setBottomMargin(properties["bottomMargin"].toFloat()); - } -} - -/**jsdoc - * These are the properties of a text3d {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.Text3DProperties - * - * @property {string} type=text3d - Has the value "text3d". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: scale, size. - * - * @property {boolean} isFacingAvatar - If true, the overlay is rotated to face the user's camera about an axis - * parallel to the user's avatar's "up" direction. - * - * @property {string} text="" - The text to display. Text does not automatically wrap; use \n for a line break. - * @property {number} textAlpha=1 - The text alpha value. - * @property {Color} backgroundColor=0,0,0 - The background color. - * @property {number} backgroundAlpha=0.7 - The background alpha value. - * @property {number} lineHeight=1 - The height of a line of text in meters. - * @property {number} leftMargin=0.1 - The left margin, in meters. - * @property {number} topMargin=0.1 - The top margin, in meters. - * @property {number} rightMargin=0.1 - The right margin, in meters. - * @property {number} bottomMargin=0.1 - The bottom margin, in meters. - */ - -QVariant Text3DOverlay::getProperty(const QString& property) { - if (property == "text") { - return getText(); - } - if (property == "textAlpha") { - return _textAlpha; - } - if (property == "backgroundColor") { - return u8vec3ColortoVariant(_backgroundColor); - } - if (property == "backgroundAlpha") { - return Billboard3DOverlay::getProperty("alpha"); - } - if (property == "lineHeight") { - return _lineHeight; - } - if (property == "leftMargin") { - return _leftMargin; - } - if (property == "topMargin") { - return _topMargin; - } - if (property == "rightMargin") { - return _rightMargin; - } - if (property == "bottomMargin") { - return _bottomMargin; - } - - return Billboard3DOverlay::getProperty(property); -} - -Text3DOverlay* Text3DOverlay::createClone() const { - return new Text3DOverlay(this);; -} - -QSizeF Text3DOverlay::textSize(const QString& text) const { - auto extents = _textRenderer->computeExtent(text); - - float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO; - float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; - - return QSizeF(extents.x, extents.y) * pointToWorldScale; -} diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h deleted file mode 100644 index 16bbdcb4c4..0000000000 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// Text3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Text3DOverlay_h -#define hifi_Text3DOverlay_h - -#include -#include -#include "Billboard3DOverlay.h" - -class TextRenderer3D; - -class Text3DOverlay : public Billboard3DOverlay { - Q_OBJECT - using Parent = Billboard3DOverlay; - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Text3DOverlay(); - Text3DOverlay(const Text3DOverlay* text3DOverlay); - ~Text3DOverlay(); - virtual void render(RenderArgs* args) override; - - virtual const render::ShapeKey getShapeKey() override; - - // getters - const QString getText() const; - float getLineHeight() const { return _lineHeight; } - float getLeftMargin() const { return _leftMargin; } - float getTopMargin() const { return _topMargin; } - float getRightMargin() const { return _rightMargin; } - float getBottomMargin() const { return _bottomMargin; } - glm::u8vec3 getBackgroundColor(); - float getTextAlpha() { return _textAlpha; } - float getBackgroundAlpha() { return getAlpha(); } - bool isTransparent() override { return Overlay::isTransparent() || _textAlpha < 1.0f; } - - // setters - void setText(const QString& text); - void setTextAlpha(float alpha) { _textAlpha = alpha; } - void setLineHeight(float value) { _lineHeight = value; } - void setLeftMargin(float margin) { _leftMargin = margin; } - void setTopMargin(float margin) { _topMargin = margin; } - void setRightMargin(float margin) { _rightMargin = margin; } - void setBottomMargin(float margin) { _bottomMargin = margin; } - - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - - QSizeF textSize(const QString& test) const; // Meters - - virtual Text3DOverlay* createClone() const override; - -private: - TextRenderer3D* _textRenderer = nullptr; - - QString _text; - mutable QMutex _mutex; // used to make get/setText threadsafe, mutable so can be used in const functions - glm::u8vec3 _backgroundColor { 0, 0, 0 }; - float _textAlpha { 1.0f }; - float _lineHeight { 1.0f }; - float _leftMargin { 0.1f }; - float _topMargin { 0.1f }; - float _rightMargin { 0.1f }; - float _bottomMargin { 0.1f }; - int _geometryId { 0 }; -}; - -#endif // hifi_Text3DOverlay_h diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index e7641ab2c2..2f4353dae8 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -27,43 +27,12 @@ QString const TextOverlay::TYPE = "text"; QUrl const TextOverlay::URL(QString("hifi/overlays/TextOverlay.qml")); -// TextOverlay's properties are defined in the QML file specified above. -/**jsdoc - * These are the properties of a text {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.TextProperties - * - * @property {Rect} bounds - The position and size of the rectangle, in pixels. Write-only. - * @property {number} x - Integer left, x-coordinate value = bounds.x. Write-only. - * @property {number} y - Integer top, y-coordinate value = bounds.y. Write-only. - * @property {number} width - Integer width of the rectangle = bounds.width. Write-only. - * @property {number} height - Integer height of the rectangle = bounds.height. Write-only. - * - * @property {number} margin=0 - Sets the leftMargin and topMargin values, in pixels. - * Write-only. - * @property {number} leftMargin=0 - The left margin's size, in pixels. This value is also used for the right margin. - * Write-only. - * @property {number} topMargin=0 - The top margin's size, in pixels. This value is also used for the bottom margin. - * Write-only. - * @property {string} text="" - The text to display. Text does not automatically wrap; use \n for a line break. Text - * is clipped to the bounds. Write-only. - * @property {number} font.size=18 - The size of the text, in pixels. Write-only. - * @property {number} lineHeight=18 - The height of a line of text, in pixels. Write-only. - * @property {Color} color=255,255,255 - The color of the text. Synonym: textColor. Write-only. - * @property {number} alpha=1.0 - The opacity of the overlay, 0.0 - 1.0. Write-only. - * @property {Color} backgroundColor=0,0,0 - The color of the background rectangle. Write-only. - * @property {number} backgroundAlpha=0.7 - The opacity of the background rectangle. Write-only. - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * Write-only. - */ - TextOverlay::TextOverlay() : QmlOverlay(URL) { } TextOverlay::TextOverlay(const TextOverlay* textOverlay) : QmlOverlay(URL, textOverlay) { } -TextOverlay::~TextOverlay() { } - TextOverlay* TextOverlay::createClone() const { return new TextOverlay(this); } @@ -80,10 +49,4 @@ QSizeF TextOverlay::textSize(const QString& text) const { QFontMetrics fm(font); QSizeF result = QSizeF(fm.width(text), 18 * lines); return result; -} - - -void TextOverlay::setTopMargin(float margin) {} -void TextOverlay::setLeftMargin(float margin) {} -void TextOverlay::setFontSize(float size) {} -void TextOverlay::setText(const QString& text) {} +} \ No newline at end of file diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index 53c1805345..e78e2afa04 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -19,16 +19,8 @@ public: QString getType() const override { return TYPE; } static QUrl const URL; - TextOverlay(); TextOverlay(const TextOverlay* textOverlay); - ~TextOverlay(); - - void setTopMargin(float margin); - void setLeftMargin(float margin); - void setFontSize(float size); - void setText(const QString& text); - TextOverlay* createClone() const override; QSizeF textSize(const QString& text) const; // Pixels diff --git a/interface/src/ui/overlays/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp deleted file mode 100644 index 0cceb44a36..0000000000 --- a/interface/src/ui/overlays/Volume3DOverlay.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// Volume3DOverlay.cpp -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Volume3DOverlay.h" - -#include -#include - -Volume3DOverlay::Volume3DOverlay(const Volume3DOverlay* volume3DOverlay) : - Base3DOverlay(volume3DOverlay), - _localBoundingBox(volume3DOverlay->_localBoundingBox) -{ -} - -AABox Volume3DOverlay::getBounds() const { - AABox bounds = _localBoundingBox; - bounds.transform(getTransform()); - return bounds; -} - -void Volume3DOverlay::setDimensions(const glm::vec3& value) { - _localBoundingBox.setBox(-value / 2.0f, value); - notifyRenderVariableChange(); -} - -void Volume3DOverlay::setProperties(const QVariantMap& properties) { - Base3DOverlay::setProperties(properties); - - auto dimensions = properties["dimensions"]; - - // if "dimensions" property was not there, check to see if they included aliases: scale, size - if (!dimensions.isValid()) { - dimensions = properties["scale"]; - if (!dimensions.isValid()) { - dimensions = properties["size"]; - } - } - - if (dimensions.isValid()) { - glm::vec3 scale = vec3FromVariant(dimensions); - // don't allow a zero or negative dimension component to reach the renderTransform - const float MIN_DIMENSION = 0.0001f; - scale = glm::max(scale, MIN_DIMENSION); - setDimensions(scale); - } -} - -// JSDoc for copying to @typedefs of overlay types that inherit Volume3DOverlay. -/**jsdoc - * @typedef - * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. - */ -QVariant Volume3DOverlay::getProperty(const QString& property) { - if (property == "dimensions" || property == "scale" || property == "size") { - return vec3toVariant(getDimensions()); - } - - return Base3DOverlay::getProperty(property); -} - -bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 worldToEntityMatrix; - Transform transform = getTransform(); - transform.setScale(1.0f); // ignore any inherited scale from SpatiallyNestable - transform.getInverseMatrix(worldToEntityMatrix); - - glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); - glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - - // we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame - // and testing intersection there. - bool hit = _localBoundingBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, 1.0f / overlayFrameDirection, distance, face, surfaceNormal); - - if (hit) { - surfaceNormal = transform.getRotation() * surfaceNormal; - } - return hit; -} - -bool Volume3DOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, - float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) { - // extents is the entity relative, scaled, centered extents of the entity - glm::mat4 worldToEntityMatrix; - Transform transform = getTransform(); - transform.setScale(1.0f); // ignore any inherited scale from SpatiallyNestable - transform.getInverseMatrix(worldToEntityMatrix); - - glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); - glm::vec3 overlayFrameVelocity = glm::vec3(worldToEntityMatrix * glm::vec4(velocity, 0.0f)); - glm::vec3 overlayFrameAcceleration = glm::vec3(worldToEntityMatrix * glm::vec4(acceleration, 0.0f)); - - // we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame - // and testing intersection there. - bool hit = _localBoundingBox.findParabolaIntersection(overlayFrameOrigin, overlayFrameVelocity, overlayFrameAcceleration, parabolicDistance, face, surfaceNormal); - - if (hit) { - surfaceNormal = transform.getRotation() * surfaceNormal; - } - return hit; -} - -Transform Volume3DOverlay::evalRenderTransform() { - Transform transform = getTransform(); -#ifndef USE_SN_SCALE - transform.setScale(1.0f); // ignore any inherited scale from SpatiallyNestable -#endif - return transform; -} diff --git a/interface/src/ui/overlays/Volume3DOverlay.h b/interface/src/ui/overlays/Volume3DOverlay.h deleted file mode 100644 index 2083f7344a..0000000000 --- a/interface/src/ui/overlays/Volume3DOverlay.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Volume3DOverlay.h -// interface/src/ui/overlays -// -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Volume3DOverlay_h -#define hifi_Volume3DOverlay_h - -#include "Base3DOverlay.h" - -class Volume3DOverlay : public Base3DOverlay { - Q_OBJECT - using Parent = Base3DOverlay; - -public: - Volume3DOverlay() {} - Volume3DOverlay(const Volume3DOverlay* volume3DOverlay); - - virtual AABox getBounds() const override; - - const glm::vec3& getDimensions() const { return _localBoundingBox.getDimensions(); } - void setDimensions(const glm::vec3& value); - - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - - virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance, - BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override; - -protected: - // Centered local bounding box - AABox _localBoundingBox { vec3(-0.5), 1.0f }; - - Transform evalRenderTransform() override; -}; - - -#endif // hifi_Volume3DOverlay_h diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp deleted file mode 100644 index eb61ca7281..0000000000 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ /dev/null @@ -1,490 +0,0 @@ -// -// Web3DOverlay.cpp -// -// Created by Clement on 7/1/14. -// Modified and renamed by Zander Otavka on 8/4/15 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "Web3DOverlay.h" - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "scripting/HMDScriptingInterface.h" -#include "scripting/AssetMappingsScriptingInterface.h" -#include "scripting/MenuScriptingInterface.h" -#include "scripting/SettingsScriptingInterface.h" -#include "scripting/KeyboardScriptingInterface.h" -#include -#include -#include -#include "FileDialogHelper.h" -#include "avatar/AvatarManager.h" -#include "AudioClient.h" -#include "LODManager.h" -#include "ui/LoginDialog.h" -#include "ui/OctreeStatsProvider.h" -#include "ui/DomainConnectionModel.h" -#include "ui/AvatarInputs.h" -#include "avatar/AvatarManager.h" -#include "scripting/AccountServicesScriptingInterface.h" -#include "scripting/WalletScriptingInterface.h" -#include -#include "ui/Snapshot.h" -#include "SoundCacheScriptingInterface.h" -#include "raypick/PointerScriptingInterface.h" -#include -#include "AboutUtil.h" -#include "ResourceRequestObserver.h" - -#include - -static int MAX_WINDOW_SIZE = 4096; -static const float METERS_TO_INCHES = 39.3701f; -static const float OPAQUE_ALPHA_THRESHOLD = 0.99f; - -const QString Web3DOverlay::TYPE = "web3d"; - -Web3DOverlay::Web3DOverlay() { - _touchDevice.setCapabilities(QTouchDevice::Position); - _touchDevice.setType(QTouchDevice::TouchScreen); - _touchDevice.setName("Web3DOverlayTouchDevice"); - _touchDevice.setMaximumTouchPoints(4); - - _geometryId = DependencyManager::get()->allocateID(); - connect(this, &Web3DOverlay::requestWebSurface, this, &Web3DOverlay::buildWebSurface); - connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface); - - buildWebSurface(true); -} - -Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) : - Billboard3DOverlay(Web3DOverlay), - _url(Web3DOverlay->_url), - _scriptURL(Web3DOverlay->_scriptURL), - _dpi(Web3DOverlay->_dpi) -{ - _geometryId = DependencyManager::get()->allocateID(); -} - -Web3DOverlay::~Web3DOverlay() { - destroyWebSurface(); - auto geometryCache = DependencyManager::get(); - if (geometryCache) { - geometryCache->releaseID(_geometryId); - } -} - -void Web3DOverlay::rebuildWebSurface() { - destroyWebSurface(); - buildWebSurface(); -} - -void Web3DOverlay::destroyWebSurface() { - if (_webSurface) { - render::entities::WebEntityRenderer::releaseWebSurface(_webSurface, _cachedWebSurface, _connections); - } -} - -void Web3DOverlay::buildWebSurface(bool overrideWeb) { - if (_webSurface) { - return; - } - - render::entities::WebEntityRenderer::acquireWebSurface(_url, overrideWeb || isWebContent(), _webSurface, _cachedWebSurface); - onResizeWebSurface(); - _webSurface->resume(); - - _connections.push_back(QObject::connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent)); - _connections.push_back(QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived)); -} - -void Web3DOverlay::update(float deltatime) { - if (_webSurface) { - // update globalPosition - _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getWorldPosition())); - } - Parent::update(deltatime); -} - -bool Web3DOverlay::isWebContent() const { - QUrl sourceUrl(_url); - if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || - _url.toLower().endsWith(".htm") || _url.toLower().endsWith(".html")) { - return true; - } - return false; -} - -void Web3DOverlay::setMaxFPS(uint8_t maxFPS) { - // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces and the current rendering load) - _desiredMaxFPS = maxFPS; - if (_webSurface) { - _webSurface->setMaxFps(_desiredMaxFPS); - _currentMaxFPS = _desiredMaxFPS; - } -} - -void Web3DOverlay::onResizeWebSurface() { - glm::vec2 dims = glm::vec2(getDimensions()); - dims *= METERS_TO_INCHES * _dpi; - - // ensure no side is never larger then MAX_WINDOW_SIZE - float max = (dims.x > dims.y) ? dims.x : dims.y; - if (max > MAX_WINDOW_SIZE) { - dims *= MAX_WINDOW_SIZE / max; - } - - _webSurface->resize(QSize(dims.x, dims.y)); -} - -void Web3DOverlay::render(RenderArgs* args) { - if (!_renderVisible || !getParentVisible()) { - return; - } - - if (!_webSurface) { - emit requestWebSurface(false); - return; - } - - if (_mayNeedResize) { - emit resizeWebSurface(); - } - - if (_currentMaxFPS != _desiredMaxFPS) { - setMaxFPS(_desiredMaxFPS); - } - - vec4 color(toGlm(getColor()), getAlpha()); - - if (!_texture) { - _texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); - _texture->setSource(__FUNCTION__); - } - OffscreenQmlSurface::TextureAndFence newTextureAndFence; - bool newTextureAvailable = _webSurface->fetchTexture(newTextureAndFence); - if (newTextureAvailable) { - _texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second); - } - - Q_ASSERT(args->_batch); - gpu::Batch& batch = *args->_batch; - batch.setResourceTexture(0, _texture); - - auto renderTransform = getRenderTransform(); - auto size = renderTransform.getScale(); - renderTransform.setScale(1.0f); - batch.setModelTransform(renderTransform); - - // Turn off jitter for these entities - batch.pushProjectionJitter(); - - auto geometryCache = DependencyManager::get(); - if (color.a < OPAQUE_ALPHA_THRESHOLD) { - geometryCache->bindWebBrowserProgram(batch, true); - } else { - geometryCache->bindWebBrowserProgram(batch); - } - vec2 halfSize = vec2(size.x, size.y) / 2.0f; - geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color, _geometryId); - batch.popProjectionJitter(); // Restore jitter - batch.setResourceTexture(0, nullptr); // restore default white color after me - -} - -Transform Web3DOverlay::evalRenderTransform() { - Transform transform = Parent::evalRenderTransform(); - transform.setScale(1.0f); - transform.postScale(glm::vec3(getDimensions(), 1.0f)); - return transform; -} - -const render::ShapeKey Web3DOverlay::getShapeKey() { - auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline(); - if (isTransparent()) { - builder.withTranslucent(); - } - return builder.build(); -} - -QObject* Web3DOverlay::getEventHandler() { - if (!_webSurface) { - return nullptr; - } - return _webSurface->getEventHandler(); -} - -void Web3DOverlay::setProxyWindow(QWindow* proxyWindow) { - if (!_webSurface) { - return; - } - - _webSurface->setProxyWindow(proxyWindow); -} - -void Web3DOverlay::hoverEnterOverlay(const PointerEvent& event) { - if (_inputMode == Mouse) { - handlePointerEvent(event); - } else if (_webSurface) { - PointerEvent webEvent = event; - webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); - _webSurface->hoverBeginEvent(webEvent, _touchDevice); - } -} - -void Web3DOverlay::hoverLeaveOverlay(const PointerEvent& event) { - if (_inputMode == Mouse) { - PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(), - event.getButton(), event.getButtons(), event.getKeyboardModifiers()); - handlePointerEvent(endEvent); - // QML onReleased is only triggered if a click has happened first. We need to send this "fake" mouse move event to properly trigger an onExited. - PointerEvent endMoveEvent(PointerEvent::Move, event.getID()); - handlePointerEvent(endMoveEvent); - } else if (_webSurface) { - PointerEvent webEvent = event; - webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); - _webSurface->hoverEndEvent(webEvent, _touchDevice); - } -} - -void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { - if (_inputMode == Touch) { - handlePointerEventAsTouch(event); - } else { - handlePointerEventAsMouse(event); - } -} - -void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) { - if (_webSurface) { - PointerEvent webEvent = event; - webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); - _webSurface->handlePointerEvent(webEvent, _touchDevice); - } -} - -void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) { - if (!_webSurface) { - return; - } - - glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); - QPointF windowPoint(windowPos.x, windowPos.y); - - Qt::MouseButtons buttons = Qt::NoButton; - if (event.getButtons() & PointerEvent::PrimaryButton) { - buttons |= Qt::LeftButton; - } - - Qt::MouseButton button = Qt::NoButton; - if (event.getButton() == PointerEvent::PrimaryButton) { - button = Qt::LeftButton; - } - - QEvent::Type type; - switch (event.getType()) { - case PointerEvent::Press: - type = QEvent::MouseButtonPress; - break; - case PointerEvent::Release: - type = QEvent::MouseButtonRelease; - break; - case PointerEvent::Move: - type = QEvent::MouseMove; - break; - default: - return; - } - - QMouseEvent mouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, event.getKeyboardModifiers()); - QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); -} - -void Web3DOverlay::setProperties(const QVariantMap& properties) { - Billboard3DOverlay::setProperties(properties); - - auto urlValue = properties["url"]; - if (urlValue.isValid()) { - QString newURL = urlValue.toString(); - if (newURL != _url) { - setURL(newURL); - } - } - - auto scriptURLValue = properties["scriptURL"]; - if (scriptURLValue.isValid()) { - QString newScriptURL = scriptURLValue.toString(); - if (newScriptURL != _scriptURL) { - setScriptURL(newScriptURL); - } - } - - auto dpi = properties["dpi"]; - if (dpi.isValid()) { - _dpi = dpi.toFloat(); - _mayNeedResize = true; - } - - auto maxFPS = properties["maxFPS"]; - if (maxFPS.isValid()) { - _desiredMaxFPS = maxFPS.toInt(); - } - - auto inputModeValue = properties["inputMode"]; - if (inputModeValue.isValid()) { - QString inputModeStr = inputModeValue.toString(); - if (inputModeStr == "Mouse") { - _inputMode = Mouse; - } else { - _inputMode = Touch; - } - } -} - -// Web3DOverlay overrides the meaning of Planar3DOverlay's dimensions property. -/**jsdoc - * These are the properties of a web3d {@link Overlays.OverlayType|OverlayType}. - * @typedef {object} Overlays.Web3DProperties - * - * @property {string} type=web3d - Has the value "web3d". Read-only. - * @property {Color} color=255,255,255 - The color of the overlay. - * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. - * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. - * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. - * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from - * pulseMin to pulseMax, then pulseMax to pulseMin in one period. - * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the - * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 - * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise - * used.) - * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. - * - * @property {string} name="" - A friendly name for the overlay. - * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and - * start. - * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as position. - * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. - * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a - * parentID set, otherwise the same value as rotation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. - * @property {boolean} isDashedLine=false - If true, a dashed line is drawn on the overlay's edges. Synonym: - * dashed. Deprecated. - * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. - * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of other overlays that don't - * have drawInFront set to true, and in front of entities. - * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. - * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. - * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if - * parentID is an avatar skeleton. A value of 65535 means "no joint". - * - * @property {boolean} isFacingAvatar - If true, the overlay is rotated to face the user's camera about an axis - * parallel to the user's avatar's "up" direction. - * - * @property {string} url - The URL of the Web page to display. - * @property {string} scriptURL="" - The URL of a JavaScript file to inject into the Web page. - * @property {number} dpi=30 - The dots per inch to display the Web page at, on the overlay. - * @property {Vec2} dimensions=1,1 - The size of the overlay to display the Web page on, in meters. Synonyms: - * scale, size. - * @property {number} maxFPS=10 - The maximum update rate for the Web overlay content, in frames/second. - * @property {string} inputMode=Touch - The user input mode to use - either "Touch" or "Mouse". - */ -QVariant Web3DOverlay::getProperty(const QString& property) { - if (property == "url") { - return _url; - } - if (property == "scriptURL") { - return _scriptURL; - } - if (property == "dpi") { - return _dpi; - } - if (property == "maxFPS") { - return _desiredMaxFPS; - } - - if (property == "inputMode") { - if (_inputMode == Mouse) { - return QVariant("Mouse"); - } else { - return QVariant("Touch"); - } - } - return Billboard3DOverlay::getProperty(property); -} - -void Web3DOverlay::setURL(const QString& url) { - if (url != _url) { - bool wasWebContent = isWebContent(); - _url = url; - if (_webSurface) { - if (wasWebContent && isWebContent()) { - // If we're just targeting a new web URL, then switch to that without messing around - // with the underlying QML - AbstractViewStateInterface::instance()->postLambdaEvent([this] { - _webSurface->getRootItem()->setProperty(render::entities::WebEntityRenderer::URL_PROPERTY, _url); - _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); - }); - } else { - // If we're switching to or from web content, or between different QML content - // we need to destroy and rebuild the entire QML surface - AbstractViewStateInterface::instance()->postLambdaEvent([this] { - rebuildWebSurface(); - }); - } - } - } -} - -void Web3DOverlay::setScriptURL(const QString& scriptURL) { - _scriptURL = scriptURL; - if (_webSurface) { - AbstractViewStateInterface::instance()->postLambdaEvent([this, scriptURL] { - if (!_webSurface) { - return; - } - _webSurface->getRootItem()->setProperty("scriptURL", scriptURL); - }); - } -} - -Web3DOverlay* Web3DOverlay::createClone() const { - return new Web3DOverlay(this); -} - -void Web3DOverlay::emitScriptEvent(const QVariant& message) { - QMetaObject::invokeMethod(this, "scriptEventReceived", Q_ARG(QVariant, message)); -} diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h deleted file mode 100644 index 4265c35699..0000000000 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ /dev/null @@ -1,99 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/08/31 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Web3DOverlay_h -#define hifi_Web3DOverlay_h - -#include "Billboard3DOverlay.h" - -#include - -#include - -class OffscreenQmlSurface; - -class Web3DOverlay : public Billboard3DOverlay { - Q_OBJECT - using Parent = Billboard3DOverlay; - -public: - static QString const TYPE; - virtual QString getType() const override { return TYPE; } - - Web3DOverlay(); - Web3DOverlay(const Web3DOverlay* Web3DOverlay); - virtual ~Web3DOverlay(); - - void setMaxFPS(uint8_t maxFPS); - virtual void render(RenderArgs* args) override; - virtual const render::ShapeKey getShapeKey() override; - - virtual void update(float deltatime) override; - - QObject* getEventHandler(); - void setProxyWindow(QWindow* proxyWindow); - Q_INVOKABLE void hoverEnterOverlay(const PointerEvent& event); - Q_INVOKABLE void hoverLeaveOverlay(const PointerEvent& event); - Q_INVOKABLE void handlePointerEvent(const PointerEvent& event); - void handlePointerEventAsTouch(const PointerEvent& event); - void handlePointerEventAsMouse(const PointerEvent& event); - - // setters - void setURL(const QString& url); - void setScriptURL(const QString& script); - - void setProperties(const QVariantMap& properties) override; - QVariant getProperty(const QString& property) override; - - virtual Web3DOverlay* createClone() const override; - - enum InputMode { - Touch, - Mouse - }; - - void buildWebSurface(bool overrideWeb = false); - void destroyWebSurface(); - void onResizeWebSurface(); - -public slots: - void emitScriptEvent(const QVariant& scriptMessage); - -signals: - void scriptEventReceived(const QVariant& message); - void webEventReceived(const QVariant& message); - void resizeWebSurface(); - void requestWebSurface(bool overrideWeb); - -protected: - Transform evalRenderTransform() override; - -private: - void rebuildWebSurface(); - bool isWebContent() const; - - InputMode _inputMode { Touch }; - QSharedPointer _webSurface; - bool _cachedWebSurface { false }; - gpu::TexturePointer _texture; - QString _url; - QString _scriptURL; - float _dpi { 30.0f }; - int _geometryId { 0 }; - - QTouchDevice _touchDevice; - - uint8_t _desiredMaxFPS { 10 }; - uint8_t _currentMaxFPS { 0 }; - - bool _mayNeedResize { false }; - - std::vector _connections; -}; - -#endif // hifi_Web3DOverlay_h diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 92db4ec1e0..b7078a00a7 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -61,7 +61,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto& items = fetchedItems.get0(); - // Extract opaques / transparents / lights / metas / overlays / background + // Extract opaques / transparents / lights / metas / layered / background const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; const auto& metas = items[RenderFetchCullSortTask::META]; From bb5c55665720a784a05d57db1a19785dd495cbd8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 25 Jan 2019 19:15:53 -0800 Subject: [PATCH 009/139] working on conversion --- interface/src/devices/DdeFaceTracker.cpp | 10 +- interface/src/ui/overlays/Overlays.cpp | 403 +++++++++++++++--- interface/src/ui/overlays/Overlays.h | 7 +- interface/src/ui/overlays/QmlOverlay.cpp | 4 +- interface/src/ui/overlays/QmlOverlay.h | 2 +- .../entities/src/EntityEditPacketSender.h | 1 - 6 files changed, 344 insertions(+), 83 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index fed5b702cb..c123585afa 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -633,12 +633,8 @@ void DdeFaceTracker::calibrate() { _calibrationCount = 0; _calibrationMessage = CALIBRATION_INSTRUCTION_MESSAGE + "\n\n"; + // FIXME: this overlay probably doesn't work anymore _calibrationBillboard = new TextOverlay(); - _calibrationBillboard->setTopMargin(CALIBRATION_BILLBOARD_TOP_MARGIN); - _calibrationBillboard->setLeftMargin(CALIBRATION_BILLBOARD_LEFT_MARGIN); - _calibrationBillboard->setFontSize(CALIBRATION_BILLBOARD_FONT_SIZE); - _calibrationBillboard->setText(CALIBRATION_INSTRUCTION_MESSAGE); - _calibrationBillboard->setAlpha(CALIBRATION_BILLBOARD_ALPHA); glm::vec2 viewport = qApp->getCanvasSize(); _calibrationBillboard->setX((viewport.x - CALIBRATION_BILLBOARD_WIDTH) / 2); _calibrationBillboard->setY((viewport.y - CALIBRATION_BILLBOARD_HEIGHT) / 2); @@ -658,10 +654,10 @@ void DdeFaceTracker::addCalibrationDatum() { int samplesLeft = CALIBRATION_SAMPLES - _calibrationCount; if (samplesLeft % LARGE_TICK_INTERVAL == 0) { _calibrationMessage += QString::number(samplesLeft / LARGE_TICK_INTERVAL); - _calibrationBillboard->setText(_calibrationMessage); + // FIXME: set overlay text } else if (samplesLeft % SMALL_TICK_INTERVAL == 0) { _calibrationMessage += "."; - _calibrationBillboard->setText(_calibrationMessage); + // FIXME: set overlay text } for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) { diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 14328a349a..9dd85db43f 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -27,13 +27,14 @@ #include "RectangleOverlay.h" #include +#include #include +#include "VariantMapToScriptValue.h" #include "ui/Keyboard.h" #include -#include Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") @@ -51,10 +52,12 @@ Overlays::Overlays() { ADD_TYPE_MAP(Box, cube); ADD_TYPE_MAP(Sphere, sphere); + _overlayToEntityTypes["rectangle"] = "Shape"; ADD_TYPE_MAP(Shape, shape); ADD_TYPE_MAP(Model, model); ADD_TYPE_MAP(Text, text3d); ADD_TYPE_MAP(Image, image3d); + _overlayToEntityTypes["billboard"] = "Image"; ADD_TYPE_MAP(Web, web3d); ADD_TYPE_MAP(PolyLine, line3d); ADD_TYPE_MAP(Grid, grid); @@ -138,8 +141,6 @@ void Overlays::enable() { _enabled = true; } -// Note, can't be invoked by scripts, but can be called by the InterfaceParentFinder -// class on packet processing threads Overlay::Pointer Overlays::get2DOverlay(const QUuid& id) const { if (_shuttingDown) { return nullptr; @@ -165,19 +166,266 @@ QString Overlays::overlayToEntityType(const QString& type) { auto iter = _overlayToEntityTypes.find(type); if (iter != _overlayToEntityTypes.end()) { return iter->second; - } else if (type == "billboard") { - return "Image"; } return "Unknown"; } -EntityItemProperties convertOverlayToEntityProperties(const QVariantMap& overlayProps) { - EntityItemProperties props; +#define SET_OVERLAY_PROP_DEFAULT(o, d) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter == overlayProps.end()) { \ + overlayProps[#o] = d; \ + } \ + } - return props; +#define OVERLAY_TO_ENTITY_PROP(o, e) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + overlayProps[#e] = iter.value(); \ + } \ + } + +#define OVERLAY_TO_GROUP_ENTITY_PROP(o, g, e) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + auto iter2 = overlayProps.find(#g); \ + if (iter2 == overlayProps.end()) { \ + overlayProps[#g] = QVariantMap(); \ + } \ + overlayProps[#g].toMap()[#e] = iter.value(); \ + } \ + } + +#define OVERLAY_TO_GROUP_ENTITY_PROP_DEFAULT(o, g, e, d) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + auto iter2 = overlayProps.find(#g); \ + if (iter2 == overlayProps.end()) { \ + overlayProps[#g] = QVariantMap(); \ + } \ + overlayProps[#g].toMap()[#e] = iter.value(); \ + } else { \ + auto iter2 = overlayProps.find(#g); \ + if (iter2 == overlayProps.end()) { \ + overlayProps[#g] = QVariantMap(); \ + } \ + overlayProps[#g].toMap()[#e] = d; \ + } \ + } + +#define OVERLAY_TO_ENTITY_PROP_CONVERT(o, e, C) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + overlayProps[#e] = C(iter.value()); \ + } \ + } + +#define OVERLAY_TO_ENTITY_PROP_CONVERT_DEFAULT(o, e, d, C) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + overlayProps[#e] = C(iter.value()); \ + } else { \ + overlayProps[#e] = C(d); \ + } \ + } + +#define OVERLAY_TO_GROUP_ENTITY_PROP_CONVERT(o, g, e, C) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + auto iter2 = overlayProps.find(#g); \ + if (iter2 == overlayProps.end()) { \ + overlayProps[#g] = QVariantMap(); \ + } \ + overlayProps[#g].toMap()[#e] = C(iter.value()); \ + } \ + } + +EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps) { + SET_OVERLAY_PROP_DEFAULT(alpha, 0.7); + if (overlayProps["type"] != "PolyLine") { + OVERLAY_TO_ENTITY_PROP(p1, position); + OVERLAY_TO_ENTITY_PROP(start, position); + } + OVERLAY_TO_ENTITY_PROP(point, position); + OVERLAY_TO_ENTITY_PROP(scale, dimensions); + OVERLAY_TO_ENTITY_PROP(size, dimensions); + OVERLAY_TO_ENTITY_PROP(orientation, rotation); + OVERLAY_TO_ENTITY_PROP(localOrientation, localRotation); + OVERLAY_TO_ENTITY_PROP(ignoreRayIntersection, ignorePickIntersection); + + { + OVERLAY_TO_ENTITY_PROP(solid, isSolid); + OVERLAY_TO_ENTITY_PROP(isFilled, isSolid); + OVERLAY_TO_ENTITY_PROP(filled, isSolid); + OVERLAY_TO_ENTITY_PROP_CONVERT_DEFAULT(isSolid, primitiveMode, false, [](const QVariant& v) { return v.toBool() ? "solid" : "lines"; }); + + OVERLAY_TO_ENTITY_PROP(wire, isWire); + OVERLAY_TO_ENTITY_PROP_CONVERT(isWire, primitiveMode, [](const QVariant& v) { return v.toBool() ? "lines" : "solid"; }); + } + + OVERLAY_TO_ENTITY_PROP_CONVERT(drawInFront, renderLayer, [](const QVariant& v) { return v.toBool() ? "front" : "world"; }); + OVERLAY_TO_ENTITY_PROP_CONVERT(drawHUDLayer, renderLayer, [](const QVariant& v) { return v.toBool() ? "hud" : "world"; }); + + OVERLAY_TO_GROUP_ENTITY_PROP_DEFAULT(grabbable, grab, grabbable, false); + + OVERLAY_TO_GROUP_ENTITY_PROP(pulseMin, pulse, min); + OVERLAY_TO_GROUP_ENTITY_PROP(pulseMax, pulse, max); + OVERLAY_TO_GROUP_ENTITY_PROP(pulsePeriod, pulse, period); + OVERLAY_TO_GROUP_ENTITY_PROP_CONVERT(colorPulse, pulse, colorMode, [](const QVariant& v) { + float f = v.toFloat(); + if (f > 0.0f) { + return "in"; + } else if (f < 0.0f) { + return "out"; + } + return "none"; + }); + OVERLAY_TO_GROUP_ENTITY_PROP_CONVERT(alphaPulse, pulse, alphaMode, [](const QVariant& v) { + float f = v.toFloat(); + if (f > 0.0f) { + return "in"; + } else if (f < 0.0f) { + return "out"; + } + return "none"; + }); + + if (overlayProps["type"] == "Shape") { + SET_OVERLAY_PROP_DEFAULT(shape, "Hexagon"); + } else if (overlayProps["type"] == "Model") { + OVERLAY_TO_ENTITY_PROP(url, modelURL); + OVERLAY_TO_ENTITY_PROP(animationSettings, animation); + } else if (overlayProps["type"] == "Image") { + OVERLAY_TO_ENTITY_PROP(url, imageURL); + } else if (overlayProps["type"] == "Web") { + OVERLAY_TO_ENTITY_PROP(url, sourceUrl); + OVERLAY_TO_ENTITY_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "Mouse" ? "mouse" : "touch"; }); + } else if (overlayProps["type"] == "Gizmo") { + { + float ratio = 2.0f; + { + auto iter = overlayProps.find("outerRadius"); + if (iter != overlayProps.end()) { + ratio = iter.value().toFloat() / 0.5f; + } + } + glm::vec3 dimensions = glm::vec3(1.0f); + { + auto iter = overlayProps.find("dimensions"); + if (iter != overlayProps.end()) { + dimensions = vec3FromVariant(iter.value()); + } + } + overlayProps["dimensions"] = vec3toVariant(ratio * dimensions); + } + + { + OVERLAY_TO_ENTITY_PROP(color, innerStartColor); + OVERLAY_TO_ENTITY_PROP(color, innerEndColor); + OVERLAY_TO_ENTITY_PROP(color, outerStartColor); + OVERLAY_TO_ENTITY_PROP(color, outerEndColor); + + OVERLAY_TO_ENTITY_PROP(startColor, innerStartColor); + OVERLAY_TO_ENTITY_PROP(startColor, outerStartColor); + + OVERLAY_TO_ENTITY_PROP(endColor, innerEndColor); + OVERLAY_TO_ENTITY_PROP(endColor, outerEndColor); + + OVERLAY_TO_ENTITY_PROP(innerColor, innerStartColor); + OVERLAY_TO_ENTITY_PROP(innerColor, innerEndColor); + + OVERLAY_TO_ENTITY_PROP(outerColor, outerStartColor); + OVERLAY_TO_ENTITY_PROP(outerColor, outerEndColor); + } + + { + OVERLAY_TO_ENTITY_PROP(alpha, innerStartAlpha); + OVERLAY_TO_ENTITY_PROP(alpha, innerEndAlpha); + OVERLAY_TO_ENTITY_PROP(alpha, outerStartAlpha); + OVERLAY_TO_ENTITY_PROP(alpha, outerEndAlpha); + + OVERLAY_TO_ENTITY_PROP(startAlpha, innerStartAlpha); + OVERLAY_TO_ENTITY_PROP(startAlpha, outerStartAlpha); + + OVERLAY_TO_ENTITY_PROP(endAlpha, innerEndAlpha); + OVERLAY_TO_ENTITY_PROP(endAlpha, outerEndAlpha); + + OVERLAY_TO_ENTITY_PROP(innerAlpha, innerStartAlpha); + OVERLAY_TO_ENTITY_PROP(innerAlpha, innerEndAlpha); + + OVERLAY_TO_ENTITY_PROP(outerAlpha, outerStartAlpha); + OVERLAY_TO_ENTITY_PROP(outerAlpha, outerEndAlpha); + } + + OVERLAY_TO_GROUP_ENTITY_PROP(startAt, ring, startAngle); + OVERLAY_TO_GROUP_ENTITY_PROP(endAt, ring, endAngle); + OVERLAY_TO_GROUP_ENTITY_PROP(innerRadius, ring, innerRadius); + + OVERLAY_TO_GROUP_ENTITY_PROP(innerStartColor, ring, innerStartColor); + OVERLAY_TO_GROUP_ENTITY_PROP(innerEndColor, ring, innerEndColor); + OVERLAY_TO_GROUP_ENTITY_PROP(outerStartColor, ring, outerStartColor); + OVERLAY_TO_GROUP_ENTITY_PROP(outerEndColor, ring, outerEndColor); + OVERLAY_TO_GROUP_ENTITY_PROP(innerStartAlpha, ring, innerStartAlpha); + OVERLAY_TO_GROUP_ENTITY_PROP(innerEndAlpha, ring, innerEndAlpha); + OVERLAY_TO_GROUP_ENTITY_PROP(outerStartAlpha, ring, outerStartAlpha); + OVERLAY_TO_GROUP_ENTITY_PROP(outerEndAlpha, ring, outerEndAlpha); + + OVERLAY_TO_GROUP_ENTITY_PROP(hasTickMarks, ring, hasTickMarks); + OVERLAY_TO_GROUP_ENTITY_PROP(majorTickMarksAngle, ring, majorTickMarksAngle); + OVERLAY_TO_GROUP_ENTITY_PROP(minorTickMarksAngle, ring, minorTickMarksAngle); + OVERLAY_TO_GROUP_ENTITY_PROP(majorTickMarksLength, ring, majorTickMarksLength); + OVERLAY_TO_GROUP_ENTITY_PROP(minorTickMarksLength, ring, minorTickMarksLength); + OVERLAY_TO_GROUP_ENTITY_PROP(majorTickMarksColor, ring, majorTickMarksColor); + OVERLAY_TO_GROUP_ENTITY_PROP(minorTickMarksColor, ring, minorTickMarksColor); + } else if (overlayProps["type"] == "PolyLine") { + OVERLAY_TO_ENTITY_PROP(startPoint, start); + OVERLAY_TO_ENTITY_PROP(p1, start); + OVERLAY_TO_ENTITY_PROP(localStart, start); + OVERLAY_TO_ENTITY_PROP(endPoint, end); + OVERLAY_TO_ENTITY_PROP(p2, end); + OVERLAY_TO_ENTITY_PROP(localEnd, end); + + { + QVariantList points; + { + auto iter = overlayProps.find("start"); + if (iter != overlayProps.end()) { + points.push_back(iter.value()); + } + } + { + auto iter = overlayProps.find("end"); + if (iter != overlayProps.end()) { + points.push_back(iter.value()); + } + } + overlayProps["linePoints"] = points; + } + { + auto iter = overlayProps.find("lineWidth"); + if (iter != overlayProps.end()) { + QVariantList widths; + widths.append(iter.value()); + overlayProps["strokeWidths"] = widths; + } + } + } + + EntityItemProperties toReturn; + EntityItemPropertiesFromScriptValueHonorReadOnly(variantMapToScriptValue(overlayProps, _scriptEngine), toReturn); + return toReturn; } -QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps) { +QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemProperties& entityProps) { + QScriptValue entityProperties; + EntityItemPropertiesToScriptValue(&_scriptEngine, entityProps); + QVariantMap props; return props; @@ -195,63 +443,6 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { return result; } - /**jsdoc - *

An overlay may be one of the following types:

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Value2D/3DDescription
image2DAn image. Synonym: billboard.
rectangle2DA rectangle.
text2DText.
circle3d3DA circle.
cube3DA cube. Can also use a shape overlay to create a - * cube.
grid3DA grid of lines in a plane.
image3d3DAn image.
line3d3DA line.
model3DA model.
rectangle3d3DA rectangle.
shape3DA geometric shape, such as a cube, sphere, or cylinder.
sphere3DA sphere. Can also use a shape overlay to create a - * sphere.
text3d3DText.
web3d3DWeb content.
- *

2D overlays are rendered on the display surface in desktop mode and on the HUD surface in HMD mode. 3D overlays are - * rendered at a position and orientation in-world, but are deprecated (use local entities instead).

- *

Each overlay type has different {@link Overlays.OverlayProperties|OverlayProperties}.

- * @typedef {string} Overlays.OverlayType - */ - - /**jsdoc - *

Different overlay types have different properties:

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
{@link Overlays.OverlayType|OverlayType}Overlay Properties
image{@link Overlays.ImageProperties|ImageProperties}
rectangle{@link Overlays.RectangleProperties|RectangleProperties}
text{@link Overlays.TextProperties|TextProperties}
circle3d{@link Overlays.Circle3DProperties|Circle3DProperties}
cube{@link Overlays.CubeProperties|CubeProperties}
grid{@link Overlays.GridProperties|GridProperties}
image3d{@link Overlays.Image3DProperties|Image3DProperties}
line3d{@link Overlays.Line3DProperties|Line3DProperties}
model{@link Overlays.ModelProperties|ModelProperties}
rectangle3d{@link Overlays.Rectangle3DProperties|Rectangle3DProperties}
shape{@link Overlays.ShapeProperties|ShapeProperties}
sphere{@link Overlays.SphereProperties|SphereProperties}
text3d{@link Overlays.Text3DProperties|Text3DProperties}
web3d{@link Overlays.Web3DProperties|Web3DProperties}
- * @typedef {object} Overlays.OverlayProperties - */ - Overlay::Pointer overlay; if (type == ImageOverlay::TYPE) { #if !defined(DISABLE_QML) @@ -271,13 +462,15 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { } QString entityType = overlayToEntityType(type); - if (entityType == "Unknown") { return UNKNOWN_ENTITY_ID; } QVariantMap propertyMap = properties.toMap(); propertyMap["type"] = entityType; + if (type == "rectangle") { + propertyMap["shape"] = "Quad"; + } return DependencyManager::get()->addEntity(convertOverlayToEntityProperties(propertyMap), "local"); } @@ -942,14 +1135,44 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { return result; } + + +/**jsdoc + *

An overlay may be one of the following types:

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Value2D/3DDescription
image2DAn image. Synonym: billboard.
rectangle2DA rectangle.
text2DText.
cube3DA cube. Can also use a shape overlay to create a cube.
sphere3DA sphere. Can also use a shape overlay to create a sphere.
rectangle3d3DA rectangle.
shape3DA geometric shape, such as a cube, sphere, or cylinder.
model3DA model.
text3d3DText.
image3d3DAn image.
web3d3DWeb content.
line3d3DA line.
grid3DA grid of lines in a plane.
circle3d3DA circle.
+ *

2D overlays are rendered on the display surface in desktop mode and on the HUD surface in HMD mode. 3D overlays are + * rendered at a position and orientation in-world, but are deprecated (use local entities instead).

+ *

Each overlay type has different {@link Overlays.OverlayProperties|OverlayProperties}.

+ * @typedef {string} Overlays.OverlayType + */ + /**jsdoc * Different overlay types have different properties: some common to all overlays (listed below) and some specific to each * {@link Overlays.OverlayType|OverlayType} (linked to below). The properties are accessed as an object of property names and - * values. + * values. 3D Overlays are local entities, internally, so they also support the corresponding entity properties. * * @typedef {object} Overlays.OverlayProperties * @property {Uuid} id - The ID of the overlay. Read-only. - * @property {string} type=TODO - Has the value "TODO". Read-only. * @property {Overlays.OverlayType} type - The overlay type. Read-only. * @property {boolean} visible=true - If true, the overlay is rendered, otherwise it is not rendered. * @@ -959,6 +1182,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * @see {@link Overlays.OverlayProperties-Rectangle|OverlayProperties-Rectangle} * @see {@link Overlays.OverlayProperties-Cube|OverlayProperties-Cube} * @see {@link Overlays.OverlayProperties-Sphere|OverlayProperties-Sphere} + * @see {@link Overlays.OverlayProperties-Rectangle3D|OverlayProperties-Rectangle3D} * @see {@link Overlays.OverlayProperties-Shape|OverlayProperties-Shape} * @see {@link Overlays.OverlayProperties-Model|OverlayProperties-Model} * @see {@link Overlays.OverlayProperties-Text3D|OverlayProperties-Text3D} @@ -1014,7 +1238,7 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { */ /**jsdoc - * The "Text" {@link Overlays.OverlayType|OverlayType} is for 2D rectangles. + * The "Rectangle" {@link Overlays.OverlayType|OverlayType} is for 2D rectangles. * @typedef {object} Overlays.OverlayProperties-Rectangle * @property {Rect} bounds - The position and size of the rectangle, in pixels. Write-only. * @property {number} x - Integer left, x-coordinate value = bounds.x. Write-only. @@ -1110,6 +1334,45 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * */ +/**jsdoc + * The "Rectangle3D" {@link Overlays.OverlayType|OverlayType} is for 3D rectangles. + * @typedef {object} Overlays.OverlayProperties-Rectangle3D + * @property {string} name - The name of the overlay. + * @property {Color} color=255,255,255 - The color of the overlay. + * @property {number} alpha=0.7 - The opacity of the overlay, 0.0 - 1.0. + * @property {number} pulseMax=0 - The maximum value of the pulse multiplier. + * @property {number} pulseMin=0 - The minimum value of the pulse multiplier. + * @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * pulseMin to pulseMax, then pulseMax to pulseMin in one period. + * @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the + * current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0 + * the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise + * used.) + * + * @property {Vec3} position - The position of the overlay center. Synonyms: p1, point, and + * start. + * @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: scale, size. + * @property {Quat} rotation - The orientation of the overlay. Synonym: orientation. + * @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as position. + * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a + * parentID set, otherwise the same value as rotation. Synonym: localOrientation. + * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. + * Antonyms: isWire and wire. + * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. + * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. + * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. + * @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed. + * @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to. + * @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if + * parentID is an avatar skeleton. A value of 65535 means "no joint". + * + */ + /**jsdoc *

A shape {@link Overlays.OverlayType|OverlayType} may display as one of the following geometrical shapes:

* diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index a9d3cffe41..fb6fb024aa 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -26,8 +26,6 @@ #include "Overlay.h" -#include "PanelAttachable.h" - #include class PickRay; @@ -119,6 +117,8 @@ public: void cleanupAllOverlays(); + mutable QScriptEngine _scriptEngine; + public slots: /**jsdoc * Add an overlay to the scene. @@ -723,6 +723,9 @@ private: static std::unordered_map _entityToOverlayTypes; static std::unordered_map _overlayToEntityTypes; + QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps); + EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps); + private slots: void mousePressPointerEvent(const QUuid& id, const PointerEvent& event); void mouseMovePointerEvent(const QUuid& id, const PointerEvent& event); diff --git a/interface/src/ui/overlays/QmlOverlay.cpp b/interface/src/ui/overlays/QmlOverlay.cpp index 2a583e0450..537c421ca7 100644 --- a/interface/src/ui/overlays/QmlOverlay.cpp +++ b/interface/src/ui/overlays/QmlOverlay.cpp @@ -26,8 +26,8 @@ QmlOverlay::QmlOverlay(const QUrl& url) { buildQmlElement(url); } -QmlOverlay::QmlOverlay(const QUrl& url, const QmlOverlay* textOverlay) - : Overlay2D(textOverlay) { +QmlOverlay::QmlOverlay(const QUrl& url, const QmlOverlay* overlay) + : Overlay2D(overlay) { buildQmlElement(url); } diff --git a/interface/src/ui/overlays/QmlOverlay.h b/interface/src/ui/overlays/QmlOverlay.h index ce25ee75ba..0951a04772 100644 --- a/interface/src/ui/overlays/QmlOverlay.h +++ b/interface/src/ui/overlays/QmlOverlay.h @@ -22,7 +22,7 @@ class QmlOverlay : public Overlay2D { public: QmlOverlay(const QUrl& url); - QmlOverlay(const QUrl& url, const QmlOverlay* textOverlay); + QmlOverlay(const QUrl& url, const QmlOverlay* overlay); ~QmlOverlay(); bool supportsGetProperty() const override { return false; } diff --git a/libraries/entities/src/EntityEditPacketSender.h b/libraries/entities/src/EntityEditPacketSender.h index a4ec2c45f9..99a5202986 100644 --- a/libraries/entities/src/EntityEditPacketSender.h +++ b/libraries/entities/src/EntityEditPacketSender.h @@ -56,6 +56,5 @@ private: private: std::mutex _mutex; AvatarData* _myAvatar { nullptr }; - QScriptEngine _scriptEngine; }; #endif // hifi_EntityEditPacketSender_h From abd7d6bddf057237fa6fdfbe9b0976a698d4944f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 25 Jan 2019 22:57:00 -0800 Subject: [PATCH 010/139] some stuff is working! --- interface/src/Application.cpp | 4 +- interface/src/avatar/OtherAvatar.cpp | 2 +- interface/src/ui/Keyboard.cpp | 8 +- .../ui/overlays/ContextOverlayInterface.cpp | 2 +- interface/src/ui/overlays/Overlays.cpp | 116 ++++++++++++------ interface/src/ui/overlays/Overlays.h | 2 +- .../src/RenderableGizmoEntityItem.cpp | 4 +- .../src/RenderableWebEntityItem.cpp | 1 - .../entities/src/EntityScriptingInterface.cpp | 4 +- .../shared/src/VariantMapToScriptValue.cpp | 3 + 10 files changed, 94 insertions(+), 52 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 285b9f140b..c1f0f1fbd8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5729,7 +5729,7 @@ void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm properties.getPulse().setMax(1.0f); properties.getPulse().setColorMode(PulseMode::IN_PHASE); properties.setIgnorePickIntersection(true); - _keyboardFocusHighlightID = entityScriptingInterface->addEntity(properties, "local"); + _keyboardFocusHighlightID = entityScriptingInterface->addEntity(properties, QString("local")); } // Position focus @@ -8760,7 +8760,7 @@ void Application::createLoginDialog() { properties.setVisible(true); auto entityScriptingInterface = DependencyManager::get(); - _loginDialogID = entityScriptingInterface->addEntity(properties, "local"); + _loginDialogID = entityScriptingInterface->addEntity(properties, QString("local")); auto keyboard = DependencyManager::get().data(); if (!keyboard->getAnchorID().isNull() && !_loginDialogID.isNull()) { diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 409fa51388..0bbdb697de 100644 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -84,7 +84,7 @@ void OtherAvatar::createOrb() { properties.setDimensions(glm::vec3(0.5f, 0.5f, 0.5f)); properties.setVisible(true); - _otherAvatarOrbMeshPlaceholderID = DependencyManager::get()->addEntity(properties, "local"); + _otherAvatarOrbMeshPlaceholderID = DependencyManager::get()->addEntity(properties, QString("local")); } } diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 01d21a211a..be42853f08 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -743,7 +743,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setRotation(quatFromVariant(anchorObject["rotation"].toVariant())); Anchor anchor; - anchor.entityID = entityScriptingInterface->addEntity(properties, "local"); + anchor.entityID = entityScriptingInterface->addEntity(properties, QString("local")); anchor.originalDimensions = dimensions; _anchor = anchor; } @@ -765,7 +765,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setParentID(_anchor.entityID); BackPlate backPlate; - backPlate.entityID = entityScriptingInterface->addEntity(properties, "local"); + backPlate.entityID = entityScriptingInterface->addEntity(properties, QString("local")); backPlate.dimensions = dimensions; EntityPropertyFlags desiredProperties; desiredProperties += PROP_LOCAL_POSITION; @@ -822,7 +822,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setTextures(QVariant(textureMap).toString()); properties.getGrab().setGrabbable(false); properties.setLocalRotation(quatFromVariant(keyboardKeyValue["localOrientation"].toVariant())); - QUuid id = entityScriptingInterface->addEntity(properties, "local"); + QUuid id = entityScriptingInterface->addEntity(properties, QString("local")); key.setID(id); key.setKeyString(keyString); key.saveDimensionsAndLocalPosition(); @@ -859,7 +859,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setParentID(_anchor.entityID); TextDisplay textDisplay; - textDisplay.entityID = entityScriptingInterface->addEntity(properties, "local"); + textDisplay.entityID = entityScriptingInterface->addEntity(properties, QString("local")); textDisplay.localPosition = localPosition; textDisplay.dimensions = dimensions; textDisplay.lineHeight = lineHeight; diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 9eb9a75432..3e0bd0479f 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -205,7 +205,7 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID& properties.setImageURL(PathUtils::resourcesUrl() + "images/inspect-icon.png"); properties.setBillboardMode(BillboardMode::FULL); - _contextOverlayID = entityScriptingInterface->addEntity(properties, "local"); + _contextOverlayID = entityScriptingInterface->addEntity(properties, QString("local")); } EntityItemProperties properties; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 9dd85db43f..d9a4bad026 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -52,7 +52,7 @@ Overlays::Overlays() { ADD_TYPE_MAP(Box, cube); ADD_TYPE_MAP(Sphere, sphere); - _overlayToEntityTypes["rectangle"] = "Shape"; + _overlayToEntityTypes["rectangle3d"] = "Shape"; ADD_TYPE_MAP(Shape, shape); ADD_TYPE_MAP(Model, model); ADD_TYPE_MAP(Text, text3d); @@ -172,8 +172,7 @@ QString Overlays::overlayToEntityType(const QString& type) { #define SET_OVERLAY_PROP_DEFAULT(o, d) \ { \ - auto iter = overlayProps.find(#o); \ - if (iter == overlayProps.end()) { \ + if (add && !overlayProps.contains(#o)) { \ overlayProps[#o] = d; \ } \ } @@ -190,11 +189,12 @@ QString Overlays::overlayToEntityType(const QString& type) { { \ auto iter = overlayProps.find(#o); \ if (iter != overlayProps.end()) { \ - auto iter2 = overlayProps.find(#g); \ - if (iter2 == overlayProps.end()) { \ + if (!overlayProps.contains(#g)) { \ overlayProps[#g] = QVariantMap(); \ } \ - overlayProps[#g].toMap()[#e] = iter.value(); \ + auto map = overlayProps[#g].toMap(); \ + map[#e] = iter.value(); \ + overlayProps[#g] = map; \ } \ } @@ -202,17 +202,19 @@ QString Overlays::overlayToEntityType(const QString& type) { { \ auto iter = overlayProps.find(#o); \ if (iter != overlayProps.end()) { \ - auto iter2 = overlayProps.find(#g); \ - if (iter2 == overlayProps.end()) { \ + if (!overlayProps.contains(#g)) { \ overlayProps[#g] = QVariantMap(); \ } \ - overlayProps[#g].toMap()[#e] = iter.value(); \ - } else { \ - auto iter2 = overlayProps.find(#g); \ - if (iter2 == overlayProps.end()) { \ + auto map = overlayProps[#g].toMap(); \ + map[#e] = iter.value(); \ + overlayProps[#g] = map; \ + } else if (add) { \ + if (!overlayProps.contains(#g)) { \ overlayProps[#g] = QVariantMap(); \ } \ - overlayProps[#g].toMap()[#e] = d; \ + auto map = overlayProps[#g].toMap(); \ + map[#e] = d; \ + overlayProps[#g] = map; \ } \ } @@ -229,7 +231,7 @@ QString Overlays::overlayToEntityType(const QString& type) { auto iter = overlayProps.find(#o); \ if (iter != overlayProps.end()) { \ overlayProps[#e] = C(iter.value()); \ - } else { \ + } else if (add) { \ overlayProps[#e] = C(d); \ } \ } @@ -238,17 +240,20 @@ QString Overlays::overlayToEntityType(const QString& type) { { \ auto iter = overlayProps.find(#o); \ if (iter != overlayProps.end()) { \ - auto iter2 = overlayProps.find(#g); \ - if (iter2 == overlayProps.end()) { \ + if (!overlayProps.contains(#g)) { \ overlayProps[#g] = QVariantMap(); \ } \ - overlayProps[#g].toMap()[#e] = C(iter.value()); \ + auto map = overlayProps[#g].toMap(); \ + map[#e] = C(iter.value()); \ + overlayProps[#g] = map; \ } \ } -EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps) { +EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id) { + overlayProps["type"] = type; + SET_OVERLAY_PROP_DEFAULT(alpha, 0.7); - if (overlayProps["type"] != "PolyLine") { + if (type != "PolyLine") { OVERLAY_TO_ENTITY_PROP(p1, position); OVERLAY_TO_ENTITY_PROP(start, position); } @@ -296,18 +301,18 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove return "none"; }); - if (overlayProps["type"] == "Shape") { + if (type == "Shape") { SET_OVERLAY_PROP_DEFAULT(shape, "Hexagon"); - } else if (overlayProps["type"] == "Model") { + } else if (type == "Model") { OVERLAY_TO_ENTITY_PROP(url, modelURL); OVERLAY_TO_ENTITY_PROP(animationSettings, animation); - } else if (overlayProps["type"] == "Image") { + } else if (type == "Image") { OVERLAY_TO_ENTITY_PROP(url, imageURL); - } else if (overlayProps["type"] == "Web") { + } else if (type == "Web") { OVERLAY_TO_ENTITY_PROP(url, sourceUrl); OVERLAY_TO_ENTITY_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "Mouse" ? "mouse" : "touch"; }); - } else if (overlayProps["type"] == "Gizmo") { - { + } else if (type == "Gizmo") { + if (add || overlayProps.contains("outerRadius")) { float ratio = 2.0f; { auto iter = overlayProps.find("outerRadius"); @@ -315,16 +320,36 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove ratio = iter.value().toFloat() / 0.5f; } } - glm::vec3 dimensions = glm::vec3(1.0f); + glm::vec3 dimensions = ENTITY_ITEM_DEFAULT_DIMENSIONS; { auto iter = overlayProps.find("dimensions"); if (iter != overlayProps.end()) { dimensions = vec3FromVariant(iter.value()); + } else if (!add) { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_DIMENSIONS; + dimensions = DependencyManager::get()->getEntityProperties(id, desiredProperties).getDimensions(); } } overlayProps["dimensions"] = vec3toVariant(ratio * dimensions); } + if (add || overlayProps.contains("rotation")) { + glm::quat rotation; + { + auto iter = overlayProps.find("rotation"); + if (iter != overlayProps.end()) { + rotation = vec3FromVariant(iter.value()); + } else if (!add) { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_ROTATION; + rotation = DependencyManager::get()->getEntityProperties(id, desiredProperties).getRotation(); + } + } + // FIXME: + overlayProps["rotation"] = quatToVariant(glm::angleAxis((float)M_PI_2, Vectors::RIGHT) * rotation); + } + { OVERLAY_TO_ENTITY_PROP(color, innerStartColor); OVERLAY_TO_ENTITY_PROP(color, innerEndColor); @@ -383,12 +408,27 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove OVERLAY_TO_GROUP_ENTITY_PROP(minorTickMarksLength, ring, minorTickMarksLength); OVERLAY_TO_GROUP_ENTITY_PROP(majorTickMarksColor, ring, majorTickMarksColor); OVERLAY_TO_GROUP_ENTITY_PROP(minorTickMarksColor, ring, minorTickMarksColor); - } else if (overlayProps["type"] == "PolyLine") { + } else if (type == "PolyLine") { OVERLAY_TO_ENTITY_PROP(startPoint, start); OVERLAY_TO_ENTITY_PROP(p1, start); - OVERLAY_TO_ENTITY_PROP(localStart, start); OVERLAY_TO_ENTITY_PROP(endPoint, end); OVERLAY_TO_ENTITY_PROP(p2, end); + + if (overlayProps.contains("start") || overlayProps.contains("end")) { + glm::vec3 position; + auto iter = overlayProps.find("position"); + if (iter != overlayProps.end()) { + position = vec3FromVariant(iter.value()); + } else if (!add) { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_POSITION; + position = DependencyManager::get()->getEntityProperties(id, desiredProperties).getPosition(); + } + OVERLAY_TO_ENTITY_PROP_CONVERT(start, start, [position](const QVariant& v) { return vec3toVariant(vec3FromVariant(v) - position); }) + OVERLAY_TO_ENTITY_PROP_CONVERT(end, end, [position](const QVariant& v) { return vec3toVariant(vec3FromVariant(v) - position); }) + } + + OVERLAY_TO_ENTITY_PROP(localStart, start); OVERLAY_TO_ENTITY_PROP(localEnd, end); { @@ -417,17 +457,17 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove } } + QScriptEngine scriptEngine; + QScriptValue props = variantMapToScriptValue(overlayProps, scriptEngine); EntityItemProperties toReturn; - EntityItemPropertiesFromScriptValueHonorReadOnly(variantMapToScriptValue(overlayProps, _scriptEngine), toReturn); + EntityItemPropertiesFromScriptValueHonorReadOnly(props, toReturn); return toReturn; } QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemProperties& entityProps) { QScriptValue entityProperties; - EntityItemPropertiesToScriptValue(&_scriptEngine, entityProps); QVariantMap props; - return props; } @@ -467,11 +507,10 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { } QVariantMap propertyMap = properties.toMap(); - propertyMap["type"] = entityType; - if (type == "rectangle") { + if (type == "rectangle3d") { propertyMap["shape"] = "Quad"; } - return DependencyManager::get()->addEntity(convertOverlayToEntityProperties(propertyMap), "local"); + return DependencyManager::get()->addEntity(convertOverlayToEntityProperties(propertyMap, entityType, true), QString("local")); } QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) { @@ -530,8 +569,9 @@ bool Overlays::editOverlay(const QUuid& id, const QVariant& properties) { return true; } - EntityItemProperties entityProperties = convertOverlayToEntityProperties(properties.toMap()); - return !DependencyManager::get()->editEntity(id, entityProperties).isNull(); + auto entityScriptingInterface = DependencyManager::get(); + EntityItemProperties entityProperties = convertOverlayToEntityProperties(properties.toMap(), entityScriptingInterface->getEntityType(id), false, id); + return !entityScriptingInterface->editEntity(id, entityProperties).isNull(); } bool Overlays::editOverlays(const QVariant& propertiesById) { @@ -543,6 +583,7 @@ bool Overlays::editOverlays(const QVariant& propertiesById) { QVariantMap deferred; const QVariantMap map = propertiesById.toMap(); + auto entityScriptingInterface = DependencyManager::get(); for (const auto& key : map.keys()) { QUuid id = QUuid(key); const QVariant& properties = map[key]; @@ -555,8 +596,7 @@ bool Overlays::editOverlays(const QVariant& propertiesById) { } overlay->setProperties(properties.toMap()); } else { - EntityItemProperties entityProperties = convertOverlayToEntityProperties(properties.toMap()); - DependencyManager::get()->editEntity(id, entityProperties); + entityScriptingInterface->editEntity(id, convertOverlayToEntityProperties(properties.toMap(), entityScriptingInterface->getEntityType(id), false, id)); } } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index fb6fb024aa..acd7f1bcbd 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -724,7 +724,7 @@ private: static std::unordered_map _overlayToEntityTypes; QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps); - EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps); + EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id = QUuid()); private slots: void mousePressPointerEvent(const QUuid& id, const PointerEvent& event); diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index f2e95c2159..814a4d8ab3 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -279,10 +279,10 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) { // Ticks if (hasTickMarks) { if (tickProperties.x > 0.0f && tickProperties.y != 0.0f) { - geometryCache->renderVertices(batch, gpu::LINE_STRIP, _majorTicksGeometryID); + geometryCache->renderVertices(batch, gpu::LINES, _majorTicksGeometryID); } if (tickProperties.z > 0.0f && tickProperties.w != 0.0f) { - geometryCache->renderVertices(batch, gpu::LINE_STRIP, _minorTicksGeometryID); + geometryCache->renderVertices(batch, gpu::LINES, _minorTicksGeometryID); } } } diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 2510e41780..31ca189311 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -361,7 +361,6 @@ void WebEntityRenderer::hoverEnterEntity(const PointerEvent& event) { if (_inputMode == WebInputMode::MOUSE) { handlePointerEvent(event); } else if (_webSurface) { - qDebug() << "boop5" << this << _webSurface << _webSurface->getRootItem(); PointerEvent webEvent = event; webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi)); _webSurface->hoverBeginEvent(webEvent, _touchDevice); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 20af206162..381de7d5d9 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -579,9 +579,9 @@ QUuid EntityScriptingInterface::cloneEntity(const QUuid& entityIDToClone) { if (properties.getEntityHostType() == entity::HostType::LOCAL) { // Local entities are only cloned locally - return addEntity(properties, "local"); + return addEntity(properties, QString("local")); } else if (cloneAvatarEntity) { - return addEntity(properties, "avatar"); + return addEntity(properties, QString("avatar")); } else { // setLastEdited timestamp to 0 to ensure this entity gets updated with the properties // from the server-created entity, don't change this unless you know what you are doing diff --git a/libraries/shared/src/VariantMapToScriptValue.cpp b/libraries/shared/src/VariantMapToScriptValue.cpp index 008c3a5d9b..1a747a4e5b 100644 --- a/libraries/shared/src/VariantMapToScriptValue.cpp +++ b/libraries/shared/src/VariantMapToScriptValue.cpp @@ -41,6 +41,9 @@ QScriptValue variantToScriptValue(QVariant& qValue, QScriptEngine& scriptEngine) break; } default: + if (qValue.canConvert()) { + return qValue.toFloat(); + } qCDebug(shared) << "unhandled QScript type" << qValue.type(); break; } From 8f0bd2449bb45a64f586ceabe22af481dbd79ef6 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Sat, 26 Jan 2019 21:53:46 -0800 Subject: [PATCH 011/139] pointerevents are working! --- interface/src/Application.cpp | 14 +- interface/src/avatar/OtherAvatar.cpp | 2 +- interface/src/ui/Keyboard.cpp | 8 +- .../ui/overlays/ContextOverlayInterface.cpp | 2 +- interface/src/ui/overlays/Overlays.cpp | 180 +++++++----------- interface/src/ui/overlays/Overlays.h | 1 + .../src/EntityTreeRenderer.cpp | 14 +- .../entities/src/EntityScriptingInterface.cpp | 12 +- .../entities/src/EntityScriptingInterface.h | 19 +- 9 files changed, 120 insertions(+), 132 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c1f0f1fbd8..3041811b49 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1884,6 +1884,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } } }); + connect(&_overlays, &Overlays::mousePressOnOverlay, [this](const QUuid& id, const PointerEvent& event) { + if (event.shouldFocus()) { + if (getEntities()->wantsKeyboardFocus(id)) { + setKeyboardFocusLocalEntity(id); + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); + } else { + setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); + } + } + }); connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [this](const EntityItemID& entityItemID) { if (entityItemID == _keyboardFocusedEntity.get()) { @@ -5729,7 +5739,7 @@ void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm properties.getPulse().setMax(1.0f); properties.getPulse().setColorMode(PulseMode::IN_PHASE); properties.setIgnorePickIntersection(true); - _keyboardFocusHighlightID = entityScriptingInterface->addEntity(properties, QString("local")); + _keyboardFocusHighlightID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); } // Position focus @@ -8760,7 +8770,7 @@ void Application::createLoginDialog() { properties.setVisible(true); auto entityScriptingInterface = DependencyManager::get(); - _loginDialogID = entityScriptingInterface->addEntity(properties, QString("local")); + _loginDialogID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); auto keyboard = DependencyManager::get().data(); if (!keyboard->getAnchorID().isNull() && !_loginDialogID.isNull()) { diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 0bbdb697de..70b1d556be 100644 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -84,7 +84,7 @@ void OtherAvatar::createOrb() { properties.setDimensions(glm::vec3(0.5f, 0.5f, 0.5f)); properties.setVisible(true); - _otherAvatarOrbMeshPlaceholderID = DependencyManager::get()->addEntity(properties, QString("local")); + _otherAvatarOrbMeshPlaceholderID = DependencyManager::get()->addEntityInternal(properties, entity::HostType::LOCAL); } } diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index be42853f08..54620e36ba 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -743,7 +743,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setRotation(quatFromVariant(anchorObject["rotation"].toVariant())); Anchor anchor; - anchor.entityID = entityScriptingInterface->addEntity(properties, QString("local")); + anchor.entityID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); anchor.originalDimensions = dimensions; _anchor = anchor; } @@ -765,7 +765,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setParentID(_anchor.entityID); BackPlate backPlate; - backPlate.entityID = entityScriptingInterface->addEntity(properties, QString("local")); + backPlate.entityID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); backPlate.dimensions = dimensions; EntityPropertyFlags desiredProperties; desiredProperties += PROP_LOCAL_POSITION; @@ -822,7 +822,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setTextures(QVariant(textureMap).toString()); properties.getGrab().setGrabbable(false); properties.setLocalRotation(quatFromVariant(keyboardKeyValue["localOrientation"].toVariant())); - QUuid id = entityScriptingInterface->addEntity(properties, QString("local")); + QUuid id = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); key.setID(id); key.setKeyString(keyString); key.saveDimensionsAndLocalPosition(); @@ -859,7 +859,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setParentID(_anchor.entityID); TextDisplay textDisplay; - textDisplay.entityID = entityScriptingInterface->addEntity(properties, QString("local")); + textDisplay.entityID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); textDisplay.localPosition = localPosition; textDisplay.dimensions = dimensions; textDisplay.lineHeight = lineHeight; diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 3e0bd0479f..c382c3de43 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -205,7 +205,7 @@ bool ContextOverlayInterface::createOrDestroyContextOverlay(const EntityItemID& properties.setImageURL(PathUtils::resourcesUrl() + "images/inspect-icon.png"); properties.setBillboardMode(BillboardMode::FULL); - _contextOverlayID = entityScriptingInterface->addEntity(properties, QString("local")); + _contextOverlayID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); } EntityItemProperties properties; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index d9a4bad026..e93d41973c 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -28,6 +28,8 @@ #include #include +#include +#include #include #include "VariantMapToScriptValue.h" @@ -35,7 +37,6 @@ #include "ui/Keyboard.h" #include - Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") std::unordered_map Overlays::_entityToOverlayTypes; @@ -62,6 +63,13 @@ Overlays::Overlays() { ADD_TYPE_MAP(PolyLine, line3d); ADD_TYPE_MAP(Grid, grid); ADD_TYPE_MAP(Gizmo, circle3d); + + auto mouseRayPick = std::make_shared(Vectors::ZERO, Vectors::UP, + PickFilter(PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES) | + PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE)), 0.0f, true); + mouseRayPick->parentTransform = std::make_shared(); + mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE); + _mouseRayPickID = DependencyManager::get()->addPick(PickQuery::Ray, mouseRayPick); } void Overlays::cleanupAllOverlays() { @@ -79,6 +87,13 @@ void Overlays::cleanupAllOverlays() { } void Overlays::init() { + auto entityScriptingInterface = DependencyManager::get(); + connect(this, &Overlays::hoverEnterOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity); + connect(this, &Overlays::hoverOverOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity); + connect(this, &Overlays::hoverLeaveOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity); + connect(this, &Overlays::mousePressOnOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity); + connect(this, &Overlays::mouseMoveOnOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity); + connect(this, &Overlays::mouseReleaseOnOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity); } void Overlays::update(float deltatime) { @@ -320,7 +335,7 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove ratio = iter.value().toFloat() / 0.5f; } } - glm::vec3 dimensions = ENTITY_ITEM_DEFAULT_DIMENSIONS; + glm::vec3 dimensions = glm::vec3(1.0f); { auto iter = overlayProps.find("dimensions"); if (iter != overlayProps.end()) { @@ -347,7 +362,7 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove } } // FIXME: - overlayProps["rotation"] = quatToVariant(glm::angleAxis((float)M_PI_2, Vectors::RIGHT) * rotation); + //overlayProps["rotation"] = quatToVariant(glm::angleAxis((float)M_PI_2, Vectors::RIGHT) * rotation); } { @@ -510,7 +525,7 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { if (type == "rectangle3d") { propertyMap["shape"] = "Quad"; } - return DependencyManager::get()->addEntity(convertOverlayToEntityProperties(propertyMap, entityType, true), QString("local")); + return DependencyManager::get()->addEntityInternal(convertOverlayToEntityProperties(propertyMap, entityType, true), entity::HostType::LOCAL); } QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) { @@ -950,21 +965,63 @@ static PointerEvent::Button toPointerButton(const QMouseEvent& event) { } } -PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, - const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, - PointerEvent::EventType eventType) { - glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(id, rayPickResult.intersection); - PointerEvent pointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, - ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers()); +RayToOverlayIntersectionResult getPrevPickResult(unsigned int mouseRayPickID) { + RayToOverlayIntersectionResult overlayResult; + overlayResult.intersects = false; + auto pickResult = DependencyManager::get()->getPrevPickResultTyped(mouseRayPickID); + if (pickResult) { + overlayResult.intersects = pickResult->type != IntersectionType::NONE; + if (overlayResult.intersects) { + overlayResult.intersection = pickResult->intersection; + overlayResult.distance = pickResult->distance; + overlayResult.surfaceNormal = pickResult->surfaceNormal; + overlayResult.overlayID = pickResult->objectID; + overlayResult.extraInfo = pickResult->extraInfo; + } + } + return overlayResult; +} - return pointerEvent; +PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, + const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, + PointerEvent::EventType eventType) { + glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(id, rayPickResult.intersection); + return PointerEvent(eventType, PointerManager::MOUSE_POINTER_ID, pos2D, rayPickResult.intersection, rayPickResult.surfaceNormal, + ray.direction, toPointerButton(*event), toPointerButtons(*event), event->modifiers()); +} + +void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) { + auto keyboard = DependencyManager::get(); + // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed + if (!keyboard->getKeysID().contains(id)) { + // emit to scripts + emit hoverEnterOverlay(id, event); + } +} + +void Overlays::hoverOverPointerEvent(const QUuid& id, const PointerEvent& event) { + auto keyboard = DependencyManager::get(); + // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed + if (!keyboard->getKeysID().contains(id)) { + // emit to scripts + emit hoverOverOverlay(id, event); + } +} + +void Overlays::hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event) { + auto keyboard = DependencyManager::get(); + // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed + if (!keyboard->getKeysID().contains(id)) { + // emit to scripts + emit hoverLeaveOverlay(id, event); + } } bool Overlays::mousePressEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mousePressEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); + RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); if (rayPickResult.intersects) { _currentClickingOnOverlayID = rayPickResult.overlayID; @@ -974,27 +1031,11 @@ bool Overlays::mousePressEvent(QMouseEvent* event) { } // if we didn't press on an overlay, disable overlay keyboard focus setKeyboardFocusOverlay(UNKNOWN_ENTITY_ID); - // emit to scripts emit mousePressOffOverlay(); return false; } void Overlays::mousePressPointerEvent(const QUuid& id, const PointerEvent& event) { - // TODO: generalize this to allow any object to recieve events - auto renderable = qApp->getEntities()->renderableForEntityId(id); - if (renderable) { - auto web = std::dynamic_pointer_cast(renderable); - if (web) { - if (event.shouldFocus()) { - // Focus keyboard on web overlays - DependencyManager::get()->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); - setKeyboardFocusOverlay(id); - } - - web->handlePointerEvent(event); - } - } - auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed if (!keyboard->getKeysID().contains(id)) { @@ -1007,79 +1048,23 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); + RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); if (rayPickResult.intersects) { _currentClickingOnOverlayID = rayPickResult.overlayID; auto pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press); - // emit to scripts emit mouseDoublePressOnOverlay(_currentClickingOnOverlayID, pointerEvent); return true; } - // emit to scripts emit mouseDoublePressOffOverlay(); return false; } -void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) { - // TODO: generalize this to allow any object to recieve events - auto renderable = qApp->getEntities()->renderableForEntityId(id); - if (renderable) { - auto web = std::dynamic_pointer_cast(renderable); - if (web) { - web->hoverEnterEntity(event); - } - } - - auto keyboard = DependencyManager::get(); - // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(id)) { - // emit to scripts - emit hoverEnterOverlay(id, event); - } -} - -void Overlays::hoverOverPointerEvent(const QUuid& id, const PointerEvent& event) { - // TODO: generalize this to allow any overlay to recieve events - auto renderable = qApp->getEntities()->renderableForEntityId(id); - if (renderable) { - auto web = std::dynamic_pointer_cast(renderable); - if (web) { - web->handlePointerEvent(event); - } - } - - auto keyboard = DependencyManager::get(); - // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(id)) { - // emit to scripts - emit hoverOverOverlay(id, event); - } -} - -void Overlays::hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event) { - // TODO: generalize this to allow any overlay to recieve events - auto renderable = qApp->getEntities()->renderableForEntityId(id); - if (renderable) { - auto web = std::dynamic_pointer_cast(renderable); - if (web) { - web->hoverLeaveEntity(event); - } - } - - auto keyboard = DependencyManager::get(); - // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(id)) { - // emit to scripts - emit hoverLeaveOverlay(id, event); - } -} - bool Overlays::mouseReleaseEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseReleaseEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); + RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); if (rayPickResult.intersects) { auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release); mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent); @@ -1090,19 +1075,9 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) { } void Overlays::mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event) { - // TODO: generalize this to allow any overlay to recieve events - auto renderable = qApp->getEntities()->renderableForEntityId(id); - if (renderable) { - auto web = std::dynamic_pointer_cast(renderable); - if (web) { - web->handlePointerEvent(event); - } - } - auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed if (!keyboard->getKeysID().contains(id)) { - // emit to scripts emit mouseReleaseOnOverlay(id, event); } } @@ -1111,7 +1086,7 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseMoveEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = findRayIntersectionVector(ray, true, QVector(), QVector()); + RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); if (rayPickResult.intersects) { auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move); mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent); @@ -1144,15 +1119,6 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { } void Overlays::mouseMovePointerEvent(const QUuid& id, const PointerEvent& event) { - // TODO: generalize this to allow any overlay to recieve events - auto renderable = qApp->getEntities()->renderableForEntityId(id); - if (renderable) { - auto web = std::dynamic_pointer_cast(renderable); - if (web) { - web->handlePointerEvent(event); - } - } - auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed if (!keyboard->getKeysID().contains(id)) { @@ -1175,8 +1141,6 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { return result; } - - /**jsdoc *

An overlay may be one of the following types:

*
diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index acd7f1bcbd..a6d36bae9a 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -715,6 +715,7 @@ private: PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, PointerEvent::EventType eventType); + unsigned int _mouseRayPickID; QUuid _currentClickingOnOverlayID; QUuid _currentHoverOverOverlayID; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c71b296a74..61344e3193 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -84,38 +84,38 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf connect(pointerManager.data(), &PointerManager::triggerEndEntity, entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity); // Forward mouse events to web entities - auto handlePointerEvent = [&](const EntityItemID& entityID, const PointerEvent& event) { + auto handlePointerEvent = [&](const QUuid& entityID, const PointerEvent& event) { std::shared_ptr thisEntity; auto entity = getEntity(entityID); if (entity && entity->getType() == EntityTypes::Web) { thisEntity = std::static_pointer_cast(renderableForEntityId(entityID)); } if (thisEntity) { - QMetaObject::invokeMethod(thisEntity.get(), "handlePointerEvent", Q_ARG(PointerEvent, event)); + QMetaObject::invokeMethod(thisEntity.get(), "handlePointerEvent", Q_ARG(const PointerEvent&, event)); } }; connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, this, handlePointerEvent); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent); connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity, this, handlePointerEvent); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, this, [&](const EntityItemID& entityID, const PointerEvent& event) { + connect(entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity, this, handlePointerEvent); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) { std::shared_ptr thisEntity; auto entity = getEntity(entityID); if (entity && entity->getType() == EntityTypes::Web) { thisEntity = std::static_pointer_cast(renderableForEntityId(entityID)); } if (thisEntity) { - QMetaObject::invokeMethod(thisEntity.get(), "hoverEnterEntity", Q_ARG(PointerEvent, event)); + QMetaObject::invokeMethod(thisEntity.get(), "hoverEnterEntity", Q_ARG(const PointerEvent&, event)); } }); connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity, this, handlePointerEvent); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const EntityItemID& entityID, const PointerEvent& event) { + connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) { std::shared_ptr thisEntity; auto entity = getEntity(entityID); if (entity && entity->getType() == EntityTypes::Web) { thisEntity = std::static_pointer_cast(renderableForEntityId(entityID)); } if (thisEntity) { - QMetaObject::invokeMethod(thisEntity.get(), "hoverLeaveEntity", Q_ARG(PointerEvent, event)); + QMetaObject::invokeMethod(thisEntity.get(), "hoverLeaveEntity", Q_ARG(const PointerEvent&, event)); } }); } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 381de7d5d9..9a910e10c5 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -474,7 +474,7 @@ void synchronizeEditedGrabProperties(EntityItemProperties& properties, const QSt } -QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties, const QString& entityHostTypeString) { +QUuid EntityScriptingInterface::addEntityInternal(const EntityItemProperties& properties, entity::HostType entityHostType) { PROFILE_RANGE(script_entities, __FUNCTION__); _activityTracking.addedEntityCount++; @@ -483,10 +483,10 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties const auto sessionID = nodeList->getSessionUUID(); EntityItemProperties propertiesWithSimID = properties; - propertiesWithSimID.setEntityHostTypeFromString(entityHostTypeString); - if (propertiesWithSimID.getEntityHostType() == entity::HostType::AVATAR) { + propertiesWithSimID.setEntityHostType(entityHostType); + if (entityHostType == entity::HostType::AVATAR) { propertiesWithSimID.setOwningAvatarID(sessionID); - } else if (propertiesWithSimID.getEntityHostType() == entity::HostType::LOCAL) { + } else if (entityHostType == entity::HostType::LOCAL) { // For now, local entities are always collisionless // TODO: create a separate, local physics simulation that just handles local entities (and MyAvatar?) propertiesWithSimID.setCollisionless(true); @@ -579,9 +579,9 @@ QUuid EntityScriptingInterface::cloneEntity(const QUuid& entityIDToClone) { if (properties.getEntityHostType() == entity::HostType::LOCAL) { // Local entities are only cloned locally - return addEntity(properties, QString("local")); + return addEntityInternal(properties, entity::HostType::LOCAL); } else if (cloneAvatarEntity) { - return addEntity(properties, QString("avatar")); + return addEntityInternal(properties, entity::HostType::AVATAR); } else { // setLastEdited timestamp to 0 to ensure this entity gets updated with the properties // from the server-created entity, don't change this unless you know what you are doing diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 0cdc71c8ff..71df8e57bd 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -167,6 +167,9 @@ public: */ static QScriptValue getMultipleEntityProperties(QScriptContext* context, QScriptEngine* engine); QScriptValue getMultipleEntityPropertiesInternal(QScriptEngine* engine, QVector entityIDs, const QScriptValue& extendedDesiredProperties); + + QUuid addEntityInternal(const EntityItemProperties& properties, entity::HostType entityHostType); + public slots: /**jsdoc @@ -269,7 +272,17 @@ public slots: * }); * print("Entity created: " + entityID); */ - Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, const QString& entityHostTypeString); + Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, const QString& entityHostTypeString) { + entity::HostType entityHostType; + if (entityHostTypeString == "domain") { + entityHostType = entity::HostType::DOMAIN; + } else if (entityHostTypeString == "avatar") { + entityHostType = entity::HostType::AVATAR; + } else if (entityHostTypeString == "local") { + entityHostType = entity::HostType::LOCAL; + } + return addEntityInternal(properties, entityHostType); + } /**jsdoc * Add a new entity with specified properties. @@ -279,8 +292,8 @@ public slots: * @returns {Uuid} The ID of the entity if successfully created, otherwise {@link Uuid|Uuid.NULL}. */ Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, bool avatarEntity = false) { - QString entityHostType = avatarEntity ? "avatar" : "domain"; - return addEntity(properties, entityHostType); + entity::HostType entityHostType = avatarEntity ? entity::HostType::AVATAR : entity::HostType::DOMAIN; + return addEntityInternal(properties, entityHostType); } /// temporary method until addEntity can be used from QJSEngine From 0dd729232bfcd6e18515de9bd2e3f0be1d4228ef Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Sat, 26 Jan 2019 22:49:12 -0800 Subject: [PATCH 012/139] simplify keyboard focus highlight --- interface/src/Application.cpp | 122 +++--------------- interface/src/Application.h | 4 - interface/src/ui/DialogsManager.cpp | 4 +- interface/src/ui/overlays/Overlays.h | 14 +- .../entities/src/EntityScriptingInterface.cpp | 16 +-- .../entities/src/EntityScriptingInterface.h | 27 +--- 6 files changed, 36 insertions(+), 151 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3041811b49..859cc4d4c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1874,23 +1874,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it auto entityScriptingInterface = DependencyManager::get(); connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, - [this](const EntityItemID& entityItemID, const PointerEvent& event) { - if (event.shouldFocus()) { - if (getEntities()->wantsKeyboardFocus(entityItemID)) { - setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); - setKeyboardFocusEntity(entityItemID); - } else { - setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); - } - } - }); - connect(&_overlays, &Overlays::mousePressOnOverlay, [this](const QUuid& id, const PointerEvent& event) { + [this](const QUuid& id, const PointerEvent& event) { if (event.shouldFocus()) { if (getEntities()->wantsKeyboardFocus(id)) { - setKeyboardFocusLocalEntity(id); - setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); + setKeyboardFocusEntity(id); } else { - setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); } } }); @@ -1971,13 +1960,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Keyboard focus handling for local Web entities. connect(&qApp->getOverlays(), &Overlays::overlayDeleted, [this](const QUuid& id) { - if (id == _keyboardFocusedLocalEntity.get()) { - setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); + if (id == _keyboardFocusedEntity.get()) { + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); } }); connect(this, &Application::aboutToQuit, [this]() { - setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); }); @@ -3801,27 +3789,6 @@ bool Application::handleKeyEventForFocusedEntity(QEvent* event) { } } - if (!_keyboardFocusedLocalEntity.get().isInvalidID()) { - switch (event->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease: { - auto eventHandler = getEntities()->getEventHandler(_keyboardFocusedEntity.get()); - if (eventHandler) { - event->setAccepted(false); - QCoreApplication::sendEvent(eventHandler, event); - if (event->isAccepted()) { - _lastAcceptedKeyPress = usecTimestampNow(); - return true; - } - } - } - break; - - default: - break; - } - } - return false; } @@ -4332,8 +4299,8 @@ void Application::mouseMoveEvent(QMouseEvent* event) { if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() || !getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())).isNull()) { - getOverlays().mouseMoveEvent(&mappedEvent); getEntities()->mouseMoveEvent(&mappedEvent); + getOverlays().mouseMoveEvent(&mappedEvent); } _controllerScriptingInterface->emitMouseMoveEvent(&mappedEvent); // send events to any registered scripts @@ -4370,10 +4337,10 @@ void Application::mousePressEvent(QMouseEvent* event) { event->screenPos(), event->button(), event->buttons(), event->modifiers()); - getOverlays().mousePressEvent(&mappedEvent); if (!_controllerScriptingInterface->areEntityClicksCaptured()) { getEntities()->mousePressEvent(&mappedEvent); } + getOverlays().mousePressEvent(&mappedEvent); _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts @@ -4413,10 +4380,10 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) { event->screenPos(), event->button(), event->buttons(), event->modifiers()); - getOverlays().mouseDoublePressEvent(&mappedEvent); if (!_controllerScriptingInterface->areEntityClicksCaptured()) { getEntities()->mouseDoublePressEvent(&mappedEvent); } + getOverlays().mouseDoublePressEvent(&mappedEvent); // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface->isMouseCaptured()) { @@ -4440,8 +4407,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { event->screenPos(), event->button(), event->buttons(), event->modifiers()); - getOverlays().mouseReleaseEvent(&mappedEvent); getEntities()->mouseReleaseEvent(&mappedEvent); + getOverlays().mouseReleaseEvent(&mappedEvent); _controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts @@ -4902,12 +4869,11 @@ void Application::idle() { // Update focus highlight for entities { - if (!_keyboardFocusedEntity.get().isInvalidID() || !_keyboardFocusedLocalEntity.get().isInvalidID()) { + if (!_keyboardFocusedEntity.get().isInvalidID()) { const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress; if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); - setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); } else { // update position of highlight object if (!_keyboardFocusedEntity.get().isInvalidID()) { @@ -4918,14 +4884,6 @@ void Application::idle() { properties.setRotation(entity->getWorldOrientation()); DependencyManager::get()->editEntity(_keyboardFocusHighlightID, properties); } - } else { - auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get()); - if (entity && !_keyboardFocusHighlightID.isNull()) { - EntityItemProperties properties; - properties.setPosition(entity->getWorldPosition()); - properties.setRotation(entity->getWorldOrientation()); - DependencyManager::get()->editEntity(_keyboardFocusHighlightID, properties); - } } } } @@ -5758,10 +5716,16 @@ QUuid Application::getKeyboardFocusEntity() const { static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f; void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { - if (qApp->getLoginDialogPoppedUp()) { - return; - } if (_keyboardFocusedEntity.get() != entityItemID) { + if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) { + if (entityItemID == _loginDialogID) { + emit loginDialogFocusEnabled(); + } else { + // that's the only entity we want in focus; + return; + } + } + _keyboardFocusedEntity.set(entityItemID); auto entityScriptingInterface = DependencyManager::get(); @@ -5793,52 +5757,6 @@ void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { } } -EntityItemID Application::getKeyboardFocusLocalEntity() { - return _keyboardFocusedLocalEntity.get(); -} - -void Application::setKeyboardFocusLocalEntity(const EntityItemID& entityItemID) { - if (entityItemID != _keyboardFocusedLocalEntity.get()) { - if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) { - if (entityItemID == _loginDialogID) { - emit loginDialogFocusEnabled(); - } else { - // that's the only entity we want in focus; - return; - } - } - - _keyboardFocusedLocalEntity.set(entityItemID); - - auto entityScriptingInterface = DependencyManager::get(); - if (entityItemID == UNKNOWN_ENTITY_ID) { - EntityItemProperties properties; - properties.setVisible(false); - entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties); - return; - } - - auto properties = entityScriptingInterface->getEntityProperties(entityItemID); - if (!properties.getLocked() && properties.getVisible()) { - auto entities = getEntities(); - auto entityId = _keyboardFocusedLocalEntity.get(); - if (entities->wantsKeyboardFocus(entityId)) { - entities->setProxyWindow(entityId, _window->windowHandle()); - if (_keyboardMouseDevice->isActive()) { - _keyboardMouseDevice->pluginFocusOutEvent(); - } - _lastAcceptedKeyPress = usecTimestampNow(); - - auto entity = getEntities()->getEntity(entityId); - if (entity) { - setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), - entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); - } - } - } - } -} - void Application::updateDialogs(float deltaTime) const { PerformanceTimer perfTimer("updateDialogs"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); @@ -8784,7 +8702,7 @@ void Application::createLoginDialog() { entityScriptingInterface->editEntity(keyboard->getAnchorID(), properties); keyboard->setResetKeyboardPositionOnRaise(false); } - setKeyboardFocusLocalEntity(_loginDialogID); + setKeyboardFocusEntity(_loginDialogID); emit loginDialogFocusEnabled(); getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false); getApplicationCompositor().getReticleInterface()->setVisible(false); diff --git a/interface/src/Application.h b/interface/src/Application.h index 150675d823..5862ead763 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -439,9 +439,6 @@ public slots: QUuid getKeyboardFocusEntity() const; // thread-safe void setKeyboardFocusEntity(const EntityItemID& entityItemID); - EntityItemID getKeyboardFocusLocalEntity(); - void setKeyboardFocusLocalEntity(const EntityItemID& id); - void addAssetToWorldMessageClose(); void loadLODToolsDialog(); @@ -720,7 +717,6 @@ private: DialogsManagerScriptingInterface* _dialogsManagerScriptingInterface = new DialogsManagerScriptingInterface(); ThreadSafeValueCache _keyboardFocusedEntity; - ThreadSafeValueCache _keyboardFocusedLocalEntity; quint64 _lastAcceptedKeyPress = 0; bool _isForeground = true; // starts out assumed to be in foreground bool _isGLInitialized { false }; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 27e55a8586..a3a875ac40 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -57,7 +57,7 @@ void DialogsManager::showAddressBar() { if (!hmd->getShouldShowTablet()) { hmd->openTablet(); } - qApp->setKeyboardFocusLocalEntity(hmd->getCurrentTabletScreenID()); + qApp->setKeyboardFocusEntity(hmd->getCurrentTabletScreenID()); setAddressBarVisible(true); } @@ -70,7 +70,7 @@ void DialogsManager::hideAddressBar() { tablet->gotoHomeScreen(); hmd->closeTablet(); } - qApp->setKeyboardFocusLocalEntity(UNKNOWN_ENTITY_ID); + qApp->setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); setAddressBarVisible(false); } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index a6d36bae9a..5db90fecf4 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -75,8 +75,8 @@ public: * @hifi-interface * @hifi-client-entity * - * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Entities.EntityTypes|Web} local entity that has keyboard focus. - * If no local entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to + * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Entities.EntityTypes|Web} entity that has keyboard focus. + * If no entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to * clear keyboard focus. */ @@ -552,20 +552,20 @@ public slots: void sendHoverLeaveOverlay(const QUuid& id, const PointerEvent& event); /**jsdoc - * Get the ID of the Web3D local entity that has keyboard focus. + * Get the ID of the Web3D entity that has keyboard focus. * @function Overlays.getKeyboardFocusOverlay * @returns {Uuid} The ID of the {@link Entities.EntityTypes|Web} overlay that has focus, if any, otherwise * null. */ - EntityItemID getKeyboardFocusOverlay() { return DependencyManager::get()->getKeyboardFocusLocalEntity(); } + QUuid getKeyboardFocusOverlay() { return DependencyManager::get()->getKeyboardFocusEntity(); } /**jsdoc - * Set the Web3D local entity that has keyboard focus. + * Set the Web3D entity that has keyboard focus. * @function Overlays.setKeyboardFocusOverlay - * @param {Uuid} id - The ID of the {@link Entities.EntityTypes|Web} overlay to set keyboard focus to. Use + * @param {Uuid} id - The ID of the {@link Entities.EntityTypes|Web} entity to set keyboard focus to. Use * null or {@link Uuid|Uuid.NULL} to unset keyboard focus from an overlay. */ - void setKeyboardFocusOverlay(const EntityItemID& id) { DependencyManager::get()->setKeyboardFocusLocalEntity(id); } + void setKeyboardFocusOverlay(const QUuid& id) { DependencyManager::get()->setKeyboardFocusEntity(id); } signals: /**jsdoc diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 9a910e10c5..363f463eb7 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -58,7 +58,7 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged); // If the user clicks somewhere where there is no entity at all, we will release focus - connect(this, &EntityScriptingInterface::mousePressOffEntity, [=]() { + connect(this, &EntityScriptingInterface::mousePressOffEntity, [this]() { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); }); @@ -2160,18 +2160,8 @@ QUuid EntityScriptingInterface::getKeyboardFocusEntity() const { return result; } -void EntityScriptingInterface::setKeyboardFocusEntity(const EntityItemID& id) { - QMetaObject::invokeMethod(qApp, "setKeyboardFocusEntity", Qt::DirectConnection, Q_ARG(EntityItemID, id)); -} - -QUuid EntityScriptingInterface::getKeyboardFocusLocalEntity() const { - QUuid result; - QMetaObject::invokeMethod(qApp, "getKeyboardFocusLocalEntity", Qt::DirectConnection, Q_RETURN_ARG(QUuid, result)); - return result; -} - -void EntityScriptingInterface::setKeyboardFocusLocalEntity(const EntityItemID& id) { - QMetaObject::invokeMethod(qApp, "setKeyboardFocusLocalEntity", Qt::DirectConnection, Q_ARG(EntityItemID, id)); +void EntityScriptingInterface::setKeyboardFocusEntity(const QUuid& id) { + QMetaObject::invokeMethod(qApp, "setKeyboardFocusEntity", Qt::DirectConnection, Q_ARG(const QUuid&, id)); } void EntityScriptingInterface::sendMousePressOnEntity(const EntityItemID& id, const PointerEvent& event) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 71df8e57bd..6157d3663a 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -115,15 +115,11 @@ public: * @property {Uuid} keyboardFocusEntity - Get or set the {@link Entities.EntityType|Web} entity that has keyboard focus. * If no entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to * clear keyboard focus. - * @property {Uuid} keyboardFocusLocalEntity - Get or set the {@link Entities.EntityType|Web} local entity that has keyboard focus. - * If no local entity has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to - * clear keyboard focus. */ /// handles scripting of Entity commands from JS passed to assigned clients class EntityScriptingInterface : public OctreeScriptingInterface, public Dependency { Q_OBJECT Q_PROPERTY(QUuid keyboardFocusEntity READ getKeyboardFocusEntity WRITE setKeyboardFocusEntity) - Q_PROPERTY(QUuid keyboardFocusLocalEntity READ getKeyboardFocusLocalEntity WRITE setKeyboardFocusLocalEntity) friend EntityPropertyMetadataRequest; public: @@ -1415,7 +1411,7 @@ public slots: /**jsdoc * Get the type — entity or avatar — of an in-world item. * @function Entities.getNestableType - * @param {Uuid} entityID - The ID of the item to get the type of. + * @param {Uuid} id - The ID of the item to get the type of. * @returns {string} The type of the item: "entity" if the item is an entity, "avatar" * if the item is an avatar; otherwise "unknown" if the item cannot be found. * @example @@ -1428,7 +1424,7 @@ public slots: * print(Entities.getNestableType(entity)); // "entity" * print(Entities.getNestableType(Uuid.generate())); // "unknown" */ - Q_INVOKABLE QString getNestableType(const QUuid& entityID); + Q_INVOKABLE QString getNestableType(const QUuid& id); /**jsdoc * Get the ID of the {@link Entities.EntityType|Web} entity that has keyboard focus. @@ -1440,25 +1436,10 @@ public slots: /**jsdoc * Set the {@link Entities.EntityType|Web} entity that has keyboard focus. * @function Entities.setKeyboardFocusEntity - * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|Web} entity to set keyboard focus to. Use + * @param {Uuid} id - The ID of the {@link Entities.EntityType|Web} entity to set keyboard focus to. Use * null or {@link Uuid|Uuid.NULL} to unset keyboard focus from an entity. */ - Q_INVOKABLE void setKeyboardFocusEntity(const EntityItemID& id); - - /**jsdoc - * Get the ID of the {@link Entities.EntityType|Web} local entity that has keyboard focus. - * @function Entities.getKeyboardFocusEntity - * @returns {Uuid} The ID of the {@link Entities.EntityType|Web} local entity that has focus, if any, otherwise null. - */ - Q_INVOKABLE QUuid getKeyboardFocusLocalEntity() const; - - /**jsdoc - * Set the {@link Entities.EntityType|Web} local entity that has keyboard focus. - * @function Entities.setKeyboardFocusEntity - * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|Web} local entity to set keyboard focus to. Use - * null or {@link Uuid|Uuid.NULL} to unset keyboard focus from an entity. - */ - Q_INVOKABLE void setKeyboardFocusLocalEntity(const EntityItemID& id); + Q_INVOKABLE void setKeyboardFocusEntity(const QUuid& id); /**jsdoc * Emit a {@link Entities.mousePressOnEntity|mousePressOnEntity} event. From 70b1e17a8c076b7d367f22af9436a92f3478f84b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Sat, 26 Jan 2019 23:26:40 -0800 Subject: [PATCH 013/139] more wip --- interface/src/Application.cpp | 12 +- interface/src/Application.h | 2 +- interface/src/ui/overlays/Overlays.cpp | 255 +++++++++++++------------ 3 files changed, 135 insertions(+), 134 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 859cc4d4c1..7e4afd1518 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5715,10 +5715,10 @@ QUuid Application::getKeyboardFocusEntity() const { static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f; -void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { - if (_keyboardFocusedEntity.get() != entityItemID) { +void Application::setKeyboardFocusEntity(const QUuid& id) { + if (_keyboardFocusedEntity.get() != id) { if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) { - if (entityItemID == _loginDialogID) { + if (id == _loginDialogID) { emit loginDialogFocusEnabled(); } else { // that's the only entity we want in focus; @@ -5726,17 +5726,17 @@ void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { } } - _keyboardFocusedEntity.set(entityItemID); + _keyboardFocusedEntity.set(id); auto entityScriptingInterface = DependencyManager::get(); - if (entityItemID == UNKNOWN_ENTITY_ID) { + if (id == UNKNOWN_ENTITY_ID) { EntityItemProperties properties; properties.setVisible(false); entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties); return; } - auto properties = entityScriptingInterface->getEntityProperties(entityItemID); + auto properties = entityScriptingInterface->getEntityProperties(id); if (!properties.getLocked() && properties.getVisible()) { auto entities = getEntities(); auto entityId = _keyboardFocusedEntity.get(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 5862ead763..55d396bb62 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -437,7 +437,7 @@ public slots: void setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions); QUuid getKeyboardFocusEntity() const; // thread-safe - void setKeyboardFocusEntity(const EntityItemID& entityItemID); + void setKeyboardFocusEntity(const QUuid& id); void addAssetToWorldMessageClose(); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index e93d41973c..1f52f9f28e 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -185,83 +185,83 @@ QString Overlays::overlayToEntityType(const QString& type) { return "Unknown"; } -#define SET_OVERLAY_PROP_DEFAULT(o, d) \ - { \ - if (add && !overlayProps.contains(#o)) { \ - overlayProps[#o] = d; \ - } \ +#define SET_OVERLAY_PROP_DEFAULT(o, d) \ + { \ + if (add && !overlayProps.contains(#o)) { \ + overlayProps[#o] = d; \ + } \ } -#define OVERLAY_TO_ENTITY_PROP(o, e) \ - { \ - auto iter = overlayProps.find(#o); \ - if (iter != overlayProps.end()) { \ - overlayProps[#e] = iter.value(); \ - } \ +#define RENAME_PROP(o, e) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + overlayProps[#e] = iter.value(); \ + } \ } -#define OVERLAY_TO_GROUP_ENTITY_PROP(o, g, e) \ - { \ - auto iter = overlayProps.find(#o); \ - if (iter != overlayProps.end()) { \ - if (!overlayProps.contains(#g)) { \ - overlayProps[#g] = QVariantMap(); \ - } \ - auto map = overlayProps[#g].toMap(); \ - map[#e] = iter.value(); \ - overlayProps[#g] = map; \ - } \ +#define RENAME_PROP_CONVERT(o, e, C) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + overlayProps[#e] = C(iter.value()); \ + } \ } -#define OVERLAY_TO_GROUP_ENTITY_PROP_DEFAULT(o, g, e, d) \ - { \ - auto iter = overlayProps.find(#o); \ - if (iter != overlayProps.end()) { \ - if (!overlayProps.contains(#g)) { \ - overlayProps[#g] = QVariantMap(); \ - } \ - auto map = overlayProps[#g].toMap(); \ - map[#e] = iter.value(); \ - overlayProps[#g] = map; \ - } else if (add) { \ - if (!overlayProps.contains(#g)) { \ - overlayProps[#g] = QVariantMap(); \ - } \ - auto map = overlayProps[#g].toMap(); \ - map[#e] = d; \ - overlayProps[#g] = map; \ - } \ +#define OVERLAY_TO_GROUP_ENTITY_PROP(o, g, e) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + if (!overlayProps.contains(#g)) { \ + overlayProps[#g] = QVariantMap(); \ + } \ + auto map = overlayProps[#g].toMap(); \ + map[#e] = iter.value(); \ + overlayProps[#g] = map; \ + } \ } -#define OVERLAY_TO_ENTITY_PROP_CONVERT(o, e, C) \ - { \ - auto iter = overlayProps.find(#o); \ - if (iter != overlayProps.end()) { \ - overlayProps[#e] = C(iter.value()); \ - } \ +#define OVERLAY_TO_GROUP_ENTITY_PROP_DEFAULT(o, g, e, d) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + if (!overlayProps.contains(#g)) { \ + overlayProps[#g] = QVariantMap(); \ + } \ + auto map = overlayProps[#g].toMap(); \ + map[#e] = iter.value(); \ + overlayProps[#g] = map; \ + } else if (add) { \ + if (!overlayProps.contains(#g)) { \ + overlayProps[#g] = QVariantMap(); \ + } \ + auto map = overlayProps[#g].toMap(); \ + map[#e] = d; \ + overlayProps[#g] = map; \ + } \ } -#define OVERLAY_TO_ENTITY_PROP_CONVERT_DEFAULT(o, e, d, C) \ - { \ - auto iter = overlayProps.find(#o); \ - if (iter != overlayProps.end()) { \ - overlayProps[#e] = C(iter.value()); \ - } else if (add) { \ - overlayProps[#e] = C(d); \ - } \ +#define OVERLAY_TO_ENTITY_PROP_CONVERT_DEFAULT(o, e, d, C) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + overlayProps[#e] = C(iter.value()); \ + } else if (add) { \ + overlayProps[#e] = C(d); \ + } \ } -#define OVERLAY_TO_GROUP_ENTITY_PROP_CONVERT(o, g, e, C) \ - { \ - auto iter = overlayProps.find(#o); \ - if (iter != overlayProps.end()) { \ - if (!overlayProps.contains(#g)) { \ - overlayProps[#g] = QVariantMap(); \ - } \ - auto map = overlayProps[#g].toMap(); \ - map[#e] = C(iter.value()); \ - overlayProps[#g] = map; \ - } \ +#define OVERLAY_TO_GROUP_ENTITY_PROP_CONVERT(o, g, e, C) \ + { \ + auto iter = overlayProps.find(#o); \ + if (iter != overlayProps.end()) { \ + if (!overlayProps.contains(#g)) { \ + overlayProps[#g] = QVariantMap(); \ + } \ + auto map = overlayProps[#g].toMap(); \ + map[#e] = C(iter.value()); \ + overlayProps[#g] = map; \ + } \ } EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id) { @@ -269,28 +269,28 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove SET_OVERLAY_PROP_DEFAULT(alpha, 0.7); if (type != "PolyLine") { - OVERLAY_TO_ENTITY_PROP(p1, position); - OVERLAY_TO_ENTITY_PROP(start, position); + RENAME_PROP(p1, position); + RENAME_PROP(start, position); } - OVERLAY_TO_ENTITY_PROP(point, position); - OVERLAY_TO_ENTITY_PROP(scale, dimensions); - OVERLAY_TO_ENTITY_PROP(size, dimensions); - OVERLAY_TO_ENTITY_PROP(orientation, rotation); - OVERLAY_TO_ENTITY_PROP(localOrientation, localRotation); - OVERLAY_TO_ENTITY_PROP(ignoreRayIntersection, ignorePickIntersection); + RENAME_PROP(point, position); + RENAME_PROP(scale, dimensions); + RENAME_PROP(size, dimensions); + RENAME_PROP(orientation, rotation); + RENAME_PROP(localOrientation, localRotation); + RENAME_PROP(ignoreRayIntersection, ignorePickIntersection); { - OVERLAY_TO_ENTITY_PROP(solid, isSolid); - OVERLAY_TO_ENTITY_PROP(isFilled, isSolid); - OVERLAY_TO_ENTITY_PROP(filled, isSolid); + RENAME_PROP(solid, isSolid); + RENAME_PROP(isFilled, isSolid); + RENAME_PROP(filled, isSolid); OVERLAY_TO_ENTITY_PROP_CONVERT_DEFAULT(isSolid, primitiveMode, false, [](const QVariant& v) { return v.toBool() ? "solid" : "lines"; }); - OVERLAY_TO_ENTITY_PROP(wire, isWire); - OVERLAY_TO_ENTITY_PROP_CONVERT(isWire, primitiveMode, [](const QVariant& v) { return v.toBool() ? "lines" : "solid"; }); + RENAME_PROP(wire, isWire); + RENAME_PROP_CONVERT(isWire, primitiveMode, [](const QVariant& v) { return v.toBool() ? "lines" : "solid"; }); } - OVERLAY_TO_ENTITY_PROP_CONVERT(drawInFront, renderLayer, [](const QVariant& v) { return v.toBool() ? "front" : "world"; }); - OVERLAY_TO_ENTITY_PROP_CONVERT(drawHUDLayer, renderLayer, [](const QVariant& v) { return v.toBool() ? "hud" : "world"; }); + RENAME_PROP_CONVERT(drawInFront, renderLayer, [](const QVariant& v) { return v.toBool() ? "front" : "world"; }); + RENAME_PROP_CONVERT(drawHUDLayer, renderLayer, [](const QVariant& v) { return v.toBool() ? "hud" : "world"; }); OVERLAY_TO_GROUP_ENTITY_PROP_DEFAULT(grabbable, grab, grabbable, false); @@ -319,13 +319,13 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove if (type == "Shape") { SET_OVERLAY_PROP_DEFAULT(shape, "Hexagon"); } else if (type == "Model") { - OVERLAY_TO_ENTITY_PROP(url, modelURL); - OVERLAY_TO_ENTITY_PROP(animationSettings, animation); + RENAME_PROP(url, modelURL); + RENAME_PROP(animationSettings, animation); } else if (type == "Image") { - OVERLAY_TO_ENTITY_PROP(url, imageURL); + RENAME_PROP(url, imageURL); } else if (type == "Web") { - OVERLAY_TO_ENTITY_PROP(url, sourceUrl); - OVERLAY_TO_ENTITY_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "Mouse" ? "mouse" : "touch"; }); + RENAME_PROP(url, sourceUrl); + RENAME_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "Mouse" ? "mouse" : "touch"; }); } else if (type == "Gizmo") { if (add || overlayProps.contains("outerRadius")) { float ratio = 2.0f; @@ -366,41 +366,41 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove } { - OVERLAY_TO_ENTITY_PROP(color, innerStartColor); - OVERLAY_TO_ENTITY_PROP(color, innerEndColor); - OVERLAY_TO_ENTITY_PROP(color, outerStartColor); - OVERLAY_TO_ENTITY_PROP(color, outerEndColor); + RENAME_PROP(color, innerStartColor); + RENAME_PROP(color, innerEndColor); + RENAME_PROP(color, outerStartColor); + RENAME_PROP(color, outerEndColor); - OVERLAY_TO_ENTITY_PROP(startColor, innerStartColor); - OVERLAY_TO_ENTITY_PROP(startColor, outerStartColor); + RENAME_PROP(startColor, innerStartColor); + RENAME_PROP(startColor, outerStartColor); - OVERLAY_TO_ENTITY_PROP(endColor, innerEndColor); - OVERLAY_TO_ENTITY_PROP(endColor, outerEndColor); + RENAME_PROP(endColor, innerEndColor); + RENAME_PROP(endColor, outerEndColor); - OVERLAY_TO_ENTITY_PROP(innerColor, innerStartColor); - OVERLAY_TO_ENTITY_PROP(innerColor, innerEndColor); + RENAME_PROP(innerColor, innerStartColor); + RENAME_PROP(innerColor, innerEndColor); - OVERLAY_TO_ENTITY_PROP(outerColor, outerStartColor); - OVERLAY_TO_ENTITY_PROP(outerColor, outerEndColor); + RENAME_PROP(outerColor, outerStartColor); + RENAME_PROP(outerColor, outerEndColor); } { - OVERLAY_TO_ENTITY_PROP(alpha, innerStartAlpha); - OVERLAY_TO_ENTITY_PROP(alpha, innerEndAlpha); - OVERLAY_TO_ENTITY_PROP(alpha, outerStartAlpha); - OVERLAY_TO_ENTITY_PROP(alpha, outerEndAlpha); + RENAME_PROP(alpha, innerStartAlpha); + RENAME_PROP(alpha, innerEndAlpha); + RENAME_PROP(alpha, outerStartAlpha); + RENAME_PROP(alpha, outerEndAlpha); - OVERLAY_TO_ENTITY_PROP(startAlpha, innerStartAlpha); - OVERLAY_TO_ENTITY_PROP(startAlpha, outerStartAlpha); + RENAME_PROP(startAlpha, innerStartAlpha); + RENAME_PROP(startAlpha, outerStartAlpha); - OVERLAY_TO_ENTITY_PROP(endAlpha, innerEndAlpha); - OVERLAY_TO_ENTITY_PROP(endAlpha, outerEndAlpha); + RENAME_PROP(endAlpha, innerEndAlpha); + RENAME_PROP(endAlpha, outerEndAlpha); - OVERLAY_TO_ENTITY_PROP(innerAlpha, innerStartAlpha); - OVERLAY_TO_ENTITY_PROP(innerAlpha, innerEndAlpha); + RENAME_PROP(innerAlpha, innerStartAlpha); + RENAME_PROP(innerAlpha, innerEndAlpha); - OVERLAY_TO_ENTITY_PROP(outerAlpha, outerStartAlpha); - OVERLAY_TO_ENTITY_PROP(outerAlpha, outerEndAlpha); + RENAME_PROP(outerAlpha, outerStartAlpha); + RENAME_PROP(outerAlpha, outerEndAlpha); } OVERLAY_TO_GROUP_ENTITY_PROP(startAt, ring, startAngle); @@ -424,38 +424,39 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove OVERLAY_TO_GROUP_ENTITY_PROP(majorTickMarksColor, ring, majorTickMarksColor); OVERLAY_TO_GROUP_ENTITY_PROP(minorTickMarksColor, ring, minorTickMarksColor); } else if (type == "PolyLine") { - OVERLAY_TO_ENTITY_PROP(startPoint, start); - OVERLAY_TO_ENTITY_PROP(p1, start); - OVERLAY_TO_ENTITY_PROP(endPoint, end); - OVERLAY_TO_ENTITY_PROP(p2, end); + RENAME_PROP(startPoint, p1); + RENAME_PROP(start, p1); + RENAME_PROP(endPoint, p2); + RENAME_PROP(end, p1); - if (overlayProps.contains("start") || overlayProps.contains("end")) { + RENAME_PROP(p1, position); + RENAME_PROP_CONVERT(p1, p1, [](const QVariant& v) { return vec3toVariant(glm::vec3(0.0f)); }); + RENAME_PROP_CONVERT(p2, p2, [=](const QVariant& v) { glm::vec3 position; - auto iter = overlayProps.find("position"); - if (iter != overlayProps.end()) { + auto iter2 = overlayProps.find("position"); + if (iter2 != overlayProps.end()) { position = vec3FromVariant(iter.value()); } else if (!add) { EntityPropertyFlags desiredProperties; desiredProperties += PROP_POSITION; position = DependencyManager::get()->getEntityProperties(id, desiredProperties).getPosition(); } - OVERLAY_TO_ENTITY_PROP_CONVERT(start, start, [position](const QVariant& v) { return vec3toVariant(vec3FromVariant(v) - position); }) - OVERLAY_TO_ENTITY_PROP_CONVERT(end, end, [position](const QVariant& v) { return vec3toVariant(vec3FromVariant(v) - position); }) - } + return vec3toVariant(vec3FromVariant(v) - position); + }); - OVERLAY_TO_ENTITY_PROP(localStart, start); - OVERLAY_TO_ENTITY_PROP(localEnd, end); + RENAME_PROP(localStart, p1); + RENAME_PROP(localEnd, p2); { QVariantList points; { - auto iter = overlayProps.find("start"); + auto iter = overlayProps.find("p1"); if (iter != overlayProps.end()) { points.push_back(iter.value()); } } { - auto iter = overlayProps.find("end"); + auto iter = overlayProps.find("p2"); if (iter != overlayProps.end()) { points.push_back(iter.value()); } @@ -479,11 +480,11 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove return toReturn; } -QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemProperties& entityProps) { - QScriptValue entityProperties; +QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemProperties& properties) { + QScriptEngine scriptEngine; + QVariantMap overlayProps = EntityItemPropertiesToScriptValue(&scriptEngine, properties).toVariant().toMap(); - QVariantMap props; - return props; + return overlayProps; } QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { From a747bf4cbdc56281899e3ef002e888ecbbcb6467 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 27 Jan 2019 23:48:55 -0800 Subject: [PATCH 014/139] Exploring removing the COmpositing buffer in the display plugin, using srgb for swapchain and debuging from there --- interface/src/graphics/GraphicsEngine.cpp | 1 + .../display-plugins/OpenGLDisplayPlugin.cpp | 27 +++++++++-------- .../src/display-plugins/SrgbToLinear.slf | 29 +++++++++++++++++-- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 4 ++- libraries/gl/src/gl/GLHelpers.cpp | 2 ++ .../render-utils/src/RenderForwardTask.cpp | 16 +++++----- libraries/render-utils/src/toneMapping.slf | 6 ++-- 7 files changed, 60 insertions(+), 25 deletions(-) diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index c2137d3d97..861dfea7f8 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -66,6 +66,7 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { } void GraphicsEngine::initializeRender(bool disableDeferred) { + disableDeferred = false; // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 5835316efe..f103494094 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -351,14 +351,14 @@ void OpenGLDisplayPlugin::customizeContext() { if ((image.width() > 0) && (image.height() > 0)) { cursorData.texture = gpu::Texture::createStrict( - gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), + gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::SRGBA), image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); cursorData.texture->setSource("cursor texture"); auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); cursorData.texture->setUsage(usage.build()); - cursorData.texture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); + cursorData.texture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::SRGBA)); cursorData.texture->assignStoredMip(0, image.byteCount(), image.constBits()); cursorData.texture->setAutoGenerateMips(true); } @@ -379,12 +379,13 @@ void OpenGLDisplayPlugin::customizeContext() { { gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTexture); _simplePipeline = gpu::Pipeline::create(program, scissorState); - _hudPipeline = gpu::Pipeline::create(program, blendState); + // _hudPipeline = gpu::Pipeline::create(program, blendState); } { gpu::ShaderPointer program = gpu::Shader::createProgram(shader::display_plugins::program::SrgbToLinear); _presentPipeline = gpu::Pipeline::create(program, scissorState); + _hudPipeline = gpu::Pipeline::create(program, blendState); } { @@ -474,12 +475,13 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur batch.enableStereo(false); batch.resetViewTransform(); batch.setFramebuffer(fbo); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); +// batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); batch.setStateScissorRect(scissor); batch.setViewportTransform(viewport); batch.setResourceTexture(0, texture); #ifndef USE_GLES - batch.setPipeline(_presentPipeline); + batch.setPipeline(_simplePipeline); + // batch.setPipeline(_presentPipeline); #else batch.setPipeline(_simplePipeline); #endif @@ -507,7 +509,7 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur batch.resetViewTransform(); batch.setViewportTransform(copyFboRect); batch.setStateScissorRect(copyFboRect); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, {0.0f, 0.0f, 0.0f, 1.0f}); + // batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, {0.0f, 0.0f, 0.0f, 1.0f}); batch.blit(fbo, sourceRect, copyFbo, copyRect); } } @@ -570,7 +572,7 @@ void OpenGLDisplayPlugin::compositePointer() { render([&](gpu::Batch& batch) { batch.enableStereo(false); batch.setProjectionTransform(mat4()); - batch.setFramebuffer(_compositeFramebuffer); + // batch.setFramebuffer(_compositeFramebuffer); batch.setPipeline(_cursorPipeline); batch.setResourceTexture(0, cursorData.texture); batch.resetViewTransform(); @@ -606,7 +608,7 @@ void OpenGLDisplayPlugin::compositeLayers() { { PROFILE_RANGE_EX(render_detail, "compositeScene", 0xff0077ff, (uint64_t)presentCount()) - compositeScene(); + // compositeScene(); } #ifdef HIFI_ENABLE_NSIGHT_DEBUG @@ -620,10 +622,10 @@ void OpenGLDisplayPlugin::compositeLayers() { }); } - { + /* { PROFILE_RANGE_EX(render_detail, "compositeExtra", 0xff0077ff, (uint64_t)presentCount()) compositeExtra(); - } + }*/ // Draw the pointer last so it's on top of everything auto compositorHelper = DependencyManager::get(); @@ -638,7 +640,8 @@ void OpenGLDisplayPlugin::internalPresent() { // Note: _displayTexture must currently be the same size as the display. uvec2 dims = _displayTexture ? uvec2(_displayTexture->getDimensions()) : getSurfacePixels(); auto viewport = ivec4(uvec2(0), dims); - renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, viewport); + // renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, viewport); + renderFromTexture(batch, _displayTexture ? _displayTexture : _currentFrame->framebuffer->getRenderBuffer(0), viewport, viewport); }); swapBuffers(); _presentRate.increment(); @@ -847,7 +850,7 @@ OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { void OpenGLDisplayPlugin::updateCompositeFramebuffer() { auto renderSize = glm::uvec2(getRecommendedRenderSize()); if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { - _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y)); + _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_SRGBA_32, renderSize.x, renderSize.y)); } } diff --git a/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf b/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf index 8b324c81a5..f9b333b3db 100644 --- a/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf +++ b/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf @@ -17,6 +17,31 @@ vec3 colorToLinearRGB(vec3 srgb) { } void main(void) { - outFragColor.a = 1.0; - outFragColor.rgb = colorToLinearRGB(texture(colorMap, varTexCoord0).rgb); + vec4 fetched = texture(colorMap, varTexCoord0); + //outFragColor = fetched; + outFragColor.a = fetched.a; + outFragColor.rgb = pow(fetched.rgb, vec3(2.2)); + + /* int vSize = 300; + int hSize = 400; + + if (gl_FragCoord.y < vSize) { + finalColor *= pow(2.0, 0.1); + } + else if (gl_FragCoord.y > 2 * vSize) { + finalColor *= pow(2.0, -0.1); + } + else { + finalColor; + } + + if (gl_FragCoord.x 2 * hSize) { + outFragColor.rgb = pow(finalColor, vec3(1.0 / 2.2)); + } + else { + outFragColor.rgb = finalColor; + }*/ + // outFragColor.rgb = sqrt(finalColor); } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 321bcc3fd2..0a953f142d 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -260,7 +260,9 @@ void HmdDisplayPlugin::internalPresent() { viewport.z *= 2; } - renderFromTexture(batch, _compositeFramebuffer->getRenderBuffer(0), viewport, scissor, fbo); + // renderFromTexture(batch, _compositeFramebuffer->getRenderBuffer(0), viewport, scissor, fbo); + renderFromTexture(batch, _currentFrame->framebuffer->getRenderBuffer(0), viewport, scissor, fbo); + }); swapBuffers(); diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index 15a41c3dc1..8194c6e4fc 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -99,6 +99,8 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() { #else format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); #endif + format.setColorSpace(QSurfaceFormat::sRGBColorSpace); + if (gl::Context::enableDebugLogger()) { format.setOption(QSurfaceFormat::DebugContext); } diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 8616214992..e6f687df59 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -124,16 +124,16 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend task.addJob("DrawBounds", opaques); task.addJob("DrawTransparentBounds", transparents); - task.addJob("DrawZones", zones); + task.addJob("DrawZones", zones);*/ const auto debugZoneInputs = DebugZoneLighting::Inputs(deferredFrameTransform, lightFrame, backgroundFrame).asVarying(); task.addJob("DrawZoneStack", debugZoneInputs); - }*/ + // } // Lighting Buffer ready for tone mapping // Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify // the output FBO as null, which causes the tonemapping to target the blit framebuffer - const auto toneMappingInputs = ToneMappingDeferred::Inputs(framebuffer, static_cast(nullptr) ).asVarying(); - task.addJob("ToneMapping", toneMappingInputs); + // const auto toneMappingInputs = ToneMappingDeferred::Inputs(framebuffer, static_cast(nullptr) ).asVarying(); + // task.addJob("ToneMapping", toneMappingInputs); // Layered Overlays // Composite the HUD and HUD overlays @@ -154,21 +154,23 @@ void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::Fra if (!_framebuffer) { _framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward")); + + int numSamples = 8; auto colorFormat = gpu::Element::COLOR_SRGBA_32; - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); /* auto colorTexture = gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); _framebuffer->setRenderBuffer(0, colorTexture);*/ auto colorTexture = - gpu::Texture::createRenderBufferMultisample(colorFormat, frameSize.x, frameSize.y, 16, defaultSampler); + gpu::Texture::createRenderBufferMultisample(colorFormat, frameSize.x, frameSize.y, numSamples, defaultSampler); _framebuffer->setRenderBuffer(0, colorTexture); auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format /* auto depthTexture = gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat);*/ auto depthTexture = - gpu::Texture::createRenderBufferMultisample(depthFormat, frameSize.x, frameSize.y, 16, defaultSampler); + gpu::Texture::createRenderBufferMultisample(depthFormat, frameSize.x, frameSize.y, numSamples, defaultSampler); _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); } diff --git a/libraries/render-utils/src/toneMapping.slf b/libraries/render-utils/src/toneMapping.slf index 29f618c2f0..cb3e73dd4d 100644 --- a/libraries/render-utils/src/toneMapping.slf +++ b/libraries/render-utils/src/toneMapping.slf @@ -36,8 +36,8 @@ int getToneCurve() { return params._toneCurve_s0_s1_s2.x; } -LAYOUT(binding=RENDER_UTILS_TEXTURE_TM_COLOR) uniform sampler2D colorMap; - +LAYOUT(binding = RENDER_UTILS_TEXTURE_TM_COLOR) uniform sampler2D colorMap; + layout(location=0) in vec2 varTexCoord0; layout(location=0) out vec4 outFragColor; @@ -54,7 +54,7 @@ void main(void) { tonedColor = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); } else if (toneCurve == ToneCurveReinhard) { tonedColor = srcColor/(1.0 + srcColor); - tonedColor = pow(tonedColor, vec3(INV_GAMMA_22)); + // tonedColor = pow(tonedColor, vec3(INV_GAMMA_22)); } else if (toneCurve == ToneCurveGamma22) { tonedColor = pow(srcColor, vec3(INV_GAMMA_22)); } // else None toned = src From e2bdac1bddcd0d4625ff0c3da8740e8f68c9dca8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 28 Jan 2019 10:52:30 -0800 Subject: [PATCH 015/139] working on polylines --- interface/src/ui/overlays/Overlays.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 1f52f9f28e..f5cc73aacd 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -362,7 +362,7 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove } } // FIXME: - //overlayProps["rotation"] = quatToVariant(glm::angleAxis((float)M_PI_2, Vectors::RIGHT) * rotation); + overlayProps["rotation"] = quatToVariant(glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation); } { @@ -427,7 +427,7 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove RENAME_PROP(startPoint, p1); RENAME_PROP(start, p1); RENAME_PROP(endPoint, p2); - RENAME_PROP(end, p1); + RENAME_PROP(end, p2); RENAME_PROP(p1, position); RENAME_PROP_CONVERT(p1, p1, [](const QVariant& v) { return vec3toVariant(glm::vec3(0.0f)); }); @@ -471,6 +471,15 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove overlayProps["strokeWidths"] = widths; } } + + RENAME_PROP_CONVERT(glow, glow, [](const QVariant& v) { return v.toFloat() > 0.0f ? true : false; }); + SET_OVERLAY_PROP_DEFAULT(faceCamera, true); + { + QVariantList normals; + normals.append(vec3toVariant(Vectors::UP)); + normals.append(vec3toVariant(Vectors::UP)); + SET_OVERLAY_PROP_DEFAULT(normals, normals); + } } QScriptEngine scriptEngine; From 2db45b3ec9583c5c79dd9c1ac689b488eaedd8aa Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 28 Jan 2019 14:03:43 -0800 Subject: [PATCH 016/139] dante's keyboard changes + getProperty + some fixes --- interface/src/Application.cpp | 13 +- interface/src/ui/Keyboard.cpp | 100 ++++++------ interface/src/ui/Keyboard.h | 7 +- interface/src/ui/overlays/Overlays.cpp | 143 +++++++++++++++++- .../entities/src/EntityItemProperties.cpp | 5 +- 5 files changed, 211 insertions(+), 57 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7e4afd1518..4bea8cabfb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2361,6 +2361,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }); // Preload Tablet sounds + DependencyManager::get()->setEntityTree(qApp->getEntities()->getTree()); DependencyManager::get()->preloadSounds(); DependencyManager::get()->createKeyboard(); @@ -8692,12 +8693,11 @@ void Application::createLoginDialog() { auto keyboard = DependencyManager::get().data(); if (!keyboard->getAnchorID().isNull() && !_loginDialogID.isNull()) { - const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f); auto keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); EntityItemProperties properties; properties.setPosition(position + keyboardLocalOffset); - properties.setRotation(cameraOrientation * KEYBOARD_LOCAL_ORIENTATION); + properties.setRotation(cameraOrientation * Quaternions::Y_180); entityScriptingInterface->editEntity(keyboard->getAnchorID(), properties); keyboard->setResetKeyboardPositionOnRaise(false); @@ -8728,7 +8728,6 @@ void Application::updateLoginDialogPosition() { auto upVec = getMyAvatar()->getWorldOrientation() * Vectors::UNIT_Y; auto offset = headLookVec * OFFSET.x; auto newPositionVec = (cameraPositionVec + offset) + (upVec * OFFSET.y); - auto newOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180; bool outOfBounds = glm::distance(positionVec, cameraPositionVec) > 1.0f; @@ -8736,17 +8735,17 @@ void Application::updateLoginDialogPosition() { { EntityItemProperties properties; properties.setPosition(newPositionVec); - properties.setRotation(newOrientation); + properties.setRotation(cameraOrientation); entityScriptingInterface->editEntity(_loginDialogID, properties); } { - const auto KEYBOARD_LOCAL_ORIENTATION = glm::quat(0.0f, 0.0, 1.0f, 0.25f); - auto keyboardLocalOffset = newOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); + glm::vec3 keyboardLocalOffset = cameraOrientation * glm::vec3(-0.4f * getMyAvatar()->getSensorToWorldScale(), -0.3f, 0.2f); + glm::quat keyboardOrientation = cameraOrientation * glm::quat(glm::radians(glm::vec3(-30.0f, 180.0f, 0.0f))); EntityItemProperties properties; properties.setPosition(newPositionVec + keyboardLocalOffset); - properties.setRotation(newOrientation * KEYBOARD_LOCAL_ORIENTATION); + properties.setRotation(keyboardOrientation); entityScriptingInterface->editEntity(DependencyManager::get()->getAnchorID(), properties); } } diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 54620e36ba..280c14167b 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -151,17 +151,20 @@ void Key::saveDimensionsAndLocalPosition() { _originalLocalPosition = properties.getLocalPosition(); _originalDimensions = properties.getDimensions(); _currentLocalPosition = _originalLocalPosition; + _originalDimensionsAndLocalPositionSaved = true; } void Key::scaleKey(float sensorToWorldScale) { - glm::vec3 scaledLocalPosition = _originalLocalPosition * sensorToWorldScale; - glm::vec3 scaledDimensions = _originalDimensions * sensorToWorldScale; - _currentLocalPosition = scaledLocalPosition; + if (_originalDimensionsAndLocalPositionSaved) { + glm::vec3 scaledLocalPosition = _originalLocalPosition * sensorToWorldScale; + glm::vec3 scaledDimensions = _originalDimensions * sensorToWorldScale; + _currentLocalPosition = scaledLocalPosition; - EntityItemProperties properties; - properties.setDimensions(scaledDimensions); - properties.setLocalPosition(scaledLocalPosition); - DependencyManager::get()->editEntity(_keyID, properties); + EntityItemProperties properties; + properties.setDimensions(scaledDimensions); + properties.setLocalPosition(scaledLocalPosition); + DependencyManager::get()->editEntity(_keyID, properties); + } } void Key::startTimer(int time) { @@ -229,6 +232,18 @@ void Keyboard::registerKeyboardHighlighting() { selection->enableListToScene(KEY_PRESSED_HIGHLIGHT); } +void Keyboard::disableSelectionLists() { + auto selection = DependencyManager::get(); + selection->disableListHighlight(KEY_HOVER_HIGHLIGHT); + selection->disableListHighlight(KEY_PRESSED_HIGHLIGHT); +} + +void Keyboard::enableSelectionLists() { + auto selection = DependencyManager::get(); + selection->enableListHighlight(KEY_HOVER_HIGHLIGHT, KEY_HOVERING_STYLE); + selection->enableListHighlight(KEY_PRESSED_HIGHLIGHT, KEY_PRESSING_STYLE); +} + bool Keyboard::getUse3DKeyboard() const { return _use3DKeyboardLock.resultWithReadLock([&] { return _use3DKeyboard.get(); @@ -288,6 +303,7 @@ void Keyboard::setRaised(bool raised) { raiseKeyboardAnchor(raised); raiseKeyboard(raised); raised ? enableStylus() : disableStylus(); + raised ? enableSelectionLists() : disableSelectionLists(); withWriteLock([&] { _raised = raised; _layerIndex = 0; @@ -340,8 +356,9 @@ void Keyboard::scaleKeyboard(float sensorToWorldScale) { { EntityItemProperties properties; - properties.setDimensions(_anchor.originalDimensions * sensorToWorldScale); - entityScriptingInterface->editEntity(_anchor.entityID, properties); + properties.setLocalPosition(_backPlate.localPosition * sensorToWorldScale); + properties.setDimensions(_backPlate.dimensions * sensorToWorldScale); + entityScriptingInterface->editEntity(_backPlate.entityID, properties); } for (auto& keyboardLayer : _keyboardLayers) { @@ -357,13 +374,6 @@ void Keyboard::scaleKeyboard(float sensorToWorldScale) { properties.setLineHeight(_textDisplay.lineHeight * sensorToWorldScale); entityScriptingInterface->editEntity(_textDisplay.entityID, properties); } - - { - EntityItemProperties properties; - properties.setLocalPosition(_backPlate.localPosition * sensorToWorldScale); - properties.setDimensions(_backPlate.dimensions * sensorToWorldScale); - entityScriptingInterface->editEntity(_backPlate.entityID, properties); - } } void Keyboard::startLayerSwitchTimer() { @@ -456,8 +466,8 @@ void Keyboard::switchToLayer(int layerIndex) { } } -bool Keyboard::shouldProcessEntityAndPointerEvent(const PointerEvent& event, const QUuid& id) const { - return (shouldProcessPointerEvent(event) && shouldProcessEntity(id)); +bool Keyboard::shouldProcessEntityAndPointerEvent(const PointerEvent& event) const { + return (shouldProcessPointerEvent(event) && shouldProcessEntity()); } bool Keyboard::shouldProcessPointerEvent(const PointerEvent& event) const { @@ -470,7 +480,7 @@ bool Keyboard::shouldProcessPointerEvent(const PointerEvent& event) const { void Keyboard::handleTriggerBegin(const QUuid& id, const PointerEvent& event) { auto buttonType = event.getButton(); - if (!shouldProcessEntityAndPointerEvent(event, id) || buttonType != PointerEvent::PrimaryButton) { + if (!shouldProcessEntityAndPointerEvent(event) || buttonType != PointerEvent::PrimaryButton) { return; } @@ -572,7 +582,7 @@ void Keyboard::setRightHandLaser(unsigned int rightHandLaser) { } void Keyboard::handleTriggerEnd(const QUuid& id, const PointerEvent& event) { - if (!shouldProcessEntityAndPointerEvent(event, id)) { + if (!shouldProcessEntityAndPointerEvent(event)) { return; } @@ -599,7 +609,7 @@ void Keyboard::handleTriggerEnd(const QUuid& id, const PointerEvent& event) { } void Keyboard::handleTriggerContinue(const QUuid& id, const PointerEvent& event) { - if (!shouldProcessEntityAndPointerEvent(event, id)) { + if (!shouldProcessEntityAndPointerEvent(event)) { return; } @@ -639,7 +649,7 @@ void Keyboard::handleTriggerContinue(const QUuid& id, const PointerEvent& event) } void Keyboard::handleHoverBegin(const QUuid& id, const PointerEvent& event) { - if (!shouldProcessEntityAndPointerEvent(event, id)) { + if (!shouldProcessEntityAndPointerEvent(event)) { return; } @@ -655,7 +665,7 @@ void Keyboard::handleHoverBegin(const QUuid& id, const PointerEvent& event) { } void Keyboard::handleHoverEnd(const QUuid& id, const PointerEvent& event) { - if (!shouldProcessEntityAndPointerEvent(event, id)) { + if (!shouldProcessEntityAndPointerEvent(event)) { return; } @@ -750,26 +760,28 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { { QJsonObject backPlateObject = jsonObject["backPlate"].toObject(); + glm::vec3 position = vec3FromVariant(backPlateObject["position"].toVariant()); glm::vec3 dimensions = vec3FromVariant(backPlateObject["dimensions"].toVariant()); + glm::quat rotation = quatFromVariant(backPlateObject["rotation"].toVariant()); EntityItemProperties properties; properties.setType(EntityTypes::Box); - properties.setName("BackPlate"); + properties.setName("Keyboard-BackPlate"); properties.setVisible(true); properties.getGrab().setGrabbable(false); properties.setAlpha(0.0f); properties.setIgnorePickIntersection(false); properties.setDimensions(dimensions); - properties.setPosition(vec3FromVariant(backPlateObject["position"].toVariant())); - properties.setRotation(quatFromVariant(backPlateObject["rotation"].toVariant())); + properties.setPosition(position); + properties.setRotation(rotation); properties.setParentID(_anchor.entityID); BackPlate backPlate; backPlate.entityID = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); backPlate.dimensions = dimensions; - EntityPropertyFlags desiredProperties; - desiredProperties += PROP_LOCAL_POSITION; - backPlate.localPosition = entityScriptingInterface->getEntityProperties(backPlate.entityID, desiredProperties).getLocalPosition(); + glm::quat anchorEntityInverseWorldOrientation = glm::inverse(rotation); + glm::vec3 anchorEntityLocalTranslation = anchorEntityInverseWorldOrientation * -position; + backPlate.localPosition = (anchorEntityInverseWorldOrientation * position) + anchorEntityLocalTranslation; _backPlate = backPlate; } @@ -797,6 +809,19 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { QString modelUrl = keyboardKeyValue["modelURL"].toString(); QString url = (useResourcePath ? (resourcePath + modelUrl) : modelUrl); + EntityItemProperties properties; + properties.setType(EntityTypes::Model); + properties.setDimensions(vec3FromVariant(keyboardKeyValue["dimensions"].toVariant())); + properties.setPosition(vec3FromVariant(keyboardKeyValue["position"].toVariant())); + properties.setVisible(false); + properties.setEmissive(true); + properties.setParentID(_anchor.entityID); + properties.setModelURL(url); + properties.setTextures(QVariant(textureMap).toString()); + properties.getGrab().setGrabbable(false); + properties.setLocalRotation(quatFromVariant(keyboardKeyValue["localOrientation"].toVariant())); + QUuid id = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); + QString keyType = keyboardKeyValue["type"].toString(); QString keyString = keyboardKeyValue["key"].toString(); @@ -810,19 +835,6 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { key.setSwitchToLayerIndex(switchToLayer); } } - - EntityItemProperties properties; - properties.setType(EntityTypes::Model); - properties.setDimensions(vec3FromVariant(keyboardKeyValue["dimensions"].toVariant())); - properties.setPosition(vec3FromVariant(keyboardKeyValue["position"].toVariant())); - properties.setVisible(false); - properties.setEmissive(true); - properties.setParentID(_anchor.entityID); - properties.setModelURL(url); - properties.setTextures(QVariant(textureMap).toString()); - properties.getGrab().setGrabbable(false); - properties.setLocalRotation(quatFromVariant(keyboardKeyValue["localOrientation"].toVariant())); - QUuid id = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); key.setID(id); key.setKeyString(keyString); key.saveDimensionsAndLocalPosition(); @@ -886,8 +898,8 @@ QUuid Keyboard::getAnchorID() { }); } -bool Keyboard::shouldProcessEntity(const QUuid& id) const { - return (!_keyboardLayers.empty() && isLayerSwitchTimerFinished() && id != _backPlate.entityID); +bool Keyboard::shouldProcessEntity() const { + return (!_keyboardLayers.empty() && isLayerSwitchTimerFinished()); } QVector Keyboard::getKeysID() { diff --git a/interface/src/ui/Keyboard.h b/interface/src/ui/Keyboard.h index dcb9deac4e..7056411578 100644 --- a/interface/src/ui/Keyboard.h +++ b/interface/src/ui/Keyboard.h @@ -81,6 +81,7 @@ private: glm::vec3 _originalLocalPosition; glm::vec3 _originalDimensions; glm::vec3 _currentLocalPosition; + bool _originalDimensionsAndLocalPositionSaved { false }; std::shared_ptr _timer { std::make_shared() }; }; @@ -146,14 +147,16 @@ private: void raiseKeyboardAnchor(bool raise) const; void enableStylus(); void disableStylus(); + void enableSelectionLists(); + void disableSelectionLists(); void setLayerIndex(int layerIndex); void clearKeyboardKeys(); void switchToLayer(int layerIndex); void updateTextDisplay(); - bool shouldProcessEntityAndPointerEvent(const PointerEvent& event, const QUuid& id) const; + bool shouldProcessEntityAndPointerEvent(const PointerEvent& event) const; bool shouldProcessPointerEvent(const PointerEvent& event) const; - bool shouldProcessEntity(const QUuid& id) const; + bool shouldProcessEntity() const; void startLayerSwitchTimer(); bool isLayerSwitchTimerFinished() const; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index f5cc73aacd..61ae714445 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -264,6 +264,30 @@ QString Overlays::overlayToEntityType(const QString& type) { } \ } +#define GROUP_ENTITY_TO_OVERLAY_PROP(g, e, o) \ + { \ + auto iter = overlayProps.find(#g); \ + if (iter != overlayProps.end()) { \ + auto map = iter.value().toMap(); \ + auto iter2 = map.find(#e); \ + if (iter2 != map.end()) { \ + overlayProps[#o] = iter2.value(); \ + } \ + } \ + } + +#define GROUP_ENTITY_TO_OVERLAY_PROP_CONVERT(g, e, o, C) \ + { \ + auto iter = overlayProps.find(#g); \ + if (iter != overlayProps.end()) { \ + auto map = iter.value().toMap(); \ + auto iter2 = map.find(#e); \ + if (iter2 != map.end()) { \ + overlayProps[#o] = C(iter2.value()); \ + } \ + } \ + } + EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id) { overlayProps["type"] = type; @@ -279,7 +303,8 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove RENAME_PROP(localOrientation, localRotation); RENAME_PROP(ignoreRayIntersection, ignorePickIntersection); - { + // Model overlays didn't support wireframe drawing + if (type != "Model") { RENAME_PROP(solid, isSolid); RENAME_PROP(isFilled, isSolid); RENAME_PROP(filled, isSolid); @@ -327,6 +352,7 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove RENAME_PROP(url, sourceUrl); RENAME_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "Mouse" ? "mouse" : "touch"; }); } else if (type == "Gizmo") { + RENAME_PROP(radius, outerRadius); if (add || overlayProps.contains("outerRadius")) { float ratio = 2.0f; { @@ -435,7 +461,7 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove glm::vec3 position; auto iter2 = overlayProps.find("position"); if (iter2 != overlayProps.end()) { - position = vec3FromVariant(iter.value()); + position = vec3FromVariant(iter2.value()); } else if (!add) { EntityPropertyFlags desiredProperties; desiredProperties += PROP_POSITION; @@ -493,6 +519,119 @@ QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemPropertie QScriptEngine scriptEngine; QVariantMap overlayProps = EntityItemPropertiesToScriptValue(&scriptEngine, properties).toVariant().toMap(); + QString type = overlayProps["type"].toString(); + overlayProps["type"] = entityToOverlayType(type); + + if (type != "PolyLine") { + RENAME_PROP(position, p1); + RENAME_PROP(position, start); + } + RENAME_PROP(position, point); + RENAME_PROP(dimensions, scale); + RENAME_PROP(dimensions, size); + RENAME_PROP(rotation, orientation); + RENAME_PROP(localRotation, localOrientation); + RENAME_PROP(ignorePickIntersection, ignoreRayIntersection); + + { + RENAME_PROP_CONVERT(primitiveMode, isSolid, [](const QVariant& v) { return v.toString() == "solid" ? true : false; }); + RENAME_PROP(isSolid, solid); + RENAME_PROP(isSolid, isFilled); + RENAME_PROP(isSolid, filled); + + RENAME_PROP_CONVERT(primitiveMode, isWire, [](const QVariant& v) { return v.toString() == "lines" ? true : false; }); + RENAME_PROP(isWire, wire); + } + + RENAME_PROP_CONVERT(renderLayer, drawInFront, [](const QVariant& v) { return v.toString() == "front" ? true : false; }); + RENAME_PROP_CONVERT(renderLayer, drawHUDLayer, [](const QVariant& v) { return v.toString() == "hud" ? true : false; }); + + GROUP_ENTITY_TO_OVERLAY_PROP(grab, grabbable, grabbable); + + GROUP_ENTITY_TO_OVERLAY_PROP(pulse, min, pulseMin); + GROUP_ENTITY_TO_OVERLAY_PROP(pulse, max, pulseMax); + GROUP_ENTITY_TO_OVERLAY_PROP(pulse, period, pulsePeriod); + GROUP_ENTITY_TO_OVERLAY_PROP_CONVERT(pulse, colorMode, colorPulse, [](const QVariant& v) { + QString f = v.toString(); + if (f == "in") { + return 1.0f; + } else if (f == "out") { + return -1.0f; + } + return 0.0f; + }); + GROUP_ENTITY_TO_OVERLAY_PROP_CONVERT(pulse, alphaMode, alphaPulse, [](const QVariant& v) { + QString f = v.toString(); + if (f == "in") { + return 1.0f; + } else if (f == "out") { + return -1.0f; + } + return 0.0f; + }); + + if (type == "Model") { + RENAME_PROP(modelURL, url); + RENAME_PROP(animation, animationSettings); + } else if (type == "Image") { + RENAME_PROP(imageURL, url); + } else if (type == "Web") { + RENAME_PROP(sourceUrl, url); + RENAME_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "mouse" ? "Mouse" : "Touch"; }); + } else if (type == "Gizmo") { + RENAME_PROP_CONVERT(dimensions, outerRadius, [](const QVariant& v) { return vec3FromVariant(v).x; }); + RENAME_PROP(outerRadius, radius); + + RENAME_PROP_CONVERT(rotation, rotation, [](const QVariant& v) { + glm::quat rot = quatFromVariant(v); + // FIXME: + return quatToVariant(glm::angleAxis((float)M_PI_2, rot * Vectors::RIGHT) * rot); + }); + + GROUP_ENTITY_TO_OVERLAY_PROP(ring, startAngle, startAt); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, endAngle, endAt); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, innerRadius, innerRadius); + + GROUP_ENTITY_TO_OVERLAY_PROP(ring, innerStartColor, innerStartColor); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, innerEndColor, innerEndColor); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, outerStartColor, outerStartColor); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, outerEndColor, outerEndColor); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, innerStartAlpha, innerStartAlpha); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, innerEndAlpha, innerEndAlpha); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, outerStartAlpha, outerStartAlpha); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, outerEndAlpha, outerEndAlpha); + + GROUP_ENTITY_TO_OVERLAY_PROP(ring, hasTickMarks, hasTickMarks); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, majorTickMarksAngle, majorTickMarksAngle); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, minorTickMarksAngle, minorTickMarksAngle); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, majorTickMarksLength, majorTickMarksLength); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, minorTickMarksLength, minorTickMarksLength); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, majorTickMarksColor, majorTickMarksColor); + GROUP_ENTITY_TO_OVERLAY_PROP(ring, minorTickMarksColor, minorTickMarksColor); + } else if (type == "PolyLine") { + QVector points = qVectorVec3FromScriptValue(scriptEngine.newVariant(overlayProps["linePoints"])); + glm::vec3 position = vec3FromVariant(overlayProps["position"]); + if (points.length() > 1) { + overlayProps["p1"] = vec3toVariant(points[0] + position); + overlayProps["p2"] = vec3toVariant(points[1] + position); + + overlayProps["localStart"] = vec3toVariant(points[0]); + overlayProps["localEnd"] = vec3toVariant(points[1]); + } + + RENAME_PROP(p1, startPoint); + RENAME_PROP(p1, start); + RENAME_PROP(p2, endPoint); + RENAME_PROP(p2, end); + + QVector widths = qVectorFloatFromScriptValue(scriptEngine.newVariant(overlayProps["strokeWidths"])); + if (widths.length() > 0) { + overlayProps["lineWidth"] = widths[0]; + } + + RENAME_PROP_CONVERT(glow, glow, [](const QVariant& v) { return v.toBool() ? 1.0f : 0.0f; }); + } + return overlayProps; } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ad5c9660f4..3b6bdc44b8 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1489,6 +1489,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * minorGridEvery: 0.5, * lifetime: 300 // Delete after 5 minutes. * }); + */ /**jsdoc * The "Gizmo" {@link Entities.EntityType|EntityType} displays an entity that could be used as UI. @@ -1922,7 +1923,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool properties.setProperty("localEntity", convertScriptValue(engine, getEntityHostType() == entity::HostType::LOCAL)); } - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::FaceCamera)) { + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::FaceCamera) && _type != EntityTypes::PolyLine) { properties.setProperty("faceCamera", convertScriptValue(engine, getBillboardMode() == BillboardMode::YAW)); } if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::IsFacingAvatar)) { @@ -2189,7 +2190,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool } // Handle old "faceCamera" and "isFacingAvatar" props - { + if (_type != EntityTypes::PolyLine) { QScriptValue P = object.property("faceCamera"); if (P.isValid() && !object.property("billboardMode").isValid()) { bool newValue = P.toVariant().toBool(); From 445608e163e882fe496f8562d5ee8de803da2a77 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 28 Jan 2019 15:04:34 -0800 Subject: [PATCH 017/139] fix entity selection tool --- interface/src/ui/overlays/Overlays.cpp | 14 ++- libraries/entities/src/GizmoEntityItem.cpp | 10 +- .../system/libraries/entitySelectionTool.js | 119 ++++++------------ 3 files changed, 52 insertions(+), 91 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 61ae714445..e55ebcc159 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -315,7 +315,15 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove } RENAME_PROP_CONVERT(drawInFront, renderLayer, [](const QVariant& v) { return v.toBool() ? "front" : "world"; }); - RENAME_PROP_CONVERT(drawHUDLayer, renderLayer, [](const QVariant& v) { return v.toBool() ? "hud" : "world"; }); + RENAME_PROP_CONVERT(drawHUDLayer, renderLayer, [=](const QVariant& v) { + bool f = v.toBool(); + if (f) { + return QVariant("hud"); + } else if (overlayProps.contains("renderLayer")) { + return overlayProps["renderLayer"]; + } + return QVariant("world"); + }); OVERLAY_TO_GROUP_ENTITY_PROP_DEFAULT(grabbable, grab, grabbable, false); @@ -380,14 +388,13 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove { auto iter = overlayProps.find("rotation"); if (iter != overlayProps.end()) { - rotation = vec3FromVariant(iter.value()); + rotation = quatFromVariant(iter.value()); } else if (!add) { EntityPropertyFlags desiredProperties; desiredProperties += PROP_ROTATION; rotation = DependencyManager::get()->getEntityProperties(id, desiredProperties).getRotation(); } } - // FIXME: overlayProps["rotation"] = quatToVariant(glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation); } @@ -584,7 +591,6 @@ QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemPropertie RENAME_PROP_CONVERT(rotation, rotation, [](const QVariant& v) { glm::quat rot = quatFromVariant(v); - // FIXME: return quatToVariant(glm::angleAxis((float)M_PI_2, rot * Vectors::RIGHT) * rot); }); diff --git a/libraries/entities/src/GizmoEntityItem.cpp b/libraries/entities/src/GizmoEntityItem.cpp index c9f205d289..f2bef0cb80 100644 --- a/libraries/entities/src/GizmoEntityItem.cpp +++ b/libraries/entities/src/GizmoEntityItem.cpp @@ -10,6 +10,8 @@ #include "EntityItemProperties.h" +#include + EntityItemPointer GizmoEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { Pointer entity(new GizmoEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); entity->setProperties(properties); @@ -109,15 +111,14 @@ bool GizmoEntityItem::supportsDetailedIntersection() const { return _gizmoType == GizmoType::RING; } -#include - bool GizmoEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const { glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.z); - glm::quat rotation = glm::angleAxis((float)M_PI_2, Vectors::RIGHT) * getWorldOrientation(); + glm::quat rotation = getWorldOrientation(); + rotation = glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation; glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { @@ -150,7 +151,8 @@ bool GizmoEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, //// Scale the dimensions by the diameter glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.z); - glm::quat rotation = glm::angleAxis((float)M_PI_2, Vectors::RIGHT) * getWorldOrientation(); + glm::quat rotation = getWorldOrientation(); + rotation = glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation; glm::vec3 position = getWorldPosition(); glm::quat inverseRot = glm::inverse(rotation); diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 83cd010337..c0b28cbf9c 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -796,26 +796,14 @@ SelectionDisplay = (function() { borderSize: 1.4 }); - var handlePropertiesBoundingEdge = { + var handleBoundingBox = Overlays.addOverlay("cube", { alpha: 1, color: COLOR_BOUNDING_EDGE, visible: false, - ignoreRayIntersection: true, + ignorePickIntersection: true, drawInFront: true, - lineWidth: 0.2 - }; - var handleBoundingTREdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingTLEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingTFEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingTNEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingBREdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingBLEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingBFEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingBNEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingNREdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingNLEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingFREdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); - var handleBoundingFLEdge = Overlays.addOverlay("line3d", handlePropertiesBoundingEdge); + isSolid: false + }); var handleDuplicator = Overlays.addOverlay("cube", { alpha: 1, @@ -903,25 +891,13 @@ SelectionDisplay = (function() { handleStretchYPanel, handleStretchZPanel, handleScaleCube, - handleBoundingTREdge, - handleBoundingTLEdge, - handleBoundingTFEdge, - handleBoundingTNEdge, - handleBoundingBREdge, - handleBoundingBLEdge, - handleBoundingBFEdge, - handleBoundingBNEdge, - handleBoundingNREdge, - handleBoundingNLEdge, - handleBoundingFREdge, - handleBoundingFLEdge, + handleBoundingBox, handleDuplicator, selectionBox, iconSelectionBox, xRailOverlay, yRailOverlay, zRailOverlay - ]; var maximumHandleInAllOverlays = handleDuplicator; @@ -947,18 +923,7 @@ SelectionDisplay = (function() { overlayNames[handleScaleCube] = "handleScaleCube"; - overlayNames[handleBoundingTREdge] = "handleBoundingTREdge"; - overlayNames[handleBoundingTLEdge] = "handleBoundingTLEdge"; - overlayNames[handleBoundingTFEdge] = "handleBoundingTFEdge"; - overlayNames[handleBoundingTNEdge] = "handleBoundingTNEdge"; - overlayNames[handleBoundingBREdge] = "handleBoundingBREdge"; - overlayNames[handleBoundingBLEdge] = "handleBoundingBLEdge"; - overlayNames[handleBoundingBFEdge] = "handleBoundingBFEdge"; - overlayNames[handleBoundingBNEdge] = "handleBoundingBNEdge"; - overlayNames[handleBoundingNREdge] = "handleBoundingNREdge"; - overlayNames[handleBoundingNLEdge] = "handleBoundingNLEdge"; - overlayNames[handleBoundingFREdge] = "handleBoundingFREdge"; - overlayNames[handleBoundingFLEdge] = "handleBoundingFLEdge"; + overlayNames[handleBoundingBox] = "handleBoundingBox"; overlayNames[handleDuplicator] = "handleDuplicator"; overlayNames[selectionBox] = "selectionBox"; @@ -1048,7 +1013,19 @@ SelectionDisplay = (function() { return null; } - var intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludes, overlayExcludes); + var overlayIncludesLayered = overlayIncludes.filter(function (value, index, arr) { + return value != selectionBox && value != iconSelectionBox; + }); + var intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludesLayered, overlayExcludes); + + if (!intersectObj.intersects) { + var overlayIncludesNonLayered = overlayIncludes.filter(function (value, index, arr) { + return value == selectionBox || value == iconSelectionBox; + }); + if (overlayIncludesNonLayered.length > 0) { + intersectObj = Overlays.findRayIntersection(queryRay, true, [], overlayExcludes); + } + } if (wantDebug) { if (!overlayIncludes) { @@ -1174,9 +1151,10 @@ SelectionDisplay = (function() { that.updateHighlight = function(event) { // if no tool is active, then just look for handles to highlight... var pickRay = generalComputePickRay(event.x, event.y); - var result = Overlays.findRayIntersection(pickRay); + var result = testRayIntersect(pickRay, allOverlays); var pickedColor; var highlightNeeded = false; + print(JSON.stringify(result)); if (result.intersects) { switch (result.overlayID) { @@ -1677,40 +1655,26 @@ SelectionDisplay = (function() { dimensions: scaleCubeDimensions }); - // UPDATE BOUNDING BOX EDGES + // UPDATE BOUNDING BOX + Overlays.editOverlay(handleBoundingBox, { + position: position, + rotation: rotation, + dimensions: dimensions + }); + + // UPDATE STRETCH HIGHLIGHT PANELS var edgeOffsetX = BOUNDING_EDGE_OFFSET * dimensions.x; var edgeOffsetY = BOUNDING_EDGE_OFFSET * dimensions.y; var edgeOffsetZ = BOUNDING_EDGE_OFFSET * dimensions.z; - var LBNPosition = { x: -edgeOffsetX, y: -edgeOffsetY, z: -edgeOffsetZ }; - LBNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LBNPosition)); - var RBNPosition = { x: edgeOffsetX, y: -edgeOffsetY, z: -edgeOffsetZ }; - RBNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RBNPosition)); - var LBFPosition = { x: -edgeOffsetX, y: -edgeOffsetY, z: edgeOffsetZ }; - LBFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LBFPosition)); var RBFPosition = { x: edgeOffsetX, y: -edgeOffsetY, z: edgeOffsetZ }; RBFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RBFPosition)); + var RTFPosition = { x: edgeOffsetX, y: edgeOffsetY, z: edgeOffsetZ }; + RTFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RTFPosition)); var LTNPosition = { x: -edgeOffsetX, y: edgeOffsetY, z: -edgeOffsetZ }; LTNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LTNPosition)); var RTNPosition = { x: edgeOffsetX, y: edgeOffsetY, z: -edgeOffsetZ }; RTNPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RTNPosition)); - var LTFPosition = { x: -edgeOffsetX, y: edgeOffsetY, z: edgeOffsetZ }; - LTFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, LTFPosition)); - var RTFPosition = { x: edgeOffsetX, y: edgeOffsetY, z: edgeOffsetZ }; - RTFPosition = Vec3.sum(position, Vec3.multiplyQbyV(rotation, RTFPosition)); - Overlays.editOverlay(handleBoundingTREdge, { start: RTNPosition, end: RTFPosition }); - Overlays.editOverlay(handleBoundingTLEdge, { start: LTNPosition, end: LTFPosition }); - Overlays.editOverlay(handleBoundingTFEdge, { start: LTFPosition, end: RTFPosition }); - Overlays.editOverlay(handleBoundingTNEdge, { start: LTNPosition, end: RTNPosition }); - Overlays.editOverlay(handleBoundingBREdge, { start: RBNPosition, end: RBFPosition }); - Overlays.editOverlay(handleBoundingBLEdge, { start: LBNPosition, end: LBFPosition }); - Overlays.editOverlay(handleBoundingBFEdge, { start: LBFPosition, end: RBFPosition }); - Overlays.editOverlay(handleBoundingBNEdge, { start: LBNPosition, end: RBNPosition }); - Overlays.editOverlay(handleBoundingNREdge, { start: RTNPosition, end: RBNPosition }); - Overlays.editOverlay(handleBoundingNLEdge, { start: LTNPosition, end: LBNPosition }); - Overlays.editOverlay(handleBoundingFREdge, { start: RTFPosition, end: RBFPosition }); - Overlays.editOverlay(handleBoundingFLEdge, { start: LTFPosition, end: LBFPosition }); - - // UPDATE STRETCH HIGHLIGHT PANELS + var RBFPositionRotated = Vec3.multiplyQbyV(rotationInverse, RBFPosition); var RTFPositionRotated = Vec3.multiplyQbyV(rotationInverse, RTFPosition); var LTNPositionRotated = Vec3.multiplyQbyV(rotationInverse, LTNPosition); @@ -1841,7 +1805,7 @@ SelectionDisplay = (function() { var showOutlineForZone = (SelectionManager.selections.length === 1 && typeof SelectionManager.savedProperties[SelectionManager.selections[0]] !== "undefined" && SelectionManager.savedProperties[SelectionManager.selections[0]].type === "Zone"); - that.setHandleBoundingEdgeVisible(showOutlineForZone || (!isActiveTool(handleRotatePitchRing) && + that.setHandleBoundingBoxVisible(showOutlineForZone || (!isActiveTool(handleRotatePitchRing) && !isActiveTool(handleRotateYawRing) && !isActiveTool(handleRotateRollRing))); @@ -1941,26 +1905,15 @@ SelectionDisplay = (function() { // FUNCTION: SET HANDLE SCALE VISIBLE that.setHandleScaleVisible = function(isVisible) { that.setHandleScaleVisible(isVisible); - that.setHandleBoundingEdgeVisible(isVisible); + that.setHandleBoundingBoxVisible(isVisible); }; that.setHandleScaleVisible = function(isVisible) { Overlays.editOverlay(handleScaleCube, { visible: isVisible }); }; - that.setHandleBoundingEdgeVisible = function(isVisible) { - Overlays.editOverlay(handleBoundingTREdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingTLEdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingTFEdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingTNEdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingBREdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingBLEdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingBFEdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingBNEdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingNREdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingNLEdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingFREdge, { visible: isVisible }); - Overlays.editOverlay(handleBoundingFLEdge, { visible: isVisible }); + that.setHandleBoundingBoxVisible = function(isVisible) { + Overlays.editOverlay(handleBoundingBox, { visible: isVisible }); }; // FUNCTION: SET HANDLE DUPLICATOR VISIBLE From 7b88efa42c64e98ce100cae2e19303d1b0d1614c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 28 Jan 2019 18:29:09 -0800 Subject: [PATCH 018/139] trying to fix web surfaces?? --- interface/src/Application.cpp | 2 +- .../src/RenderableWebEntityItem.cpp | 12 +++++++----- .../entities-renderer/src/RenderableWebEntityItem.h | 1 + libraries/entities/src/WebEntityItem.cpp | 12 ++---------- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7aa4d0dd81..4d4d76172a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2332,7 +2332,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Fix for crash in QtWebEngineCore when rapidly switching domains // Call stop on the QWebEngineView before destroying OffscreenQMLSurface. - if (rootItem) { + if (rootItem && !cachedWebSurface) { // stop loading QMetaObject::invokeMethod(rootItem, "stop"); } diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 31ca189311..8d4ba3ea4e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -189,13 +189,13 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene }); if (urlChanged) { + if (!_loading && (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent)) { + destroyWebSurface(); + } + withWriteLock([&] { _contentType = newContentType; }); - - if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) { - destroyWebSurface(); - } } } @@ -214,10 +214,12 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene // This work must be done on the main thread if (!_webSurface) { buildWebSurface(entity, newSourceURL); + _loading = true; } - if (_webSurface && _webSurface->getRootItem()) { + if (_webSurface) { if (_webSurface->getRootItem()) { + _loading = false; if (_contentType == ContentType::HtmlContent && urlChanged) { _webSurface->getRootItem()->setProperty(URL_PROPERTY, newSourceURL); _sourceURL = newSourceURL; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index e5eff5818b..b97ad98502 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -77,6 +77,7 @@ private: }; static ContentType getContentType(const QString& urlString); ContentType _contentType { ContentType::NoContent }; + bool _loading { false }; QSharedPointer _webSurface { nullptr }; bool _cachedWebSurface { false }; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 459d512311..21d8b876f0 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -232,15 +232,7 @@ float WebEntityItem::getAlpha() const { void WebEntityItem::setSourceUrl(const QString& value) { withWriteLock([&] { - if (_sourceUrl != value) { - auto newURL = QUrl::fromUserInput(value); - - if (newURL.isValid()) { - _sourceUrl = newURL.toDisplayString(); - } else { - qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL."; - } - } + _sourceUrl = value; }); } @@ -270,7 +262,7 @@ void WebEntityItem::setScriptURL(const QString& value) { if (newURL.isValid()) { _scriptURL = newURL.toDisplayString(); } else { - qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL."; + qCDebug(entities) << "Not setting web entity script URL since" << value << "cannot be parsed to a valid URL."; } } }); From 6ad0b3412a92a153ce9a9d183820955a66c5c40a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 28 Jan 2019 20:43:47 -0800 Subject: [PATCH 019/139] showKeyboardFocusHighlight + fixes --- interface/src/Application.cpp | 7 ++- interface/src/ui/overlays/Overlays.cpp | 6 +- .../src/RenderableWebEntityItem.cpp | 61 +++++++++---------- .../src/RenderableWebEntityItem.h | 1 - .../entities/src/EntityItemProperties.cpp | 12 ++++ libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityPropertyFlags.h | 1 + .../entities/src/EntityScriptingInterface.h | 8 +-- libraries/entities/src/WebEntityItem.cpp | 17 ++++++ libraries/entities/src/WebEntityItem.h | 4 ++ libraries/networking/src/udt/PacketHeaders.h | 1 + .../system/libraries/entitySelectionTool.js | 1 - 12 files changed, 79 insertions(+), 41 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4d4d76172a..138d415515 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4314,7 +4314,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { buttons, event->modifiers()); if (compositor.getReticleVisible() || !isHMDMode() || !compositor.getReticleOverDesktop() || - !getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())).isNull()) { + getOverlays().getOverlayAtPoint(glm::vec2(transformedPos.x(), transformedPos.y())) != UNKNOWN_ENTITY_ID) { getEntities()->mouseMoveEvent(&mappedEvent); getOverlays().mouseMoveEvent(&mappedEvent); } @@ -5756,8 +5756,11 @@ void Application::setKeyboardFocusEntity(const QUuid& id) { return; } + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_VISIBLE; + desiredProperties += PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT; auto properties = entityScriptingInterface->getEntityProperties(id); - if (!properties.getLocked() && properties.getVisible()) { + if (properties.getVisible() && properties.getShowKeyboardFocusHighlight()) { auto entities = getEntities(); auto entityId = _keyboardFocusedEntity.get(); if (entities->wantsKeyboardFocus(entityId)) { diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index e55ebcc159..c677c3dbb5 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -740,7 +740,8 @@ bool Overlays::editOverlay(const QUuid& id, const QVariant& properties) { } auto entityScriptingInterface = DependencyManager::get(); - EntityItemProperties entityProperties = convertOverlayToEntityProperties(properties.toMap(), entityScriptingInterface->getEntityType(id), false, id); + auto propertyMap = properties.toMap(); + EntityItemProperties entityProperties = convertOverlayToEntityProperties(propertyMap, entityScriptingInterface->getEntityType(id), false, id); return !entityScriptingInterface->editEntity(id, entityProperties).isNull(); } @@ -766,7 +767,8 @@ bool Overlays::editOverlays(const QVariant& propertiesById) { } overlay->setProperties(properties.toMap()); } else { - entityScriptingInterface->editEntity(id, convertOverlayToEntityProperties(properties.toMap(), entityScriptingInterface->getEntityType(id), false, id)); + auto propertyMap = properties.toMap(); + entityScriptingInterface->editEntity(id, convertOverlayToEntityProperties(propertyMap, entityScriptingInterface->getEntityType(id), false, id)); } } diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 8d4ba3ea4e..4403237fb7 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -115,35 +115,39 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe } } - if (_color != entity->getColor()) { - return true; - } + if(resultWithReadLock([&] { + if (_color != entity->getColor()) { + return true; + } - if (_alpha != entity->getAlpha()) { - return true; - } + if (_alpha != entity->getAlpha()) { + return true; + } - if (_sourceURL != entity->getSourceUrl()) { - return true; - } + if (_sourceURL != entity->getSourceUrl()) { + return true; + } - if (_dpi != entity->getDPI()) { - return true; - } + if (_dpi != entity->getDPI()) { + return true; + } - if (_scriptURL != entity->getScriptURL()) { - return true; - } + if (_scriptURL != entity->getScriptURL()) { + return true; + } - if (_maxFPS != entity->getMaxFPS()) { - return true; - } + if (_maxFPS != entity->getMaxFPS()) { + return true; + } - if (_inputMode != entity->getInputMode()) { - return true; - } + if (_inputMode != entity->getInputMode()) { + return true; + } - if (_pulseProperties != entity->getPulseProperties()) { + if (_pulseProperties != entity->getPulseProperties()) { + return true; + } + })) { return true; } @@ -185,17 +189,14 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene ContentType currentContentType; withReadLock([&] { urlChanged = _sourceURL != newSourceURL; - currentContentType = _contentType; }); + currentContentType = _contentType; if (urlChanged) { - if (!_loading && (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent)) { + if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) { destroyWebSurface(); } - - withWriteLock([&] { - _contentType = newContentType; - }); + _contentType = newContentType; } } @@ -214,16 +215,14 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene // This work must be done on the main thread if (!_webSurface) { buildWebSurface(entity, newSourceURL); - _loading = true; } if (_webSurface) { if (_webSurface->getRootItem()) { - _loading = false; if (_contentType == ContentType::HtmlContent && urlChanged) { _webSurface->getRootItem()->setProperty(URL_PROPERTY, newSourceURL); - _sourceURL = newSourceURL; } + _sourceURL = newSourceURL; { auto scriptURL = entity->getScriptURL(); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index b97ad98502..e5eff5818b 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -77,7 +77,6 @@ private: }; static ContentType getContentType(const QString& urlString); ContentType _contentType { ContentType::NoContent }; - bool _loading { false }; QSharedPointer _webSurface { nullptr }; bool _cachedWebSurface { false }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 0c8396f405..fbc897d8ae 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -642,6 +642,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_SCRIPT_URL, scriptURL); CHECK_PROPERTY_CHANGE(PROP_MAX_FPS, maxFPS); CHECK_PROPERTY_CHANGE(PROP_INPUT_MODE, inputMode); + CHECK_PROPERTY_CHANGE(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, showKeyboardFocusHighlight); // Polyline CHECK_PROPERTY_CHANGE(PROP_LINE_POINTS, linePoints); @@ -1345,6 +1346,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} maxFPS=10 - The maximum update rate for the Web content, in frames/second. * @property {WebInputMode} inputMode="touch" - The user input mode to use. * @property {Entities.Pulse} pulse - The pulse-related properties. Deprecated. + * @property {boolean} showKeyboardFocusHighlight - Whether or not to show the keyboard focus highlight when this entity has focus. * @example * var METERS_TO_INCHES = 39.3701; * var entity = Entities.addEntity({ @@ -1764,6 +1766,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SCRIPT_URL, scriptURL); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_FPS, maxFPS); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_INPUT_MODE, inputMode, getInputModeAsString()); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, showKeyboardFocusHighlight); } // PolyVoxel only @@ -2131,6 +2134,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(scriptURL, QString, setScriptURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(maxFPS, uint8_t, setMaxFPS); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(inputMode, InputMode); + COPY_PROPERTY_FROM_QSCRIPTVALUE(showKeyboardFocusHighlight, bool, setShowKeyboardFocusHighlight); // Polyline COPY_PROPERTY_FROM_QSCRIPTVALUE(linePoints, qVectorVec3, setLinePoints); @@ -2409,6 +2413,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(scriptURL); COPY_PROPERTY_IF_CHANGED(maxFPS); COPY_PROPERTY_IF_CHANGED(inputMode); + COPY_PROPERTY_IF_CHANGED(showKeyboardFocusHighlight); // Polyline COPY_PROPERTY_IF_CHANGED(linePoints); @@ -2793,6 +2798,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_SCRIPT_URL, ScriptURL, scriptURL, QString); ADD_PROPERTY_TO_MAP(PROP_MAX_FPS, MaxFPS, maxFPS, uint8_t); ADD_PROPERTY_TO_MAP(PROP_INPUT_MODE, InputMode, inputMode, WebInputMode); + ADD_PROPERTY_TO_MAP(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, ShowKeyboardFocusHighlight, showKeyboardFocusHighlight, bool); // Polyline ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector); @@ -3201,6 +3207,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_SCRIPT_URL, properties.getScriptURL()); APPEND_ENTITY_PROPERTY(PROP_MAX_FPS, properties.getMaxFPS()); APPEND_ENTITY_PROPERTY(PROP_INPUT_MODE, (uint32_t)properties.getInputMode()); + APPEND_ENTITY_PROPERTY(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, properties.getShowKeyboardFocusHighlight()); } if (properties.getType() == EntityTypes::Line) { @@ -3661,6 +3668,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_URL, QString, setScriptURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_FPS, uint8_t, setMaxFPS); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_INPUT_MODE, WebInputMode, setInputMode); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, bool, setShowKeyboardFocusHighlight); } if (properties.getType() == EntityTypes::Line) { @@ -4035,6 +4043,7 @@ void EntityItemProperties::markAllChanged() { _scriptURLChanged = true; _maxFPSChanged = true; _inputModeChanged = true; + _showKeyboardFocusHighlightChanged = true; // Polyline _linePointsChanged = true; @@ -4686,6 +4695,9 @@ QList EntityItemProperties::listChangedProperties() { if (faceCameraChanged()) { out += "faceCamera"; } + if (showKeyboardFocusHighlightChanged()) { + out += "showKeyboardFocusHighlight"; + } // Shape if (shapeChanged()) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index dcba60b004..58fe63cf40 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -341,6 +341,7 @@ public: DEFINE_PROPERTY_REF(PROP_SCRIPT_URL, ScriptURL, scriptURL, QString, ""); DEFINE_PROPERTY_REF(PROP_MAX_FPS, MaxFPS, maxFPS, uint8_t, WebEntityItem::DEFAULT_MAX_FPS); DEFINE_PROPERTY_REF_ENUM(PROP_INPUT_MODE, InputMode, inputMode, WebInputMode, WebInputMode::TOUCH); + DEFINE_PROPERTY_REF(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, ShowKeyboardFocusHighlight, showKeyboardFocusHighlight, bool, true); // Polyline DEFINE_PROPERTY_REF(PROP_LINE_POINTS, LinePoints, linePoints, QVector, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index b11ecff5bb..5cf809e38e 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -296,6 +296,7 @@ enum EntityPropertyList { PROP_SCRIPT_URL = PROP_DERIVED_2, PROP_MAX_FPS = PROP_DERIVED_3, PROP_INPUT_MODE = PROP_DERIVED_4, + PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT = PROP_DERIVED_5, // Polyline PROP_LINE_POINTS = PROP_DERIVED_0, diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 6157d3663a..1853d0fa73 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -270,12 +270,12 @@ public slots: */ Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, const QString& entityHostTypeString) { entity::HostType entityHostType; - if (entityHostTypeString == "domain") { - entityHostType = entity::HostType::DOMAIN; + if (entityHostTypeString == "local") { + entityHostType = entity::HostType::LOCAL; } else if (entityHostTypeString == "avatar") { entityHostType = entity::HostType::AVATAR; - } else if (entityHostTypeString == "local") { - entityHostType = entity::HostType::LOCAL; + } else { + entityHostType = entity::HostType::DOMAIN; } return addEntityInternal(properties, entityHostType); } diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 21d8b876f0..51b78aaec7 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -54,6 +54,7 @@ EntityItemProperties WebEntityItem::getProperties(const EntityPropertyFlags& des COPY_ENTITY_PROPERTY_TO_PROPERTIES(scriptURL, getScriptURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxFPS, getMaxFPS); COPY_ENTITY_PROPERTY_TO_PROPERTIES(inputMode, getInputMode); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(showKeyboardFocusHighlight, getShowKeyboardFocusHighlight); return properties; } @@ -73,6 +74,7 @@ bool WebEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(scriptURL, setScriptURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxFPS, setMaxFPS); SET_ENTITY_PROPERTY_FROM_PROPERTIES(inputMode, setInputMode); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(showKeyboardFocusHighlight, setShowKeyboardFocusHighlight); if (somethingChanged) { bool wantDebug = false; @@ -111,6 +113,7 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i READ_ENTITY_PROPERTY(PROP_SCRIPT_URL, QString, setScriptURL); READ_ENTITY_PROPERTY(PROP_MAX_FPS, uint8_t, setMaxFPS); READ_ENTITY_PROPERTY(PROP_INPUT_MODE, WebInputMode, setInputMode); + READ_ENTITY_PROPERTY(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, bool, setShowKeyboardFocusHighlight); return bytesRead; } @@ -126,6 +129,7 @@ EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& pa requestedProperties += PROP_SCRIPT_URL; requestedProperties += PROP_MAX_FPS; requestedProperties += PROP_INPUT_MODE; + requestedProperties += PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT; return requestedProperties; } @@ -150,6 +154,7 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst APPEND_ENTITY_PROPERTY(PROP_SCRIPT_URL, getScriptURL()); APPEND_ENTITY_PROPERTY(PROP_MAX_FPS, getMaxFPS()); APPEND_ENTITY_PROPERTY(PROP_INPUT_MODE, (uint32_t)getInputMode()); + APPEND_ENTITY_PROPERTY(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, getShowKeyboardFocusHighlight()); } bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, @@ -298,6 +303,18 @@ WebInputMode WebEntityItem::getInputMode() const { }); } +void WebEntityItem::setShowKeyboardFocusHighlight(bool value) { + withWriteLock([&] { + _showKeyboardFocusHighlight = value; + }); +} + +bool WebEntityItem::getShowKeyboardFocusHighlight() const { + return resultWithReadLock([&] { + return _showKeyboardFocusHighlight; + }); +} + PulsePropertyGroup WebEntityItem::getPulseProperties() const { return resultWithReadLock([&] { return _pulseProperties; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index a0a2d65253..86b2377c90 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -77,6 +77,9 @@ public: void setInputMode(const WebInputMode& value); WebInputMode getInputMode() const; + bool getShowKeyboardFocusHighlight() const; + void setShowKeyboardFocusHighlight(bool value); + PulsePropertyGroup getPulseProperties() const; protected: @@ -89,6 +92,7 @@ protected: QString _scriptURL; uint8_t _maxFPS; WebInputMode _inputMode; + bool _showKeyboardFocusHighlight; }; #endif // hifi_WebEntityItem_h diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index d898c03597..0697fe8885 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -260,6 +260,7 @@ enum class EntityVersion : PacketVersion { MissingWebEntityProperties, PulseProperties, RingGizmoEntities, + ShowKeyboardFocusHighlight, // Add new versions above here NUM_PACKET_TYPE, diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index c0b28cbf9c..4cbc44bc2b 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1154,7 +1154,6 @@ SelectionDisplay = (function() { var result = testRayIntersect(pickRay, allOverlays); var pickedColor; var highlightNeeded = false; - print(JSON.stringify(result)); if (result.intersects) { switch (result.overlayID) { From a8dbe5e7619b605e5ebcd055fb5b684ca9630306 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 28 Jan 2019 21:10:24 -0800 Subject: [PATCH 020/139] working on build errors --- interface/src/Application.cpp | 2 ++ libraries/entities-renderer/src/RenderableWebEntityItem.cpp | 2 ++ libraries/entities/src/EntityItemProperties.cpp | 2 +- scripts/system/libraries/WebTablet.js | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 138d415515..6b71c51a6e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -617,6 +617,8 @@ public: switch (type) { case NestableType::Entity: return getEntityModelProvider(static_cast(uuid)); + case NestableType::Overlay: + return nullptr; case NestableType::Avatar: return getAvatarModelProvider(uuid); } diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 4403237fb7..ba136256cb 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -147,6 +147,8 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe if (_pulseProperties != entity->getPulseProperties()) { return true; } + + return false; })) { return true; } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index fbc897d8ae..9e087c3ac2 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1926,7 +1926,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool properties.setProperty("localEntity", convertScriptValue(engine, getEntityHostType() == entity::HostType::LOCAL)); } - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::FaceCamera) && _type != EntityTypes::PolyLine) { + if ((!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::FaceCamera)) && _type != EntityTypes::PolyLine) { properties.setProperty("faceCamera", convertScriptValue(engine, getBillboardMode() == BillboardMode::YAW)); } if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::IsFacingAvatar)) { diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index f29edd8ff9..4178cd4aec 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -196,7 +196,7 @@ WebTablet = function (url, width, dpi, hand, location, visible) { color: {red: 255, green: 255, blue: 255}, solid: true, innerRadius: 0.9, - ignoreIntersection: true, + ignorePickIntersection: true, alpha: 0.0, visible: visible, drawInFront: false, From 9aae9d13f6cc8fe128ad20fb7167ef6d00ca2dde Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 28 Jan 2019 22:19:31 -0800 Subject: [PATCH 021/139] fix tablet home button --- interface/src/devices/DdeFaceTracker.cpp | 4 -- interface/src/ui/overlays/Overlays.cpp | 26 +++++++++-- interface/src/ui/overlays/Overlays.h | 6 ++- scripts/system/libraries/WebTablet.js | 55 ++---------------------- scripts/system/libraries/utils.js | 3 +- 5 files changed, 31 insertions(+), 63 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index c123585afa..b9dc8326e8 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -615,10 +615,6 @@ void DdeFaceTracker::setEyeClosingThreshold(float eyeClosingThreshold) { static const int CALIBRATION_BILLBOARD_WIDTH = 300; static const int CALIBRATION_BILLBOARD_HEIGHT = 120; -static const int CALIBRATION_BILLBOARD_TOP_MARGIN = 30; -static const int CALIBRATION_BILLBOARD_LEFT_MARGIN = 30; -static const int CALIBRATION_BILLBOARD_FONT_SIZE = 16; -static const float CALIBRATION_BILLBOARD_ALPHA = 0.5f; static QString CALIBRATION_INSTRUCTION_MESSAGE = "Hold still to calibrate camera"; void DdeFaceTracker::calibrate() { diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index c677c3dbb5..13476e4841 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -397,6 +397,20 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove } overlayProps["rotation"] = quatToVariant(glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation); } + if (add || overlayProps.contains("localRotation")) { + glm::quat rotation; + { + auto iter = overlayProps.find("localRotation"); + if (iter != overlayProps.end()) { + rotation = quatFromVariant(iter.value()); + } else if (!add) { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_LOCAL_ROTATION; + rotation = DependencyManager::get()->getEntityProperties(id, desiredProperties).getLocalRotation(); + } + } + overlayProps["localRotation"] = quatToVariant(glm::angleAxis(-(float)M_PI_2, rotation * Vectors::RIGHT) * rotation); + } { RENAME_PROP(color, innerStartColor); @@ -536,8 +550,6 @@ QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemPropertie RENAME_PROP(position, point); RENAME_PROP(dimensions, scale); RENAME_PROP(dimensions, size); - RENAME_PROP(rotation, orientation); - RENAME_PROP(localRotation, localOrientation); RENAME_PROP(ignorePickIntersection, ignoreRayIntersection); { @@ -586,13 +598,17 @@ QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemPropertie RENAME_PROP(sourceUrl, url); RENAME_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "mouse" ? "Mouse" : "Touch"; }); } else if (type == "Gizmo") { - RENAME_PROP_CONVERT(dimensions, outerRadius, [](const QVariant& v) { return vec3FromVariant(v).x; }); + RENAME_PROP_CONVERT(dimensions, outerRadius, [](const QVariant& v) { return 2.0f * vec3FromVariant(v).x; }); RENAME_PROP(outerRadius, radius); RENAME_PROP_CONVERT(rotation, rotation, [](const QVariant& v) { glm::quat rot = quatFromVariant(v); return quatToVariant(glm::angleAxis((float)M_PI_2, rot * Vectors::RIGHT) * rot); }); + RENAME_PROP_CONVERT(localRotation, localRotation, [](const QVariant& v) { + glm::quat rot = quatFromVariant(v); + return quatToVariant(glm::angleAxis((float)M_PI_2, rot * Vectors::RIGHT) * rot); + }); GROUP_ENTITY_TO_OVERLAY_PROP(ring, startAngle, startAt); GROUP_ENTITY_TO_OVERLAY_PROP(ring, endAngle, endAt); @@ -638,6 +654,10 @@ QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemPropertie RENAME_PROP_CONVERT(glow, glow, [](const QVariant& v) { return v.toBool() ? 1.0f : 0.0f; }); } + // Do at the end, in case this type was rotated above + RENAME_PROP(rotation, orientation); + RENAME_PROP(localRotation, localOrientation); + return overlayProps; } diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 5db90fecf4..992431f3ed 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -358,8 +358,10 @@ public slots: * @param {boolean} [precisionPicking=false] - Unused; exists to match Entity API. * @param {Array.} [include=[]] - If not empty then the search is restricted to these overlays. * @param {Array.} [discard=[]] - Overlays to ignore during the search. - * @param {boolean} [visibleOnly=false] - Unused; exists to match Entity API. - * @param {boolean} [collidableOnly=false] - Unused; exists to match Entity API. + * @param {boolean} [visibleOnly=false] - If true then only entities that are + * {@link Entities.EntityProperties|visible} are searched. + * @param {boolean} [collideableOnly=false] - If true then only entities that are not + * {@link Entities.EntityProperties|collisionless} are searched. * @returns {Overlays.RayToOverlayIntersectionResult} The closest 3D overlay intersected by pickRay, taking * into account overlayIDsToInclude and overlayIDsToExclude if they're not empty. * @example * // Create a box and copy the following text into the entity's "Script URL" field. diff --git a/interface/src/scripting/SettingsScriptingInterface.h b/interface/src/scripting/SettingsScriptingInterface.h index 32d868bb24..e907e550f3 100644 --- a/interface/src/scripting/SettingsScriptingInterface.h +++ b/interface/src/scripting/SettingsScriptingInterface.h @@ -21,6 +21,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class SettingsScriptingInterface : public QObject { diff --git a/interface/src/scripting/WalletScriptingInterface.h b/interface/src/scripting/WalletScriptingInterface.h index 36ee021b29..005af7f558 100644 --- a/interface/src/scripting/WalletScriptingInterface.h +++ b/interface/src/scripting/WalletScriptingInterface.h @@ -34,6 +34,7 @@ public: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} walletStatus * @property {bool} limitedCommerce diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index c5e558eb3a..baff6444e1 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -31,6 +31,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} innerWidth - The width of the drawable area of the Interface window (i.e., without borders or other * chrome), in pixels. Read-only. diff --git a/interface/src/ui/AvatarInputs.h b/interface/src/ui/AvatarInputs.h index e67d35e59f..6569792807 100644 --- a/interface/src/ui/AvatarInputs.h +++ b/interface/src/ui/AvatarInputs.h @@ -29,6 +29,7 @@ class AvatarInputs : public QObject { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {boolean} cameraEnabled Read-only. * @property {boolean} cameraMuted Read-only. diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 8fc05775bd..77bdfd4ac1 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -42,6 +42,7 @@ private: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class Snapshot : public QObject, public Dependency { diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index ae608cfddb..5488da9115 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -27,6 +27,7 @@ private: \ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 208fc8d78d..14e30b3b22 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -87,6 +87,7 @@ public: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {Uuid} keyboardFocusOverlay - Get or set the {@link Overlays.OverlayType|web3d} overlay that has keyboard focus. * If no overlay has keyboard focus, get returns null; set to null or {@link Uuid|Uuid.NULL} to diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 2f8168625e..8d951a584d 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -50,6 +50,7 @@ Q_DECLARE_METATYPE(AnimationPointer) * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/animation/src/AnimationCacheScriptingInterface.h b/libraries/animation/src/AnimationCacheScriptingInterface.h index 1f5735dd0f..06db5ef352 100644 --- a/libraries/animation/src/AnimationCacheScriptingInterface.h +++ b/libraries/animation/src/AnimationCacheScriptingInterface.h @@ -30,6 +30,7 @@ class AnimationCacheScriptingInterface : public ScriptableResourceCache, public * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-assignment-client * * @property {number} numTotal - Total number of total resources. Read-only. diff --git a/libraries/audio-client/src/AudioIOStats.h b/libraries/audio-client/src/AudioIOStats.h index 45fcf365da..ffd7163586 100644 --- a/libraries/audio-client/src/AudioIOStats.h +++ b/libraries/audio-client/src/AudioIOStats.h @@ -44,6 +44,7 @@ class AudioStreamStatsInterface : public QObject { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} lossRate Read-only. * @property {number} lossCount Read-only. @@ -192,6 +193,7 @@ class AudioStatsInterface : public QObject { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} pingMs Read-only. * @property {number} inputReadMsMax Read-only. diff --git a/libraries/audio/src/AudioEffectOptions.h b/libraries/audio/src/AudioEffectOptions.h index 4bc7957142..e090832510 100644 --- a/libraries/audio/src/AudioEffectOptions.h +++ b/libraries/audio/src/AudioEffectOptions.h @@ -25,6 +25,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h index 836e28d582..da165c778a 100644 --- a/libraries/audio/src/Sound.h +++ b/libraries/audio/src/Sound.h @@ -132,6 +132,7 @@ typedef QSharedPointer SharedSoundPointer; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/audio/src/SoundCacheScriptingInterface.h b/libraries/audio/src/SoundCacheScriptingInterface.h index c985e8c211..9caa7a8066 100644 --- a/libraries/audio/src/SoundCacheScriptingInterface.h +++ b/libraries/audio/src/SoundCacheScriptingInterface.h @@ -30,6 +30,7 @@ class SoundCacheScriptingInterface : public ScriptableResourceCache, public Depe * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index 5bc7357dd7..845e19f6c3 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -57,6 +57,7 @@ class UserInputMapper; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ /**jsdoc diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index 804709ebfa..eb610af78a 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -39,6 +39,7 @@ class ScriptingInterface; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ // TODO migrate functionality to a RouteBuilder class and make the proxy defer to that diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index e25d30109f..9c7d01082c 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -178,6 +178,7 @@ private: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {boolean} allowMouseCapture * @property {number} depth diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 0e96cb2d25..7950025ff1 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -109,6 +109,7 @@ public: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h index 1ec60c4244..163e317ffa 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h @@ -27,6 +27,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class GraphicsScriptingInterface : public QObject, public QScriptable, public Dependency { diff --git a/libraries/midi/src/Midi.h b/libraries/midi/src/Midi.h index e5c44c6b7e..081a44f7b6 100644 --- a/libraries/midi/src/Midi.h +++ b/libraries/midi/src/Midi.h @@ -25,6 +25,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class Midi : public QObject, public Dependency { diff --git a/libraries/model-networking/src/model-networking/ModelCacheScriptingInterface.h b/libraries/model-networking/src/model-networking/ModelCacheScriptingInterface.h index 5ac7ac1e50..16532fafc3 100644 --- a/libraries/model-networking/src/model-networking/ModelCacheScriptingInterface.h +++ b/libraries/model-networking/src/model-networking/ModelCacheScriptingInterface.h @@ -30,6 +30,7 @@ class ModelCacheScriptingInterface : public ScriptableResourceCache, public Depe * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} numTotal - Total number of total resources. Read-only. * @property {number} numCached - Total number of cached resource. Read-only. diff --git a/libraries/model-networking/src/model-networking/TextureCacheScriptingInterface.h b/libraries/model-networking/src/model-networking/TextureCacheScriptingInterface.h index 4120840759..1cc4f4f948 100644 --- a/libraries/model-networking/src/model-networking/TextureCacheScriptingInterface.h +++ b/libraries/model-networking/src/model-networking/TextureCacheScriptingInterface.h @@ -30,6 +30,7 @@ class TextureCacheScriptingInterface : public ScriptableResourceCache, public De * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} numTotal - Total number of total resources. Read-only. * @property {number} numCached - Total number of cached resource. Read-only. diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 450b71023c..3b95923634 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -43,6 +43,7 @@ const QString GET_PLACE = "/api/v1/places/%1"; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-assignment-client * * @property {Uuid} domainID - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid|Uuid.NULL} if you're not diff --git a/libraries/networking/src/MessagesClient.h b/libraries/networking/src/MessagesClient.h index f2ccfe33f4..255487f0bb 100644 --- a/libraries/networking/src/MessagesClient.h +++ b/libraries/networking/src/MessagesClient.h @@ -40,6 +40,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client */ diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 275684f73e..cbe54e4e00 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -95,6 +95,7 @@ class ScriptableResource : public QObject { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/networking/src/ResourceScriptingInterface.h b/libraries/networking/src/ResourceScriptingInterface.h index cc3f12f990..5f81537e99 100644 --- a/libraries/networking/src/ResourceScriptingInterface.h +++ b/libraries/networking/src/ResourceScriptingInterface.h @@ -22,6 +22,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client */ diff --git a/libraries/plugins/src/plugins/SteamClientPlugin.h b/libraries/plugins/src/plugins/SteamClientPlugin.h index fc1b85c572..2124d16b5e 100644 --- a/libraries/plugins/src/plugins/SteamClientPlugin.h +++ b/libraries/plugins/src/plugins/SteamClientPlugin.h @@ -45,6 +45,7 @@ public: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {boolean} running - Read-only. */ diff --git a/libraries/pointers/src/Pick.h b/libraries/pointers/src/Pick.h index 857a72caa8..1a9d3fd32c 100644 --- a/libraries/pointers/src/Pick.h +++ b/libraries/pointers/src/Pick.h @@ -68,6 +68,7 @@ public: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} Ray Ray picks intersect a ray with the nearest object in front of them, along a given direction. * @property {number} Stylus Stylus picks provide "tapping" functionality on/into flat surfaces. diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index 0e05a563b2..07d681ca88 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -30,6 +30,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client */ diff --git a/libraries/script-engine/src/FileScriptingInterface.h b/libraries/script-engine/src/FileScriptingInterface.h index 7b833399e0..859f343ec5 100644 --- a/libraries/script-engine/src/FileScriptingInterface.h +++ b/libraries/script-engine/src/FileScriptingInterface.h @@ -21,6 +21,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client */ diff --git a/libraries/script-engine/src/Mat4.h b/libraries/script-engine/src/Mat4.h index 288a101234..7ad77b9b24 100644 --- a/libraries/script-engine/src/Mat4.h +++ b/libraries/script-engine/src/Mat4.h @@ -26,6 +26,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client */ diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index 76b7ac45e3..d24db786d0 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -40,6 +40,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/script-engine/src/RecordingScriptingInterface.h b/libraries/script-engine/src/RecordingScriptingInterface.h index c4d576351f..6a058feea5 100644 --- a/libraries/script-engine/src/RecordingScriptingInterface.h +++ b/libraries/script-engine/src/RecordingScriptingInterface.h @@ -28,6 +28,7 @@ class QScriptValue; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-assignment-client */ class RecordingScriptingInterface : public QObject, public Dependency { diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index da42cf2df3..a78fa44641 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -115,6 +115,7 @@ namespace SceneScripting { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {string} backgroundMode * @property {Scene.Stage.KeyLight} keyLight @@ -178,6 +179,7 @@ namespace SceneScripting { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {boolean} shouldRenderAvatars * @property {boolean} shouldRenderEntities diff --git a/libraries/script-engine/src/ScriptAudioInjector.h b/libraries/script-engine/src/ScriptAudioInjector.h index 2c88d618e1..c7fb2f8a9a 100644 --- a/libraries/script-engine/src/ScriptAudioInjector.h +++ b/libraries/script-engine/src/ScriptAudioInjector.h @@ -23,6 +23,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index fa7a8e1114..5d33a6a061 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -588,6 +588,7 @@ static void scriptableResourceFromScriptValue(const QScriptValue& value, Scripta * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 8753010089..48fb4f0b83 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -104,6 +104,7 @@ public: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 4d5964e462..4db150fce5 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -32,6 +32,7 @@ class ScriptEngine; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {string} debugScriptUrl * @property {string} defaultScriptsPath diff --git a/libraries/script-engine/src/ScriptUUID.h b/libraries/script-engine/src/ScriptUUID.h index 45e6ec0ad1..7387cefeff 100644 --- a/libraries/script-engine/src/ScriptUUID.h +++ b/libraries/script-engine/src/ScriptUUID.h @@ -27,6 +27,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/script-engine/src/ScriptsModel.h b/libraries/script-engine/src/ScriptsModel.h index 2466347baa..adfb15affc 100644 --- a/libraries/script-engine/src/ScriptsModel.h +++ b/libraries/script-engine/src/ScriptsModel.h @@ -71,6 +71,7 @@ public: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class ScriptsModel : public QAbstractItemModel { Q_OBJECT diff --git a/libraries/script-engine/src/ScriptsModelFilter.h b/libraries/script-engine/src/ScriptsModelFilter.h index 05a76334bb..81ae4c1226 100644 --- a/libraries/script-engine/src/ScriptsModelFilter.h +++ b/libraries/script-engine/src/ScriptsModelFilter.h @@ -23,6 +23,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class ScriptsModelFilter : public QSortFilterProxyModel { Q_OBJECT diff --git a/libraries/script-engine/src/UsersScriptingInterface.h b/libraries/script-engine/src/UsersScriptingInterface.h index e80d38239f..57de205066 100644 --- a/libraries/script-engine/src/UsersScriptingInterface.h +++ b/libraries/script-engine/src/UsersScriptingInterface.h @@ -21,6 +21,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-assignment-client * * @property {boolean} canKick - true if the domain server allows the node or avatar to kick (ban) avatars, diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h index fe903c07e2..7887938004 100644 --- a/libraries/script-engine/src/Vec3.h +++ b/libraries/script-engine/src/Vec3.h @@ -31,6 +31,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/shared/src/DebugDraw.h b/libraries/shared/src/DebugDraw.h index 81acbf554c..785e549c03 100644 --- a/libraries/shared/src/DebugDraw.h +++ b/libraries/shared/src/DebugDraw.h @@ -28,6 +28,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client */ diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h index 2247f4cc6a..0096cb6c90 100644 --- a/libraries/shared/src/PathUtils.h +++ b/libraries/shared/src/PathUtils.h @@ -25,6 +25,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @deprecated The Paths API is deprecated. Use {@link Script.resolvePath} and {@link Script.resourcesPath} instead. * @readonly diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 9d5bca6b9f..729816cf82 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -645,6 +645,7 @@ using MeshPointer = std::shared_ptr; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index d14489b92c..31e6228bb9 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -43,6 +43,7 @@ class Camera : public QObject { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {Vec3} position - The position of the camera. You can set this value only when the camera is in independent * mode. diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index da9b95a274..486b28b6b9 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -196,6 +196,7 @@ public: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} cpuRunTime - Read-only. * @property {boolean} enabled diff --git a/libraries/ui/src/InteractiveWindow.h b/libraries/ui/src/InteractiveWindow.h index a25d559557..af4e7e29ab 100644 --- a/libraries/ui/src/InteractiveWindow.h +++ b/libraries/ui/src/InteractiveWindow.h @@ -45,6 +45,7 @@ using namespace InteractiveWindowEnums; * * @hifi-interface * @hifi-client-en + * @hifi-avatar * * @property {string} title * @property {Vec2} position diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index a719593df2..137cffde94 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -36,6 +36,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @property {boolean} navigationFocused * @property {boolean} navigationFocusDisabled */ diff --git a/libraries/ui/src/QmlWebWindowClass.h b/libraries/ui/src/QmlWebWindowClass.h index e3aea22e3d..770f8ec965 100644 --- a/libraries/ui/src/QmlWebWindowClass.h +++ b/libraries/ui/src/QmlWebWindowClass.h @@ -17,6 +17,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {string} url - Read-only. * @property {Vec2} position diff --git a/libraries/ui/src/QmlWindowClass.h b/libraries/ui/src/QmlWindowClass.h index 18ee1fedd5..d84ea8ffcc 100644 --- a/libraries/ui/src/QmlWindowClass.h +++ b/libraries/ui/src/QmlWindowClass.h @@ -25,6 +25,7 @@ class QScriptContext; * * @hifi-interface * @hifi-client-en + * @hifi-avatar * * @property {Vec2} position * @property {Vec2} size diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index 9821ad1263..1a6df83d93 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -43,12 +43,14 @@ class OffscreenQmlSurface; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ /**jsdoc * @namespace tabletInterface * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @deprecated This API is deprecated and will be removed. Use {@link Tablet} instead. */ @@ -208,6 +210,7 @@ Q_DECLARE_METATYPE(TabletButtonsProxyModel*); * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {string} name - Name of this tablet. Read-only. * @property {boolean} toolbarMode - Used to transition this tablet into and out of toolbar mode. @@ -456,6 +459,7 @@ Q_DECLARE_METATYPE(TabletProxy*); * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {Uuid} uuid - Uniquely identifies this button. Read-only. * @property {TabletButtonProxy.ButtonProperties} properties diff --git a/libraries/ui/src/ui/ToolbarScriptingInterface.h b/libraries/ui/src/ui/ToolbarScriptingInterface.h index 777eeba9dd..409ea28fdc 100644 --- a/libraries/ui/src/ui/ToolbarScriptingInterface.h +++ b/libraries/ui/src/ui/ToolbarScriptingInterface.h @@ -24,6 +24,7 @@ class QQuickItem; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class ToolbarButtonProxy : public QmlWrapper { Q_OBJECT @@ -83,6 +84,7 @@ Q_DECLARE_METATYPE(ToolbarButtonProxy*); * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class ToolbarProxy : public QmlWrapper { Q_OBJECT @@ -136,6 +138,7 @@ Q_DECLARE_METATYPE(ToolbarProxy*); * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class ToolbarScriptingInterface : public QObject, public Dependency { Q_OBJECT diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index 76f33e2c73..a525093965 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -107,6 +107,9 @@ exports.handlers = { if (e.doclet.hifiClientEntity) { rows.push("Client Entity Scripts"); } + if (e.doclet.hifiAvatar) { + rows.push("Avatar Scripts"); + } if (e.doclet.hifiServerEntity) { rows.push("Server Entity Scripts"); } @@ -140,6 +143,14 @@ exports.defineTags = function (dictionary) { } }); + // @hifi-avatar-script + dictionary.defineTag("hifi-avatar", { + onTagged: function (doclet, tag) { + doclet.hifiAvatar = true; + } + }); + + // @hifi-client-entity dictionary.defineTag("hifi-client-entity", { onTagged: function (doclet, tag) { From 8e0ff9b4de691d9f0b3e737df554344a2714cfbc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 12 Feb 2019 11:50:09 +1300 Subject: [PATCH 071/139] Fix up some "Client Entity" JSDoc API classifications --- libraries/ui/src/InteractiveWindow.h | 2 +- libraries/ui/src/QmlWindowClass.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/ui/src/InteractiveWindow.h b/libraries/ui/src/InteractiveWindow.h index af4e7e29ab..22a3df7530 100644 --- a/libraries/ui/src/InteractiveWindow.h +++ b/libraries/ui/src/InteractiveWindow.h @@ -44,7 +44,7 @@ using namespace InteractiveWindowEnums; * @class InteractiveWindow * * @hifi-interface - * @hifi-client-en + * @hifi-client-entity * @hifi-avatar * * @property {string} title diff --git a/libraries/ui/src/QmlWindowClass.h b/libraries/ui/src/QmlWindowClass.h index d84ea8ffcc..8aad9a8b36 100644 --- a/libraries/ui/src/QmlWindowClass.h +++ b/libraries/ui/src/QmlWindowClass.h @@ -24,7 +24,7 @@ class QScriptContext; * @param {OverlayWindow.Properties} [properties=null] * * @hifi-interface - * @hifi-client-en + * @hifi-client-entity * @hifi-avatar * * @property {Vec2} position From f53ccf7363b79397612ece27db0485a7d67e8c7b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 11 Feb 2019 13:45:36 -0800 Subject: [PATCH 072/139] fix create, working on mini tablet --- interface/src/ui/overlays/Overlays.cpp | 10 ++++- .../src/RenderableWebEntityItem.cpp | 2 +- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 6 +-- scripts/system/libraries/WebTablet.js | 10 +++-- scripts/system/miniTablet.js | 41 ++++++++++++------- 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 8a0f3cfd8b..e1708c14fe 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -581,7 +581,15 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove { auto iter = overlayProps.find("dimensions"); if (iter != overlayProps.end()) { - dimensions = vec3FromVariant(iter.value()); + bool valid = false; + dimensions = vec3FromVariant(iter.value(), valid); + if (!valid) { + dimensions = glm::vec3(vec2FromVariant(iter.value()), 0.0f); + } + } else if (!add) { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_DIMENSIONS; + dimensions = DependencyManager::get()->getEntityProperties(id, desiredProperties).getDimensions(); } } diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index ba136256cb..164adae8ce 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -452,5 +452,5 @@ QObject* WebEntityRenderer::getEventHandler() { } void WebEntityRenderer::emitScriptEvent(const QVariant& message) { - QMetaObject::invokeMethod(this, "scriptEventReceived", Q_ARG(QVariant, message)); + emit scriptEventReceived(message); } \ No newline at end of file diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 71bb65509f..5f3957fe34 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -716,11 +716,7 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n } void OffscreenQmlSurface::emitScriptEvent(const QVariant& message) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "emitScriptEvent", Qt::QueuedConnection, Q_ARG(QVariant, message)); - } else { - emit scriptEventReceived(message); - } + emit scriptEventReceived(message); } void OffscreenQmlSurface::emitWebEvent(const QVariant& message) { diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index a578ed0d97..c0e3178521 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -23,7 +23,6 @@ var SENSOR_TO_ROOM_MATRIX = -2; var CAMERA_MATRIX = -7; var ROT_Y_180 = {x: 0.0, y: 1.0, z: 0, w: 0}; var ROT_LANDSCAPE = {x: 1.0, y: 1.0, z: 0, w: 0}; -var ROT_LANDSCAPE_WINDOW = {x: 0.0, y: 0.0, z: 0.0, w: 0}; var TABLET_TEXTURE_RESOLUTION = { x: 480, y: 706 }; var INCHES_TO_METERS = 1 / 39.3701; @@ -286,16 +285,19 @@ WebTablet.prototype.setLandscape = function(newLandscapeValue) { this.landscape = newLandscapeValue; var cameraOrientation = Quat.cancelOutRollAndPitch(Camera.orientation); - Overlays.editOverlay(this.tabletEntityID, - { rotation: Quat.multiply(cameraOrientation, this.landscape ? ROT_LANDSCAPE : ROT_Y_180) }); + var tabletRotation = Quat.multiply(cameraOrientation, this.landscape ? ROT_LANDSCAPE : ROT_Y_180); + Overlays.editOverlay(this.tabletEntityID, { + rotation: tabletRotation + }); var tabletWidth = getTabletWidthFromSettings() * MyAvatar.sensorToWorldScale; var tabletScaleFactor = tabletWidth / TABLET_NATURAL_DIMENSIONS.x; var tabletHeight = TABLET_NATURAL_DIMENSIONS.y * tabletScaleFactor; var screenWidth = 0.9275 * tabletWidth; var screenHeight = 0.8983 * tabletHeight; + var screenRotation = Quat.angleAxis(180, Vec3.UP); Overlays.editOverlay(this.webOverlayID, { - rotation: Quat.multiply(cameraOrientation, ROT_LANDSCAPE_WINDOW), + localRotation: this.landscape ? Quat.multiply(screenRotation, Quat.angleAxis(-90, Vec3.FRONT)) : screenRotation, dimensions: {x: this.landscape ? screenHeight : screenWidth, y: this.landscape ? screenWidth : screenHeight, z: 0.1} }); }; diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index 780dacf85e..12550c9d9c 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -114,7 +114,7 @@ uiHand = LEFT_HAND, miniUIOverlay = null, MINI_UI_HTML = Script.resolvePath("./html/miniTablet.html"), - MINI_UI_DIMENSIONS = { x: 0.059, y: 0.0865 }, + MINI_UI_DIMENSIONS = { x: 0.059, y: 0.0865, z: 0.01 }, MINI_UI_WIDTH_PIXELS = 150, METERS_TO_INCHES = 39.3701, MINI_UI_DPI = MINI_UI_WIDTH_PIXELS / (MINI_UI_DIMENSIONS.x * METERS_TO_INCHES), @@ -172,18 +172,22 @@ function updateMutedStatus() { var isMuted = Audio.muted; - miniOverlayObject.emitScriptEvent(JSON.stringify({ - type: MUTE_MESSAGE, - on: isMuted, - icon: isMuted ? MUTE_ON_ICON : MUTE_OFF_ICON - })); + if (miniOverlayObject) { + miniOverlayObject.emitScriptEvent(JSON.stringify({ + type: MUTE_MESSAGE, + on: isMuted, + icon: isMuted ? MUTE_ON_ICON : MUTE_OFF_ICON + })); + } } function setGotoIcon() { - miniOverlayObject.emitScriptEvent(JSON.stringify({ - type: GOTO_MESSAGE, - icon: GOTO_ICON - })); + if (miniOverlayObject) { + miniOverlayObject.emitScriptEvent(JSON.stringify({ + type: GOTO_MESSAGE, + icon: GOTO_ICON + })); + } } function onWebEventReceived(data) { @@ -452,7 +456,7 @@ solid: true, grabbable: true, showKeyboardFocusHighlight: false, - displayInFront: true, + drawInFront: true, visible: false }); miniUIOverlay = Overlays.addOverlay("web3d", { @@ -465,14 +469,11 @@ alpha: 0, // Hide overlay while its content is being created. grabbable: false, showKeyboardFocusHighlight: false, - displayInFront: true, + drawInFront: true, visible: false }); miniUIOverlayEnabled = false; // This and alpha = 0 hides overlay while its content is being created. - - miniOverlayObject = Overlays.getOverlayObject(miniUIOverlay); - miniOverlayObject.webEventReceived.connect(onWebEventReceived); } function destroy() { @@ -978,6 +979,16 @@ } function updateState() { + if (!ui.miniOverlayObject) { + // Keep trying to connect the event bridge until we succeed + ui.miniOverlayObject = Overlays.getOverlayObject(ui.miniUIOverlay); + if (ui.miniOverlayObject) { + ui.miniOverlayObject.webEventReceived.connect(ui.onWebEventReceived); + ui.updateMutedStatus(); + ui.setGotoIcon(); + } + } + if (STATE_MACHINE[STATE_STRINGS[miniState]].update) { STATE_MACHINE[STATE_STRINGS[miniState]].update(); } From 96f32a9f7229f5be58cf3701cf83c10572af843e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 11 Feb 2019 15:17:32 -0800 Subject: [PATCH 073/139] fix keyboard focus thing --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1501b71dea..6307470f7f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1891,7 +1891,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto keyboard = DependencyManager::get(); if (getEntities()->wantsKeyboardFocus(id)) { setKeyboardFocusEntity(id); - } else if (!keyboard->getKeyIDs().contains(id)) { // FIXME: this is a hack to make the keyboard work for now, since the keys would otherwise steal focus + } else if (!keyboard->containsID(id)) { // FIXME: this is a hack to make the keyboard work for now, since the keys would otherwise steal focus setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); } } From 16b48046c64c60466f116d5d8976b7df34db2321 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 11 Feb 2019 15:27:30 -0800 Subject: [PATCH 074/139] Fix not being able to type text into particle url field --- scripts/system/html/js/entityProperties.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index ee95312fa4..14a0031f1f 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -2328,7 +2328,7 @@ function createTextureProperty(property, elProperty) { elInput.setAttribute("id", elementID); elInput.setAttribute("type", "text"); - let imageLoad = _.debounce(function (url) { + let imageLoad = function(url) { if (url.slice(0, 5).toLowerCase() === "atp:/") { elImage.src = ""; elImage.style.display = "none"; @@ -2348,15 +2348,12 @@ function createTextureProperty(property, elProperty) { elDiv.classList.remove("no-preview"); elDiv.classList.add("no-texture"); } - }, IMAGE_DEBOUNCE_TIMEOUT); - elInput.imageLoad = imageLoad; - elInput.oninput = function (event) { - // Add throttle - let url = event.target.value; - imageLoad(url); - updateProperty(property.name, url, property.isParticleProperty) }; - elInput.onchange = elInput.oninput; + elInput.imageLoad = imageLoad; + elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); + elInput.addEventListener('change', function(ev) { + imageLoad(ev.target.value); + }); elProperty.appendChild(elInput); elProperty.appendChild(elDiv); From a9767e4c22b78425c6907083288db0f688f316fa Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 11 Feb 2019 15:46:29 -0800 Subject: [PATCH 075/139] working on mini tablet --- scripts/system/html/js/miniTablet.js | 8 +++++--- scripts/system/miniTablet.js | 20 +++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/scripts/system/html/js/miniTablet.js b/scripts/system/html/js/miniTablet.js index c48201cef5..6bc75161b3 100644 --- a/scripts/system/html/js/miniTablet.js +++ b/scripts/system/html/js/miniTablet.js @@ -61,6 +61,11 @@ } switch (message.type) { + case READY_MESSAGE: + EventBridge.emitWebEvent(JSON.stringify({ + type: READY_MESSAGE + })); + break; case MUTE_MESSAGE: muteImage.src = message.icon; break; @@ -114,9 +119,6 @@ function connectEventBridge() { EventBridge.scriptEventReceived.connect(onScriptEventReceived); - EventBridge.emitWebEvent(JSON.stringify({ - type: READY_MESSAGE - })); } function disconnectEventBridge() { diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index 12550c9d9c..e99c2631d9 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -124,6 +124,7 @@ miniUIOverlayEnabled = false, MINI_UI_OVERLAY_ENABLED_DELAY = 500, miniOverlayObject = null, + isReady = false, // Button icons. MUTE_ON_ICON = Script.resourcesPath() + "icons/tablet-icons/mic-mute-a.svg", @@ -203,6 +204,7 @@ switch (message.type) { case READY_MESSAGE: // Send initial button statuses. + isReady = true; updateMutedStatus(); setGotoIcon(); break; @@ -979,13 +981,17 @@ } function updateState() { - if (!ui.miniOverlayObject) { - // Keep trying to connect the event bridge until we succeed - ui.miniOverlayObject = Overlays.getOverlayObject(ui.miniUIOverlay); - if (ui.miniOverlayObject) { - ui.miniOverlayObject.webEventReceived.connect(ui.onWebEventReceived); - ui.updateMutedStatus(); - ui.setGotoIcon(); + if (!ui.isReady) { + if (!ui.miniOverlayObject) { + // Keep trying to connect the event bridge until we succeed + ui.miniOverlayObject = Overlays.getOverlayObject(ui.miniUIOverlay); + if (ui.miniOverlayObject) { + ui.miniOverlayObject.webEventReceived.connect(ui.onWebEventReceived); + } + } else { + ui.miniOverlayObject.emitScriptEvent(JSON.stringify({ + type: READY_MESSAGE + })); } } From d96b0534ab539aab1be085f2edf8c06d6b0e3480 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 11 Feb 2019 16:12:13 -0800 Subject: [PATCH 076/139] fix resource texture crash --- .../src/model-networking/TextureCache.cpp | 12 ++++++++---- .../src/model-networking/TextureCache.h | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index c7235337c2..d4cf7e6ce9 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -333,10 +333,14 @@ QSharedPointer TextureCache::createResourceCopy(const QSharedPointer>(); -NetworkTexture::NetworkTexture(const QUrl& url) : +NetworkTexture::NetworkTexture(const QUrl& url, bool resourceTexture) : Resource(url), _maxNumPixels(100) { + if (resourceTexture) { + _textureSource = std::make_shared(url); + _loaded = true; + } } NetworkTexture::NetworkTexture(const NetworkTexture& other) : @@ -1244,11 +1248,11 @@ void ImageReader::read() { Q_ARG(int, texture->getHeight())); } -NetworkTexturePointer TextureCache::getResourceTexture(QUrl resourceTextureUrl) { +NetworkTexturePointer TextureCache::getResourceTexture(const QUrl& resourceTextureUrl) { gpu::TexturePointer texture; if (resourceTextureUrl == SPECTATOR_CAMERA_FRAME_URL) { if (!_spectatorCameraNetworkTexture) { - _spectatorCameraNetworkTexture.reset(new NetworkTexture(resourceTextureUrl)); + _spectatorCameraNetworkTexture.reset(new NetworkTexture(resourceTextureUrl, true)); } if (!_spectatorCameraFramebuffer) { getSpectatorCameraFramebuffer(); // initialize frame buffer @@ -1259,7 +1263,7 @@ NetworkTexturePointer TextureCache::getResourceTexture(QUrl resourceTextureUrl) // FIXME: Generalize this, DRY up this code if (resourceTextureUrl == HMD_PREVIEW_FRAME_URL) { if (!_hmdPreviewNetworkTexture) { - _hmdPreviewNetworkTexture.reset(new NetworkTexture(resourceTextureUrl)); + _hmdPreviewNetworkTexture.reset(new NetworkTexture(resourceTextureUrl, true)); } if (_hmdPreviewFramebuffer) { texture = _hmdPreviewFramebuffer->getRenderBuffer(0); diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index d744d060b6..cdedc64ea5 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -45,7 +45,7 @@ class NetworkTexture : public Resource, public Texture { Q_OBJECT public: - NetworkTexture(const QUrl& url); + NetworkTexture(const QUrl& url, bool resourceTexture = false); NetworkTexture(const NetworkTexture& other); ~NetworkTexture() override; @@ -183,7 +183,7 @@ public: gpu::TexturePointer getTextureByHash(const std::string& hash); gpu::TexturePointer cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture); - NetworkTexturePointer getResourceTexture(QUrl resourceTextureUrl); + NetworkTexturePointer getResourceTexture(const QUrl& resourceTextureUrl); const gpu::FramebufferPointer& getHmdPreviewFramebuffer(int width, int height); const gpu::FramebufferPointer& getSpectatorCameraFramebuffer(); const gpu::FramebufferPointer& getSpectatorCameraFramebuffer(int width, int height); From b896e2577b4e87857290733c7b09a862f83a02e0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 11 Feb 2019 16:17:06 -0800 Subject: [PATCH 077/139] Fix QML file selectors --- libraries/ui/src/ui/OffscreenQmlSurface.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 7fd60a0b1d..8e938ce25b 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -238,10 +238,11 @@ void OffscreenQmlSurface::clearFocusItem() { void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) { Parent::initializeEngine(engine); - auto fileSelector = getFileSelector(); - if (fileSelector) { - fileSelector->setExtraSelectors(FileUtils::getFileSelectors()); + auto fileSelector = QQmlFileSelector::get(engine); + if (!fileSelector) { + fileSelector = new QQmlFileSelector(engine); } + fileSelector->setExtraSelectors(FileUtils::getFileSelectors()); static std::once_flag once; std::call_once(once, [] { From 50dd865bdc763aeaafb9d68fc4e268c2f804c193 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Mon, 11 Feb 2019 16:48:34 -0800 Subject: [PATCH 078/139] fix spatially nestable parent overwrite --- interface/src/avatar/OtherAvatar.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index a3950c8e96..8ad9c6b121 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -489,6 +489,9 @@ void OtherAvatar::handleChangedAvatarEntityData() { bool success = true; if (entity) { QUuid oldParentID = entity->getParentID(); + const QUuid NULL_ID = QUuid("{00000000-0000-0000-0000-000000000005}"); + entity->setParentID(NULL_ID); + entity->setParentID(oldParentID); if (entityTree->updateEntity(entityID, properties)) { entity->updateLastEditedFromRemote(); } else { From 73296aa986cd4a92ee99ed218b92dfc6c82ac8c3 Mon Sep 17 00:00:00 2001 From: Simon Walton <36682372+SimonWalton-HiFi@users.noreply.github.com> Date: Mon, 11 Feb 2019 16:59:18 -0800 Subject: [PATCH 079/139] Change update rate to 1 Hz --- interface/resources/qml/hifi/Pal.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 7c22b98dc2..1c190a2b79 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -43,7 +43,7 @@ Rectangle { property bool currentlyEditingDisplayName: false property bool punctuationMode: false; property double loudSortTime: 0.0; - readonly property double kLOUD_SORT_PERIOD_MS: 100.0; + readonly property double kLOUD_SORT_PERIOD_MS: 1000.0; HifiConstants { id: hifi; } RootHttpRequest { id: http; } From 9ad783135cde25eb5d5b49eae73f2c1e6b8975d4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 11 Feb 2019 19:42:05 -0800 Subject: [PATCH 080/139] Bringing back brownBis to just msaa support --- interface/src/graphics/GraphicsEngine.cpp | 1 + .../display-plugins/OpenGLDisplayPlugin.cpp | 23 ++++++------- .../src/display-plugins/SrgbToLinear.slf | 29 ++-------------- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 4 +-- libraries/gl/src/gl/GLHelpers.cpp | 1 - libraries/gpu/src/gpu/State.h | 1 + .../render-utils/src/RenderForwardTask.cpp | 33 +++++++------------ .../render-utils/src/RenderForwardTask.h | 19 +---------- .../render-utils/src/ToneMappingEffect.cpp | 11 ++----- .../render-utils/src/ToneMappingEffect.h | 14 ++------ libraries/render-utils/src/toneMapping.slf | 10 ++---- plugins/oculus/src/OculusDisplayPlugin.cpp | 19 ++++------- 12 files changed, 43 insertions(+), 122 deletions(-) diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index bff778bd62..c2137d3d97 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -66,6 +66,7 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { } void GraphicsEngine::initializeRender(bool disableDeferred) { + // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; _renderEngine->addJob("UpdateScene"); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index ffd51cd61f..18d961d7bd 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -354,14 +354,14 @@ void OpenGLDisplayPlugin::customizeContext() { if ((image.width() > 0) && (image.height() > 0)) { cursorData.texture = gpu::Texture::createStrict( - gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::SRGBA), + gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA), image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); cursorData.texture->setSource("cursor texture"); auto usage = gpu::Texture::Usage::Builder().withColor().withAlpha(); cursorData.texture->setUsage(usage.build()); - cursorData.texture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::SRGBA)); + cursorData.texture->setStoredMipFormat(gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); cursorData.texture->assignStoredMip(0, image.byteCount(), image.constBits()); cursorData.texture->setAutoGenerateMips(true); } @@ -382,13 +382,12 @@ void OpenGLDisplayPlugin::customizeContext() { { gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::DrawTexture); _simplePipeline = gpu::Pipeline::create(program, scissorState); - // _hudPipeline = gpu::Pipeline::create(program, blendState); + _hudPipeline = gpu::Pipeline::create(program, blendState); } { gpu::ShaderPointer program = gpu::Shader::createProgram(shader::display_plugins::program::SrgbToLinear); _presentPipeline = gpu::Pipeline::create(program, scissorState); - _hudPipeline = gpu::Pipeline::create(program, blendState); } { @@ -515,8 +514,7 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur batch.setViewportTransform(viewport); batch.setResourceTexture(0, texture); #ifndef USE_GLES - batch.setPipeline(_simplePipeline); - // batch.setPipeline(_presentPipeline); + batch.setPipeline(_presentPipeline); #else batch.setPipeline(_simplePipeline); #endif @@ -607,7 +605,7 @@ void OpenGLDisplayPlugin::compositePointer() { render([&](gpu::Batch& batch) { batch.enableStereo(false); batch.setProjectionTransform(mat4()); - // batch.setFramebuffer(_compositeFramebuffer); + batch.setFramebuffer(_compositeFramebuffer); batch.setPipeline(_cursorPipeline); batch.setResourceTexture(0, cursorData.texture); batch.resetViewTransform(); @@ -643,7 +641,7 @@ void OpenGLDisplayPlugin::compositeLayers() { { PROFILE_RANGE_EX(render_detail, "compositeScene", 0xff0077ff, (uint64_t)presentCount()) - // compositeScene(); + compositeScene(); } #ifdef HIFI_ENABLE_NSIGHT_DEBUG @@ -657,10 +655,10 @@ void OpenGLDisplayPlugin::compositeLayers() { }); } - /* { + { PROFILE_RANGE_EX(render_detail, "compositeExtra", 0xff0077ff, (uint64_t)presentCount()) compositeExtra(); - }*/ + } // Draw the pointer last so it's on top of everything auto compositorHelper = DependencyManager::get(); @@ -675,8 +673,7 @@ void OpenGLDisplayPlugin::internalPresent() { // Note: _displayTexture must currently be the same size as the display. uvec2 dims = _displayTexture ? uvec2(_displayTexture->getDimensions()) : getSurfacePixels(); auto viewport = ivec4(uvec2(0), dims); - // renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, viewport); - renderFromTexture(batch, _displayTexture ? _displayTexture : _currentFrame->framebuffer->getRenderBuffer(0), viewport, viewport); + renderFromTexture(batch, _displayTexture ? _displayTexture : _compositeFramebuffer->getRenderBuffer(0), viewport, viewport); }); swapBuffers(); _presentRate.increment(); @@ -885,7 +882,7 @@ OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { void OpenGLDisplayPlugin::updateCompositeFramebuffer() { auto renderSize = glm::uvec2(getRecommendedRenderSize()); if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { - _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_SRGBA_32, renderSize.x, renderSize.y)); + _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y)); } } diff --git a/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf b/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf index f9b333b3db..8b324c81a5 100644 --- a/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf +++ b/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf @@ -17,31 +17,6 @@ vec3 colorToLinearRGB(vec3 srgb) { } void main(void) { - vec4 fetched = texture(colorMap, varTexCoord0); - //outFragColor = fetched; - outFragColor.a = fetched.a; - outFragColor.rgb = pow(fetched.rgb, vec3(2.2)); - - /* int vSize = 300; - int hSize = 400; - - if (gl_FragCoord.y < vSize) { - finalColor *= pow(2.0, 0.1); - } - else if (gl_FragCoord.y > 2 * vSize) { - finalColor *= pow(2.0, -0.1); - } - else { - finalColor; - } - - if (gl_FragCoord.x 2 * hSize) { - outFragColor.rgb = pow(finalColor, vec3(1.0 / 2.2)); - } - else { - outFragColor.rgb = finalColor; - }*/ - // outFragColor.rgb = sqrt(finalColor); + outFragColor.a = 1.0; + outFragColor.rgb = colorToLinearRGB(texture(colorMap, varTexCoord0).rgb); } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 0a953f142d..321bcc3fd2 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -260,9 +260,7 @@ void HmdDisplayPlugin::internalPresent() { viewport.z *= 2; } - // renderFromTexture(batch, _compositeFramebuffer->getRenderBuffer(0), viewport, scissor, fbo); - renderFromTexture(batch, _currentFrame->framebuffer->getRenderBuffer(0), viewport, scissor, fbo); - + renderFromTexture(batch, _compositeFramebuffer->getRenderBuffer(0), viewport, scissor, fbo); }); swapBuffers(); diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index 5f6e305b92..879ea7c5e2 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -99,7 +99,6 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() { #else format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); #endif - format.setColorSpace(QSurfaceFormat::sRGBColorSpace); if (gl::Context::enableDebugLogger()) { format.setOption(QSurfaceFormat::DebugContext); diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 8354f940c8..abe0cd7731 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -278,6 +278,7 @@ public: FillMode fillMode{ FILL_FACE }; CullMode cullMode{ CULL_NONE }; ColorMask colorWriteMask{ WRITE_ALL }; + Flags flags; }; diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 01da7f73df..ffdbc1c4b1 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -118,22 +118,22 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend const auto transparentInputs = DrawForward::Inputs(transparents, lightingModel).asVarying(); task.addJob("DrawTransparents", transparentInputs, shapePlumber); - /* { // Debug the bounds of the rendered items, still look at the zbuffer + { // Debug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); task.addJob("DrawBounds", opaques); task.addJob("DrawTransparentBounds", transparents); - task.addJob("DrawZones", zones);*/ + task.addJob("DrawZones", zones); const auto debugZoneInputs = DebugZoneLighting::Inputs(deferredFrameTransform, lightFrame, backgroundFrame).asVarying(); task.addJob("DrawZoneStack", debugZoneInputs); - // } + } // Lighting Buffer ready for tone mapping // Forward rendering on GLES doesn't support tonemapping to and from the same FBO, so we specify // the output FBO as null, which causes the tonemapping to target the blit framebuffer - // const auto toneMappingInputs = ToneMappingDeferred::Inputs(framebuffer, static_cast(nullptr) ).asVarying(); - // task.addJob("ToneMapping", toneMappingInputs); + const auto toneMappingInputs = ToneMappingDeferred::Inputs(framebuffer, static_cast(nullptr) ).asVarying(); + task.addJob("ToneMapping", toneMappingInputs); // Layered Overlays // Composite the HUD and HUD overlays @@ -141,40 +141,29 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend // Disable blit because we do tonemapping and compositing directly to the blit FBO // Blit! - task.addJob("Blit", framebuffer); -} - -void PrepareFramebuffer::configure(const PrepareFramebuffer::Config& config) { - _numSamples = config.getNumSamples(); + // task.addJob("Blit", framebuffer); } void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); // Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering - if (_framebuffer && (_framebuffer->getSize() != frameSize || _framebuffer->getNumSamples() != _numSamples)) { + if (_framebuffer && _framebuffer->getSize() != frameSize) { _framebuffer.reset(); } if (!_framebuffer) { _framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward")); - - int numSamples = _numSamples; auto colorFormat = gpu::Element::COLOR_SRGBA_32; - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); - /* auto colorTexture = - gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); - _framebuffer->setRenderBuffer(0, colorTexture);*/ + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); auto colorTexture = - gpu::Texture::createRenderBufferMultisample(colorFormat, frameSize.x, frameSize.y, numSamples, defaultSampler); + gpu::Texture::createRenderBuffer(colorFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); _framebuffer->setRenderBuffer(0, colorTexture); + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format - /* auto depthTexture = - gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); - _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat);*/ auto depthTexture = - gpu::Texture::createRenderBufferMultisample(depthFormat, frameSize.x, frameSize.y, numSamples, defaultSampler); + gpu::Texture::createRenderBuffer(depthFormat, frameSize.x, frameSize.y, gpu::Texture::SINGLE_MIP, defaultSampler); _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); } diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index 909e09452c..e6a6008319 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -27,33 +27,16 @@ public: void build(JobModel& task, const render::Varying& input, render::Varying& output); }; -class PrepareFramebufferConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples NOTIFY dirty) -public: - int getNumSamples() const { return numSamples; } - void setNumSamples(int num) { numSamples = num; emit dirty(); } - -signals: - void dirty(); - -protected: - int numSamples{ 8 }; -}; - class PrepareFramebuffer { public: using Inputs = gpu::FramebufferPointer; - using Config = PrepareFramebufferConfig; - using JobModel = render::Job::ModelO; + using JobModel = render::Job::ModelO; - void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer); private: gpu::FramebufferPointer _framebuffer; - int _numSamples { 8 }; }; class PrepareForward { diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index c631ae4383..64a2adb5d4 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -40,13 +40,6 @@ void ToneMappingEffect::setExposure(float exposure) { } } -void ToneMappingEffect::setColorFilter(const glm::vec3& colorFilter) { - auto& params = _parametersBuffer.get(); - if (params._colorFilter != colorFilter) { - _parametersBuffer.edit()._colorFilter = colorFilter; - } -} - void ToneMappingEffect::setToneCurve(ToneCurve curve) { auto& params = _parametersBuffer.get(); if (params._toneCurve != curve) { @@ -69,6 +62,9 @@ void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& ligh batch.enableStereo(false); batch.setFramebuffer(destinationFramebuffer); + // FIXME: Generate the Luminosity map + //batch.generateTextureMips(lightingBuffer); + batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); @@ -84,7 +80,6 @@ void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& ligh void ToneMappingDeferred::configure(const Config& config) { _toneMappingEffect.setExposure(config.exposure); - _toneMappingEffect.setColorFilter(toGlm(config.colorFilter)); _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)config.curve); } diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index 163805ae91..69694b13f5 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -31,9 +31,6 @@ public: void setExposure(float exposure); float getExposure() const { return _parametersBuffer.get()._exposure; } - void setColorFilter(const glm::vec3& colorFilter); - glm::vec3 getColorFIlter() const { return _parametersBuffer.get()._colorFilter; } - // Different tone curve available enum ToneCurve { None = 0, @@ -54,10 +51,8 @@ private: float _exposure = 0.0f; float _twoPowExposure = 1.0f; glm::vec2 spareA; - glm::vec3 _colorFilter{ 1.0f }; - float spareB; - int _toneCurve = None; - glm::vec3 spareC; + int _toneCurve = Gamma22; + glm::vec3 spareB; Parameters() {} }; @@ -70,19 +65,16 @@ private: class ToneMappingConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(float exposure MEMBER exposure WRITE setExposure); - Q_PROPERTY(QColor colorFilter MEMBER colorFilter WRITE setColorFilter); Q_PROPERTY(int curve MEMBER curve WRITE setCurve); public: ToneMappingConfig() : render::Job::Config(true) {} void setExposure(float newExposure) { exposure = newExposure; emit dirty(); } - void setColorFilter(const QColor& newColorFilter) { colorFilter = newColorFilter; emit dirty(); } void setCurve(int newCurve) { curve = std::max((int)ToneMappingEffect::None, std::min((int)ToneMappingEffect::Filmic, newCurve)); emit dirty(); } float exposure{ 0.0f }; - QColor colorFilter { 255, 255, 255 }; - int curve{ ToneMappingEffect::None }; + int curve{ ToneMappingEffect::Gamma22 }; signals: void dirty(); }; diff --git a/libraries/render-utils/src/toneMapping.slf b/libraries/render-utils/src/toneMapping.slf index 3b13425816..3fe53d9be1 100644 --- a/libraries/render-utils/src/toneMapping.slf +++ b/libraries/render-utils/src/toneMapping.slf @@ -17,7 +17,6 @@ struct ToneMappingParams { vec4 _exp_2powExp_s0_s1; - vec4 _colorFilter_s0; ivec4 _toneCurve_s0_s1_s2; }; @@ -33,14 +32,11 @@ LAYOUT(binding=RENDER_UTILS_BUFFER_TM_PARAMS) uniform toneMappingParamsBuffer { float getTwoPowExposure() { return params._exp_2powExp_s0_s1.y; } -vec3 getColorFilter() { - return params._colorFilter_s0.xyz; -} int getToneCurve() { return params._toneCurve_s0_s1_s2.x; } -LAYOUT(binding = RENDER_UTILS_TEXTURE_TM_COLOR) uniform sampler2D colorMap; +LAYOUT(binding=RENDER_UTILS_TEXTURE_TM_COLOR) uniform sampler2D colorMap; layout(location=0) in vec2 varTexCoord0; layout(location=0) out vec4 outFragColor; @@ -49,7 +45,7 @@ void main(void) { vec4 fragColorRaw = texture(colorMap, varTexCoord0); vec3 fragColor = fragColorRaw.xyz; - vec3 srcColor = fragColor * getColorFilter() * getTwoPowExposure(); + vec3 srcColor = fragColor * getTwoPowExposure(); int toneCurve = getToneCurve(); vec3 tonedColor = srcColor; @@ -58,7 +54,7 @@ void main(void) { tonedColor = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); } else if (toneCurve == ToneCurveReinhard) { tonedColor = srcColor/(1.0 + srcColor); - // tonedColor = pow(tonedColor, vec3(INV_GAMMA_22)); + tonedColor = pow(tonedColor, vec3(INV_GAMMA_22)); } else if (toneCurve == ToneCurveGamma22) { tonedColor = pow(srcColor, vec3(INV_GAMMA_22)); } // else None toned = src diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index a34f068665..d3703c348e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -150,26 +150,21 @@ void OculusDisplayPlugin::hmdPresent() { // Manually bind the texture to the FBO // FIXME we should have a way of wrapping raw GL ids in GPU objects without // taking ownership of the object - auto srcfbo = getGLBackend()->getFramebufferID(_currentFrame->framebuffer); - auto dstfbo = getGLBackend()->getFramebufferID(_outputFramebuffer); - glNamedFramebufferTexture(dstfbo, GL_COLOR_ATTACHMENT0, curTexId, 0); + auto fbo = getGLBackend()->getFramebufferID(_outputFramebuffer); + glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, curTexId, 0); auto viewport = ivec4(uvec2(), _outputFramebuffer->getSize()); - /* render([&](gpu::Batch& batch) { + render([&](gpu::Batch& batch) { batch.enableStereo(false); batch.setFramebuffer(_outputFramebuffer); batch.setViewportTransform(ivec4(uvec2(), _outputFramebuffer->getSize())); batch.setStateScissorRect(ivec4(uvec2(), _outputFramebuffer->getSize())); batch.resetViewTransform(); batch.setProjectionTransform(mat4()); - // batch.setPipeline(_presentPipeline); - batch.setPipeline(_simplePipeline); - // batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0)); - batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0)); + batch.setPipeline(_presentPipeline); + batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0)); batch.draw(gpu::TRIANGLE_STRIP, 4); - });*/ - glBlitNamedFramebuffer(srcfbo, dstfbo, viewport.x, viewport.y, viewport.z, viewport.w, viewport.x, viewport.y, - viewport.z, viewport.w, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glNamedFramebufferTexture(dstfbo, GL_COLOR_ATTACHMENT0, 0, 0); + }); + glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, 0, 0); } { From afb6c838ebfb5fde0d8a1a95201b9af9ff0d5f35 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 11 Feb 2019 20:13:37 -0800 Subject: [PATCH 081/139] REverting all the changes from the brown branch not used --- .../display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp | 2 +- libraries/gl/src/gl/GLHelpers.cpp | 1 - plugins/oculus/src/OculusDisplayPlugin.cpp | 1 - scripts/developer/utilities/lib/plotperf/Color.qml | 1 - scripts/developer/utilities/render/deferredLighting.qml | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 18d961d7bd..6c59dbd861 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -542,7 +542,7 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur batch.resetViewTransform(); batch.setViewportTransform(copyFboRect); batch.setStateScissorRect(copyFboRect); - // batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, {0.0f, 0.0f, 0.0f, 1.0f}); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, {0.0f, 0.0f, 0.0f, 1.0f}); batch.blit(fbo, sourceRect, copyFbo, copyRect); } } diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index 879ea7c5e2..2c02fdca03 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -99,7 +99,6 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() { #else format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); #endif - if (gl::Context::enableDebugLogger()) { format.setOption(QSurfaceFormat::DebugContext); } diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index d3703c348e..a34e647a5e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -152,7 +152,6 @@ void OculusDisplayPlugin::hmdPresent() { // taking ownership of the object auto fbo = getGLBackend()->getFramebufferID(_outputFramebuffer); glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, curTexId, 0); - auto viewport = ivec4(uvec2(), _outputFramebuffer->getSize()); render([&](gpu::Batch& batch) { batch.enableStereo(false); batch.setFramebuffer(_outputFramebuffer); diff --git a/scripts/developer/utilities/lib/plotperf/Color.qml b/scripts/developer/utilities/lib/plotperf/Color.qml index 64a3980947..1ad72fe2e6 100644 --- a/scripts/developer/utilities/lib/plotperf/Color.qml +++ b/scripts/developer/utilities/lib/plotperf/Color.qml @@ -23,7 +23,6 @@ Item { height: 24 property var _color: Qt.rgba(1.0, 1.0, 1.0, 1.0 ); - property var _lcolor: Qt.vec4(1.0, 1.0, 1.0, 1.0 ); property var zoneWidth: width / 3; property var hoveredOn: 0.0; property var sliderHeight: height / 2; diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index d3cc7adca3..6d98e96780 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -14,7 +14,6 @@ import QtQuick.Layouts 1.3 import stylesUit 1.0 import controlsUit 1.0 as HifiControls import "configSlider" -import "../lib/plotperf" Rectangle { HifiConstants { id: hifi;} From 0c2c581c646b8620433752529b8532986a76c1b9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 11 Feb 2019 22:52:35 -0800 Subject: [PATCH 082/139] Add the gles backend MS texture ad framebuffer support --- .../src/gpu/gles/GLESBackendOutput.cpp | 4 ++ .../src/gpu/gles/GLESBackendTexture.cpp | 44 ++++++++++++------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp b/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp index 90ce8c853a..36b37083cb 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp @@ -130,6 +130,8 @@ public: } #endif + } else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) { + glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[unit], GL_TEXTURE_2D_MULTISAMPLE, gltexture->_texture, 0); } else { glFramebufferTextureLayer(GL_FRAMEBUFFER, colorAttachments[unit], gltexture->_texture, 0, b._subresource); @@ -162,6 +164,8 @@ public: if (gltexture) { if (gltexture->_target == GL_TEXTURE_2D) { glFramebufferTexture2D(GL_FRAMEBUFFER, attachement, GL_TEXTURE_2D, gltexture->_texture, 0); + } else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) { + glFramebufferTexture2D(GL_FRAMEBUFFER, attachement, GL_TEXTURE_2D_MULTISAMPLE, gltexture->_texture, 0); } else { glFramebufferTextureLayer(GL_FRAMEBUFFER, attachement, gltexture->_texture, 0, _gpuObject.getDepthStencilBufferSubresource()); diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackendTexture.cpp b/libraries/gpu-gles/src/gpu/gles/GLESBackendTexture.cpp index 23dc271af9..4b2d4d09e6 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackendTexture.cpp +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackendTexture.cpp @@ -272,28 +272,40 @@ void GLESFixedAllocationTexture::allocateStorage() const { const GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat()); const auto numMips = _gpuObject.getNumMips(); const auto numSlices = _gpuObject.getNumSlices(); + const auto numSamples = _gpuObject.getNumSamples(); // glTextureStorage2D(_id, mips, texelFormat.internalFormat, dimensions.x, dimensions.y); - for (GLint level = 0; level < numMips; level++) { - Vec3u dimensions = _gpuObject.evalMipDimensions(level); - for (GLenum target : getFaceTargets(_target)) { - if (texelFormat.isCompressed()) { - auto size = getCompressedImageSize(dimensions.x, dimensions.y, texelFormat.internalFormat); - if (!_gpuObject.isArray()) { - glCompressedTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, size, nullptr); + if (!_gpuObject.isMultisample()) { + for (GLint level = 0; level < numMips; level++) { + Vec3u dimensions = _gpuObject.evalMipDimensions(level); + for (GLenum target : getFaceTargets(_target)) { + if (texelFormat.isCompressed()) { + auto size = getCompressedImageSize(dimensions.x, dimensions.y, texelFormat.internalFormat); + if (!_gpuObject.isArray()) { + glCompressedTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, size, nullptr); + } else { + glCompressedTexImage3D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, numSlices, 0, size * numSlices, nullptr); + } } else { - glCompressedTexImage3D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, numSlices, 0, size * numSlices, nullptr); - } - } else { - if (!_gpuObject.isArray()) { - glTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, - texelFormat.type, nullptr); - } else { - glTexImage3D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, numSlices, 0, - texelFormat.format, texelFormat.type, nullptr); + if (!_gpuObject.isArray()) { + glTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, + texelFormat.type, nullptr); + } else { + glTexImage3D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, numSlices, 0, + texelFormat.format, texelFormat.type, nullptr); + } } } } + } else { + const auto dimensions = _gpuObject.getDimensions(); + if (!_gpuObject.isArray()) { + glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, + texelFormat.internalFormat, dimensions.x, dimensions.y, + GL_FALSE); + } else { + // NOT SUPPORTED (yet) + } } glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, 0); From 6225d973572c3adf74bba3459a606daf2422b35b Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 12 Feb 2019 09:06:04 -0800 Subject: [PATCH 083/139] Check for adb and python when needed. Look for adb and python in PATH. --- tools/nitpick/src/AdbInterface.cpp | 38 +++++++++++++++++ tools/nitpick/src/AdbInterface.h | 30 +++++++++++++ tools/nitpick/src/Nitpick.cpp | 2 +- tools/nitpick/src/Nitpick.h | 4 -- tools/nitpick/src/PathUtils.cpp | 31 ++++++++++++++ tools/nitpick/src/PathUtils.h | 20 +++++++++ tools/nitpick/src/PythonInterface.cpp | 25 +++++------ tools/nitpick/src/PythonInterface.h | 2 - tools/nitpick/src/Test.cpp | 30 ++++++++++--- tools/nitpick/src/Test.h | 4 +- tools/nitpick/src/TestRailInterface.cpp | 2 +- tools/nitpick/src/TestRunnerMobile.cpp | 57 +++++++++++-------------- tools/nitpick/src/TestRunnerMobile.h | 3 ++ tools/nitpick/ui/Nitpick.ui | 8 ++-- 14 files changed, 189 insertions(+), 67 deletions(-) create mode 100644 tools/nitpick/src/AdbInterface.cpp create mode 100644 tools/nitpick/src/AdbInterface.h create mode 100644 tools/nitpick/src/PathUtils.cpp create mode 100644 tools/nitpick/src/PathUtils.h diff --git a/tools/nitpick/src/AdbInterface.cpp b/tools/nitpick/src/AdbInterface.cpp new file mode 100644 index 0000000000..82ef1446e3 --- /dev/null +++ b/tools/nitpick/src/AdbInterface.cpp @@ -0,0 +1,38 @@ +// +// AdbInterface.cpp +// +// Created by Nissim Hadar on Feb 11, 2019. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "AdbInterface.h" +#include + +#include +#include + +QString AdbInterface::getAdbCommand() { +#ifdef Q_OS_WIN + if (_adbCommand.isNull()) { + QString adbPath = PathUtils::getPathToExecutable("adb.exe"); + if (!adbPath.isNull()) { + _adbCommand = adbPath + _adbExe; + } else { + QMessageBox::critical(0, "python.exe not found", + "Please verify that pyton.exe is in the PATH"); + exit(-1); + } + } +#elif defined Q_OS_MAC + _adbCommand = "/usr/local/bin/adb"; + if (!QFile::exists(_adbCommand)) { + QMessageBox::critical(0, "adb not found", + "adb not found at " + _adbCommand); + exit(-1); + } +#endif + + return _adbCommand; +} diff --git a/tools/nitpick/src/AdbInterface.h b/tools/nitpick/src/AdbInterface.h new file mode 100644 index 0000000000..c1ce84c019 --- /dev/null +++ b/tools/nitpick/src/AdbInterface.h @@ -0,0 +1,30 @@ +// +// AdbInterface.h +// +// Created by Nissim Hadar on Feb 11, 2019. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_AdbInterface_h +#define hifi_AdbInterface_h + +#include + +class AdbInterface { +public: + QString getAdbCommand(); + +private: +#ifdef Q_OS_WIN + const QString _adbExe{ "adb.exe" }; +#else + // Both Mac and Linux use "python" + const QString _adbExe{ "adb" }; +#endif + + QString _adbCommand; +}; + +#endif // hifi_AdbInterface_h diff --git a/tools/nitpick/src/Nitpick.cpp b/tools/nitpick/src/Nitpick.cpp index fa53730ce0..3a799ce3c2 100644 --- a/tools/nitpick/src/Nitpick.cpp +++ b/tools/nitpick/src/Nitpick.cpp @@ -40,7 +40,7 @@ Nitpick::Nitpick(QWidget* parent) : QMainWindow(parent) { _ui.plainTextEdit->setReadOnly(true); - setWindowTitle("Nitpick - v2.1.0"); + setWindowTitle("Nitpick - v2.1.1"); } Nitpick::~Nitpick() { diff --git a/tools/nitpick/src/Nitpick.h b/tools/nitpick/src/Nitpick.h index 29726be3bd..36ec7e534b 100644 --- a/tools/nitpick/src/Nitpick.h +++ b/tools/nitpick/src/Nitpick.h @@ -21,8 +21,6 @@ #include "TestRunnerDesktop.h" #include "TestRunnerMobile.h" -#include "AWSInterface.h" - class Nitpick : public QMainWindow { Q_OBJECT @@ -112,8 +110,6 @@ private: TestRunnerDesktop* _testRunnerDesktop{ nullptr }; TestRunnerMobile* _testRunnerMobile{ nullptr }; - AWSInterface _awsInterface; - std::vector _downloaders; // local storage for parameters - folder to store downloaded files in, and a list of their names diff --git a/tools/nitpick/src/PathUtils.cpp b/tools/nitpick/src/PathUtils.cpp new file mode 100644 index 0000000000..711570d568 --- /dev/null +++ b/tools/nitpick/src/PathUtils.cpp @@ -0,0 +1,31 @@ +// +// PathUtils.h +// +// Created by Nissim Hadar on 11 Feb 2019. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "PathUtils.h" + +#include +#include +#include + +QString PathUtils::getPathToExecutable(const QString& executableName) { + QString path = QProcessEnvironment::systemEnvironment().value("PATH"); + + QStringList pathLocations = path.replace('\\', '/').split(';'); + + foreach (QString pathLocation, pathLocations) { + if (pathLocation[pathLocation.length() - 1] != '/') { + pathLocation += '/'; + } + if (QFile::exists(pathLocation + executableName)) { + return pathLocation; + } + } + + return QString(); +} diff --git a/tools/nitpick/src/PathUtils.h b/tools/nitpick/src/PathUtils.h new file mode 100644 index 0000000000..01f6906ee1 --- /dev/null +++ b/tools/nitpick/src/PathUtils.h @@ -0,0 +1,20 @@ +// +// PathUtils.h +// +// Created by Nissim Hadar on 11 Feb 2019. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_PathUtils_h +#define hifi_PathUtils_h + +#include + +class PathUtils { +public: + static QString getPathToExecutable(const QString& executableName); +}; + +#endif \ No newline at end of file diff --git a/tools/nitpick/src/PythonInterface.cpp b/tools/nitpick/src/PythonInterface.cpp index 9e2fec005f..dcf4ecc682 100644 --- a/tools/nitpick/src/PythonInterface.cpp +++ b/tools/nitpick/src/PythonInterface.cpp @@ -8,36 +8,31 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "PythonInterface.h" +#include #include #include -#include -PythonInterface::PythonInterface() { +QString PythonInterface::getPythonCommand() { #ifdef Q_OS_WIN - if (QProcessEnvironment::systemEnvironment().contains("PYTHON_PATH")) { - QString pythonPath = QProcessEnvironment::systemEnvironment().value("PYTHON_PATH"); - if (!QFile::exists(pythonPath + "/" + _pythonExe)) { - QMessageBox::critical(0, _pythonExe, QString("Python executable not found in ") + pythonPath); + if (_pythonCommand.isNull()) { + QString pythonPath = PathUtils::getPathToExecutable("python.exe"); + if (!pythonPath.isNull()) { + _pythonCommand = pythonPath + _pythonExe; + } else { + QMessageBox::critical(0, "python.exe not found", + "Please verify that pyton.exe is in the PATH"); exit(-1); } - - _pythonCommand = pythonPath + "/" + _pythonExe; - } else { - QMessageBox::critical(0, "PYTHON_PATH not defined", - "Please set PYTHON_PATH to directory containing the Python executable"); - exit(-1); } #elif defined Q_OS_MAC _pythonCommand = "/usr/local/bin/python3"; if (!QFile::exists(_pythonCommand)) { QMessageBox::critical(0, "python not found", - "python3 not found at " + _pythonCommand); + "python3 not found at " + _pythonCommand); exit(-1); } #endif -} -QString PythonInterface::getPythonCommand() { return _pythonCommand; } diff --git a/tools/nitpick/src/PythonInterface.h b/tools/nitpick/src/PythonInterface.h index 947b359037..7972d55cce 100644 --- a/tools/nitpick/src/PythonInterface.h +++ b/tools/nitpick/src/PythonInterface.h @@ -14,8 +14,6 @@ class PythonInterface { public: - PythonInterface(); - QString getPythonCommand(); private: diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp index 20d5ad89a6..f618118289 100644 --- a/tools/nitpick/src/Test.cpp +++ b/tools/nitpick/src/Test.cpp @@ -24,7 +24,7 @@ extern Nitpick* nitpick; #include -Test::Test(QProgressBar* progressBar, QCheckBox* checkBoxInteractiveMode) { +Test::Test(QProgressBar* progressBar, QCheckBox* checkBoxInteractiveMode) : _awsInterface(NULL) { _progressBar = progressBar; _checkBoxInteractiveMode = checkBoxInteractiveMode; @@ -966,11 +966,15 @@ void Test::createTestRailTestCases() { return; } + if (!_testRailInterface) { + _testRailInterface = new TestRailInterface; + } + if (_testRailCreateMode == PYTHON) { - _testRailInterface.createTestSuitePython(_testDirectory, outputDirectory, nitpick->getSelectedUser(), + _testRailInterface->createTestSuitePython(_testDirectory, outputDirectory, nitpick->getSelectedUser(), nitpick->getSelectedBranch()); } else { - _testRailInterface.createTestSuiteXML(_testDirectory, outputDirectory, nitpick->getSelectedUser(), + _testRailInterface->createTestSuiteXML(_testDirectory, outputDirectory, nitpick->getSelectedUser(), nitpick->getSelectedBranch()); } } @@ -983,7 +987,12 @@ void Test::createTestRailRun() { return; } - _testRailInterface.createTestRailRun(outputDirectory); + + if (!_testRailInterface) { + _testRailInterface = new TestRailInterface; + } + + _testRailInterface->createTestRailRun(outputDirectory); } void Test::updateTestRailRunResult() { @@ -999,7 +1008,12 @@ void Test::updateTestRailRunResult() { return; } - _testRailInterface.updateTestRailRunResults(testResults, tempDirectory); + + if (!_testRailInterface) { + _testRailInterface = new TestRailInterface; + } + + _testRailInterface->updateTestRailRunResults(testResults, tempDirectory); } QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { @@ -1088,5 +1102,9 @@ void Test::createWebPage(QCheckBox* updateAWSCheckBox, QLineEdit* urlLineEdit) { return; } - _awsInterface.createWebPageFromResults(testResults, workingDirectory, updateAWSCheckBox, urlLineEdit); + if (!_awsInterface) { + _awsInterface = new AWSInterface; + } + + _awsInterface->createWebPageFromResults(testResults, workingDirectory, updateAWSCheckBox, urlLineEdit); } \ No newline at end of file diff --git a/tools/nitpick/src/Test.h b/tools/nitpick/src/Test.h index 842e4bdb48..166c71688d 100644 --- a/tools/nitpick/src/Test.h +++ b/tools/nitpick/src/Test.h @@ -159,10 +159,10 @@ private: bool _exitWhenComplete{ false }; - TestRailInterface _testRailInterface; + TestRailInterface* _testRailInterface; TestRailCreateMode _testRailCreateMode { PYTHON }; - AWSInterface _awsInterface; + AWSInterface* _awsInterface; }; #endif // hifi_test_h \ No newline at end of file diff --git a/tools/nitpick/src/TestRailInterface.cpp b/tools/nitpick/src/TestRailInterface.cpp index 1d7aa0a32f..6ed13a72b6 100644 --- a/tools/nitpick/src/TestRailInterface.cpp +++ b/tools/nitpick/src/TestRailInterface.cpp @@ -20,7 +20,7 @@ #include #include -TestRailInterface::TestRailInterface() { +TestRailInterface::TestRailInterface() : _pythonInterface(NULL) { _testRailTestCasesSelectorWindow.setURL("https://highfidelity.testrail.net"); _testRailTestCasesSelectorWindow.setUser("@highfidelity.io"); diff --git a/tools/nitpick/src/TestRunnerMobile.cpp b/tools/nitpick/src/TestRunnerMobile.cpp index e1c82854f4..3f44a610f8 100644 --- a/tools/nitpick/src/TestRunnerMobile.cpp +++ b/tools/nitpick/src/TestRunnerMobile.cpp @@ -30,7 +30,7 @@ TestRunnerMobile::TestRunnerMobile( QLabel* statusLabel, QObject* parent -) : QObject(parent) +) : QObject(parent), _adbInterface(NULL) { _workingFolderLabel = workingFolderLabel; _connectDeviceButton = connectDeviceButton; @@ -47,30 +47,6 @@ TestRunnerMobile::TestRunnerMobile( folderLineEdit->setText("/sdcard/DCIM/TEST"); modelNames["SM_G955U1"] = "Samsung S8+ unlocked"; - - // Find ADB (Android Debugging Bridge) -#ifdef Q_OS_WIN - if (QProcessEnvironment::systemEnvironment().contains("ADB_PATH")) { - QString adbExePath = QProcessEnvironment::systemEnvironment().value("ADB_PATH") + "/platform-tools"; - if (!QFile::exists(adbExePath + "/" + _adbExe)) { - QMessageBox::critical(0, _adbExe, QString("ADB executable not found in ") + adbExePath); - exit(-1); - } - - _adbCommand = adbExePath + "/" + _adbExe; - } else { - QMessageBox::critical(0, "ADB_PATH not defined", - "Please set ADB_PATH to directory containing the `adb` executable"); - exit(-1); - } -#elif defined Q_OS_MAC - _adbCommand = "/usr/local/bin/adb"; - if (!QFile::exists(_adbCommand)) { - QMessageBox::critical(0, "adb not found", - "python3 not found at " + _adbCommand); - exit(-1); - } -#endif } TestRunnerMobile::~TestRunnerMobile() { @@ -84,8 +60,12 @@ void TestRunnerMobile::setWorkingFolderAndEnableControls() { void TestRunnerMobile::connectDevice() { #if defined Q_OS_WIN || defined Q_OS_MAC + if (!_adbInterface) { + _adbInterface = new AdbInterface(); + } + QString devicesFullFilename{ _workingFolder + "/devices.txt" }; - QString command = _adbCommand + " devices -l > " + devicesFullFilename; + QString command = _adbInterface->getAdbCommand() + " devices -l > " + devicesFullFilename; system(command.toStdString().c_str()); if (!QFile::exists(devicesFullFilename)) { @@ -100,12 +80,13 @@ void TestRunnerMobile::connectDevice() { QString line2 = devicesFile.readLine(); const QString DEVICE{ "device" }; - if (line2.contains(DEVICE)) { - // Make sure only 1 device + if (line2.contains("unauthorized")) { + QMessageBox::critical(0, "Unauthorized device detected", "Please allow USB debug on device"); + } else if (line2.contains(DEVICE)) { + // Make sure only 1 device QString line3 = devicesFile.readLine(); if (line3.contains(DEVICE)) { QMessageBox::critical(0, "Too many devices detected", "Tests will run only if a single device is attached"); - } else { // Line looks like this: 988a1b47335239434b device product:dream2qlteue model:SM_G955U1 device:dream2qlteue transport_id:2 QStringList tokens = line2.split(QRegExp("[\r\n\t ]+")); @@ -169,8 +150,12 @@ void TestRunnerMobile::downloadComplete() { void TestRunnerMobile::installAPK() { #if defined Q_OS_WIN || defined Q_OS_MAC + if (!_adbInterface) { + _adbInterface = new AdbInterface(); + } + _statusLabel->setText("Installing"); - QString command = _adbCommand + " install -r -d " + _workingFolder + "/" + _installerFilename + " >" + _workingFolder + "/installOutput.txt"; + QString command = _adbInterface->getAdbCommand() + " install -r -d " + _workingFolder + "/" + _installerFilename + " >" + _workingFolder + "/installOutput.txt"; system(command.toStdString().c_str()); _statusLabel->setText("Installation complete"); _runInterfacePushbutton->setEnabled(true); @@ -179,8 +164,12 @@ void TestRunnerMobile::installAPK() { void TestRunnerMobile::runInterface() { #if defined Q_OS_WIN || defined Q_OS_MAC + if (!_adbInterface) { + _adbInterface = new AdbInterface(); + } + _statusLabel->setText("Starting Interface"); - QString command = _adbCommand + " shell monkey -p io.highfidelity.hifiinterface -v 1"; + QString command = _adbInterface->getAdbCommand() + " shell monkey -p io.highfidelity.hifiinterface -v 1"; system(command.toStdString().c_str()); _statusLabel->setText("Interface started"); #endif @@ -188,8 +177,12 @@ void TestRunnerMobile::runInterface() { void TestRunnerMobile::pullFolder() { #if defined Q_OS_WIN || defined Q_OS_MAC + if (!_adbInterface) { + _adbInterface = new AdbInterface(); + } + _statusLabel->setText("Pulling folder"); - QString command = _adbCommand + " pull " + _folderLineEdit->text() + " " + _workingFolder + _installerFilename; + QString command = _adbInterface->getAdbCommand() + " pull " + _folderLineEdit->text() + " " + _workingFolder + _installerFilename; system(command.toStdString().c_str()); _statusLabel->setText("Pull complete"); #endif diff --git a/tools/nitpick/src/TestRunnerMobile.h b/tools/nitpick/src/TestRunnerMobile.h index 247f864976..52c2ba096d 100644 --- a/tools/nitpick/src/TestRunnerMobile.h +++ b/tools/nitpick/src/TestRunnerMobile.h @@ -17,6 +17,7 @@ #include #include "TestRunner.h" +#include "AdbInterface.h" class TestRunnerMobile : public QObject, public TestRunner { Q_OBJECT @@ -70,5 +71,7 @@ private: QString _adbCommand; std::map modelNames; + + AdbInterface* _adbInterface; }; #endif diff --git a/tools/nitpick/ui/Nitpick.ui b/tools/nitpick/ui/Nitpick.ui index 16aaa9594d..79bdfd158b 100644 --- a/tools/nitpick/ui/Nitpick.ui +++ b/tools/nitpick/ui/Nitpick.ui @@ -686,8 +686,8 @@ - 290 - 20 + 300 + 60 41 31 @@ -699,8 +699,8 @@ - 340 - 20 + 350 + 60 271 31 From 61346437da1faf3e92707c16b4a56ff240c38d0b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 12 Feb 2019 09:22:31 -0800 Subject: [PATCH 084/139] working on material mapping --- libraries/model-baker/CMakeLists.txt | 4 ++- libraries/model-networking/CMakeLists.txt | 3 ++ libraries/networking/src/ResourceCache.h | 8 ++--- .../render-utils/src/CauterizedModel.cpp | 1 + libraries/render-utils/src/Model.cpp | 31 ++++++++++++------- libraries/render-utils/src/Model.h | 1 + 6 files changed, 31 insertions(+), 17 deletions(-) diff --git a/libraries/model-baker/CMakeLists.txt b/libraries/model-baker/CMakeLists.txt index 1e67d04bc1..22c240b487 100644 --- a/libraries/model-baker/CMakeLists.txt +++ b/libraries/model-baker/CMakeLists.txt @@ -2,4 +2,6 @@ set(TARGET_NAME model-baker) setup_hifi_library() link_hifi_libraries(shared shaders task gpu graphics hfm material-networking) -include_hifi_library_headers(networking) \ No newline at end of file +include_hifi_library_headers(networking) +include_hifi_library_headers(image) +include_hifi_library_headers(ktx) \ No newline at end of file diff --git a/libraries/model-networking/CMakeLists.txt b/libraries/model-networking/CMakeLists.txt index 7701f54d43..e79d18f779 100644 --- a/libraries/model-networking/CMakeLists.txt +++ b/libraries/model-networking/CMakeLists.txt @@ -3,3 +3,6 @@ setup_hifi_library() link_hifi_libraries(shared shaders networking graphics fbx material-networking model-baker) include_hifi_library_headers(hfm) include_hifi_library_headers(task) +include_hifi_library_headers(gpu) +include_hifi_library_headers(image) +include_hifi_library_headers(ktx) \ No newline at end of file diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 4693bc0613..be514f48f0 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -365,7 +365,7 @@ public: virtual ~Resource(); virtual QString getType() const { return "Resource"; } - + /// Returns the key last used to identify this resource in the unused map. int getLRUKey() const { return _lruKey; } @@ -374,13 +374,13 @@ public: /// Sets the load priority for one owner. virtual void setLoadPriority(const QPointer& owner, float priority); - + /// Sets a set of priorities at once. virtual void setLoadPriorities(const QHash, float>& priorities); - + /// Clears the load priority for one owner. virtual void clearLoadPriority(const QPointer& owner); - + /// Returns the highest load priority across all owners. float getLoadPriority(); diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index d4baddadee..4df933c972 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -64,6 +64,7 @@ void CauterizedModel::createRenderItemSet() { _modelMeshRenderItems.clear(); _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); + _priorityMap.clear(); Transform transform; transform.setTranslation(_translation); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index f278c5e2e9..7acdd10a8c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1434,6 +1434,7 @@ void Model::createRenderItemSet() { _modelMeshRenderItems.clear(); _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); + _priorityMap.clear(); Transform transform; transform.setTranslation(_translation); @@ -1525,30 +1526,30 @@ void Model::applyMaterialMapping() { PrimitiveMode primitiveMode = getPrimitiveMode(); bool useDualQuaternionSkinning = _useDualQuaternionSkinning; - render::Transaction transaction; - std::unordered_map priorityMap; auto& materialMapping = getMaterialMapping(); - qDebug() << "boop" << materialMapping.size(); for (auto& mapping : materialMapping) { std::set shapeIDs = getMeshIDsFromMaterialID(QString(mapping.first.c_str())); - - qDebug() << "boop2" << mapping.first.c_str() << shapeIDs.size(); - if (shapeIDs.size() == 0) { + auto networkMaterialResource = mapping.second; + if (!networkMaterialResource || shapeIDs.size() == 0) { continue; } - auto networkMaterialResource = mapping.second; - qDebug() << (bool)networkMaterialResource; - if (networkMaterialResource && networkMaterialResource->isLoaded() && networkMaterialResource->parsedMaterials.names.size() > 0) { + auto materialLoaded = [this, networkMaterialResource, shapeIDs, renderItemsKey, primitiveMode, useDualQuaternionSkinning]() { + qDebug() << "boop2" << networkMaterialResource->isFailed() << networkMaterialResource->parsedMaterials.names.size(); + if (networkMaterialResource->isFailed() || networkMaterialResource->parsedMaterials.names.size() > 0) { + return; + } + render::Transaction transaction; auto networkMaterial = networkMaterialResource->parsedMaterials.networkMaterials[networkMaterialResource->parsedMaterials.names[0]]; for (auto shapeID : shapeIDs) { + qDebug() << "boop3" << shapeID << _modelMeshRenderItemIDs.size(); if (shapeID < _modelMeshRenderItemIDs.size()) { auto itemID = _modelMeshRenderItemIDs[shapeID]; auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); - graphics::MaterialLayer material = graphics::MaterialLayer(networkMaterial, ++priorityMap[shapeID]); + graphics::MaterialLayer material = graphics::MaterialLayer(networkMaterial, ++_priorityMap[shapeID]); transaction.updateItem(itemID, [material, renderItemsKey, - invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) { + invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.addMaterial(material); // if the material changed, we might need to update our item key or shape key data.updateKey(renderItemsKey); @@ -1556,9 +1557,15 @@ void Model::applyMaterialMapping() { }); } } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); + }; + qDebug() << "boop" << networkMaterialResource->isLoaded(); + if (networkMaterialResource->isLoaded()) { + materialLoaded(); + } else { + connect(networkMaterialResource.data(), &Resource::finished, materialLoaded); } } - AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); } void Model::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index c484a82705..c4d1feaa1b 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -374,6 +374,7 @@ signals: protected: + std::unordered_map _priorityMap; // only used for materialMapping void applyMaterialMapping(); void setBlendshapeCoefficients(const QVector& coefficients) { _blendshapeCoefficients = coefficients; } From 9d81ace243bfe0304fc2b95ae1f27afc4a5eecc9 Mon Sep 17 00:00:00 2001 From: Mark <33107309+MarkBrosche@users.noreply.github.com> Date: Tue, 12 Feb 2019 09:45:51 -0800 Subject: [PATCH 085/139] Fixed MS21059: Avatar App Keyboard Raise in Desktop --- interface/resources/qml/hifi/avatarapp/Settings.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/avatarapp/Settings.qml b/interface/resources/qml/hifi/avatarapp/Settings.qml index 39c48646d3..c59fe42608 100644 --- a/interface/resources/qml/hifi/avatarapp/Settings.qml +++ b/interface/resources/qml/hifi/avatarapp/Settings.qml @@ -21,7 +21,7 @@ Rectangle { HifiControlsUit.Keyboard { id: keyboard z: 1000 - raised: parent.keyboardEnabled && parent.keyboardRaised + raised: parent.keyboardEnabled && parent.keyboardRaised && HMD.active numeric: parent.punctuationMode anchors { left: parent.left From 189ccfde4ae1cd7c27408cec46ff9f83c7d80a39 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 12 Feb 2019 09:51:11 -0800 Subject: [PATCH 086/139] clement's comments from PR14858 --- libraries/animation/src/AnimationCache.cpp | 2 +- libraries/audio/src/SoundCache.cpp | 2 +- .../src/material-networking/MaterialCache.cpp | 2 +- .../src/material-networking/ShaderCache.cpp | 2 +- .../src/material-networking/TextureCache.cpp | 13 ++++++------- .../src/model-networking/ModelCache.cpp | 6 +++--- libraries/networking/src/ResourceCache.h | 10 +++++----- libraries/recording/src/recording/ClipCache.cpp | 2 +- 8 files changed, 19 insertions(+), 20 deletions(-) diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 4e988334f9..237fd3da02 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -41,7 +41,7 @@ QSharedPointer AnimationCache::createResource(const QUrl& url) { } QSharedPointer AnimationCache::createResourceCopy(const QSharedPointer& resource) { - return QSharedPointer(new Animation(*resource.staticCast().data()), &Resource::deleter); + return QSharedPointer(new Animation(*resource.staticCast()), &Resource::deleter); } AnimationReader::AnimationReader(const QUrl& url, const QByteArray& data) : diff --git a/libraries/audio/src/SoundCache.cpp b/libraries/audio/src/SoundCache.cpp index 343de46e9a..c36897c766 100644 --- a/libraries/audio/src/SoundCache.cpp +++ b/libraries/audio/src/SoundCache.cpp @@ -40,5 +40,5 @@ QSharedPointer SoundCache::createResource(const QUrl& url) { } QSharedPointer SoundCache::createResourceCopy(const QSharedPointer& resource) { - return QSharedPointer(new Sound(*resource.staticCast().data()), &Resource::deleter); + return QSharedPointer(new Sound(*resource.staticCast()), &Resource::deleter); } \ No newline at end of file diff --git a/libraries/material-networking/src/material-networking/MaterialCache.cpp b/libraries/material-networking/src/material-networking/MaterialCache.cpp index bccf1ca0c4..1b5ba6f0f6 100644 --- a/libraries/material-networking/src/material-networking/MaterialCache.cpp +++ b/libraries/material-networking/src/material-networking/MaterialCache.cpp @@ -425,7 +425,7 @@ QSharedPointer MaterialCache::createResource(const QUrl& url) { } QSharedPointer MaterialCache::createResourceCopy(const QSharedPointer& resource) { - return QSharedPointer(new NetworkMaterialResource(*resource.staticCast().data()), &Resource::deleter); + return QSharedPointer(new NetworkMaterialResource(*resource.staticCast()), &Resource::deleter); } NetworkMaterial::NetworkMaterial(const NetworkMaterial& m) : diff --git a/libraries/material-networking/src/material-networking/ShaderCache.cpp b/libraries/material-networking/src/material-networking/ShaderCache.cpp index 8d060c42f2..4c8d659315 100644 --- a/libraries/material-networking/src/material-networking/ShaderCache.cpp +++ b/libraries/material-networking/src/material-networking/ShaderCache.cpp @@ -29,5 +29,5 @@ QSharedPointer ShaderCache::createResource(const QUrl& url) { } QSharedPointer ShaderCache::createResourceCopy(const QSharedPointer& resource) { - return QSharedPointer(new NetworkShader(*resource.staticCast().data()), &Resource::deleter); + return QSharedPointer(new NetworkShader(*resource.staticCast()), &Resource::deleter); } diff --git a/libraries/material-networking/src/material-networking/TextureCache.cpp b/libraries/material-networking/src/material-networking/TextureCache.cpp index 2cc7a4b032..95cf7dfd90 100644 --- a/libraries/material-networking/src/material-networking/TextureCache.cpp +++ b/libraries/material-networking/src/material-networking/TextureCache.cpp @@ -197,16 +197,16 @@ public: namespace std { template <> struct hash { - size_t operator()(const QByteArray& a) const { - return qHash(a); + size_t operator()(const QByteArray& byteArray) const { + return qHash(byteArray); } }; template <> struct hash { - size_t operator()(const TextureExtra& a) const { + size_t operator()(const TextureExtra& textureExtra) const { size_t result = 0; - hash_combine(result, (int)a.type, a.content, a.maxNumPixels); + hash_combine(result, (int)textureExtra.type, textureExtra.content, textureExtra.maxNumPixels); return result; } }; @@ -328,14 +328,13 @@ QSharedPointer TextureCache::createResource(const QUrl& url) { } QSharedPointer TextureCache::createResourceCopy(const QSharedPointer& resource) { - return QSharedPointer(new NetworkTexture(*resource.staticCast().data()), &Resource::deleter); + return QSharedPointer(new NetworkTexture(*resource.staticCast()), &Resource::deleter); } int networkTexturePointerMetaTypeId = qRegisterMetaType>(); NetworkTexture::NetworkTexture(const QUrl& url, bool resourceTexture) : - Resource(url), - _maxNumPixels(100) + Resource(url) { if (resourceTexture) { _textureSource = std::make_shared(url); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 0ed518937d..1a4542d279 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -76,9 +76,9 @@ namespace std { template <> struct hash { - size_t operator()(const GeometryExtra& a) const { + size_t operator()(const GeometryExtra& geometryExtra) const { size_t result = 0; - hash_combine(result, a.mapping, a.textureBaseUrl, a.combineParts); + hash_combine(result, geometryExtra.mapping, geometryExtra.textureBaseUrl, geometryExtra.combineParts); return result; } }; @@ -394,7 +394,7 @@ QSharedPointer ModelCache::createResource(const QUrl& url) { } QSharedPointer ModelCache::createResourceCopy(const QSharedPointer& resource) { - return QSharedPointer(new GeometryDefinitionResource(*resource.staticCast().data()), &Resource::deleter); + return QSharedPointer(new GeometryDefinitionResource(*resource.staticCast()), &Resource::deleter); } GeometryResource::Pointer ModelCache::getGeometryResource(const QUrl& url, diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index be514f48f0..9ff8070768 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -489,14 +489,14 @@ protected: QWeakPointer _self; QPointer _cache; - qint64 _bytesReceived{ 0 }; - qint64 _bytesTotal{ 0 }; - qint64 _bytes{ 0 }; + qint64 _bytesReceived { 0 }; + qint64 _bytesTotal { 0 }; + qint64 _bytes { 0 }; int _requestID; - ResourceRequest* _request{ nullptr }; + ResourceRequest* _request { nullptr }; - size_t _extraHash; + size_t _extraHash { std::numeric_limits::max() }; public slots: void handleDownloadProgress(uint64_t bytesReceived, uint64_t bytesTotal); diff --git a/libraries/recording/src/recording/ClipCache.cpp b/libraries/recording/src/recording/ClipCache.cpp index c08dd40ad8..bc20e4d8eb 100644 --- a/libraries/recording/src/recording/ClipCache.cpp +++ b/libraries/recording/src/recording/ClipCache.cpp @@ -54,5 +54,5 @@ QSharedPointer ClipCache::createResource(const QUrl& url) { } QSharedPointer ClipCache::createResourceCopy(const QSharedPointer& resource) { - return QSharedPointer(new NetworkClipLoader(*resource.staticCast().data()), &Resource::deleter); + return QSharedPointer(new NetworkClipLoader(*resource.staticCast()), &Resource::deleter); } \ No newline at end of file From fcfb1b7a4a8cfef84009ae36788cf9344288f3ec Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 12 Feb 2019 10:06:25 -0800 Subject: [PATCH 087/139] Update edit.js to auto close dropdowns when clicking outside --- scripts/system/html/js/entityProperties.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index ee95312fa4..89ddd6f33e 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -3018,6 +3018,13 @@ function toggleDropdown(event) { element.setAttribute("dropped", isDropped !== "true" ? "true" : "false"); } +function closeAllDropdowns() { + elDropdowns = document.querySelectorAll("div.dropdown > dl"); + for (let i = 0; i < elDropdowns.length; ++i) { + elDropdowns[i].setAttribute('dropped', 'false'); + } +} + function setDropdownValue(event) { let dt = event.target.parentNode.parentNode.previousSibling; dt.value = event.target.getAttribute("value"); @@ -3780,6 +3787,8 @@ function loaded() { property.elInput = dt; dt.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); } + + document.addEventListener('click', function(ev) { closeAllDropdowns() }, true); elDropdowns = document.getElementsByTagName("select"); while (elDropdowns.length > 0) { From 2728654d352ba22f7133e810afe16af96a97d916 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 12 Feb 2019 10:09:28 -0800 Subject: [PATCH 088/139] Fix duplicating non-dynamic grabbed entities in edit.js --- scripts/system/libraries/entitySelectionTool.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 01e5f6e22b..3e16315c6d 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -284,6 +284,8 @@ SelectionManager = (function() { properties.parentJointIndex = null; properties.localPosition = properties.position; properties.localRotation = properties.rotation; + properties.velocity = { x: 0, y: 0, z: 0 }; + properties.angularVelocity = { x: 0, y: 0, z: 0 }; } delete properties.actionData; var newEntityID = Entities.addEntity(properties); From 0b1034c290313816d42482f5327115253bacd399 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 12 Feb 2019 11:11:22 -0800 Subject: [PATCH 089/139] Improved wording of error message. --- tools/nitpick/src/TestRunnerMobile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/src/TestRunnerMobile.cpp b/tools/nitpick/src/TestRunnerMobile.cpp index 3f44a610f8..ab276f3337 100644 --- a/tools/nitpick/src/TestRunnerMobile.cpp +++ b/tools/nitpick/src/TestRunnerMobile.cpp @@ -81,7 +81,7 @@ void TestRunnerMobile::connectDevice() { const QString DEVICE{ "device" }; if (line2.contains("unauthorized")) { - QMessageBox::critical(0, "Unauthorized device detected", "Please allow USB debug on device"); + QMessageBox::critical(0, "Unauthorized device detected", "Please allow USB debugging on device"); } else if (line2.contains(DEVICE)) { // Make sure only 1 device QString line3 = devicesFile.readLine(); From 305ce746592fbf7c5b4ad38f79aab28fd6ac653c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 12 Feb 2019 11:11:59 -0800 Subject: [PATCH 090/139] Updated the Windows installation instructions. --- tools/nitpick/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index c5e3a5e21d..25f9001409 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -18,7 +18,7 @@ Nitpick has 5 functions, separated into separate tabs: ### Windows 1. (First time) download and install Python 3 from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/python-3.7.0-amd64.exe (also located at https://www.python.org/downloads/) 1. Click the "add python to path" checkbox on the python installer - 1. After installation - create an environment variable called PYTHON_PATH and set it to the folder containing the Python executable. + 1. After installation - add the path to python.exe to the Windows PATH environment variable. 1. (First time) download and install AWS CLI from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/AWSCLI64PY3.msi (also available at https://aws.amazon.com/cli/ 1. Open a new command prompt and run `aws configure` @@ -31,7 +31,7 @@ Nitpick has 5 functions, separated into separate tabs: 1. (First time) Download adb (Android Debug Bridge) from *https://dl.google.com/android/repository/platform-tools-latest-windows.zip* 1. Copy the downloaded file to (for example) **C:\adb** and extract in place. Verify you see *adb.exe* in **C:\adb\platform-tools\\**. - 1. Create an environment variable named ADB_PATH and set its value to the installation location (e.g. **C:\adb**) + 1. After installation - add the path to adb.exe to the Windows PATH environment variable (note that it is in *adb\platform-tools*). ### Mac 1. (first time) Install brew In a terminal: From f75a3e1a727bc8842701b9d33fd39f3574d91ac4 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 12 Feb 2019 11:41:47 -0800 Subject: [PATCH 091/139] it's working! --- .../model-baker/ParseMaterialMappingTask.cpp | 60 ++++++++++++------- .../render-utils/src/CauterizedModel.cpp | 2 - libraries/render-utils/src/Model.cpp | 10 ++-- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp index 7a4acb595a..b313593be2 100644 --- a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp +++ b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp @@ -25,35 +25,51 @@ void ParseMaterialMappingTask::run(const baker::BakeContextPointer& context, con } else { auto mappingKeys = materialMap.keys(); for (auto mapping : mappingKeys) { - auto mappingValue = materialMap[mapping].toObject(); + auto mappingJSON = materialMap[mapping]; + if (mappingJSON.isObject()) { + auto mappingValue = mappingJSON.toObject(); - // Old subsurface scattering mapping - { - auto scatteringIter = mappingValue.find("scattering"); - auto scatteringMapIter = mappingValue.find("scatteringMap"); - if (scatteringIter != mappingValue.end() || scatteringMapIter != mappingValue.end()) { - std::shared_ptr material = std::make_shared(); + // Old subsurface scattering mapping + { + auto scatteringIter = mappingValue.find("scattering"); + auto scatteringMapIter = mappingValue.find("scatteringMap"); + if (scatteringIter != mappingValue.end() || scatteringMapIter != mappingValue.end()) { + std::shared_ptr material = std::make_shared(); - if (scatteringIter != mappingValue.end()) { - float scattering = (float)scatteringIter.value().toDouble(); - material->setScattering(scattering); + if (scatteringIter != mappingValue.end()) { + float scattering = (float)scatteringIter.value().toDouble(); + material->setScattering(scattering); + } + + if (scatteringMapIter != mappingValue.end()) { + QString scatteringMap = scatteringMapIter.value().toString(); + material->setScatteringMap(scatteringMap); + } + + material->setDefaultFallthrough(true); + + NetworkMaterialResourcePointer materialResource = NetworkMaterialResourcePointer(new NetworkMaterialResource(), [](NetworkMaterialResource* ptr) { ptr->deleteLater(); }); + materialResource->moveToThread(qApp->thread()); + materialResource->parsedMaterials.names.push_back("scattering"); + materialResource->parsedMaterials.networkMaterials["scattering"] = material; + + materialMapping.push_back(std::pair("mat::" + mapping.toStdString(), materialResource)); + continue; } + } - if (scatteringMapIter != mappingValue.end()) { - QString scatteringMap = scatteringMapIter.value().toString(); - material->setScatteringMap(scatteringMap); - } - - material->setDefaultFallthrough(true); - + // Material JSON description + { NetworkMaterialResourcePointer materialResource = NetworkMaterialResourcePointer(new NetworkMaterialResource(), [](NetworkMaterialResource* ptr) { ptr->deleteLater(); }); materialResource->moveToThread(qApp->thread()); - materialResource->parsedMaterials.names.push_back("scattering"); - materialResource->parsedMaterials.networkMaterials["scattering"] = material; - - materialMapping.push_back(std::pair("mat::" + mapping.toStdString(), materialResource)); - continue; + // TODO: add baseURL to allow FSTs to reference relative files next to them + materialResource->parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument(mappingValue), QUrl()); + materialMapping.push_back(std::pair(mapping.toStdString(), materialResource)); } + + } else if (mappingJSON.isString()) { + auto mappingValue = mappingJSON.toString(); + materialMapping.push_back(std::pair(mapping.toStdString(), MaterialCache::instance().getMaterial(mappingValue))); } } } diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 4df933c972..b70925201a 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -64,7 +64,6 @@ void CauterizedModel::createRenderItemSet() { _modelMeshRenderItems.clear(); _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); - _priorityMap.clear(); Transform transform; transform.setTranslation(_translation); @@ -98,7 +97,6 @@ void CauterizedModel::createRenderItemSet() { } } _blendshapeOffsetsInitialized = true; - applyMaterialMapping(); } else { Model::createRenderItemSet(); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 7acdd10a8c..c15941b465 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -956,6 +956,7 @@ bool Model::addToScene(const render::ScenePointer& scene, } if (somethingAdded) { + applyMaterialMapping(); _addedToScene = true; updateRenderItems(); _needsFixupInScene = false; @@ -973,6 +974,7 @@ void Model::removeFromScene(const render::ScenePointer& scene, render::Transacti _modelMeshRenderItems.clear(); _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); + _priorityMap.clear(); _blendshapeOffsets.clear(); _blendshapeOffsetsInitialized = false; @@ -1434,7 +1436,6 @@ void Model::createRenderItemSet() { _modelMeshRenderItems.clear(); _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); - _priorityMap.clear(); Transform transform; transform.setTranslation(_translation); @@ -1466,7 +1467,6 @@ void Model::createRenderItemSet() { } } _blendshapeOffsetsInitialized = true; - applyMaterialMapping(); } bool Model::isRenderable() const { @@ -1535,14 +1535,12 @@ void Model::applyMaterialMapping() { } auto materialLoaded = [this, networkMaterialResource, shapeIDs, renderItemsKey, primitiveMode, useDualQuaternionSkinning]() { - qDebug() << "boop2" << networkMaterialResource->isFailed() << networkMaterialResource->parsedMaterials.names.size(); - if (networkMaterialResource->isFailed() || networkMaterialResource->parsedMaterials.names.size() > 0) { + if (networkMaterialResource->isFailed() || networkMaterialResource->parsedMaterials.names.size() == 0) { return; } render::Transaction transaction; auto networkMaterial = networkMaterialResource->parsedMaterials.networkMaterials[networkMaterialResource->parsedMaterials.names[0]]; for (auto shapeID : shapeIDs) { - qDebug() << "boop3" << shapeID << _modelMeshRenderItemIDs.size(); if (shapeID < _modelMeshRenderItemIDs.size()) { auto itemID = _modelMeshRenderItemIDs[shapeID]; auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; @@ -1559,7 +1557,7 @@ void Model::applyMaterialMapping() { } AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); }; - qDebug() << "boop" << networkMaterialResource->isLoaded(); + if (networkMaterialResource->isLoaded()) { materialLoaded(); } else { From fdfb9196d351a7811e71b463850a627b64035fe9 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Tue, 12 Feb 2019 11:45:08 -0800 Subject: [PATCH 092/139] comments explaining horrible code --- interface/src/avatar/OtherAvatar.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 8ad9c6b121..9496336ae1 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -447,6 +447,10 @@ void OtherAvatar::handleChangedAvatarEntityData() { EntityItemProperties properties; int32_t bytesLeftToRead = data.size(); unsigned char* dataAt = (unsigned char*)(data.data()); + // FIXME: This function will cause unintented changes in SpaillyNestable + // E.g overriding the ID index of an exisiting entity to temporary entity + // in the following map QHash _children; + // Andrew Meadows will address this issue if (!properties.constructFromBuffer(dataAt, bytesLeftToRead)) { // properties are corrupt continue; @@ -489,6 +493,14 @@ void OtherAvatar::handleChangedAvatarEntityData() { bool success = true; if (entity) { QUuid oldParentID = entity->getParentID(); + + // Since has overwrtiiten the back pointer + // from the parent children map (see comment for function call above), + // we need to for reset the back pointer in the map correctly by setting the parentID, but + // since the parentID of the entity has not changed we first need to set it some ither ID, + // then set the the original ID for the changes to take effect + // TODO: This is a horrible hack and once properties.constructFromBuffer no longer causes + // side effects...remove the following three lines const QUuid NULL_ID = QUuid("{00000000-0000-0000-0000-000000000005}"); entity->setParentID(NULL_ID); entity->setParentID(oldParentID); From 2b355e9d52a7c129e642ed64334c80813d125838 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Tue, 12 Feb 2019 11:56:44 -0800 Subject: [PATCH 093/139] Re-name ColorChannelMapping to ColorChannel and put versions in two specific libraries rather than shared --- libraries/fbx/src/GLTFSerializer.cpp | 4 +-- libraries/hfm/src/hfm/ColorChannel.h | 26 +++++++++++++++++ libraries/hfm/src/hfm/HFM.h | 5 ++-- libraries/image/src/image/Image.cpp | 16 +++++------ libraries/image/src/image/Image.h | 12 ++++++-- .../src/model-networking/ModelCache.cpp | 2 +- .../src/model-networking/TextureCache.cpp | 28 +++++++++---------- .../src/model-networking/TextureCache.h | 7 +++-- libraries/procedural/CMakeLists.txt | 1 + .../shared/src/shared/ColorChannelMapping.h | 26 ----------------- 10 files changed, 69 insertions(+), 58 deletions(-) create mode 100644 libraries/hfm/src/hfm/ColorChannel.h delete mode 100644 libraries/shared/src/shared/ColorChannelMapping.h diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 428dc3a77d..eb29ef3fad 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1146,10 +1146,10 @@ void GLTFSerializer::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& mat } if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) { fbxmat.roughnessTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); - fbxmat.roughnessTexture.channelMapping = ColorChannelMapping::GREEN; + fbxmat.roughnessTexture.sourceChannel = hfm::ColorChannel::GREEN; fbxmat.useRoughnessMap = true; fbxmat.metallicTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); - fbxmat.metallicTexture.channelMapping = ColorChannelMapping::BLUE; + fbxmat.metallicTexture.sourceChannel = hfm::ColorChannel::BLUE; fbxmat.useMetallicMap = true; } if (material.pbrMetallicRoughness.defined["roughnessFactor"]) { diff --git a/libraries/hfm/src/hfm/ColorChannel.h b/libraries/hfm/src/hfm/ColorChannel.h new file mode 100644 index 0000000000..a5db0354da --- /dev/null +++ b/libraries/hfm/src/hfm/ColorChannel.h @@ -0,0 +1,26 @@ +// +// ColorChannel.h +// libraries/hfm/src +// +// Created by Sabrina Shanman on 2019/02/12. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_hfm_ColorChannel_h +#define hifi_hfm_ColorChannel_h + +namespace hfm { + enum class ColorChannel { + NONE, + RED, + GREEN, + BLUE, + ALPHA, + COUNT + }; +}; + +#endif // hifi_hfm_ColorChannel_h diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index d238ff7de0..68b091c8d8 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -24,7 +24,8 @@ #include #include -#include + +#include "ColorChannel.h" #if defined(Q_OS_ANDROID) #define HFM_PACK_NORMALS 0 @@ -124,7 +125,7 @@ public: QString name; QByteArray filename; QByteArray content; - ColorChannelMapping channelMapping { ColorChannelMapping::NONE }; + ColorChannel sourceChannel { ColorChannel::NONE }; Transform transform; int maxNumPixels { MAX_NUM_PIXELS_FOR_FBX_TEXTURE }; diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index bce322c9ee..e2ee8c68f8 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -222,7 +222,7 @@ QImage processRawImageData(QIODevice& content, const std::string& filename) { return QImage(); } -void mapToRedChannel(QImage& image, ColorChannelMapping sourceChannel) { +void mapToRedChannel(QImage& image, TextureUsage::ColorChannel sourceChannel) { // Change format of image so we know exactly how to process it if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); @@ -237,16 +237,16 @@ void mapToRedChannel(QImage& image, ColorChannelMapping sourceChannel) { for (; pixel < lineEnd; pixel++) { int colorValue; switch (sourceChannel) { - case ColorChannelMapping::RED: + case TextureUsage::ColorChannel::RED: colorValue = qRed(*pixel); break; - case ColorChannelMapping::GREEN: + case TextureUsage::ColorChannel::GREEN: colorValue = qGreen(*pixel); break; - case ColorChannelMapping::BLUE: + case TextureUsage::ColorChannel::BLUE: colorValue = qBlue(*pixel); break; - case ColorChannelMapping::ALPHA: + case TextureUsage::ColorChannel::ALPHA: colorValue = qAlpha(*pixel); break; default: @@ -260,7 +260,7 @@ void mapToRedChannel(QImage& image, ColorChannelMapping sourceChannel) { } } -gpu::TexturePointer processImage(std::shared_ptr content, const std::string& filename, ColorChannelMapping channelMapping, +gpu::TexturePointer processImage(std::shared_ptr content, const std::string& filename, TextureUsage::ColorChannel sourceChannel, int maxNumPixels, TextureUsage::Type textureType, bool compress, BackendTarget target, const std::atomic& abortProcessing) { @@ -293,8 +293,8 @@ gpu::TexturePointer processImage(std::shared_ptr content, const std:: } // Re-map to image with single red channel texture if requested - if (channelMapping != ColorChannelMapping::NONE) { - mapToRedChannel(image, channelMapping); + if (sourceChannel != TextureUsage::ColorChannel::NONE) { + mapToRedChannel(image, sourceChannel); } auto loader = TextureUsage::getTextureLoaderForType(textureType); diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index cc68ef6718..5497d72fe9 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -15,7 +15,6 @@ #include #include -#include class QByteArray; class QImage; @@ -42,6 +41,15 @@ enum Type { UNUSED_TEXTURE }; +enum class ColorChannel { + NONE, + RED, + GREEN, + BLUE, + ALPHA, + COUNT +}; + using TextureLoader = std::function&)>; TextureLoader getTextureLoaderForType(Type type, const QVariantMap& options = QVariantMap()); @@ -82,7 +90,7 @@ gpu::TexturePointer processCubeTextureColorFromImage(QImage&& srcImage, const st const QStringList getSupportedFormats(); -gpu::TexturePointer processImage(std::shared_ptr content, const std::string& url, ColorChannelMapping channelMapping, +gpu::TexturePointer processImage(std::shared_ptr content, const std::string& url, TextureUsage::ColorChannel sourceChannel, int maxNumPixels, TextureUsage::Type textureType, bool compress, gpu::BackendTarget target, const std::atomic& abortProcessing = false); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 021c70ccf2..a4fae67958 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -599,7 +599,7 @@ graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl } const auto url = getTextureUrl(baseUrl, hfmTexture); - const auto texture = DependencyManager::get()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels, hfmTexture.channelMapping); + const auto texture = DependencyManager::get()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels, hfmTexture.sourceChannel); _textures[channel] = Texture { hfmTexture.name, texture }; auto map = std::make_shared(); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index c28db444c0..54f991a179 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -192,7 +192,7 @@ public: image::TextureUsage::Type type; const QByteArray& content; int maxNumPixels; - ColorChannelMapping channelMapping; + hfm::ColorChannel sourceChannel; }; namespace std { @@ -207,19 +207,19 @@ namespace std { struct hash { size_t operator()(const TextureExtra& a) const { size_t result = 0; - hash_combine(result, (int)a.type, a.content, a.maxNumPixels, (int)a.channelMapping); + hash_combine(result, (int)a.type, a.content, a.maxNumPixels, (int)a.sourceChannel); return result; } }; } -ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels, ColorChannelMapping channelMapping) { +ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels, hfm::ColorChannel sourceChannel) { auto byteArray = QByteArray(); - TextureExtra extra = { (image::TextureUsage::Type)type, byteArray, maxNumPixels, channelMapping }; + TextureExtra extra = { (image::TextureUsage::Type)type, byteArray, maxNumPixels, sourceChannel }; return ResourceCache::prefetch(url, &extra, std::hash()(extra)); } -NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels, ColorChannelMapping channelMapping) { +NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels, hfm::ColorChannel sourceChannel) { if (url.scheme() == RESOURCE_SCHEME) { return getResourceTexture(url); } @@ -229,7 +229,7 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUs query.addQueryItem("skybox", ""); modifiedUrl.setQuery(query.toString()); } - TextureExtra extra = { type, content, maxNumPixels, channelMapping }; + TextureExtra extra = { type, content, maxNumPixels, sourceChannel }; return ResourceCache::getResource(modifiedUrl, QUrl(), &extra, std::hash()(extra)).staticCast(); } @@ -347,7 +347,7 @@ NetworkTexture::NetworkTexture(const QUrl& url, bool resourceTexture) : NetworkTexture::NetworkTexture(const NetworkTexture& other) : Resource(other), _type(other._type), - _channelMapping(other._channelMapping), + _sourceChannel(other._sourceChannel), _currentlyLoadingResourceType(other._currentlyLoadingResourceType), _originalWidth(other._originalWidth), _originalHeight(other._originalHeight), @@ -371,7 +371,7 @@ void NetworkTexture::setExtra(void* extra) { const TextureExtra* textureExtra = static_cast(extra); _type = textureExtra ? textureExtra->type : image::TextureUsage::DEFAULT_TEXTURE; _maxNumPixels = textureExtra ? textureExtra->maxNumPixels : ABSOLUTE_MAX_TEXTURE_NUM_PIXELS; - _channelMapping = textureExtra ? textureExtra->channelMapping : ColorChannelMapping::NONE; + _sourceChannel = textureExtra ? textureExtra->sourceChannel : hfm::ColorChannel::NONE; _textureSource = std::make_shared(_url, (int)_type); _lowestRequestedMipLevel = 0; @@ -434,7 +434,7 @@ class ImageReader : public QRunnable { public: ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, size_t extraHash, int maxNumPixels, - ColorChannelMapping channelMapping); + hfm::ColorChannel sourceChannel); void run() override final; void read(); @@ -446,7 +446,7 @@ private: QByteArray _content; size_t _extraHash; int _maxNumPixels; - ColorChannelMapping _channelMapping; + hfm::ColorChannel _sourceChannel; }; NetworkTexture::~NetworkTexture() { @@ -1079,7 +1079,7 @@ void NetworkTexture::loadTextureContent(const QByteArray& content) { return; } - QThreadPool::globalInstance()->start(new ImageReader(_self, _url, content, _extraHash, _maxNumPixels, _channelMapping)); + QThreadPool::globalInstance()->start(new ImageReader(_self, _url, content, _extraHash, _maxNumPixels, _sourceChannel)); } void NetworkTexture::refresh() { @@ -1104,13 +1104,13 @@ void NetworkTexture::refresh() { Resource::refresh(); } -ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, size_t extraHash, int maxNumPixels, const ColorChannelMapping channelMapping) : +ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, size_t extraHash, int maxNumPixels, hfm::ColorChannel sourceChannel) : _resource(resource), _url(url), _content(data), _extraHash(extraHash), _maxNumPixels(maxNumPixels), - _channelMapping(channelMapping) + _sourceChannel(sourceChannel) { DependencyManager::get()->incrementStat("PendingProcessing"); listSupportedImageFormats(); @@ -1218,7 +1218,7 @@ void ImageReader::read() { constexpr bool shouldCompress = false; #endif auto target = getBackendTarget(); - texture = image::processImage(std::move(buffer), _url.toString().toStdString(), _channelMapping, _maxNumPixels, networkTexture->getTextureType(), shouldCompress, target); + texture = image::processImage(std::move(buffer), _url.toString().toStdString(), (image::TextureUsage::ColorChannel)_sourceChannel, _maxNumPixels, networkTexture->getTextureType(), shouldCompress, target); if (!texture) { QMetaObject::invokeMethod(resource.data(), "setImage", diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 170cd0ceb7..16627012b3 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -96,7 +97,7 @@ private: friend class ImageReader; image::TextureUsage::Type _type; - ColorChannelMapping _channelMapping; + hfm::ColorChannel _sourceChannel; enum class ResourceType { META, @@ -180,7 +181,7 @@ public: /// Loads a texture from the specified URL. NetworkTexturePointer getTexture(const QUrl& url, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE, const QByteArray& content = QByteArray(), int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, - ColorChannelMapping channelMapping = ColorChannelMapping::NONE); + hfm::ColorChannel sourceChannel = hfm::ColorChannel::NONE); gpu::TexturePointer getTextureByHash(const std::string& hash); gpu::TexturePointer cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture); @@ -203,7 +204,7 @@ signals: protected: // Overload ResourceCache::prefetch to allow specifying texture type for loads - Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, ColorChannelMapping channelMapping = ColorChannelMapping::NONE); + Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, hfm::ColorChannel sourceChannel = hfm::ColorChannel::NONE); virtual QSharedPointer createResource(const QUrl& url) override; QSharedPointer createResourceCopy(const QSharedPointer& resource) override; diff --git a/libraries/procedural/CMakeLists.txt b/libraries/procedural/CMakeLists.txt index 6d6610a323..f2562907e0 100644 --- a/libraries/procedural/CMakeLists.txt +++ b/libraries/procedural/CMakeLists.txt @@ -2,3 +2,4 @@ set(TARGET_NAME procedural) setup_hifi_library() link_hifi_libraries(shared gpu shaders networking graphics model-networking ktx image) +include_hifi_library_headers(hfm) diff --git a/libraries/shared/src/shared/ColorChannelMapping.h b/libraries/shared/src/shared/ColorChannelMapping.h deleted file mode 100644 index 0f70b9d9f7..0000000000 --- a/libraries/shared/src/shared/ColorChannelMapping.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// ColorChannelMapping.h -// libraries/shared/src -// -// Created by Sabrina Shanman on 2019/02/05. -// Copyright 2019 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_ColorChannelMapping_h -#define hifi_ColorChannelMapping_h - -#include "../RegisteredMetaTypes.h" - -enum class ColorChannelMapping { - NONE, - RED, - GREEN, - BLUE, - ALPHA, - COUNT -}; - -#endif // hifi_ColorChannelMapping_h From fdbcf4b2ea712d569716d6f587cbf3fa56f0965c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 12 Feb 2019 12:03:35 -0800 Subject: [PATCH 094/139] cleanup and expose mapped materials to getScriptableModel --- libraries/model-baker/src/model-baker/Baker.cpp | 3 +-- .../src/model-baker/ParseMaterialMappingTask.cpp | 5 +---- .../src/model-baker/ParseMaterialMappingTask.h | 2 +- libraries/render-utils/src/Model.cpp | 12 +++++++++++- libraries/render-utils/src/Model.h | 1 + 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libraries/model-baker/src/model-baker/Baker.cpp b/libraries/model-baker/src/model-baker/Baker.cpp index 037cfb7912..dfb18eef86 100644 --- a/libraries/model-baker/src/model-baker/Baker.cpp +++ b/libraries/model-baker/src/model-baker/Baker.cpp @@ -155,8 +155,7 @@ namespace baker { const auto jointIndices = jointInfoOut.getN(2); // Parse material mapping - const auto materialMappingInputs = ParseMaterialMappingTask::Input(materials, mapping).asVarying(); - const auto materialMapping = model.addJob("ParseMaterialMapping", materialMappingInputs); + const auto materialMapping = model.addJob("ParseMaterialMapping", mapping); // Combine the outputs into a new hfm::Model const auto buildBlendshapesInputs = BuildBlendshapesTask::Input(blendshapesPerMeshIn, normalsPerBlendshapePerMesh, tangentsPerBlendshapePerMesh).asVarying(); diff --git a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp index b313593be2..7a923a3702 100644 --- a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp +++ b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp @@ -10,10 +10,7 @@ #include "ModelBakerLogging.h" -void ParseMaterialMappingTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) { - const auto& materialsIn = input.get0(); - const auto& mapping = input.get1(); - +void ParseMaterialMappingTask::run(const baker::BakeContextPointer& context, const Input& mapping, Output& output) { MaterialMapping materialMapping; auto mappingIter = mapping.find("materialMap"); diff --git a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h index 3e48c00acf..69e00b0324 100644 --- a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h +++ b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h @@ -19,7 +19,7 @@ class ParseMaterialMappingTask { public: - using Input = baker::VaryingSet2, QVariantHash>; + using Input = QVariantHash; using Output = MaterialMapping; using JobModel = baker::Job::ModelIO; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c15941b465..b4eee57d89 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -756,7 +756,16 @@ scriptable::ScriptableModelBase Model::getScriptableModel() { int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { - result.appendMaterial(graphics::MaterialLayer(getGeometry()->getShapeMaterial(shapeID), 0), shapeID, _modelMeshMaterialNames[shapeID]); + auto& materialName = _modelMeshMaterialNames[shapeID]; + result.appendMaterial(graphics::MaterialLayer(getGeometry()->getShapeMaterial(shapeID), 0), shapeID, materialName); + + auto mappedMaterialIter = _materialMapping.find(shapeID); + if (mappedMaterialIter != _materialMapping.end()) { + auto mappedMaterials = mappedMaterialIter->second; + for (auto& mappedMaterial : mappedMaterials) { + result.appendMaterial(mappedMaterial, shapeID, materialName); + } + } shapeID++; } } @@ -1546,6 +1555,7 @@ void Model::applyMaterialMapping() { auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); graphics::MaterialLayer material = graphics::MaterialLayer(networkMaterial, ++_priorityMap[shapeID]); + _materialMapping[shapeID].push_back(material); transaction.updateItem(itemID, [material, renderItemsKey, invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.addMaterial(material); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index c4d1feaa1b..2b73ac0a28 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -375,6 +375,7 @@ signals: protected: std::unordered_map _priorityMap; // only used for materialMapping + std::unordered_map> _materialMapping; // generated during applyMaterialMapping void applyMaterialMapping(); void setBlendshapeCoefficients(const QVector& coefficients) { _blendshapeCoefficients = coefficients; } From b418e43ef2250eb1bd5ddbc332c1fa28ba915be6 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 12 Feb 2019 09:25:57 -0800 Subject: [PATCH 095/139] ctrlaltdavid's minitablet fix --- scripts/system/html/js/miniTablet.js | 8 +++--- scripts/system/miniTablet.js | 38 +++++++++++++++------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/scripts/system/html/js/miniTablet.js b/scripts/system/html/js/miniTablet.js index 6bc75161b3..c48201cef5 100644 --- a/scripts/system/html/js/miniTablet.js +++ b/scripts/system/html/js/miniTablet.js @@ -61,11 +61,6 @@ } switch (message.type) { - case READY_MESSAGE: - EventBridge.emitWebEvent(JSON.stringify({ - type: READY_MESSAGE - })); - break; case MUTE_MESSAGE: muteImage.src = message.icon; break; @@ -119,6 +114,9 @@ function connectEventBridge() { EventBridge.scriptEventReceived.connect(onScriptEventReceived); + EventBridge.emitWebEvent(JSON.stringify({ + type: READY_MESSAGE + })); } function disconnectEventBridge() { diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index e99c2631d9..449921514c 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -114,7 +114,7 @@ uiHand = LEFT_HAND, miniUIOverlay = null, MINI_UI_HTML = Script.resolvePath("./html/miniTablet.html"), - MINI_UI_DIMENSIONS = { x: 0.059, y: 0.0865, z: 0.01 }, + MINI_UI_DIMENSIONS = { x: 0.059, y: 0.0865, z: 0.001 }, MINI_UI_WIDTH_PIXELS = 150, METERS_TO_INCHES = 39.3701, MINI_UI_DPI = MINI_UI_WIDTH_PIXELS / (MINI_UI_DIMENSIONS.x * METERS_TO_INCHES), @@ -124,7 +124,6 @@ miniUIOverlayEnabled = false, MINI_UI_OVERLAY_ENABLED_DELAY = 500, miniOverlayObject = null, - isReady = false, // Button icons. MUTE_ON_ICON = Script.resourcesPath() + "icons/tablet-icons/mic-mute-a.svg", @@ -172,8 +171,8 @@ function updateMutedStatus() { - var isMuted = Audio.muted; if (miniOverlayObject) { + var isMuted = Audio.muted; miniOverlayObject.emitScriptEvent(JSON.stringify({ type: MUTE_MESSAGE, on: isMuted, @@ -204,7 +203,6 @@ switch (message.type) { case READY_MESSAGE: // Send initial button statuses. - isReady = true; updateMutedStatus(); setGotoIcon(); break; @@ -451,6 +449,19 @@ }); } + function checkEventBridge() { + // The miniUIOverlay overlay's overlay object is not available immediately the overlay is created so we have to + // provide a means to check for and connect it when it does become available. + if (miniOverlayObject) { + return; + } + + miniOverlayObject = Overlays.getOverlayObject(miniUIOverlay); + if (miniOverlayObject) { + miniOverlayObject.webEventReceived.connect(onWebEventReceived); + } + } + function create() { miniOverlay = Overlays.addOverlay("model", { url: MINI_MODEL, @@ -476,6 +487,8 @@ }); miniUIOverlayEnabled = false; // This and alpha = 0 hides overlay while its content is being created. + + checkEventBridge(); } function destroy() { @@ -505,6 +518,7 @@ updateRotation: updateRotation, release: release, hide: hide, + checkEventBridge: checkEventBridge, destroy: destroy }; @@ -981,19 +995,7 @@ } function updateState() { - if (!ui.isReady) { - if (!ui.miniOverlayObject) { - // Keep trying to connect the event bridge until we succeed - ui.miniOverlayObject = Overlays.getOverlayObject(ui.miniUIOverlay); - if (ui.miniOverlayObject) { - ui.miniOverlayObject.webEventReceived.connect(ui.onWebEventReceived); - } - } else { - ui.miniOverlayObject.emitScriptEvent(JSON.stringify({ - type: READY_MESSAGE - })); - } - } + ui.checkEventBridge(); if (STATE_MACHINE[STATE_STRINGS[miniState]].update) { STATE_MACHINE[STATE_STRINGS[miniState]].update(); @@ -1142,4 +1144,4 @@ setUp(); Script.scriptEnding.connect(tearDown); -}()); +}()); \ No newline at end of file From 1b2cb94b0cd7e578b7089b0e4a55833a1a7a73e3 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Tue, 12 Feb 2019 13:21:21 -0800 Subject: [PATCH 096/139] Fix not changing input to processImage in TextureBaker.cpp --- libraries/baking/src/TextureBaker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/baking/src/TextureBaker.cpp b/libraries/baking/src/TextureBaker.cpp index b9e476b714..e069578bc5 100644 --- a/libraries/baking/src/TextureBaker.cpp +++ b/libraries/baking/src/TextureBaker.cpp @@ -154,7 +154,7 @@ void TextureBaker::processTexture() { gpu::BackendTarget::GLES32 }}; for (auto target : BACKEND_TARGETS) { - auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(), ColorChannelMapping::NONE, + auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(), image::TextureUsage::ColorChannel::NONE, ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, true, target, _abortProcessing); if (!processedTexture) { @@ -197,7 +197,7 @@ void TextureBaker::processTexture() { // Uncompressed KTX if (_textureType == image::TextureUsage::Type::CUBE_TEXTURE) { buffer->reset(); - auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), ColorChannelMapping::NONE, + auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), image::TextureUsage::ColorChannel::NONE, ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, false, gpu::BackendTarget::GL45, _abortProcessing); if (!processedTexture) { handleError("Could not process texture " + _textureURL.toString()); From eee41bc41e2c9380ddc0d3554eb3037e5fa4dd08 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Tue, 12 Feb 2019 13:46:21 -0800 Subject: [PATCH 097/139] Revert "Pack all non-instanced traits" This reverts commit 5b7d7b88331e0d5607cb6676b52b5056d7846cca. --- libraries/avatars/src/ClientTraitsHandler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index 3e188afbdf..bcbe5308c7 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -107,10 +107,11 @@ int ClientTraitsHandler::sendChangedTraitsToMixer() { if (initialSend || *simpleIt == Updated) { if (traitType == AvatarTraits::SkeletonModelURL) { + bytesWritten += _owningAvatar->packTrait(traitType, *traitsPacketList); + // keep track of our skeleton version in case we get an override back _currentSkeletonVersion = _currentTraitVersion; } - bytesWritten += _owningAvatar->packTrait(traitType, *traitsPacketList); } ++simpleIt; From 5e9b63b352c69309d5835be5ef812c8768a3baef Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 12 Feb 2019 13:56:56 -0800 Subject: [PATCH 098/139] fix-qml-crash-on-mac --- interface/resources/qml/+webengine/Browser.qml | 2 +- interface/resources/qml/+webengine/InfoView.qml | 2 +- interface/resources/qml/+webengine/QmlWebWindow.qml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/+webengine/Browser.qml b/interface/resources/qml/+webengine/Browser.qml index 52157bdf42..e00549347d 100644 --- a/interface/resources/qml/+webengine/Browser.qml +++ b/interface/resources/qml/+webengine/Browser.qml @@ -4,7 +4,7 @@ import QtWebEngine 1.5 import controlsUit 1.0 import stylesUit 1.0 -import "qrc:////qml//windows" +import "windows" ScrollingWindow { id: root diff --git a/interface/resources/qml/+webengine/InfoView.qml b/interface/resources/qml/+webengine/InfoView.qml index eb190c3c45..8c5900b4c3 100644 --- a/interface/resources/qml/+webengine/InfoView.qml +++ b/interface/resources/qml/+webengine/InfoView.qml @@ -12,7 +12,7 @@ import QtQuick 2.5 import Hifi 1.0 as Hifi import controlsUit 1.0 -import "qrc:////qml//windows" as Windows +import "windows" as Windows Windows.ScrollingWindow { id: root diff --git a/interface/resources/qml/+webengine/QmlWebWindow.qml b/interface/resources/qml/+webengine/QmlWebWindow.qml index 2e3718f6f5..35799d64a9 100644 --- a/interface/resources/qml/+webengine/QmlWebWindow.qml +++ b/interface/resources/qml/+webengine/QmlWebWindow.qml @@ -12,7 +12,7 @@ import QtQuick 2.5 import QtWebEngine 1.1 import QtWebChannel 1.0 -import "qrc:////qml//windows" as Windows +import "../windows" as Windows import controlsUit 1.0 as Controls import stylesUit 1.0 From ed8481ead9cc415562457c6626a5a9923f532753 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 12 Feb 2019 14:04:16 -0800 Subject: [PATCH 099/139] fix grab bugs --- interface/src/avatar/MyAvatar.cpp | 12 ++++++++++++ interface/src/avatar/MyAvatar.h | 1 + interface/src/avatar/OtherAvatar.cpp | 5 +++++ interface/src/avatar/OtherAvatar.h | 10 ++++++++++ .../src/avatars-renderer/Avatar.cpp | 12 +++++++----- .../src/avatars-renderer/Avatar.h | 7 ++----- libraries/avatars/src/AvatarData.h | 2 +- libraries/entities/src/EntityItem.cpp | 17 +++++++++++++++-- 8 files changed, 53 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6fef47da8e..b5a938faba 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -5313,3 +5313,15 @@ void MyAvatar::releaseGrab(const QUuid& grabID) { } } +void MyAvatar::sendPacket(const QUuid& entityID, const EntityItemProperties& properties) const { + auto treeRenderer = DependencyManager::get(); + EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; + if (entityTree) { + entityTree->withWriteLock([&] { + // force an update packet + EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender(); + packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree, entityID, properties); + }); + } +} + diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c53eae65d4..5e65c1ed7d 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1883,6 +1883,7 @@ private: bool didTeleport(); bool getIsAway() const { return _isAway; } void setAway(bool value); + void sendPacket(const QUuid& entityID, const EntityItemProperties& properties) const override; std::mutex _pinnedJointsMutex; std::vector _pinnedJoints; diff --git a/interface/src/avatar/OtherAvatar.cpp b/interface/src/avatar/OtherAvatar.cpp index 9496336ae1..f1a99ab5af 100755 --- a/interface/src/avatar/OtherAvatar.cpp +++ b/interface/src/avatar/OtherAvatar.cpp @@ -525,6 +525,11 @@ void OtherAvatar::handleChangedAvatarEntityData() { } } stateItr.value().success = success; + if (success) { + stateItr.value().hash = newHash; + } else { + stateItr.value().hash = 0; + } } AvatarEntityIDs recentlyRemovedAvatarEntities = getAndClearRecentlyRemovedIDs(); diff --git a/interface/src/avatar/OtherAvatar.h b/interface/src/avatar/OtherAvatar.h index 3ecd35413f..6461a0107c 100644 --- a/interface/src/avatar/OtherAvatar.h +++ b/interface/src/avatar/OtherAvatar.h @@ -76,6 +76,16 @@ protected: void onAddAttachedAvatarEntity(const QUuid& id); void onRemoveAttachedAvatarEntity(const QUuid& id); + class AvatarEntityDataHash { + public: + AvatarEntityDataHash(uint32_t h) : hash(h) {}; + uint32_t hash { 0 }; + bool success { false }; + }; + + using MapOfAvatarEntityDataHashes = QMap; + MapOfAvatarEntityDataHashes _avatarEntityDataHashes; + std::vector _attachedAvatarEntities; std::shared_ptr _otherAvatarOrbMeshPlaceholder { nullptr }; OverlayID _otherAvatarOrbMeshPlaceholderID { UNKNOWN_OVERLAY_ID }; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index daef0e411a..e6881b0efe 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -305,11 +305,6 @@ void Avatar::setTargetScale(float targetScale) { } } -void Avatar::setAvatarEntityDataChanged(bool value) { - AvatarData::setAvatarEntityDataChanged(value); - _avatarEntityDataHashes.clear(); -} - void Avatar::removeAvatarEntitiesFromTree() { auto treeRenderer = DependencyManager::get(); EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; @@ -368,6 +363,13 @@ bool Avatar::applyGrabChanges() { target->removeGrab(grab); _avatarGrabs.erase(itr); grabAddedOrRemoved = true; + if (isMyAvatar()) { + const EntityItemPointer& entity = std::dynamic_pointer_cast(target); + if (entity && entity->getEntityHostType() == entity::HostType::AVATAR && entity->getSimulationOwner().getID() == getID()) { + EntityItemProperties properties = entity->getProperties(); + sendPacket(entity->getID(), properties); + } + } } else { undeleted.push_back(id); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index b43fe012b7..06942a13d8 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -480,8 +481,6 @@ public: virtual void setModelScale(float scale) { _modelScale = scale; } virtual glm::vec3 scaleForChildren() const override { return glm::vec3(getModelScale()); } - virtual void setAvatarEntityDataChanged(bool value) override; - // Show hide the model representation of the avatar virtual void setEnableMeshVisible(bool isEnabled); virtual bool getEnableMeshVisible() const; @@ -603,6 +602,7 @@ protected: // protected methods... bool isLookingAtMe(AvatarSharedPointer avatar) const; + virtual void sendPacket(const QUuid& entityID, const EntityItemProperties& properties) const { } bool applyGrabChanges(); void relayJointDataToChildren(); @@ -647,9 +647,6 @@ protected: bool success { false }; }; - using MapOfAvatarEntityDataHashes = QMap; - MapOfAvatarEntityDataHashes _avatarEntityDataHashes; - uint64_t _lastRenderUpdateTime { 0 }; int _leftPointerGeometryID { 0 }; int _rightPointerGeometryID { 0 }; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index d071b74d6e..63396a59ac 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1147,7 +1147,7 @@ public: */ Q_INVOKABLE virtual void setAvatarEntityData(const AvatarEntityMap& avatarEntityData); - virtual void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; } + void setAvatarEntityDataChanged(bool value) { _avatarEntityDataChanged = value; } AvatarEntityIDs getAndClearRecentlyRemovedIDs(); /**jsdoc diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index c5d72d2d7b..d2650ca80b 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2170,6 +2170,12 @@ void EntityItem::enableNoBootstrap() { if (!(bool)(_flags & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING)) { _flags |= Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING; _flags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar + + // NOTE: unlike disableNoBootstrap() below, we do not call simulation->changeEntity() here + // because most enableNoBootstrap() cases are already correctly handled outside this scope + // and I didn't want to add redundant work. + // TODO: cleanup Grabs & dirtySimulationFlags to be more efficient and make more sense. + forEachDescendant([&](SpatiallyNestablePointer child) { if (child->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(child); @@ -2184,11 +2190,19 @@ void EntityItem::disableNoBootstrap() { if (!stillHasGrabActions()) { _flags &= ~Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING; _flags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar + + EntityTreePointer entityTree = getTree(); + assert(entityTree); + EntitySimulationPointer simulation = entityTree->getSimulation(); + assert(simulation); + simulation->changeEntity(getThisPointer()); + forEachDescendant([&](SpatiallyNestablePointer child) { if (child->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(child); entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP); entity->clearSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING); + simulation->changeEntity(entity); } }); } @@ -3445,7 +3459,7 @@ void EntityItem::addGrab(GrabPointer grab) { if (useAction) { EntityTreePointer entityTree = getTree(); assert(entityTree); - EntitySimulationPointer simulation = entityTree ? entityTree->getSimulation() : nullptr; + EntitySimulationPointer simulation = entityTree->getSimulation(); assert(simulation); auto actionFactory = DependencyManager::get(); @@ -3494,7 +3508,6 @@ void EntityItem::removeGrab(GrabPointer grab) { setLocalVelocity(glm::vec3(0.0f)); setAngularVelocity(glm::vec3(0.0f)); } - markDirtyFlags(Simulation::DIRTY_MOTION_TYPE); QUuid actionID = grab->getActionID(); if (!actionID.isNull()) { From 17ab0cb92e2c2aedf35e5b5d363acd779c01c9f8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 8 Feb 2019 13:12:10 -0800 Subject: [PATCH 100/139] more robust ShapeManager garbage collector --- libraries/physics/src/ShapeManager.cpp | 11 +++++++++-- libraries/physics/src/ShapeManager.h | 2 +- libraries/shared/src/HashKey.h | 3 +++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index ef7a4a1749..cb37b0f96d 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -57,7 +57,14 @@ bool ShapeManager::releaseShapeByKey(const HashKey& key) { if (shapeRef->refCount > 0) { shapeRef->refCount--; if (shapeRef->refCount == 0) { - _pendingGarbage.push_back(key); + // look for existing entry in _pendingGarbage, starting from the back + for (int32_t i = _pendingGarbage.size() - 1; i > -1; --i) { + if (_pendingGarbage[i] == key.getHash64()) { + // already on the list, don't add it again + return true; + } + } + _pendingGarbage.push_back(key.getHash64()); const int MAX_SHAPE_GARBAGE_CAPACITY = 255; if (_pendingGarbage.size() > MAX_SHAPE_GARBAGE_CAPACITY) { collectGarbage(); @@ -89,7 +96,7 @@ bool ShapeManager::releaseShape(const btCollisionShape* shape) { void ShapeManager::collectGarbage() { int numShapes = _pendingGarbage.size(); for (int i = 0; i < numShapes; ++i) { - HashKey& key = _pendingGarbage[i]; + HashKey key(_pendingGarbage[i]); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef && shapeRef->refCount == 0) { ShapeFactory::deleteShape(shapeRef->shape); diff --git a/libraries/physics/src/ShapeManager.h b/libraries/physics/src/ShapeManager.h index d75bb1dc4a..58f1b53c18 100644 --- a/libraries/physics/src/ShapeManager.h +++ b/libraries/physics/src/ShapeManager.h @@ -75,7 +75,7 @@ private: // btHashMap is required because it supports memory alignment of the btCollisionShapes btHashMap _shapeMap; - btAlignedObjectArray _pendingGarbage; + btAlignedObjectArray _pendingGarbage; }; #endif // hifi_ShapeManager_h diff --git a/libraries/shared/src/HashKey.h b/libraries/shared/src/HashKey.h index 5fce182084..a32a8664a7 100644 --- a/libraries/shared/src/HashKey.h +++ b/libraries/shared/src/HashKey.h @@ -32,6 +32,9 @@ class HashKey { public: static float getNumQuantizedValuesPerMeter(); + HashKey() {} + HashKey(uint64_t hash) : _hash(hash) {} + // These two methods are required by btHashMap. bool equals(const HashKey& other) const { return _hash == other._hash; } int32_t getHash() const { return (int32_t)((uint32_t)_hash); } From a3567dea3a2db620262f503a770fe750812dbf47 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 8 Feb 2019 14:18:33 -0800 Subject: [PATCH 101/139] clean HashKey API, reduce dependency tree --- libraries/physics/src/ShapeManager.cpp | 21 +++++------ libraries/physics/src/ShapeManager.h | 4 +-- libraries/shared/src/HashKey.h | 5 ++- libraries/shared/src/ShapeInfo.cpp | 49 ++++++++++++++------------ libraries/shared/src/ShapeInfo.h | 6 ++-- 5 files changed, 43 insertions(+), 42 deletions(-) diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index cb37b0f96d..991cd0efc9 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -33,8 +33,8 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { if (info.getType() == SHAPE_TYPE_NONE) { return nullptr; } - HashKey key = info.getHash(); - ShapeReference* shapeRef = _shapeMap.find(key); + HashKey hashKey(info.getHash()); + ShapeReference* shapeRef = _shapeMap.find(hashKey); if (shapeRef) { shapeRef->refCount++; return shapeRef->shape; @@ -44,27 +44,28 @@ const btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { ShapeReference newRef; newRef.refCount = 1; newRef.shape = shape; - newRef.key = key; - _shapeMap.insert(key, newRef); + newRef.key = info.getHash(); + _shapeMap.insert(hashKey, newRef); } return shape; } // private helper method -bool ShapeManager::releaseShapeByKey(const HashKey& key) { - ShapeReference* shapeRef = _shapeMap.find(key); +bool ShapeManager::releaseShapeByKey(uint64_t key) { + HashKey hashKey(key); + ShapeReference* shapeRef = _shapeMap.find(hashKey); if (shapeRef) { if (shapeRef->refCount > 0) { shapeRef->refCount--; if (shapeRef->refCount == 0) { // look for existing entry in _pendingGarbage, starting from the back for (int32_t i = _pendingGarbage.size() - 1; i > -1; --i) { - if (_pendingGarbage[i] == key.getHash64()) { + if (_pendingGarbage[i] == key) { // already on the list, don't add it again return true; } } - _pendingGarbage.push_back(key.getHash64()); + _pendingGarbage.push_back(key); const int MAX_SHAPE_GARBAGE_CAPACITY = 255; if (_pendingGarbage.size() > MAX_SHAPE_GARBAGE_CAPACITY) { collectGarbage(); @@ -107,8 +108,8 @@ void ShapeManager::collectGarbage() { } int ShapeManager::getNumReferences(const ShapeInfo& info) const { - HashKey key = info.getHash(); - const ShapeReference* shapeRef = _shapeMap.find(key); + HashKey hashKey(info.getHash()); + const ShapeReference* shapeRef = _shapeMap.find(hashKey); if (shapeRef) { return shapeRef->refCount; } diff --git a/libraries/physics/src/ShapeManager.h b/libraries/physics/src/ShapeManager.h index 58f1b53c18..47b6c5340a 100644 --- a/libraries/physics/src/ShapeManager.h +++ b/libraries/physics/src/ShapeManager.h @@ -63,13 +63,13 @@ public: bool hasShape(const btCollisionShape* shape) const; private: - bool releaseShapeByKey(const HashKey& key); + bool releaseShapeByKey(uint64_t key); class ShapeReference { public: int refCount; const btCollisionShape* shape; - HashKey key; + uint64_t key { 0 }; ShapeReference() : refCount(0), shape(nullptr) {} }; diff --git a/libraries/shared/src/HashKey.h b/libraries/shared/src/HashKey.h index a32a8664a7..446eb4c25f 100644 --- a/libraries/shared/src/HashKey.h +++ b/libraries/shared/src/HashKey.h @@ -39,13 +39,12 @@ public: bool equals(const HashKey& other) const { return _hash == other._hash; } int32_t getHash() const { return (int32_t)((uint32_t)_hash); } - void clear() { _hash = _hashCount = 0; } - bool isNull() const { return _hash == 0 && _hashCount == 0; } + // These methods for accumulating a hash. void hashUint64(uint64_t data); void hashFloat(float data); void hashVec3(const glm::vec3& data); - uint64_t getHash64() const { return _hash; } // for debug/test purposes + uint64_t getHash64() const { return _hash; } private: uint64_t _hash { 0 }; diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index c256cf2b76..bf51e455c5 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -13,6 +13,7 @@ #include +#include "HashKey.h" #include "NumericalConstants.h" // for MILLIMETERS_PER_METER /**jsdoc @@ -96,7 +97,7 @@ void ShapeInfo::clear() { _sphereCollection.clear(); _halfExtents = glm::vec3(0.0f); _offset = glm::vec3(0.0f); - _hashKey.clear(); + _hash64 = 0; _type = SHAPE_TYPE_NONE; } @@ -131,14 +132,14 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString default: break; } - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setBox(const glm::vec3& halfExtents) { _url = ""; _type = SHAPE_TYPE_BOX; setHalfExtents(halfExtents); - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setSphere(float radius) { @@ -146,7 +147,7 @@ void ShapeInfo::setSphere(float radius) { _type = SHAPE_TYPE_SPHERE; radius = glm::max(radius, MIN_HALF_EXTENT); _halfExtents = glm::vec3(radius); - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setMultiSphere(const std::vector& centers, const std::vector& radiuses) { @@ -158,12 +159,12 @@ void ShapeInfo::setMultiSphere(const std::vector& centers, const std: SphereData sphere = SphereData(centers[i], radiuses[i]); _sphereCollection.push_back(sphere); } - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setPointCollection(const ShapeInfo::PointCollection& pointCollection) { _pointCollection = pointCollection; - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setCapsuleY(float radius, float cylinderHalfHeight) { @@ -172,12 +173,12 @@ void ShapeInfo::setCapsuleY(float radius, float cylinderHalfHeight) { radius = glm::max(radius, MIN_HALF_EXTENT); cylinderHalfHeight = glm::max(cylinderHalfHeight, 0.0f); _halfExtents = glm::vec3(radius, cylinderHalfHeight + radius, radius); - _hashKey.clear(); + _hash64 = 0; } void ShapeInfo::setOffset(const glm::vec3& offset) { _offset = offset; - _hashKey.clear(); + _hash64 = 0; } uint32_t ShapeInfo::getNumSubShapes() const { @@ -269,20 +270,21 @@ float ShapeInfo::computeVolume() const { return volume; } -const HashKey& ShapeInfo::getHash() const { +uint64_t ShapeInfo::getHash() const { // NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance. - if (_hashKey.isNull() && _type != SHAPE_TYPE_NONE) { + if (_hash64 == 0 && _type != SHAPE_TYPE_NONE) { + HashKey hashKey; // The key is not yet cached therefore we must compute it. - _hashKey.hashUint64((uint64_t)_type); + hashKey.hashUint64((uint64_t)_type); if (_type == SHAPE_TYPE_MULTISPHERE) { for (auto &sphereData : _sphereCollection) { - _hashKey.hashVec3(glm::vec3(sphereData)); - _hashKey.hashFloat(sphereData.w); + hashKey.hashVec3(glm::vec3(sphereData)); + hashKey.hashFloat(sphereData.w); } } else if (_type != SHAPE_TYPE_SIMPLE_HULL) { - _hashKey.hashVec3(_halfExtents); - _hashKey.hashVec3(_offset); + hashKey.hashVec3(_halfExtents); + hashKey.hashVec3(_offset); } else { // TODO: we could avoid hashing all of these points if we were to supply the ShapeInfo with a unique // descriptive string. Shapes that are uniquely described by their type and URL could just put their @@ -292,7 +294,7 @@ const HashKey& ShapeInfo::getHash() const { const int numPoints = (int)points.size(); for (int i = 0; i < numPoints; ++i) { - _hashKey.hashVec3(points[i]); + hashKey.hashVec3(points[i]); } } @@ -300,23 +302,24 @@ const HashKey& ShapeInfo::getHash() const { if (!url.isEmpty()) { QByteArray baUrl = url.toLocal8Bit(); uint32_t urlHash = qChecksum(baUrl.data(), baUrl.size()); - _hashKey.hashUint64((uint64_t)urlHash); + hashKey.hashUint64((uint64_t)urlHash); } if (_type == SHAPE_TYPE_COMPOUND || _type == SHAPE_TYPE_SIMPLE_COMPOUND) { uint64_t numHulls = (uint64_t)_pointCollection.size(); - _hashKey.hashUint64(numHulls); + hashKey.hashUint64(numHulls); } else if (_type == SHAPE_TYPE_MULTISPHERE) { uint64_t numSpheres = (uint64_t)_sphereCollection.size(); - _hashKey.hashUint64(numSpheres); + hashKey.hashUint64(numSpheres); } else if (_type == SHAPE_TYPE_SIMPLE_HULL) { - _hashKey.hashUint64(1); - } + hashKey.hashUint64(1); + } + _hash64 = hashKey.getHash64(); } - return _hashKey; + return _hash64; } void ShapeInfo::setHalfExtents(const glm::vec3& halfExtents) { _halfExtents = glm::max(halfExtents, glm::vec3(MIN_HALF_EXTENT)); - _hashKey.clear(); + _hash64 = 0; } diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index d838d7b214..6b0f981b24 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -18,8 +18,6 @@ #include #include -#include "HashKey.h" - const float MIN_SHAPE_OFFSET = 0.001f; // offsets less than 1mm will be ignored // Bullet has a mesh generation util for convex shapes that we used to @@ -91,7 +89,7 @@ public: float computeVolume() const; - const HashKey& getHash() const; + uint64_t getHash() const; protected: void setHalfExtents(const glm::vec3& halfExtents); @@ -102,7 +100,7 @@ protected: TriangleIndices _triangleIndices; glm::vec3 _halfExtents = glm::vec3(0.0f); glm::vec3 _offset = glm::vec3(0.0f); - mutable HashKey _hashKey; + mutable uint64_t _hash64; ShapeType _type = SHAPE_TYPE_NONE; }; From d7f38bac17c9945e3eda395c366cf037fbf5ba27 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 8 Feb 2019 14:50:30 -0800 Subject: [PATCH 102/139] fix ShapeInfoTests to use reduced HashKey API --- tests/physics/src/ShapeInfoTests.cpp | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/physics/src/ShapeInfoTests.cpp b/tests/physics/src/ShapeInfoTests.cpp index efc88a4032..0116eb027f 100644 --- a/tests/physics/src/ShapeInfoTests.cpp +++ b/tests/physics/src/ShapeInfoTests.cpp @@ -55,20 +55,20 @@ void ShapeInfoTests::testHashFunctions() { // test sphere info.setSphere(radiusX); ++testCount; - HashKey key = info.getHash(); - hashPtr = hashes.find(key); + HashKey hashKey(info.getHash()); + hashPtr = hashes.find(hashKey); if (hashPtr) { std::cout << testCount << " hash collision sphere radius = " << radiusX - << " h = 0x" << std::hex << key.getHash() << " : 0x" << *hashPtr + << " h = 0x" << std::hex << hashKey.getHash() << " : 0x" << *hashPtr << std::dec << std::endl; ++numCollisions; assert(false); } else { - hashes.insert(key, key.getHash()); + hashes.insert(hashKey, hashKey.getHash()); } // track bit distribution counts to evaluate hash function randomness for (int j = 0; j < NUM_HASH_BITS; ++j) { - if (masks[j] & key.getHash()) { + if (masks[j] & hashKey.getHash()) { ++bits[j]; } } @@ -80,21 +80,21 @@ void ShapeInfoTests::testHashFunctions() { // test box info.setBox(glm::vec3(radiusX, radiusY, radiusZ)); ++testCount; - HashKey key = info.getHash(); - hashPtr = hashes.find(key); + HashKey hashKey(info.getHash()); + hashPtr = hashes.find(hashKey); if (hashPtr) { std::cout << testCount << " hash collision box dimensions = < " << radiusX << ", " << radiusY << ", " << radiusZ << " >" - << " h = 0x" << std::hex << key.getHash() << " : 0x" << *hashPtr << " : 0x" << key.getHash64() + << " h = 0x" << std::hex << hashKey.getHash() << " : 0x" << *hashPtr << " : 0x" << hashKey.getHash64() << std::dec << std::endl; ++numCollisions; assert(false); } else { - hashes.insert(key, key.getHash()); + hashes.insert(hashKey, hashKey.getHash()); } // track bit distribution counts to evaluate hash function randomness for (int k = 0; k < NUM_HASH_BITS; ++k) { - if (masks[k] & key.getHash()) { + if (masks[k] & hashKey.getHash()) { ++bits[k]; } } @@ -117,14 +117,14 @@ void ShapeInfoTests::testBoxShape() { ShapeInfo info; glm::vec3 halfExtents(1.23f, 4.56f, 7.89f); info.setBox(halfExtents); - HashKey key = info.getHash(); + HashKey hashKey(info.getHash()); const btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; HashKey otherKey = otherInfo.getHash(); - QCOMPARE(key.getHash(), otherKey.getHash()); + QCOMPARE(hashKey.getHash(), otherKey.getHash()); delete shape; } @@ -133,14 +133,14 @@ void ShapeInfoTests::testSphereShape() { ShapeInfo info; float radius = 1.23f; info.setSphere(radius); - HashKey key = info.getHash(); + HashKey hashKey = info.getHash(); const btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; HashKey otherKey = otherInfo.getHash(); - QCOMPARE(key.getHash(), otherKey.getHash()); + QCOMPARE(hashKey.getHash(), otherKey.getHash()); delete shape; } @@ -151,14 +151,14 @@ void ShapeInfoTests::testCylinderShape() { float radius = 1.23f; float height = 4.56f; info.setCylinder(radius, height); - HashKey key = info.getHash(); + HashKey hashKey(info.getHash()); btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; HashKey otherKey = otherInfo.getHash(); - QCOMPARE(key.getHash(), otherKey.getHash()); + QCOMPARE(hashKey.getHash(), otherKey.getHash()); delete shape; */ @@ -170,14 +170,14 @@ void ShapeInfoTests::testCapsuleShape() { float radius = 1.23f; float height = 4.56f; info.setCapsule(radius, height); - HashKey key = info.getHash(); + HashKey hashKey(info.getHash()); btCollisionShape* shape = ShapeFactory::createShapeFromInfo(info); QCOMPARE(shape != nullptr, true); ShapeInfo otherInfo = info; HashKey otherKey = otherInfo.getHash(); - QCOMPARE(key.getHash(), otherKey.getHash()); + QCOMPARE(hashKey.getHash(), otherKey.getHash()); delete shape; */ From c9b142531bbdbcc8b63669d70ee19d4e10eaf087 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Sat, 9 Feb 2019 08:21:24 -0800 Subject: [PATCH 103/139] add more tracing details in PrePhysics --- libraries/physics/src/ShapeManager.cpp | 36 +++++++++++++++++++------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index 991cd0efc9..ad937d2bcc 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -17,7 +17,10 @@ #include "ShapeFactory.h" +const int MAX_RING_SIZE = 256; + ShapeManager::ShapeManager() { + _garbageRing.reserve(MAX_RING_SIZE); } ShapeManager::~ShapeManager() { @@ -58,17 +61,29 @@ bool ShapeManager::releaseShapeByKey(uint64_t key) { if (shapeRef->refCount > 0) { shapeRef->refCount--; if (shapeRef->refCount == 0) { - // look for existing entry in _pendingGarbage, starting from the back - for (int32_t i = _pendingGarbage.size() - 1; i > -1; --i) { - if (_pendingGarbage[i] == key) { + // look for existing entry in _garbageRing + int32_t ringSize = _garbageRing.size(); + for (int32_t i = 0; i < ringSize; ++i) { + int32_t j = (_ringIndex + ringSize) % ringSize; + if (_garbageRing[j] == key) { // already on the list, don't add it again return true; } } - _pendingGarbage.push_back(key); - const int MAX_SHAPE_GARBAGE_CAPACITY = 255; - if (_pendingGarbage.size() > MAX_SHAPE_GARBAGE_CAPACITY) { - collectGarbage(); + if (ringSize == MAX_RING_SIZE) { + // remove one + HashKey hashKeyToRemove(_garbageRing[_ringIndex]); + ShapeReference* shapeRef = _shapeMap.find(hashKeyToRemove); + if (shapeRef && shapeRef->refCount == 0) { + ShapeFactory::deleteShape(shapeRef->shape); + _shapeMap.remove(hashKeyToRemove); + } + // replace at _ringIndex and advance + _garbageRing[_ringIndex] = key; + _ringIndex = (_ringIndex + 1) % ringSize; + } else { + // add one + _garbageRing.push_back(key); } } return true; @@ -95,16 +110,17 @@ bool ShapeManager::releaseShape(const btCollisionShape* shape) { } void ShapeManager::collectGarbage() { - int numShapes = _pendingGarbage.size(); + int numShapes = _garbageRing.size(); for (int i = 0; i < numShapes; ++i) { - HashKey key(_pendingGarbage[i]); + HashKey key(_garbageRing[i]); ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef && shapeRef->refCount == 0) { ShapeFactory::deleteShape(shapeRef->shape); _shapeMap.remove(key); } } - _pendingGarbage.clear(); + _ringIndex = 0; + _garbageRing.clear(); } int ShapeManager::getNumReferences(const ShapeInfo& info) const { From 8bdac589b88f3339bf7f4a4f9f4c1017a4cd296f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Sat, 9 Feb 2019 08:23:09 -0800 Subject: [PATCH 104/139] use RingBuffer for gradual garbage collection --- interface/src/Application.cpp | 59 +++++++++++++++++----------- libraries/physics/src/ShapeManager.h | 8 +++- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1029398794..b3c978df9a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6309,40 +6309,53 @@ void Application::update(float deltaTime) { PROFILE_RANGE(simulation_physics, "PrePhysics"); PerformanceTimer perfTimer("prePhysics)"); { + PROFILE_RANGE(simulation_physics, "RemoveEntities"); const VectorOfMotionStates& motionStates = _entitySimulation->getObjectsToRemoveFromPhysics(); _physicsEngine->removeObjects(motionStates); _entitySimulation->deleteObjectsRemovedFromPhysics(); } - VectorOfMotionStates motionStates; - getEntities()->getTree()->withReadLock([&] { - _entitySimulation->getObjectsToAddToPhysics(motionStates); - _physicsEngine->addObjects(motionStates); - - }); - getEntities()->getTree()->withReadLock([&] { - _entitySimulation->getObjectsToChange(motionStates); - VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates); - _entitySimulation->setObjectsToChange(stillNeedChange); - }); + { + PROFILE_RANGE(simulation_physics, "AddEntities"); + VectorOfMotionStates motionStates; + getEntities()->getTree()->withReadLock([&] { + _entitySimulation->getObjectsToAddToPhysics(motionStates); + _physicsEngine->addObjects(motionStates); + }); + } + { + VectorOfMotionStates motionStates; + PROFILE_RANGE(simulation_physics, "ChangeEntities"); + getEntities()->getTree()->withReadLock([&] { + _entitySimulation->getObjectsToChange(motionStates); + VectorOfMotionStates stillNeedChange = _physicsEngine->changeObjects(motionStates); + _entitySimulation->setObjectsToChange(stillNeedChange); + }); + } _entitySimulation->applyDynamicChanges(); t1 = std::chrono::high_resolution_clock::now(); - PhysicsEngine::Transaction transaction; - avatarManager->buildPhysicsTransaction(transaction); - _physicsEngine->processTransaction(transaction); - avatarManager->handleProcessedPhysicsTransaction(transaction); - myAvatar->getCharacterController()->buildPhysicsTransaction(transaction); - _physicsEngine->processTransaction(transaction); - myAvatar->getCharacterController()->handleProcessedPhysicsTransaction(transaction); - myAvatar->prepareForPhysicsSimulation(); - _physicsEngine->enableGlobalContactAddedCallback(myAvatar->isFlying()); + { + PROFILE_RANGE(simulation_physics, "Avatars"); + PhysicsEngine::Transaction transaction; + avatarManager->buildPhysicsTransaction(transaction); + _physicsEngine->processTransaction(transaction); + avatarManager->handleProcessedPhysicsTransaction(transaction); + myAvatar->getCharacterController()->buildPhysicsTransaction(transaction); + _physicsEngine->processTransaction(transaction); + myAvatar->getCharacterController()->handleProcessedPhysicsTransaction(transaction); + myAvatar->prepareForPhysicsSimulation(); + _physicsEngine->enableGlobalContactAddedCallback(myAvatar->isFlying()); + } - _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) { - dynamic->prepareForPhysicsSimulation(); - }); + { + PROFILE_RANGE(simulation_physics, "PrepareActions"); + _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) { + dynamic->prepareForPhysicsSimulation(); + }); + } } auto t2 = std::chrono::high_resolution_clock::now(); { diff --git a/libraries/physics/src/ShapeManager.h b/libraries/physics/src/ShapeManager.h index 47b6c5340a..7583b7d919 100644 --- a/libraries/physics/src/ShapeManager.h +++ b/libraries/physics/src/ShapeManager.h @@ -12,6 +12,8 @@ #ifndef hifi_ShapeManager_h #define hifi_ShapeManager_h +#include + #include #include @@ -41,6 +43,7 @@ // later. When that list grows big enough the ShapeManager will remove any matching // entries that still have zero ref-count. + class ShapeManager { public: @@ -75,7 +78,10 @@ private: // btHashMap is required because it supports memory alignment of the btCollisionShapes btHashMap _shapeMap; - btAlignedObjectArray _pendingGarbage; + //btAlignedObjectArray _pendingGarbage; + + std::vector _garbageRing; + uint32_t _ringIndex { 0 }; }; #endif // hifi_ShapeManager_h From d4c52e4b1c2fbef3b31664383a665510ebd9fd68 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 11 Feb 2019 09:16:31 -0800 Subject: [PATCH 105/139] fix implicit cast warning for Visual Studio --- libraries/physics/src/ShapeManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index ad937d2bcc..8acbe51540 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -62,7 +62,7 @@ bool ShapeManager::releaseShapeByKey(uint64_t key) { shapeRef->refCount--; if (shapeRef->refCount == 0) { // look for existing entry in _garbageRing - int32_t ringSize = _garbageRing.size(); + int32_t ringSize = (int32_t)(_garbageRing.size()); for (int32_t i = 0; i < ringSize; ++i) { int32_t j = (_ringIndex + ringSize) % ringSize; if (_garbageRing[j] == key) { @@ -110,7 +110,7 @@ bool ShapeManager::releaseShape(const btCollisionShape* shape) { } void ShapeManager::collectGarbage() { - int numShapes = _garbageRing.size(); + int numShapes = (int32_t)(_garbageRing.size()); for (int i = 0; i < numShapes; ++i) { HashKey key(_garbageRing[i]); ShapeReference* shapeRef = _shapeMap.find(key); From b2af6d1374dcf5e19a7f376ea4c773197600c9c2 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Tue, 12 Feb 2019 16:14:41 -0800 Subject: [PATCH 106/139] Have only one ColorChannel enum as header in image library --- libraries/baking/src/TextureBaker.cpp | 4 ++-- libraries/fbx/src/GLTFSerializer.cpp | 5 +++-- libraries/hfm/CMakeLists.txt | 1 + libraries/hfm/src/hfm/HFM.h | 4 ++-- .../src/hfm => image/src/image}/ColorChannel.h | 10 +++++----- libraries/image/src/image/Image.cpp | 14 +++++++------- libraries/image/src/image/Image.h | 4 +++- .../src/model-networking/TextureCache.cpp | 16 ++++++++-------- .../src/model-networking/TextureCache.h | 8 ++++---- libraries/procedural/CMakeLists.txt | 2 -- 10 files changed, 35 insertions(+), 33 deletions(-) rename libraries/{hfm/src/hfm => image/src/image}/ColorChannel.h (71%) diff --git a/libraries/baking/src/TextureBaker.cpp b/libraries/baking/src/TextureBaker.cpp index e069578bc5..6407ce1846 100644 --- a/libraries/baking/src/TextureBaker.cpp +++ b/libraries/baking/src/TextureBaker.cpp @@ -154,7 +154,7 @@ void TextureBaker::processTexture() { gpu::BackendTarget::GLES32 }}; for (auto target : BACKEND_TARGETS) { - auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(), image::TextureUsage::ColorChannel::NONE, + auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(), image::ColorChannel::NONE, ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, true, target, _abortProcessing); if (!processedTexture) { @@ -197,7 +197,7 @@ void TextureBaker::processTexture() { // Uncompressed KTX if (_textureType == image::TextureUsage::Type::CUBE_TEXTURE) { buffer->reset(); - auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), image::TextureUsage::ColorChannel::NONE, + auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), image::ColorChannel::NONE, ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, false, gpu::BackendTarget::GL45, _abortProcessing); if (!processedTexture) { handleError("Could not process texture " + _textureURL.toString()); diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index eb29ef3fad..82a4361723 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "FBXSerializer.h" @@ -1146,10 +1147,10 @@ void GLTFSerializer::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& mat } if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) { fbxmat.roughnessTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); - fbxmat.roughnessTexture.sourceChannel = hfm::ColorChannel::GREEN; + fbxmat.roughnessTexture.sourceChannel = image::ColorChannel::GREEN; fbxmat.useRoughnessMap = true; fbxmat.metallicTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); - fbxmat.metallicTexture.sourceChannel = hfm::ColorChannel::BLUE; + fbxmat.metallicTexture.sourceChannel = image::ColorChannel::BLUE; fbxmat.useMetallicMap = true; } if (material.pbrMetallicRoughness.defined["roughnessFactor"]) { diff --git a/libraries/hfm/CMakeLists.txt b/libraries/hfm/CMakeLists.txt index 553fd935d9..be3d866b70 100644 --- a/libraries/hfm/CMakeLists.txt +++ b/libraries/hfm/CMakeLists.txt @@ -5,3 +5,4 @@ link_hifi_libraries(shared) include_hifi_library_headers(gpu) include_hifi_library_headers(graphics) +include_hifi_library_headers(image) diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 68b091c8d8..577ca6f413 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -25,7 +25,7 @@ #include #include -#include "ColorChannel.h" +#include #if defined(Q_OS_ANDROID) #define HFM_PACK_NORMALS 0 @@ -125,7 +125,7 @@ public: QString name; QByteArray filename; QByteArray content; - ColorChannel sourceChannel { ColorChannel::NONE }; + image::ColorChannel sourceChannel { image::ColorChannel::NONE }; Transform transform; int maxNumPixels { MAX_NUM_PIXELS_FOR_FBX_TEXTURE }; diff --git a/libraries/hfm/src/hfm/ColorChannel.h b/libraries/image/src/image/ColorChannel.h similarity index 71% rename from libraries/hfm/src/hfm/ColorChannel.h rename to libraries/image/src/image/ColorChannel.h index a5db0354da..e1d107018b 100644 --- a/libraries/hfm/src/hfm/ColorChannel.h +++ b/libraries/image/src/image/ColorChannel.h @@ -1,6 +1,6 @@ // // ColorChannel.h -// libraries/hfm/src +// libraries/image/src/image // // Created by Sabrina Shanman on 2019/02/12. // Copyright 2019 High Fidelity, Inc. @@ -9,10 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_hfm_ColorChannel_h -#define hifi_hfm_ColorChannel_h +#ifndef hifi_image_ColorChannel_h +#define hifi_image_ColorChannel_h -namespace hfm { +namespace image { enum class ColorChannel { NONE, RED, @@ -23,4 +23,4 @@ namespace hfm { }; }; -#endif // hifi_hfm_ColorChannel_h +#endif // hifi_image_ColorChannel_h diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index e2ee8c68f8..a2161caec9 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -222,7 +222,7 @@ QImage processRawImageData(QIODevice& content, const std::string& filename) { return QImage(); } -void mapToRedChannel(QImage& image, TextureUsage::ColorChannel sourceChannel) { +void mapToRedChannel(QImage& image, ColorChannel sourceChannel) { // Change format of image so we know exactly how to process it if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); @@ -237,16 +237,16 @@ void mapToRedChannel(QImage& image, TextureUsage::ColorChannel sourceChannel) { for (; pixel < lineEnd; pixel++) { int colorValue; switch (sourceChannel) { - case TextureUsage::ColorChannel::RED: + case ColorChannel::RED: colorValue = qRed(*pixel); break; - case TextureUsage::ColorChannel::GREEN: + case ColorChannel::GREEN: colorValue = qGreen(*pixel); break; - case TextureUsage::ColorChannel::BLUE: + case ColorChannel::BLUE: colorValue = qBlue(*pixel); break; - case TextureUsage::ColorChannel::ALPHA: + case ColorChannel::ALPHA: colorValue = qAlpha(*pixel); break; default: @@ -260,7 +260,7 @@ void mapToRedChannel(QImage& image, TextureUsage::ColorChannel sourceChannel) { } } -gpu::TexturePointer processImage(std::shared_ptr content, const std::string& filename, TextureUsage::ColorChannel sourceChannel, +gpu::TexturePointer processImage(std::shared_ptr content, const std::string& filename, ColorChannel sourceChannel, int maxNumPixels, TextureUsage::Type textureType, bool compress, BackendTarget target, const std::atomic& abortProcessing) { @@ -293,7 +293,7 @@ gpu::TexturePointer processImage(std::shared_ptr content, const std:: } // Re-map to image with single red channel texture if requested - if (sourceChannel != TextureUsage::ColorChannel::NONE) { + if (sourceChannel != ColorChannel::NONE) { mapToRedChannel(image, sourceChannel); } diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index 5497d72fe9..74e9268451 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -16,6 +16,8 @@ #include +#include "ColorChannel.h" + class QByteArray; class QImage; @@ -90,7 +92,7 @@ gpu::TexturePointer processCubeTextureColorFromImage(QImage&& srcImage, const st const QStringList getSupportedFormats(); -gpu::TexturePointer processImage(std::shared_ptr content, const std::string& url, TextureUsage::ColorChannel sourceChannel, +gpu::TexturePointer processImage(std::shared_ptr content, const std::string& url, ColorChannel sourceChannel, int maxNumPixels, TextureUsage::Type textureType, bool compress, gpu::BackendTarget target, const std::atomic& abortProcessing = false); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 54f991a179..a78812b2f9 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -192,7 +192,7 @@ public: image::TextureUsage::Type type; const QByteArray& content; int maxNumPixels; - hfm::ColorChannel sourceChannel; + image::ColorChannel sourceChannel; }; namespace std { @@ -213,13 +213,13 @@ namespace std { }; } -ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels, hfm::ColorChannel sourceChannel) { +ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels, image::ColorChannel sourceChannel) { auto byteArray = QByteArray(); TextureExtra extra = { (image::TextureUsage::Type)type, byteArray, maxNumPixels, sourceChannel }; return ResourceCache::prefetch(url, &extra, std::hash()(extra)); } -NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels, hfm::ColorChannel sourceChannel) { +NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels, image::ColorChannel sourceChannel) { if (url.scheme() == RESOURCE_SCHEME) { return getResourceTexture(url); } @@ -371,7 +371,7 @@ void NetworkTexture::setExtra(void* extra) { const TextureExtra* textureExtra = static_cast(extra); _type = textureExtra ? textureExtra->type : image::TextureUsage::DEFAULT_TEXTURE; _maxNumPixels = textureExtra ? textureExtra->maxNumPixels : ABSOLUTE_MAX_TEXTURE_NUM_PIXELS; - _sourceChannel = textureExtra ? textureExtra->sourceChannel : hfm::ColorChannel::NONE; + _sourceChannel = textureExtra ? textureExtra->sourceChannel : image::ColorChannel::NONE; _textureSource = std::make_shared(_url, (int)_type); _lowestRequestedMipLevel = 0; @@ -434,7 +434,7 @@ class ImageReader : public QRunnable { public: ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, size_t extraHash, int maxNumPixels, - hfm::ColorChannel sourceChannel); + image::ColorChannel sourceChannel); void run() override final; void read(); @@ -446,7 +446,7 @@ private: QByteArray _content; size_t _extraHash; int _maxNumPixels; - hfm::ColorChannel _sourceChannel; + image::ColorChannel _sourceChannel; }; NetworkTexture::~NetworkTexture() { @@ -1104,7 +1104,7 @@ void NetworkTexture::refresh() { Resource::refresh(); } -ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, size_t extraHash, int maxNumPixels, hfm::ColorChannel sourceChannel) : +ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, size_t extraHash, int maxNumPixels, image::ColorChannel sourceChannel) : _resource(resource), _url(url), _content(data), @@ -1218,7 +1218,7 @@ void ImageReader::read() { constexpr bool shouldCompress = false; #endif auto target = getBackendTarget(); - texture = image::processImage(std::move(buffer), _url.toString().toStdString(), (image::TextureUsage::ColorChannel)_sourceChannel, _maxNumPixels, networkTexture->getTextureType(), shouldCompress, target); + texture = image::processImage(std::move(buffer), _url.toString().toStdString(), _sourceChannel, _maxNumPixels, networkTexture->getTextureType(), shouldCompress, target); if (!texture) { QMetaObject::invokeMethod(resource.data(), "setImage", diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 16627012b3..acca916acc 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -97,7 +97,7 @@ private: friend class ImageReader; image::TextureUsage::Type _type; - hfm::ColorChannel _sourceChannel; + image::ColorChannel _sourceChannel; enum class ResourceType { META, @@ -181,7 +181,7 @@ public: /// Loads a texture from the specified URL. NetworkTexturePointer getTexture(const QUrl& url, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE, const QByteArray& content = QByteArray(), int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, - hfm::ColorChannel sourceChannel = hfm::ColorChannel::NONE); + image::ColorChannel sourceChannel = image::ColorChannel::NONE); gpu::TexturePointer getTextureByHash(const std::string& hash); gpu::TexturePointer cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture); @@ -204,7 +204,7 @@ signals: protected: // Overload ResourceCache::prefetch to allow specifying texture type for loads - Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, hfm::ColorChannel sourceChannel = hfm::ColorChannel::NONE); + Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, image::ColorChannel sourceChannel = image::ColorChannel::NONE); virtual QSharedPointer createResource(const QUrl& url) override; QSharedPointer createResourceCopy(const QSharedPointer& resource) override; diff --git a/libraries/procedural/CMakeLists.txt b/libraries/procedural/CMakeLists.txt index f2562907e0..f3c3be687a 100644 --- a/libraries/procedural/CMakeLists.txt +++ b/libraries/procedural/CMakeLists.txt @@ -1,5 +1,3 @@ set(TARGET_NAME procedural) setup_hifi_library() link_hifi_libraries(shared gpu shaders networking graphics model-networking ktx image) - -include_hifi_library_headers(hfm) From b2e3b87ef474262d03f5ab88d904010a653be937 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Tue, 12 Feb 2019 16:24:13 -0800 Subject: [PATCH 107/139] Add two missing CMake includes --- libraries/animation/CMakeLists.txt | 1 + libraries/model-baker/CMakeLists.txt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/libraries/animation/CMakeLists.txt b/libraries/animation/CMakeLists.txt index 30addadcaa..1ab54ed342 100644 --- a/libraries/animation/CMakeLists.txt +++ b/libraries/animation/CMakeLists.txt @@ -4,5 +4,6 @@ link_hifi_libraries(shared graphics fbx) include_hifi_library_headers(networking) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) +include_hifi_library_headers(image) target_nsight() diff --git a/libraries/model-baker/CMakeLists.txt b/libraries/model-baker/CMakeLists.txt index 6fa7c1815a..aabd6eba3a 100644 --- a/libraries/model-baker/CMakeLists.txt +++ b/libraries/model-baker/CMakeLists.txt @@ -2,3 +2,5 @@ set(TARGET_NAME model-baker) setup_hifi_library() link_hifi_libraries(shared task gpu graphics hfm) + +include_hifi_library_headers(image) From 08ef9b6f8405d18c6dd8ad402edd507882a51cac Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Tue, 12 Feb 2019 16:44:37 -0800 Subject: [PATCH 108/139] Remove unused duplicate ColorChannel enum --- libraries/image/src/image/Image.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index 74e9268451..40c31eeeff 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -43,15 +43,6 @@ enum Type { UNUSED_TEXTURE }; -enum class ColorChannel { - NONE, - RED, - GREEN, - BLUE, - ALPHA, - COUNT -}; - using TextureLoader = std::function&)>; TextureLoader getTextureLoaderForType(Type type, const QVariantMap& options = QVariantMap()); From a111aa1724e828b8a1ef0d46fbc31d5fda62f3b1 Mon Sep 17 00:00:00 2001 From: danteruiz Date: Tue, 12 Feb 2019 16:45:45 -0800 Subject: [PATCH 109/139] fix blocks app --- .../resources/qml/hifi/tablet/+webengine/BlocksWebView.qml | 7 +++++++ interface/resources/qml/hifi/tablet/BlocksWebView.qml | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 interface/resources/qml/hifi/tablet/+webengine/BlocksWebView.qml diff --git a/interface/resources/qml/hifi/tablet/+webengine/BlocksWebView.qml b/interface/resources/qml/hifi/tablet/+webengine/BlocksWebView.qml new file mode 100644 index 0000000000..050515da37 --- /dev/null +++ b/interface/resources/qml/hifi/tablet/+webengine/BlocksWebView.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0 +import QtWebEngine 1.5 +import "../../controls" as Controls + +Controls.TabletWebView { + profile: WebEngineProfile { httpUserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"} +} diff --git a/interface/resources/qml/hifi/tablet/BlocksWebView.qml b/interface/resources/qml/hifi/tablet/BlocksWebView.qml index 03fce0a112..eaed88ba01 100644 --- a/interface/resources/qml/hifi/tablet/BlocksWebView.qml +++ b/interface/resources/qml/hifi/tablet/BlocksWebView.qml @@ -2,7 +2,6 @@ import QtQuick 2.0 import "../../controls" as Controls Controls.TabletWebView { - profile: WebEngineProfile { httpUserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"} } From efd22172b40009bd67f4ce3578388d60f66a931c Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Tue, 12 Feb 2019 17:27:04 -0800 Subject: [PATCH 110/139] Add final missing CMake includes --- tools/skeleton-dump/CMakeLists.txt | 2 ++ tools/vhacd-util/CMakeLists.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tools/skeleton-dump/CMakeLists.txt b/tools/skeleton-dump/CMakeLists.txt index baec1d163b..7d4248d171 100644 --- a/tools/skeleton-dump/CMakeLists.txt +++ b/tools/skeleton-dump/CMakeLists.txt @@ -2,3 +2,5 @@ set(TARGET_NAME skeleton-dump) setup_hifi_project(Core) setup_memory_debugger() link_hifi_libraries(shared fbx hfm graphics gpu gl animation) + +include_hifi_library_headers(image) diff --git a/tools/vhacd-util/CMakeLists.txt b/tools/vhacd-util/CMakeLists.txt index aa6642c610..90cfdf878a 100644 --- a/tools/vhacd-util/CMakeLists.txt +++ b/tools/vhacd-util/CMakeLists.txt @@ -2,6 +2,8 @@ set(TARGET_NAME vhacd-util) setup_hifi_project(Core) link_hifi_libraries(shared fbx hfm graphics gpu gl) +include_hifi_library_headers(image) + add_dependency_external_projects(vhacd) find_package(VHACD REQUIRED) From 9ed1470175f6005ce9535c019522df83477c67aa Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 12 Feb 2019 19:10:34 -0800 Subject: [PATCH 111/139] Corrected case. --- tools/nitpick/src/PathUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/src/PathUtils.h b/tools/nitpick/src/PathUtils.h index 01f6906ee1..72f6839e3d 100644 --- a/tools/nitpick/src/PathUtils.h +++ b/tools/nitpick/src/PathUtils.h @@ -10,7 +10,7 @@ #ifndef hifi_PathUtils_h #define hifi_PathUtils_h -#include +#include class PathUtils { public: From 152edd477c3952aab14d458ef55d466fa7798c75 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 13 Feb 2019 10:00:51 -0800 Subject: [PATCH 112/139] change trace context to rendering --- interface/src/ui/ApplicationOverlay.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 3579776213..8270b8d307 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -90,7 +90,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { } void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { - PROFILE_RANGE(app, __FUNCTION__); + PROFILE_RANGE(render, __FUNCTION__); if (!_uiTexture) { _uiTexture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); @@ -119,7 +119,7 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { } void ApplicationOverlay::renderOverlays(RenderArgs* renderArgs) { - PROFILE_RANGE(app, __FUNCTION__); + PROFILE_RANGE(render, __FUNCTION__); gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); @@ -178,7 +178,7 @@ static const auto DEFAULT_SAMPLER = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LI static const auto DEPTH_FORMAT = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); void ApplicationOverlay::buildFramebufferObject() { - PROFILE_RANGE(app, __FUNCTION__); + PROFILE_RANGE(render, __FUNCTION__); auto uiSize = glm::uvec2(qApp->getUiSize()); if (!_overlayFramebuffer || uiSize != _overlayFramebuffer->getSize()) { From c79e3e5a6d7eab0c0b5e374ec691c7c812b6d2ad Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 13 Feb 2019 10:02:58 -0800 Subject: [PATCH 113/139] add some trace contexts for easier debugging --- interface/src/Application.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b3c978df9a..615e9f1440 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6311,7 +6311,10 @@ void Application::update(float deltaTime) { { PROFILE_RANGE(simulation_physics, "RemoveEntities"); const VectorOfMotionStates& motionStates = _entitySimulation->getObjectsToRemoveFromPhysics(); - _physicsEngine->removeObjects(motionStates); + { + PROFILE_RANGE_EX(simulation_physics, "NumObjs", 0xffff0000, (uint64_t)motionStates.size()); + _physicsEngine->removeObjects(motionStates); + } _entitySimulation->deleteObjectsRemovedFromPhysics(); } @@ -6320,6 +6323,7 @@ void Application::update(float deltaTime) { VectorOfMotionStates motionStates; getEntities()->getTree()->withReadLock([&] { _entitySimulation->getObjectsToAddToPhysics(motionStates); + PROFILE_RANGE_EX(simulation_physics, "NumObjs", 0xffff0000, (uint64_t)motionStates.size()); _physicsEngine->addObjects(motionStates); }); } From ba91bab224a7fdab673bb36f91143a17d007c14f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 13 Feb 2019 10:05:32 -0800 Subject: [PATCH 114/139] remove cruft --- libraries/physics/src/ShapeManager.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/physics/src/ShapeManager.h b/libraries/physics/src/ShapeManager.h index 7583b7d919..c1fb57e017 100644 --- a/libraries/physics/src/ShapeManager.h +++ b/libraries/physics/src/ShapeManager.h @@ -78,8 +78,6 @@ private: // btHashMap is required because it supports memory alignment of the btCollisionShapes btHashMap _shapeMap; - //btAlignedObjectArray _pendingGarbage; - std::vector _garbageRing; uint32_t _ringIndex { 0 }; }; From 562e159ab4c775842d14013db44d47943c215f5f Mon Sep 17 00:00:00 2001 From: danteruiz Date: Wed, 13 Feb 2019 10:45:07 -0800 Subject: [PATCH 115/139] the proper fix for browser qml issues --- .../resources/qml/+webengine/Browser.qml | 275 ------------------ .../qml/+webengine/BrowserWebView.qml | 58 ++++ .../resources/qml/+webengine/InfoView.qml | 50 ---- .../resources/qml/+webengine/QmlWebWindow.qml | 108 ------- .../qml/+webengine/QmlWebWindowView.qml | 53 ++++ interface/resources/qml/Browser.qml | 18 +- interface/resources/qml/BrowserWebView.qml | 8 + interface/resources/qml/InfoView.qml | 2 +- interface/resources/qml/QmlWebWindow.qml | 7 +- interface/resources/qml/QmlWebWindowView.qml | 5 + .../qml/controlsUit/ProxyWebView.qml | 1 + 11 files changed, 140 insertions(+), 445 deletions(-) delete mode 100644 interface/resources/qml/+webengine/Browser.qml create mode 100644 interface/resources/qml/+webengine/BrowserWebView.qml delete mode 100644 interface/resources/qml/+webengine/InfoView.qml delete mode 100644 interface/resources/qml/+webengine/QmlWebWindow.qml create mode 100644 interface/resources/qml/+webengine/QmlWebWindowView.qml create mode 100644 interface/resources/qml/BrowserWebView.qml create mode 100644 interface/resources/qml/QmlWebWindowView.qml diff --git a/interface/resources/qml/+webengine/Browser.qml b/interface/resources/qml/+webengine/Browser.qml deleted file mode 100644 index e00549347d..0000000000 --- a/interface/resources/qml/+webengine/Browser.qml +++ /dev/null @@ -1,275 +0,0 @@ -import QtQuick 2.5 -import QtWebChannel 1.0 -import QtWebEngine 1.5 - -import controlsUit 1.0 -import stylesUit 1.0 -import "windows" - -ScrollingWindow { - id: root - HifiConstants { id: hifi } - //HifiStyles.HifiConstants { id: hifistyles } - title: "Browser" - resizable: true - destroyOnHidden: true - width: 800 - height: 600 - property variant permissionsBar: {'securityOrigin':'none','feature':'none'} - property alias url: webview.url - property alias webView: webview - - signal loadingChanged(int status) - - x: 100 - y: 100 - - Component.onCompleted: { - focus = true - shown = true - addressBar.text = webview.url - } - - function setProfile(profile) { - webview.profile = profile; - } - - function showPermissionsBar(){ - permissionsContainer.visible=true; - } - - function hidePermissionsBar(){ - permissionsContainer.visible=false; - } - - function allowPermissions(){ - webview.grantFeaturePermission(permissionsBar.securityOrigin, permissionsBar.feature, true); - hidePermissionsBar(); - } - - function setAutoAdd(auto) { - desktop.setAutoAdd(auto); - } - - Item { - id:item - width: pane.contentWidth - implicitHeight: pane.scrollHeight - - Row { - id: buttons - spacing: 4 - anchors.top: parent.top - anchors.topMargin: 8 - anchors.left: parent.left - anchors.leftMargin: 8 - HiFiGlyphs { - id: back; - enabled: webview.canGoBack; - text: hifi.glyphs.backward - color: enabled ? hifi.colors.text : hifi.colors.disabledText - size: 48 - MouseArea { anchors.fill: parent; onClicked: webview.goBack() } - } - - HiFiGlyphs { - id: forward; - enabled: webview.canGoForward; - text: hifi.glyphs.forward - color: enabled ? hifi.colors.text : hifi.colors.disabledText - size: 48 - MouseArea { anchors.fill: parent; onClicked: webview.goForward() } - } - - HiFiGlyphs { - id: reload; - enabled: webview.canGoForward; - text: webview.loading ? hifi.glyphs.close : hifi.glyphs.reload - color: enabled ? hifi.colors.text : hifi.colors.disabledText - size: 48 - MouseArea { anchors.fill: parent; onClicked: webview.goForward() } - } - - } - - Item { - id: border - height: 48 - anchors.top: parent.top - anchors.topMargin: 8 - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.left: buttons.right - anchors.leftMargin: 8 - - Item { - id: barIcon - width: parent.height - height: parent.height - Image { - source: webview.icon; - x: (parent.height - height) / 2 - y: (parent.width - width) / 2 - sourceSize: Qt.size(width, height); - verticalAlignment: Image.AlignVCenter; - horizontalAlignment: Image.AlignHCenter - } - } - - TextField { - id: addressBar - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.left: barIcon.right - anchors.leftMargin: 0 - anchors.verticalCenter: parent.verticalCenter - focus: true - colorScheme: hifi.colorSchemes.dark - placeholderText: "Enter URL" - Component.onCompleted: ScriptDiscoveryService.scriptsModelFilter.filterRegExp = new RegExp("^.*$", "i") - Keys.onPressed: { - switch(event.key) { - case Qt.Key_Enter: - case Qt.Key_Return: - event.accepted = true - if (text.indexOf("http") != 0) { - text = "http://" + text; - } - root.hidePermissionsBar(); - root.keyboardRaised = false; - webview.url = text; - break; - } - } - } - } - - Rectangle { - id:permissionsContainer - visible:false - color: "#000000" - width: parent.width - anchors.top: buttons.bottom - height:40 - z:100 - gradient: Gradient { - GradientStop { position: 0.0; color: "black" } - GradientStop { position: 1.0; color: "grey" } - } - - RalewayLight { - id: permissionsInfo - anchors.right:permissionsRow.left - anchors.rightMargin: 32 - anchors.topMargin:8 - anchors.top:parent.top - text: "This site wants to use your microphone/camera" - size: 18 - color: hifi.colors.white - } - - Row { - id: permissionsRow - spacing: 4 - anchors.top:parent.top - anchors.topMargin: 8 - anchors.right: parent.right - visible: true - z:101 - - Button { - id:allow - text: "Allow" - color: hifi.buttons.blue - colorScheme: root.colorScheme - width: 120 - enabled: true - onClicked: root.allowPermissions(); - z:101 - } - - Button { - id:block - text: "Block" - color: hifi.buttons.red - colorScheme: root.colorScheme - width: 120 - enabled: true - onClicked: root.hidePermissionsBar(); - z:101 - } - } - } - - WebView { - id: webview - url: "https://highfidelity.com/" - profile: FileTypeProfile; - - // Create a global EventBridge object for raiseAndLowerKeyboard. - WebEngineScript { - id: createGlobalEventBridge - sourceCode: eventBridgeJavaScriptToInject - injectionPoint: WebEngineScript.Deferred - worldId: WebEngineScript.MainWorld - } - - // Detect when may want to raise and lower keyboard. - WebEngineScript { - id: raiseAndLowerKeyboard - injectionPoint: WebEngineScript.Deferred - sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" - worldId: WebEngineScript.MainWorld - } - - userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ] - - anchors.top: buttons.bottom - anchors.topMargin: 8 - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - - onFeaturePermissionRequested: { - if (feature == 2) { // QWebEnginePage::MediaAudioCapture - grantFeaturePermission(securityOrigin, feature, true); - } else { - permissionsBar.securityOrigin = securityOrigin; - permissionsBar.feature = feature; - root.showPermissionsBar(); - } - } - - onLoadingChanged: { - if (loadRequest.status === WebEngineView.LoadSucceededStatus) { - addressBar.text = loadRequest.url - } - root.loadingChanged(loadRequest.status); - } - - onWindowCloseRequested: { - root.destroy(); - } - - Component.onCompleted: { - webChannel.registerObject("eventBridge", eventBridge); - webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper); - desktop.initWebviewProfileHandlers(webview.profile); - } - } - - } // item - - - Keys.onPressed: { - switch(event.key) { - case Qt.Key_L: - if (event.modifiers == Qt.ControlModifier) { - event.accepted = true - addressBar.selectAll() - addressBar.forceActiveFocus() - } - break; - } - } -} // dialog diff --git a/interface/resources/qml/+webengine/BrowserWebView.qml b/interface/resources/qml/+webengine/BrowserWebView.qml new file mode 100644 index 0000000000..5c5cf2cfb9 --- /dev/null +++ b/interface/resources/qml/+webengine/BrowserWebView.qml @@ -0,0 +1,58 @@ +import QtQuick 2.5 +import QtWebChannel 1.0 +import QtWebEngine 1.5 + +import controlsUit 1.0 + +WebView { + id: webview + url: "https://highfidelity.com/" + profile: FileTypeProfile; + + property var parentRoot: null + + // Create a global EventBridge object for raiseAndLowerKeyboard. + WebEngineScript { + id: createGlobalEventBridge + sourceCode: eventBridgeJavaScriptToInject + injectionPoint: WebEngineScript.Deferred + worldId: WebEngineScript.MainWorld + } + + // Detect when may want to raise and lower keyboard. + WebEngineScript { + id: raiseAndLowerKeyboard + injectionPoint: WebEngineScript.Deferred + sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" + worldId: WebEngineScript.MainWorld + } + + userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ] + + onFeaturePermissionRequested: { + if (feature == 2) { // QWebEnginePage::MediaAudioCapture + grantFeaturePermission(securityOrigin, feature, true); + } else { + permissionsBar.securityOrigin = securityOrigin; + permissionsBar.feature = feature; + parentRoot.showPermissionsBar(); + } + } + + onLoadingChanged: { + if (loadRequest.status === WebEngineView.LoadSucceededStatus) { + addressBar.text = loadRequest.url + } + parentRoot.loadingChanged(loadRequest.status); + } + + onWindowCloseRequested: { + parentRoot.destroy(); + } + + Component.onCompleted: { + webChannel.registerObject("eventBridge", eventBridge); + webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper); + desktop.initWebviewProfileHandlers(webview.profile); + } +} diff --git a/interface/resources/qml/+webengine/InfoView.qml b/interface/resources/qml/+webengine/InfoView.qml deleted file mode 100644 index 8c5900b4c3..0000000000 --- a/interface/resources/qml/+webengine/InfoView.qml +++ /dev/null @@ -1,50 +0,0 @@ -// -// InfoView.qml -// -// Created by Bradley Austin Davis on 27 Apr 2015 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.5 -import Hifi 1.0 as Hifi - -import controlsUit 1.0 -import "windows" as Windows - -Windows.ScrollingWindow { - id: root - width: 800 - height: 800 - resizable: true - - Hifi.InfoView { - id: infoView - width: pane.contentWidth - implicitHeight: pane.scrollHeight - - WebView { - id: webview - objectName: "WebView" - anchors.fill: parent - url: infoView.url - } - } - - Component.onCompleted: { - centerWindow(root); - } - - onVisibleChanged: { - if (visible) { - centerWindow(root); - } - } - - function centerWindow() { - desktop.centerOnVisible(root); - } - -} diff --git a/interface/resources/qml/+webengine/QmlWebWindow.qml b/interface/resources/qml/+webengine/QmlWebWindow.qml deleted file mode 100644 index 35799d64a9..0000000000 --- a/interface/resources/qml/+webengine/QmlWebWindow.qml +++ /dev/null @@ -1,108 +0,0 @@ -// -// QmlWebWindow.qml -// -// Created by Bradley Austin Davis on 17 Dec 2015 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.5 -import QtWebEngine 1.1 -import QtWebChannel 1.0 - -import "../windows" as Windows -import controlsUit 1.0 as Controls -import stylesUit 1.0 - -Windows.ScrollingWindow { - id: root - HifiConstants { id: hifi } - title: "WebWindow" - resizable: true - shown: false - // Don't destroy on close... otherwise the JS/C++ will have a dangling pointer - destroyOnCloseButton: false - property alias source: webview.url - property alias scriptUrl: webview.userScriptUrl - - // This is for JS/QML communication, which is unused in a WebWindow, - // but not having this here results in spurious warnings about a - // missing signal - signal sendToScript(var message); - - signal moved(vector2d position); - signal resized(size size); - - function notifyMoved() { - moved(Qt.vector2d(x, y)); - } - - function notifyResized() { - resized(Qt.size(width, height)); - } - - onXChanged: notifyMoved(); - onYChanged: notifyMoved(); - - onWidthChanged: notifyResized(); - onHeightChanged: notifyResized(); - - onShownChanged: { - keyboardEnabled = HMD.active; - } - - Item { - width: pane.contentWidth - implicitHeight: pane.scrollHeight - - Controls.WebView { - id: webview - url: "about:blank" - anchors.fill: parent - focus: true - profile: HFWebEngineProfile; - - property string userScriptUrl: "" - - // Create a global EventBridge object for raiseAndLowerKeyboard. - WebEngineScript { - id: createGlobalEventBridge - sourceCode: eventBridgeJavaScriptToInject - injectionPoint: WebEngineScript.DocumentCreation - worldId: WebEngineScript.MainWorld - } - - // Detect when may want to raise and lower keyboard. - WebEngineScript { - id: raiseAndLowerKeyboard - injectionPoint: WebEngineScript.Deferred - sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" - worldId: WebEngineScript.MainWorld - } - - // User script. - WebEngineScript { - id: userScript - sourceUrl: webview.userScriptUrl - injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. - worldId: WebEngineScript.MainWorld - } - - userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] - - function onWebEventReceived(event) { - if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") { - ApplicationInterface.addAssetToWorldFromURL(event.slice(18)); - } - } - - Component.onCompleted: { - webChannel.registerObject("eventBridge", eventBridge); - webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper); - eventBridge.webEventReceived.connect(onWebEventReceived); - } - } - } -} diff --git a/interface/resources/qml/+webengine/QmlWebWindowView.qml b/interface/resources/qml/+webengine/QmlWebWindowView.qml new file mode 100644 index 0000000000..d2f1820e9a --- /dev/null +++ b/interface/resources/qml/+webengine/QmlWebWindowView.qml @@ -0,0 +1,53 @@ +import QtQuick 2.5 +import QtWebEngine 1.1 +import QtWebChannel 1.0 + +import controlsUit 1.0 as Controls +import stylesUit 1.0 +Controls.WebView { + id: webview + url: "about:blank" + anchors.fill: parent + focus: true + profile: HFWebEngineProfile; + + property string userScriptUrl: "" + + // Create a global EventBridge object for raiseAndLowerKeyboard. + WebEngineScript { + id: createGlobalEventBridge + sourceCode: eventBridgeJavaScriptToInject + injectionPoint: WebEngineScript.DocumentCreation + worldId: WebEngineScript.MainWorld + } + + // Detect when may want to raise and lower keyboard. + WebEngineScript { + id: raiseAndLowerKeyboard + injectionPoint: WebEngineScript.Deferred + sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js" + worldId: WebEngineScript.MainWorld + } + + // User script. + WebEngineScript { + id: userScript + sourceUrl: webview.userScriptUrl + injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. + worldId: WebEngineScript.MainWorld + } + + userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] + + function onWebEventReceived(event) { + if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") { + ApplicationInterface.addAssetToWorldFromURL(event.slice(18)); + } + } + + Component.onCompleted: { + webChannel.registerObject("eventBridge", eventBridge); + webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper); + eventBridge.webEventReceived.connect(onWebEventReceived); + } +} diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 78ffb51e67..496209a2a8 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -1,14 +1,13 @@ import QtQuick 2.5 - import controlsUit 1.0 import stylesUit 1.0 - import "windows" +import "." ScrollingWindow { id: root HifiConstants { id: hifi } - //HifiStyles.HifiConstants { id: hifistyles } + title: "Browser" resizable: true destroyOnHidden: true @@ -30,6 +29,7 @@ ScrollingWindow { } function setProfile(profile) { + webview.profile = profile; } function showPermissionsBar(){ @@ -41,6 +41,7 @@ ScrollingWindow { } function allowPermissions(){ + webview.grantFeaturePermission(permissionsBar.securityOrigin, permissionsBar.feature, true); hidePermissionsBar(); } @@ -198,10 +199,15 @@ ScrollingWindow { } } - ProxyWebView { + BrowserWebView { id: webview - anchors.centerIn: parent - url: "https://highfidelity.com/" + parentRoot: root + + anchors.top: buttons.bottom + anchors.topMargin: 8 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right } } // item diff --git a/interface/resources/qml/BrowserWebView.qml b/interface/resources/qml/BrowserWebView.qml new file mode 100644 index 0000000000..6db016c284 --- /dev/null +++ b/interface/resources/qml/BrowserWebView.qml @@ -0,0 +1,8 @@ +import QtQuick 2.5 +import controlsUit 1.0 + +ProxyWebView { + property var parentRoot: null + + function grantFeaturePermission(origin, feature) {} +} diff --git a/interface/resources/qml/InfoView.qml b/interface/resources/qml/InfoView.qml index 5c2c7fcff9..2fd0ddf925 100644 --- a/interface/resources/qml/InfoView.qml +++ b/interface/resources/qml/InfoView.qml @@ -24,7 +24,7 @@ Windows.ScrollingWindow { width: pane.contentWidth implicitHeight: pane.scrollHeight - ProxyWebView { + BaseWebView { id: webview objectName: "WebView" anchors.fill: parent diff --git a/interface/resources/qml/QmlWebWindow.qml b/interface/resources/qml/QmlWebWindow.qml index a40168039e..7ee4b1c50c 100644 --- a/interface/resources/qml/QmlWebWindow.qml +++ b/interface/resources/qml/QmlWebWindow.qml @@ -11,6 +11,7 @@ import QtQuick 2.5 import "windows" as Windows +import "." import controlsUit 1.0 as Controls import stylesUit 1.0 @@ -55,12 +56,8 @@ Windows.ScrollingWindow { width: pane.contentWidth implicitHeight: pane.scrollHeight - Controls.WebView { + QmlWebWindowView { id: webview - url: "about:blank" - property string userScriptUrl: "" - anchors.fill: parent - focus: true } } } diff --git a/interface/resources/qml/QmlWebWindowView.qml b/interface/resources/qml/QmlWebWindowView.qml new file mode 100644 index 0000000000..9210468ae2 --- /dev/null +++ b/interface/resources/qml/QmlWebWindowView.qml @@ -0,0 +1,5 @@ +import QtQuick 2.5 +import controlsUit 1.0 + +BaseWebView { +} diff --git a/interface/resources/qml/controlsUit/ProxyWebView.qml b/interface/resources/qml/controlsUit/ProxyWebView.qml index adcc472831..2b13760962 100644 --- a/interface/resources/qml/controlsUit/ProxyWebView.qml +++ b/interface/resources/qml/controlsUit/ProxyWebView.qml @@ -18,6 +18,7 @@ Rectangle { property bool safeLoading: false property bool loadingLatched: false + property bool loading: false property var loadingRequest: null From 77b679606f4b168b771b033653e86fde05fc04dd Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 13 Feb 2019 15:13:55 -0800 Subject: [PATCH 116/139] Corrected bug in zip folder name. --- tools/nitpick/src/TestRunnerDesktop.cpp | 17 +++++++++++------ tools/nitpick/src/TestRunnerDesktop.h | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/tools/nitpick/src/TestRunnerDesktop.cpp b/tools/nitpick/src/TestRunnerDesktop.cpp index 50cb6f9a07..e45d895886 100644 --- a/tools/nitpick/src/TestRunnerDesktop.cpp +++ b/tools/nitpick/src/TestRunnerDesktop.cpp @@ -554,7 +554,7 @@ void TestRunnerDesktop::evaluateResults() { nitpick->startTestsEvaluation(false, true, _snapshotFolder, _branch, _user); } -void TestRunnerDesktop::automaticTestRunEvaluationComplete(QString zippedFolder, int numberOfFailures) { +void TestRunnerDesktop::automaticTestRunEvaluationComplete(const QString& zippedFolder, int numberOfFailures) { addBuildNumberToResults(zippedFolder); restoreHighFidelityAppDataFolder(); @@ -580,14 +580,19 @@ void TestRunnerDesktop::automaticTestRunEvaluationComplete(QString zippedFolder, _runNow->setEnabled(true); } -void TestRunnerDesktop::addBuildNumberToResults(QString zippedFolderName) { - QString augmentedFilename; +void TestRunnerDesktop::addBuildNumberToResults(const QString& zippedFolderName) { + QString augmentedFilename { zippedFolderName }; if (!_runLatest->isChecked()) { - augmentedFilename = zippedFolderName.replace("local", getPRNumberFromURL(_url->text())); + augmentedFilename.replace("local", getPRNumberFromURL(_url->text())); } else { - augmentedFilename = zippedFolderName.replace("local", _buildInformation.build); + augmentedFilename.replace("local", _buildInformation.build); + } + + if (!QFile::rename(zippedFolderName, augmentedFilename)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not rename '" + zippedFolderName + "' to '" + augmentedFilename); + exit(-1); + } - QFile::rename(zippedFolderName, augmentedFilename); } void TestRunnerDesktop::restoreHighFidelityAppDataFolder() { diff --git a/tools/nitpick/src/TestRunnerDesktop.h b/tools/nitpick/src/TestRunnerDesktop.h index a8f828b9d4..140a81f465 100644 --- a/tools/nitpick/src/TestRunnerDesktop.h +++ b/tools/nitpick/src/TestRunnerDesktop.h @@ -61,8 +61,8 @@ public: void runInterfaceWithTestScript(); void evaluateResults(); - void automaticTestRunEvaluationComplete(QString zippedFolderName, int numberOfFailures); - void addBuildNumberToResults(QString zippedFolderName); + void automaticTestRunEvaluationComplete(const QString& zippedFolderName, int numberOfFailures); + void addBuildNumberToResults(const QString& zippedFolderName); void copyFolder(const QString& source, const QString& destination); From 12c122ce9cf5d55a05ce3c3d1c266f43a41cfbf7 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 13 Feb 2019 15:14:36 -0800 Subject: [PATCH 117/139] Bump up version number. --- tools/nitpick/src/Nitpick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/src/Nitpick.cpp b/tools/nitpick/src/Nitpick.cpp index 3a799ce3c2..d5bc6f6e5a 100644 --- a/tools/nitpick/src/Nitpick.cpp +++ b/tools/nitpick/src/Nitpick.cpp @@ -40,7 +40,7 @@ Nitpick::Nitpick(QWidget* parent) : QMainWindow(parent) { _ui.plainTextEdit->setReadOnly(true); - setWindowTitle("Nitpick - v2.1.1"); + setWindowTitle("Nitpick - v2.1.2"); } Nitpick::~Nitpick() { From 86aaba016fb6e425886c3ed8bb274940db0a78c7 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 13 Feb 2019 15:15:46 -0800 Subject: [PATCH 118/139] Narrow filter on zip folder selection. --- tools/nitpick/src/Test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp index f618118289..6647d154af 100644 --- a/tools/nitpick/src/Test.cpp +++ b/tools/nitpick/src/Test.cpp @@ -1091,7 +1091,7 @@ void Test::setTestRailCreateMode(TestRailCreateMode testRailCreateMode) { void Test::createWebPage(QCheckBox* updateAWSCheckBox, QLineEdit* urlLineEdit) { QString testResults = QFileDialog::getOpenFileName(nullptr, "Please select the zipped test results to update from", nullptr, - "Zipped Test Results (*.zip)"); + "Zipped Test Results (TestResults--*.zip)"); if (testResults.isNull()) { return; } From 56483f48849cae173bb6fbf6b266db68d1e959ac Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 13 Feb 2019 15:18:07 -0800 Subject: [PATCH 119/139] Check that zipped folder name is in correct format. --- tools/nitpick/src/AWSInterface.cpp | 28 +++++++++++++++++++++++----- tools/nitpick/src/AWSInterface.h | 1 + 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/tools/nitpick/src/AWSInterface.cpp b/tools/nitpick/src/AWSInterface.cpp index 59be26c383..8203c41005 100644 --- a/tools/nitpick/src/AWSInterface.cpp +++ b/tools/nitpick/src/AWSInterface.cpp @@ -27,9 +27,29 @@ void AWSInterface::createWebPageFromResults(const QString& testResults, const QString& workingDirectory, QCheckBox* updateAWSCheckBox, QLineEdit* urlLineEdit) { - _testResults = testResults; _workingDirectory = workingDirectory; + // Verify filename is in correct format + // For example `D:/tt/TestResults--2019-02-10_17-30-57(local)[DESKTOP-6BO62Q9].zip` + QStringList parts = testResults.split('/'); + QString zipFilename = parts[parts.length() - 1]; + _zipFolderName = _workingDirectory + "/" + zipFilename.split('.')[0]; + + QStringList zipFolderNameParts = zipFilename.split(QRegExp("[\\(\\)\\[\\]]"), QString::SkipEmptyParts); + bool a = QRegularExpression("TestResults--\\d{4}(-\\d\\d){2}_\\d\\d(-\\d\\d){2}").match(zipFolderNameParts[0]).hasMatch(); + bool b = QRegularExpression("\\w").match(zipFolderNameParts[1]).hasMatch(); + bool c = QRegularExpression("\\w").match(zipFolderNameParts[2]).hasMatch(); + + if (!QRegularExpression("TestResults--\\d{4}(-\\d\\d){2}_\\d\\d(-\\d\\d){2}").match(zipFolderNameParts[0]).hasMatch() || + !QRegularExpression("\\w").match(zipFolderNameParts[1]).hasMatch() || // build (local, build number or PR number) + !QRegularExpression("\\w").match(zipFolderNameParts[2]).hasMatch() // machine name + ) { + QMessageBox::critical(0, "Filename is in wrong format", "'" + zipFilename + "' is not in nitpick format"); + return; + } + + _testResults = testResults; + _urlLineEdit = urlLineEdit; _urlLineEdit->setEnabled(false); @@ -48,10 +68,8 @@ void AWSInterface::extractTestFailuresFromZippedFolder() { // For a test results zip file called `D:/tt/TestResults--2018-10-02_16-54-11(9426)[DESKTOP-PMKNLSQ].zip` // the folder will be called `TestResults--2018-10-02_16-54-11(9426)[DESKTOP-PMKNLSQ]` // and, this folder will be in the working directory - QStringList parts = _testResults.split('/'); - QString zipFolderName = _workingDirectory + "/" + parts[parts.length() - 1].split('.')[0]; - if (QDir(zipFolderName).exists()) { - QDir dir = zipFolderName; + if (QDir(_zipFolderName).exists()) { + QDir dir = _zipFolderName; dir.removeRecursively(); } diff --git a/tools/nitpick/src/AWSInterface.h b/tools/nitpick/src/AWSInterface.h index 63c48580f5..7a06adea41 100644 --- a/tools/nitpick/src/AWSInterface.h +++ b/tools/nitpick/src/AWSInterface.h @@ -49,6 +49,7 @@ public: private: QString _testResults; + QString _zipFolderName; QString _workingDirectory; QString _resultsFolder; QString _htmlFailuresFolder; From 9e002c59d4630510c7c89376519da186b1c8e0b3 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 13 Feb 2019 15:24:55 -0800 Subject: [PATCH 120/139] fix pal --- libraries/audio/src/Sound.h | 3 ++- libraries/gpu/src/gpu/Texture.h | 4 ++-- libraries/hfm/src/hfm/HFM.h | 1 + .../src/model-networking/ModelCache.cpp | 2 +- .../src/model-networking/TextureCache.cpp | 9 ++++++++- libraries/networking/src/ResourceCache.cpp | 15 +++++++++------ libraries/networking/src/ResourceCache.h | 3 ++- 7 files changed, 25 insertions(+), 12 deletions(-) diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h index 836e28d582..359b931cd4 100644 --- a/libraries/audio/src/Sound.h +++ b/libraries/audio/src/Sound.h @@ -61,7 +61,8 @@ class Sound : public Resource { public: Sound(const QUrl& url, bool isStereo = false, bool isAmbisonic = false); - + Sound(const Sound& other) : Resource(other), _audioData(other._audioData), _numChannels(other._numChannels) {} + bool isReady() const { return (bool)_audioData; } bool isStereo() const { return _audioData ? _audioData->isStereo() : false; } diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 23bfff6873..517d7158e4 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -395,8 +395,6 @@ public: bool isDefined() const { return _defined; } Texture(TextureUsageType usageType); - Texture(const Texture& buf); // deep copy of the sysmem texture - Texture& operator=(const Texture& buf); // deep copy of the sysmem texture ~Texture(); Stamp getStamp() const { return _stamp; } @@ -690,8 +688,10 @@ class TextureSource { public: TextureSource(const QUrl& url, int type = 0) : _imageUrl(url), _type(type) {} + void setUrl(const QUrl& url) { _imageUrl = url; } const QUrl& getUrl() const { return _imageUrl; } const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; } + void setType(int type) { _type = type; } int getType() const { return _type; } void resetTexture(gpu::TexturePointer texture); diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index cccfaa3f7d..f1b6b4bd68 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -119,6 +119,7 @@ public: /// A texture map. class Texture { public: + QString id; QString name; QByteArray filename; diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index a4eba0c7a9..da4515392b 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -322,7 +322,7 @@ private: void GeometryDefinitionResource::setExtra(void* extra) { const GeometryExtra* geometryExtra = static_cast(extra); _mapping = geometryExtra ? geometryExtra->mapping : QVariantHash(); - _textureBaseUrl = resolveTextureBaseUrl(_url, geometryExtra ? geometryExtra->textureBaseUrl : QUrl()); + _textureBaseUrl = geometryExtra ? resolveTextureBaseUrl(_url, geometryExtra->textureBaseUrl) : QUrl(); _combineParts = geometryExtra ? geometryExtra->combineParts : true; } diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index d4cf7e6ce9..8c075f80fc 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -335,6 +335,7 @@ int networkTexturePointerMetaTypeId = qRegisterMetaTypetype : image::TextureUsage::DEFAULT_TEXTURE; _maxNumPixels = textureExtra ? textureExtra->maxNumPixels : ABSOLUTE_MAX_TEXTURE_NUM_PIXELS; - _textureSource = std::make_shared(_url, (int)_type); + if (_textureSource) { + _textureSource->setUrl(_url); + _textureSource->setType((int)_type); + } else { + _textureSource = std::make_shared(_url, (int)_type); + } _lowestRequestedMipLevel = 0; auto fileNameLowercase = _url.fileName().toLower(); diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index cb7b8c7c82..7345081380 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -362,7 +362,6 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& resource->moveToThread(qApp->thread()); connect(resource.data(), &Resource::updateSize, this, &ResourceCache::updateTotalSize); resourcesWithExtraHash.insert(extraHash, resource); - removeUnusedResource(resource); resource->ensureLoading(); } } @@ -404,7 +403,7 @@ void ResourceCache::addUnusedResource(const QSharedPointer& resource) // If it doesn't fit or its size is unknown, remove it from the cache. if (resource->getBytes() == 0 || resource->getBytes() > _unusedResourcesMaxSize) { resource->setCache(nullptr); - removeResource(resource->getURL(), resource->getBytes()); + removeResource(resource->getURL(), resource->getExtraHash(), resource->getBytes()); resetTotalResourceCounter(); return; } @@ -443,7 +442,7 @@ void ResourceCache::reserveUnusedResource(qint64 resourceSize) { auto size = it.value()->getBytes(); locker.unlock(); - removeResource(it.value()->getURL(), size); + removeResource(it.value()->getURL(), it.value()->getExtraHash(), size); locker.relock(); _unusedResourcesSize -= size; @@ -489,9 +488,13 @@ void ResourceCache::resetResourceCounters() { emit dirty(); } -void ResourceCache::removeResource(const QUrl& url, qint64 size) { +void ResourceCache::removeResource(const QUrl& url, size_t extraHash, qint64 size) { QWriteLocker locker(&_resourcesLock); - _resources.remove(url); + auto& resources = _resources[url]; + resources.remove(extraHash); + if (resources.size() == 0) { + _resources.remove(url); + } _totalResourcesSize -= size; } @@ -664,7 +667,7 @@ void Resource::allReferencesCleared() { } else { if (_cache) { // remove from the cache - _cache->removeResource(getURL(), getBytes()); + _cache->removeResource(getURL(), getExtraHash(), getBytes()); _cache->resetTotalResourceCounter(); } diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 740bdadc48..e47a8836c0 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -271,7 +271,7 @@ private: friend class ScriptableResourceCache; void reserveUnusedResource(qint64 resourceSize); - void removeResource(const QUrl& url, qint64 size = 0); + void removeResource(const QUrl& url, size_t extraHash, qint64 size = 0); void resetTotalResourceCounter(); void resetUnusedResourceCounter(); @@ -418,6 +418,7 @@ public: virtual void setExtra(void* extra) {}; void setExtraHash(size_t extraHash) { _extraHash = extraHash; } + size_t getExtraHash() const { return _extraHash; } signals: /// Fired when the resource begins downloading. From a967d7a1bc8760e647be2db86aa0e3a9d2c14189 Mon Sep 17 00:00:00 2001 From: raveenajain Date: Wed, 13 Feb 2019 15:59:55 -0800 Subject: [PATCH 121/139] tangent attribute --- libraries/fbx/src/GLTFSerializer.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 82a4361723..da77ecd77b 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -892,7 +892,24 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const QUrl& url) { for (int n = 0; n < colors.size() - 3; n += stride) { mesh.colors.push_back(glm::vec3(colors[n], colors[n + 1], colors[n + 2])); } - } else if (key == "TEXCOORD_0") { + } else if (key == "TANGENT") { + QVector tangents; + success = addArrayOfType(buffer.blob, + bufferview.byteOffset + accBoffset, + accessor.count, + tangents, + accessor.type, + accessor.componentType); + if (!success) { + qWarning(modelformat) << "There was a problem reading glTF TANGENT data for model " << _url; + continue; + } + int stride = (accessor.type == GLTFAccessorType::VEC4) ? 4 : 3; + for (int n = 0; n < tangents.size() - 3; n += stride) { + float tanW = stride == 4 ? tangents[n + 3] : 1; + mesh.tangents.push_back(glm::vec3(tanW * tangents[n], tangents[n + 1], tangents[n + 2])); + } + } else if (key == "TEXCOORD_0") { QVector texcoords; success = addArrayOfType(buffer.blob, bufferview.byteOffset + accBoffset, @@ -931,7 +948,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const QUrl& url) { } mesh.parts.push_back(part); - // populate the texture coordenates if they don't exist + // populate the texture coordinates if they don't exist if (mesh.texCoords.size() == 0) { for (int i = 0; i < part.triangleIndices.size(); i++) mesh.texCoords.push_back(glm::vec2(0.0, 1.0)); } From 3f8bfc54750b038170cdcb5ec92feaaf2d309aae Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 13 Feb 2019 16:19:39 -0800 Subject: [PATCH 122/139] CR and fix deadlock --- interface/src/Application.cpp | 4 ++-- interface/src/raypick/PathPointer.cpp | 2 +- .../src/RenderablePolyLineEntityItem.cpp | 2 +- libraries/entities/src/EntityItemProperties.cpp | 2 +- libraries/entities/src/EntityTreeElement.cpp | 2 +- libraries/entities/src/WebEntityItem.cpp | 8 ++------ 6 files changed, 8 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6307470f7f..47d4f21205 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1900,11 +1900,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, keyboardFocusOperator); auto entityScriptingInterface = DependencyManager::get(); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [this](const EntityItemID& entityItemID) { + connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, this, [this](const EntityItemID& entityItemID) { if (entityItemID == _keyboardFocusedEntity.get()) { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); } - }); + }, Qt::QueuedConnection); EntityTree::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { if (_aboutToQuit) { diff --git a/interface/src/raypick/PathPointer.cpp b/interface/src/raypick/PathPointer.cpp index 6f94d25594..8a1675cfe1 100644 --- a/interface/src/raypick/PathPointer.cpp +++ b/interface/src/raypick/PathPointer.cpp @@ -310,7 +310,7 @@ void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, EntityItemProperties properties; EntityPropertyFlags desiredProperties; desiredProperties += PROP_DIMENSIONS; - glm::vec3 dim = entityScriptingInterface->getEntityProperties(getEndID(), desiredProperties).getDimensions(); + glm::vec3 dim; if (distanceScaleEnd) { dim = getEndDim() * glm::distance(origin, end); } else { diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index bacb9adac6..64c05b576b 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -242,7 +242,7 @@ void PolyLineEntityRenderer::updateGeometry() { binormal = glm::normalize(glm::cross(tangent, normal)); // Check to make sure binormal is not a NAN. If it is, don't add to vertices vector - if (binormal.x != binormal.x) { + if (glm::any(glm::isnan(binormal))) { continue; } } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 869a13240a..abd66504b4 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1927,7 +1927,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool properties.setProperty("localEntity", convertScriptValue(engine, getEntityHostType() == entity::HostType::LOCAL)); } - if ((!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::FaceCamera)) && _type != EntityTypes::PolyLine) { + if (_type != EntityTypes::PolyLine && (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::FaceCamera))) { properties.setProperty("faceCamera", convertScriptValue(engine, getBillboardMode() == BillboardMode::YAW)); } if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::IsFacingAvatar)) { diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index a0fafbd8f9..ce6f20262f 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -151,7 +151,7 @@ bool EntityTreeElement::checkFilterSettings(const EntityItemPointer& entity, Pic // We only check the collidable filters for non-local entities, because local entities are always collisionless bool collidable = !entity->getCollisionless() && (entity->getShapeType() != SHAPE_TYPE_NONE); if (hostType != entity::HostType::LOCAL) { - if ((!searchFilter.doesPickCollidable() && collidable) || (!searchFilter.doesPickNonCollidable() && !collidable)) { + if ((collidable && !searchFilter.doesPickCollidable()) || (!collidable && !searchFilter.doesPickNonCollidable())) { return false; } } diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 51b78aaec7..7b8f081335 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -304,15 +304,11 @@ WebInputMode WebEntityItem::getInputMode() const { } void WebEntityItem::setShowKeyboardFocusHighlight(bool value) { - withWriteLock([&] { - _showKeyboardFocusHighlight = value; - }); + _showKeyboardFocusHighlight = value; } bool WebEntityItem::getShowKeyboardFocusHighlight() const { - return resultWithReadLock([&] { - return _showKeyboardFocusHighlight; - }); + return _showKeyboardFocusHighlight; } PulsePropertyGroup WebEntityItem::getPulseProperties() const { From be5f9b211b76b7f43deaa156d1236d629c4a7311 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 13 Feb 2019 18:09:06 -0800 Subject: [PATCH 123/139] Add nitpick to production (but not stable) builds --- tools/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 4d7a594d92..b9ae635a4f 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -19,8 +19,8 @@ function(check_test name) endfunction() if (BUILD_TOOLS) - # Allow different tools for production builds - if (RELEASE_TYPE STREQUAL "PRODUCTION") + # Allow different tools for stable builds + if (STABLE_BUILD) set(ALL_TOOLS udt-test vhacd-util From 301b4215e5ece64f8302a548b7be88b76efbc30e Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 13 Feb 2019 19:13:08 -0800 Subject: [PATCH 124/139] Fixed gcc warning. --- tools/nitpick/src/AWSInterface.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/nitpick/src/AWSInterface.cpp b/tools/nitpick/src/AWSInterface.cpp index 8203c41005..3707bc4a24 100644 --- a/tools/nitpick/src/AWSInterface.cpp +++ b/tools/nitpick/src/AWSInterface.cpp @@ -36,9 +36,6 @@ void AWSInterface::createWebPageFromResults(const QString& testResults, _zipFolderName = _workingDirectory + "/" + zipFilename.split('.')[0]; QStringList zipFolderNameParts = zipFilename.split(QRegExp("[\\(\\)\\[\\]]"), QString::SkipEmptyParts); - bool a = QRegularExpression("TestResults--\\d{4}(-\\d\\d){2}_\\d\\d(-\\d\\d){2}").match(zipFolderNameParts[0]).hasMatch(); - bool b = QRegularExpression("\\w").match(zipFolderNameParts[1]).hasMatch(); - bool c = QRegularExpression("\\w").match(zipFolderNameParts[2]).hasMatch(); if (!QRegularExpression("TestResults--\\d{4}(-\\d\\d){2}_\\d\\d(-\\d\\d){2}").match(zipFolderNameParts[0]).hasMatch() || !QRegularExpression("\\w").match(zipFolderNameParts[1]).hasMatch() || // build (local, build number or PR number) From 58c00781882681453c9fb1756e30734708d68893 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 13 Feb 2019 21:07:25 -0800 Subject: [PATCH 125/139] Reversed order of recursive calls. --- tools/nitpick/src/Test.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp index 6647d154af..f80058200e 100644 --- a/tools/nitpick/src/Test.cpp +++ b/tools/nitpick/src/Test.cpp @@ -766,13 +766,19 @@ void Test::createAllRecursiveScripts() { void Test::createAllRecursiveScripts(const QString& directory) { QDirIterator it(directory, QDirIterator::Subdirectories); + QStringList directories; while (it.hasNext()) { QString nextDirectory = it.next(); if (isAValidDirectory(nextDirectory)) { - createAllRecursiveScripts(nextDirectory); - createRecursiveScript(nextDirectory, false); + directories.push_front(nextDirectory); } } + + for (int i = directories.length(); i > 0; --i) { + QString nextDirectory = directories[i]; + createAllRecursiveScripts(nextDirectory); + createRecursiveScript(nextDirectory, false); + } } void Test::createRecursiveScript(const QString& directory, bool interactiveMode) { From 701c18c9eb9d36d9481ab432f4319119646055ec Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 14 Feb 2019 08:58:09 -0800 Subject: [PATCH 126/139] Correction to recursive scripts. --- tools/nitpick/src/Test.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp index f80058200e..f1e950db88 100644 --- a/tools/nitpick/src/Test.cpp +++ b/tools/nitpick/src/Test.cpp @@ -766,19 +766,13 @@ void Test::createAllRecursiveScripts() { void Test::createAllRecursiveScripts(const QString& directory) { QDirIterator it(directory, QDirIterator::Subdirectories); - QStringList directories; while (it.hasNext()) { QString nextDirectory = it.next(); if (isAValidDirectory(nextDirectory)) { - directories.push_front(nextDirectory); + createAllRecursiveScripts(nextDirectory); + createRecursiveScript(nextDirectory, false); } } - - for (int i = directories.length(); i > 0; --i) { - QString nextDirectory = directories[i]; - createAllRecursiveScripts(nextDirectory); - createRecursiveScript(nextDirectory, false); - } } void Test::createRecursiveScript(const QString& directory, bool interactiveMode) { @@ -841,11 +835,16 @@ void Test::createRecursiveScript(const QString& directory, bool interactiveMode) << endl; textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl << endl; - textStream << "if (typeof nitpick === 'undefined') nitpick = createNitpick(Script.resolvePath(\".\"));" << endl; - textStream << "if (typeof testsRootPath === 'undefined') testsRootPath = nitpick.getTestsRootPath();" << endl << endl; - - textStream << "nitpick.enableRecursive();" << endl; - textStream << "nitpick.enableAuto();" << endl << endl; + // The 'depth' variable is used to signal when to start running the recursive scripts + textStream << "if (typeof depth === 'undefined') {" << endl; + textStream << " depth = 0;" << endl; + textStream << " nitpick = createNitpick(Script.resolvePath(\".\"));" << endl; + textStream << " testsRootPath = nitpick.getTestsRootPath();" << endl << endl; + textStream << " nitpick.enableRecursive();" << endl; + textStream << " nitpick.enableAuto();" << endl; + textStream << "} else {" << endl; + textStream << " depth++" << endl; + textStream << "}" << endl << endl; // Now include the test scripts for (int i = 0; i < directories.length(); ++i) { @@ -853,8 +852,9 @@ void Test::createRecursiveScript(const QString& directory, bool interactiveMode) } textStream << endl; - textStream << "if (typeof runningRecursive === 'undefined') {" << endl; - textStream << " runningRecursive = true;" << endl; + textStream << "if (depth > 0) {" << endl; + textStream << " depth--;" << endl; + textStream << "} else {" << endl; textStream << " nitpick.runRecursive();" << endl; textStream << "}" << endl << endl; From 6752092899d9e407a2ba07b74789d00fd937671d Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 14 Feb 2019 10:38:19 -0800 Subject: [PATCH 127/139] Removed unnecessary member variable. --- tools/nitpick/src/AWSInterface.cpp | 10 +++++----- tools/nitpick/src/AWSInterface.h | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/nitpick/src/AWSInterface.cpp b/tools/nitpick/src/AWSInterface.cpp index 3707bc4a24..63d5af9272 100644 --- a/tools/nitpick/src/AWSInterface.cpp +++ b/tools/nitpick/src/AWSInterface.cpp @@ -33,7 +33,6 @@ void AWSInterface::createWebPageFromResults(const QString& testResults, // For example `D:/tt/TestResults--2019-02-10_17-30-57(local)[DESKTOP-6BO62Q9].zip` QStringList parts = testResults.split('/'); QString zipFilename = parts[parts.length() - 1]; - _zipFolderName = _workingDirectory + "/" + zipFilename.split('.')[0]; QStringList zipFolderNameParts = zipFilename.split(QRegExp("[\\(\\)\\[\\]]"), QString::SkipEmptyParts); @@ -50,7 +49,8 @@ void AWSInterface::createWebPageFromResults(const QString& testResults, _urlLineEdit = urlLineEdit; _urlLineEdit->setEnabled(false); - extractTestFailuresFromZippedFolder(); + QString zipFilenameWithoutExtension = zipFilename.split('.')[0]; + extractTestFailuresFromZippedFolder(_workingDirectory + "/" + zipFilenameWithoutExtension); createHTMLFile(); if (updateAWSCheckBox->isChecked()) { @@ -61,12 +61,12 @@ void AWSInterface::createWebPageFromResults(const QString& testResults, } } -void AWSInterface::extractTestFailuresFromZippedFolder() { +void AWSInterface::extractTestFailuresFromZippedFolder(const QString& folderName) { // For a test results zip file called `D:/tt/TestResults--2018-10-02_16-54-11(9426)[DESKTOP-PMKNLSQ].zip` // the folder will be called `TestResults--2018-10-02_16-54-11(9426)[DESKTOP-PMKNLSQ]` // and, this folder will be in the working directory - if (QDir(_zipFolderName).exists()) { - QDir dir = _zipFolderName; + if (QDir(folderName).exists()) { + QDir dir = folderName; dir.removeRecursively(); } diff --git a/tools/nitpick/src/AWSInterface.h b/tools/nitpick/src/AWSInterface.h index 7a06adea41..d95b8ecf2f 100644 --- a/tools/nitpick/src/AWSInterface.h +++ b/tools/nitpick/src/AWSInterface.h @@ -30,7 +30,7 @@ public: QCheckBox* updateAWSCheckBox, QLineEdit* urlLineEdit); - void extractTestFailuresFromZippedFolder(); + void extractTestFailuresFromZippedFolder(const QString& folderName); void createHTMLFile(); void startHTMLpage(QTextStream& stream); @@ -49,7 +49,6 @@ public: private: QString _testResults; - QString _zipFolderName; QString _workingDirectory; QString _resultsFolder; QString _htmlFailuresFolder; From a1e289cc1ce67497c93a88dfaae079b8a783ab62 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 14 Feb 2019 14:17:29 -0800 Subject: [PATCH 128/139] Compilation error on Qt 5.12 --- tools/nitpick/src/AWSInterface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/nitpick/src/AWSInterface.cpp b/tools/nitpick/src/AWSInterface.cpp index 63d5af9272..4e83460b9e 100644 --- a/tools/nitpick/src/AWSInterface.cpp +++ b/tools/nitpick/src/AWSInterface.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -589,4 +590,4 @@ void AWSInterface::updateAWS() { QStringList parameters = QStringList() << "-c" << _pythonCommand + " " + filename; process->start("sh", parameters); #endif -} \ No newline at end of file +} From 01def37efd2d5e63598fbfa37a6e4c7d193cfaf1 Mon Sep 17 00:00:00 2001 From: raveenajain Date: Thu, 14 Feb 2019 14:22:43 -0800 Subject: [PATCH 129/139] spacing --- libraries/fbx/src/GLTFSerializer.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index da77ecd77b..736e7831c1 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -900,16 +900,16 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const QUrl& url) { tangents, accessor.type, accessor.componentType); - if (!success) { - qWarning(modelformat) << "There was a problem reading glTF TANGENT data for model " << _url; - continue; - } - int stride = (accessor.type == GLTFAccessorType::VEC4) ? 4 : 3; - for (int n = 0; n < tangents.size() - 3; n += stride) { - float tanW = stride == 4 ? tangents[n + 3] : 1; - mesh.tangents.push_back(glm::vec3(tanW * tangents[n], tangents[n + 1], tangents[n + 2])); - } - } else if (key == "TEXCOORD_0") { + if (!success) { + qWarning(modelformat) << "There was a problem reading glTF TANGENT data for model " << _url; + continue; + } + int stride = (accessor.type == GLTFAccessorType::VEC4) ? 4 : 3; + for (int n = 0; n < tangents.size() - 3; n += stride) { + float tanW = stride == 4 ? tangents[n + 3] : 1; + mesh.tangents.push_back(glm::vec3(tanW * tangents[n], tangents[n + 1], tangents[n + 2])); + } + } else if (key == "TEXCOORD_0") { QVector texcoords; success = addArrayOfType(buffer.blob, bufferview.byteOffset + accBoffset, From b94655260dd7b1d66bcde5dcb30f490da675877e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 14 Feb 2019 14:54:10 -0800 Subject: [PATCH 130/139] don't traverse for fullUpdate on changed view --- assignment-client/src/octree/OctreeSendThread.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index ab357f4146..af36df1eba 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -324,12 +324,6 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* if (isFullScene) { // we're forcing a full scene, clear the force in OctreeQueryNode so we don't force it next time again nodeData->setShouldForceFullScene(false); - } else { - // we aren't forcing a full scene, check if something else suggests we should - isFullScene = nodeData->haveJSONParametersChanged() || - (nodeData->hasConicalViews() && - (nodeData->getViewFrustumJustStoppedChanging() || - nodeData->hasLodChanged())); } if (nodeData->isPacketWaiting()) { From e800a6e0306515993b4c5573dcf5bee00b4266fd Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 Feb 2019 11:59:04 -0800 Subject: [PATCH 131/139] Update hard-coded vec3 zero with Vec3.ZERO --- scripts/system/libraries/entitySelectionTool.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 3e16315c6d..13c14f2010 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -284,9 +284,11 @@ SelectionManager = (function() { properties.parentJointIndex = null; properties.localPosition = properties.position; properties.localRotation = properties.rotation; - properties.velocity = { x: 0, y: 0, z: 0 }; - properties.angularVelocity = { x: 0, y: 0, z: 0 }; } + + properties.localVelocity = Vec3.ZERO; + properties.localAngularVelocity = Vec3.ZERO; + delete properties.actionData; var newEntityID = Entities.addEntity(properties); From f0e163b4df2df1111d7134cdcc778190de1b5849 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 14 Feb 2019 16:10:26 -0800 Subject: [PATCH 132/139] Revert "AnimPose::inverse() optimization" This reverts commit 5c7e81584c204a3556e65073abb82f342b655540. --- libraries/animation/src/AnimPose.cpp | 5 +-- tests/animation/src/AnimTests.cpp | 54 ---------------------------- tests/animation/src/AnimTests.h | 1 - 3 files changed, 1 insertion(+), 59 deletions(-) diff --git a/libraries/animation/src/AnimPose.cpp b/libraries/animation/src/AnimPose.cpp index 366d863c3d..7b80e96ed5 100644 --- a/libraries/animation/src/AnimPose.cpp +++ b/libraries/animation/src/AnimPose.cpp @@ -51,10 +51,7 @@ AnimPose AnimPose::operator*(const AnimPose& rhs) const { } AnimPose AnimPose::inverse() const { - float invScale = 1.0f / _scale; - glm::quat invRot = glm::inverse(_rot); - glm::vec3 invTrans = invScale * (invRot * -_trans); - return AnimPose(invScale, invRot, invTrans); + return AnimPose(glm::inverse(static_cast(*this))); } // mirror about x-axis without applying negative scale. diff --git a/tests/animation/src/AnimTests.cpp b/tests/animation/src/AnimTests.cpp index b1926efb71..2a49846b6b 100644 --- a/tests/animation/src/AnimTests.cpp +++ b/tests/animation/src/AnimTests.cpp @@ -526,60 +526,6 @@ void AnimTests::testAnimPoseMultiply() { } } -void AnimTests::testAnimPoseInverse() { - const float PI = (float)M_PI; - const glm::quat ROT_X_90 = glm::angleAxis(PI / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - const glm::quat ROT_Y_180 = glm::angleAxis(PI, glm::vec3(0.0f, 1.0, 0.0f)); - const glm::quat ROT_Z_30 = glm::angleAxis(PI / 6.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - - std::vector scaleVec = { - 1.0f, - 2.0f, - 0.5f - }; - - std::vector rotVec = { - glm::quat(), - ROT_X_90, - ROT_Y_180, - ROT_Z_30, - ROT_X_90 * ROT_Y_180 * ROT_Z_30, - -ROT_Y_180 - }; - - std::vector transVec = { - glm::vec3(), - glm::vec3(10.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 5.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 7.5f), - glm::vec3(10.0f, 5.0f, 7.5f), - glm::vec3(-10.0f, 5.0f, 7.5f), - glm::vec3(10.0f, -5.0f, 7.5f), - glm::vec3(10.0f, 5.0f, -7.5f) - }; - - const float TEST_EPSILON = 0.001f; - - for (auto& scale : scaleVec) { - for (auto& rot : rotVec) { - for (auto& trans : transVec) { - - // build a matrix the old fashioned way. - glm::mat4 scaleMat = glm::scale(glm::mat4(), glm::vec3(scale)); - glm::mat4 rotTransMat = createMatFromQuatAndPos(rot, trans); - glm::mat4 rawMat = glm::inverse(rotTransMat * scaleMat); - - // use an anim pose to build a matrix by parts. - AnimPose pose(scale, rot, trans); - glm::mat4 poseMat = pose.inverse(); - - QCOMPARE_WITH_ABS_ERROR(rawMat, poseMat, TEST_EPSILON); - } - } - } -} - - void AnimTests::testExpressionTokenizer() { QString str = "(10 + x) >= 20.1 && (y != !z)"; AnimExpression e("x"); diff --git a/tests/animation/src/AnimTests.h b/tests/animation/src/AnimTests.h index 326545b0a9..637611e8c4 100644 --- a/tests/animation/src/AnimTests.h +++ b/tests/animation/src/AnimTests.h @@ -28,7 +28,6 @@ private slots: void testAccumulateTime(); void testAnimPose(); void testAnimPoseMultiply(); - void testAnimPoseInverse(); void testExpressionTokenizer(); void testExpressionParser(); void testExpressionEvaluator(); From 39b4eaac34de8af264f21277f40d8d31a551315a Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Thu, 14 Feb 2019 16:13:00 -0800 Subject: [PATCH 133/139] Revert "AnimPose operator* optimizations" This reverts commit 569bef50fdaea8b51abf14c8ed9afc935c84ed16. --- interface/src/avatar/AvatarActionHold.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 6 +- interface/src/avatar/MySkeletonModel.cpp | 6 +- libraries/animation/src/AnimClip.cpp | 8 +- .../animation/src/AnimInverseKinematics.cpp | 14 +-- libraries/animation/src/AnimManipulator.cpp | 2 +- .../src/AnimPoleVectorConstraint.cpp | 2 +- libraries/animation/src/AnimPose.cpp | 36 ++++-- libraries/animation/src/AnimPose.h | 17 +-- libraries/animation/src/Rig.cpp | 4 +- .../src/avatars-renderer/Avatar.cpp | 4 +- libraries/render-utils/src/AnimDebugDraw.cpp | 8 +- .../render-utils/src/CauterizedModel.cpp | 6 +- libraries/render-utils/src/Model.cpp | 2 +- libraries/render-utils/src/Model.h | 6 +- tests/animation/src/AnimTests.cpp | 105 ++---------------- tests/animation/src/AnimTests.h | 1 - 17 files changed, 81 insertions(+), 148 deletions(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index a1826076fa..5fb9c9a0ee 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -569,7 +569,7 @@ void AvatarActionHold::lateAvatarUpdate(const AnimPose& prePhysicsRoomPose, cons } btTransform worldTrans = rigidBody->getWorldTransform(); - AnimPose worldBodyPose(1.0f, bulletToGLM(worldTrans.getRotation()), bulletToGLM(worldTrans.getOrigin())); + AnimPose worldBodyPose(glm::vec3(1), bulletToGLM(worldTrans.getRotation()), bulletToGLM(worldTrans.getOrigin())); // transform the body transform into sensor space with the prePhysics sensor-to-world matrix. // then transform it back into world uisng the postAvatarUpdate sensor-to-world matrix. diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6fef47da8e..63c80ed27a 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2980,7 +2980,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) { auto animSkeleton = _skeletonModel->getRig().getAnimSkeleton(); // the rig is in the skeletonModel frame - AnimPose xform(1.0f, _skeletonModel->getRotation(), _skeletonModel->getTranslation()); + AnimPose xform(glm::vec3(1), _skeletonModel->getRotation(), _skeletonModel->getTranslation()); if (_enableDebugDrawDefaultPose && animSkeleton) { glm::vec4 gray(0.2f, 0.2f, 0.2f, 0.2f); @@ -3025,7 +3025,7 @@ void MyAvatar::postUpdate(float deltaTime, const render::ScenePointer& scene) { updateHoldActions(_prePhysicsRoomPose, postUpdateRoomPose); if (_enableDebugDrawDetailedCollision) { - AnimPose rigToWorldPose(1.0f, getWorldOrientation() * Quaternions::Y_180, getWorldPosition()); + AnimPose rigToWorldPose(glm::vec3(1.0f), getWorldOrientation() * Quaternions::Y_180, getWorldPosition()); const int NUM_DEBUG_COLORS = 8; const glm::vec4 DEBUG_COLORS[NUM_DEBUG_COLORS] = { glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), @@ -4821,7 +4821,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat swingTwistDecomposition(hipsinWorldSpace, avatarUpWorld, resultingSwingInWorld, resultingTwistInWorld); // remove scale present from sensorToWorldMatrix - followWorldPose.scale() = 1.0f; + followWorldPose.scale() = glm::vec3(1.0f); if (isActive(Rotation)) { //use the hmd reading for the hips follow diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 253cc891ee..26d69841d0 100755 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -41,7 +41,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) { if (myAvatar->isJointPinned(hipsIndex)) { Transform avatarTransform = myAvatar->getTransform(); AnimPose result = AnimPose(worldToSensorMat * avatarTransform.getMatrix() * Matrices::Y_180); - result.scale() = 1.0f; + result.scale() = glm::vec3(1.0f, 1.0f, 1.0f); return result; } @@ -108,7 +108,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Rig::ControllerParameters params; - AnimPose avatarToRigPose(1.0f, Quaternions::Y_180, glm::vec3(0.0f)); + AnimPose avatarToRigPose(glm::vec3(1.0f), Quaternions::Y_180, glm::vec3(0.0f)); glm::mat4 rigToAvatarMatrix = Matrices::Y_180; glm::mat4 avatarToWorldMatrix = createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()); @@ -127,7 +127,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { // preMult 180 is necessary to convert from avatar to rig coordinates. // postMult 180 is necessary to convert head from -z forward to z forward. glm::quat headRot = Quaternions::Y_180 * head->getFinalOrientationInLocalFrame() * Quaternions::Y_180; - params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = AnimPose(1.0f, headRot, glm::vec3(0.0f)); + params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = AnimPose(glm::vec3(1.0f), headRot, glm::vec3(0.0f)); params.primaryControllerFlags[Rig::PrimaryControllerType_Head] = 0; } diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 71b876ff8c..1adc04ee1b 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -140,10 +140,10 @@ void AnimClip::copyFromNetworkAnim() { postRot = animSkeleton.getPostRotationPose(animJoint); // cancel out scale - preRot.scale() = 1.0f; - postRot.scale() = 1.0f; + preRot.scale() = glm::vec3(1.0f); + postRot.scale() = glm::vec3(1.0f); - AnimPose rot(1.0f, hfmAnimRot, glm::vec3()); + AnimPose rot(glm::vec3(1.0f), hfmAnimRot, glm::vec3()); // adjust translation offsets, so large translation animatons on the reference skeleton // will be adjusted when played on a skeleton with short limbs. @@ -155,7 +155,7 @@ void AnimClip::copyFromNetworkAnim() { boneLengthScale = glm::length(relDefaultPose.trans()) / glm::length(hfmZeroTrans); } - AnimPose trans = AnimPose(1.0f, glm::quat(), relDefaultPose.trans() + boneLengthScale * (hfmAnimTrans - hfmZeroTrans)); + AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans() + boneLengthScale * (hfmAnimTrans - hfmZeroTrans)); _anim[frame][skeletonJoint] = trans * preRot * rot * postRot; } diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 7af9e81889..a1809f3438 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -552,7 +552,7 @@ void AnimInverseKinematics::solveTargetWithCCD(const AnimContext& context, const AnimPose accum = absolutePoses[_hipsIndex]; AnimPose baseParentPose = absolutePoses[_hipsIndex]; for (int i = (int)chainDepth - 1; i >= 0; i--) { - accum = accum * AnimPose(1.0f, jointChainInfoOut.jointInfoVec[i].rot, jointChainInfoOut.jointInfoVec[i].trans); + accum = accum * AnimPose(glm::vec3(1.0f), jointChainInfoOut.jointInfoVec[i].rot, jointChainInfoOut.jointInfoVec[i].trans); postAbsPoses[i] = accum; if (jointChainInfoOut.jointInfoVec[i].jointIndex == topJointIndex) { topChainIndex = i; @@ -734,7 +734,7 @@ void AnimInverseKinematics::computeAndCacheSplineJointInfosForIKTarget(const Ani glm::mat3 m(u, v, glm::cross(u, v)); glm::quat rot = glm::normalize(glm::quat_cast(m)); - AnimPose pose(1.0f, rot, spline(t)); + AnimPose pose(glm::vec3(1.0f), rot, spline(t)); AnimPose offsetPose = pose.inverse() * defaultPose; SplineJointInfo splineJointInfo = { index, ratio, offsetPose }; @@ -767,7 +767,7 @@ void AnimInverseKinematics::solveTargetWithSpline(const AnimContext& context, co const int baseIndex = _hipsIndex; // build spline from tip to base - AnimPose tipPose = AnimPose(1.0f, target.getRotation(), target.getTranslation()); + AnimPose tipPose = AnimPose(glm::vec3(1.0f), target.getRotation(), target.getTranslation()); AnimPose basePose = absolutePoses[baseIndex]; CubicHermiteSplineFunctorWithArcLength spline; if (target.getIndex() == _headIndex) { @@ -815,7 +815,7 @@ void AnimInverseKinematics::solveTargetWithSpline(const AnimContext& context, co glm::mat3 m(u, v, glm::cross(u, v)); glm::quat rot = glm::normalize(glm::quat_cast(m)); - AnimPose desiredAbsPose = AnimPose(1.0f, rot, trans) * splineJointInfo.offsetPose; + AnimPose desiredAbsPose = AnimPose(glm::vec3(1.0f), rot, trans) * splineJointInfo.offsetPose; // apply flex coefficent AnimPose flexedAbsPose; @@ -965,7 +965,7 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars } _relativePoses[_hipsIndex] = parentAbsPose.inverse() * absPose; - _relativePoses[_hipsIndex].scale() = 1.0f; + _relativePoses[_hipsIndex].scale() = glm::vec3(1.0f); } // if there is an active jointChainInfo for the hips store the post shifted hips into it. @@ -1753,7 +1753,7 @@ void AnimInverseKinematics::setSecondaryTargets(const AnimContext& context) { AnimPose rigToGeometryPose = AnimPose(glm::inverse(context.getGeometryToRigMatrix())); for (auto& iter : _secondaryTargetsInRigFrame) { AnimPose absPose = rigToGeometryPose * iter.second; - absPose.scale() = 1.0f; + absPose.scale() = glm::vec3(1.0f); AnimPose parentAbsPose; int parentIndex = _skeleton->getParentIndex(iter.first); @@ -1825,7 +1825,7 @@ void AnimInverseKinematics::debugDrawSpineSplines(const AnimContext& context, co const int baseIndex = _hipsIndex; // build spline - AnimPose tipPose = AnimPose(1.0f, target.getRotation(), target.getTranslation()); + AnimPose tipPose = AnimPose(glm::vec3(1.0f), target.getRotation(), target.getTranslation()); AnimPose basePose = _skeleton->getAbsolutePose(baseIndex, _relativePoses); CubicHermiteSplineFunctorWithArcLength spline; diff --git a/libraries/animation/src/AnimManipulator.cpp b/libraries/animation/src/AnimManipulator.cpp index c75c9865bb..1146cbb19a 100644 --- a/libraries/animation/src/AnimManipulator.cpp +++ b/libraries/animation/src/AnimManipulator.cpp @@ -172,5 +172,5 @@ AnimPose AnimManipulator::computeRelativePoseFromJointVar(const AnimVariantMap& break; } - return AnimPose(1.0f, relRot, relTrans); + return AnimPose(glm::vec3(1), relRot, relTrans); } diff --git a/libraries/animation/src/AnimPoleVectorConstraint.cpp b/libraries/animation/src/AnimPoleVectorConstraint.cpp index 96e4e67261..f017fe2348 100644 --- a/libraries/animation/src/AnimPoleVectorConstraint.cpp +++ b/libraries/animation/src/AnimPoleVectorConstraint.cpp @@ -95,7 +95,7 @@ const AnimPoseVec& AnimPoleVectorConstraint::evaluate(const AnimVariantMap& anim AnimPose tipPose = ikChain.getAbsolutePoseFromJointIndex(_tipJointIndex); // Look up refVector from animVars, make sure to convert into geom space. - glm::vec3 refVector = midPose.xformVector(_referenceVector); + glm::vec3 refVector = midPose.xformVectorFast(_referenceVector); float refVectorLength = glm::length(refVector); glm::vec3 axis = basePose.trans() - tipPose.trans(); diff --git a/libraries/animation/src/AnimPose.cpp b/libraries/animation/src/AnimPose.cpp index 7b80e96ed5..d77514e691 100644 --- a/libraries/animation/src/AnimPose.cpp +++ b/libraries/animation/src/AnimPose.cpp @@ -14,14 +14,15 @@ #include #include "AnimUtil.h" -const AnimPose AnimPose::identity = AnimPose(1.0f, glm::quat(), glm::vec3(0.0f)); +const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f), + glm::quat(), + glm::vec3(0.0f)); AnimPose::AnimPose(const glm::mat4& mat) { static const float EPSILON = 0.0001f; - glm::vec3 scale = extractScale(mat); + _scale = extractScale(mat); // quat_cast doesn't work so well with scaled matrices, so cancel it out. - glm::mat4 tmp = glm::scale(mat, 1.0f / scale); - _scale = extractUniformScale(scale); + glm::mat4 tmp = glm::scale(mat, 1.0f / _scale); _rot = glm::quat_cast(tmp); float lengthSquared = glm::length2(_rot); if (glm::abs(lengthSquared - 1.0f) > EPSILON) { @@ -39,15 +40,25 @@ glm::vec3 AnimPose::xformPoint(const glm::vec3& rhs) const { return *this * rhs; } +// really slow, but accurate for transforms with non-uniform scale glm::vec3 AnimPose::xformVector(const glm::vec3& rhs) const { + glm::vec3 xAxis = _rot * glm::vec3(_scale.x, 0.0f, 0.0f); + glm::vec3 yAxis = _rot * glm::vec3(0.0f, _scale.y, 0.0f); + glm::vec3 zAxis = _rot * glm::vec3(0.0f, 0.0f, _scale.z); + glm::mat3 mat(xAxis, yAxis, zAxis); + glm::mat3 transInvMat = glm::inverse(glm::transpose(mat)); + return transInvMat * rhs; +} + +// faster, but does not handle non-uniform scale correctly. +glm::vec3 AnimPose::xformVectorFast(const glm::vec3& rhs) const { return _rot * (_scale * rhs); } AnimPose AnimPose::operator*(const AnimPose& rhs) const { - float scale = _scale * rhs._scale; - glm::quat rot = _rot * rhs._rot; - glm::vec3 trans = _trans + (_rot * (_scale * rhs._trans)); - return AnimPose(scale, rot, trans); + glm::mat4 result; + glm_mat4u_mul(*this, rhs, result); + return AnimPose(result); } AnimPose AnimPose::inverse() const { @@ -60,10 +71,11 @@ AnimPose AnimPose::mirror() const { } AnimPose::operator glm::mat4() const { - glm::vec3 xAxis = _rot * glm::vec3(_scale, 0.0f, 0.0f); - glm::vec3 yAxis = _rot * glm::vec3(0.0f, _scale, 0.0f); - glm::vec3 zAxis = _rot * glm::vec3(0.0f, 0.0f, _scale); - return glm::mat4(glm::vec4(xAxis, 0.0f), glm::vec4(yAxis, 0.0f), glm::vec4(zAxis, 0.0f), glm::vec4(_trans, 1.0f)); + glm::vec3 xAxis = _rot * glm::vec3(_scale.x, 0.0f, 0.0f); + glm::vec3 yAxis = _rot * glm::vec3(0.0f, _scale.y, 0.0f); + glm::vec3 zAxis = _rot * glm::vec3(0.0f, 0.0f, _scale.z); + return glm::mat4(glm::vec4(xAxis, 0.0f), glm::vec4(yAxis, 0.0f), + glm::vec4(zAxis, 0.0f), glm::vec4(_trans, 1.0f)); } void AnimPose::blend(const AnimPose& srcPose, float alpha) { diff --git a/libraries/animation/src/AnimPose.h b/libraries/animation/src/AnimPose.h index 4d6dee1987..fb693dc31d 100644 --- a/libraries/animation/src/AnimPose.h +++ b/libraries/animation/src/AnimPose.h @@ -21,13 +21,16 @@ class AnimPose { public: AnimPose() {} explicit AnimPose(const glm::mat4& mat); - explicit AnimPose(const glm::quat& rotIn) : _rot(rotIn), _trans(0.0f), _scale(1.0f) {} - AnimPose(const glm::quat& rotIn, const glm::vec3& transIn) : _rot(rotIn), _trans(transIn), _scale(1.0f) {} - AnimPose(float scaleIn, const glm::quat& rotIn, const glm::vec3& transIn) : _rot(rotIn), _trans(transIn), _scale(scaleIn) {} + + explicit AnimPose(const glm::quat& rotIn) : _scale(1.0f), _rot(rotIn), _trans(0.0f) {} + AnimPose(const glm::quat& rotIn, const glm::vec3& transIn) : _scale(1.0f), _rot(rotIn), _trans(transIn) {} + AnimPose(const glm::vec3& scaleIn, const glm::quat& rotIn, const glm::vec3& transIn) : _scale(scaleIn), _rot(rotIn), _trans(transIn) {} + static const AnimPose identity; glm::vec3 xformPoint(const glm::vec3& rhs) const; glm::vec3 xformVector(const glm::vec3& rhs) const; // really slow, but accurate for transforms with non-uniform scale + glm::vec3 xformVectorFast(const glm::vec3& rhs) const; // faster, but does not handle non-uniform scale correctly. glm::vec3 operator*(const glm::vec3& rhs) const; // same as xformPoint AnimPose operator*(const AnimPose& rhs) const; @@ -36,8 +39,8 @@ public: AnimPose mirror() const; operator glm::mat4() const; - float scale() const { return _scale; } - float& scale() { return _scale; } + const glm::vec3& scale() const { return _scale; } + glm::vec3& scale() { return _scale; } const glm::quat& rot() const { return _rot; } glm::quat& rot() { return _rot; } @@ -49,13 +52,13 @@ public: private: friend QDebug operator<<(QDebug debug, const AnimPose& pose); + glm::vec3 _scale { 1.0f }; glm::quat _rot; glm::vec3 _trans; - float _scale { 1.0f }; // uniform scale only. }; inline QDebug operator<<(QDebug debug, const AnimPose& pose) { - debug << "AnimPose, trans = (" << pose.trans().x << pose.trans().y << pose.trans().z << "), rot = (" << pose.rot().x << pose.rot().y << pose.rot().z << pose.rot().w << "), scale =" << pose.scale(); + debug << "AnimPose, trans = (" << pose.trans().x << pose.trans().y << pose.trans().z << "), rot = (" << pose.rot().x << pose.rot().y << pose.rot().z << pose.rot().w << "), scale = (" << pose.scale().x << pose.scale().y << pose.scale().z << ")"; return debug; } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index d09de36a14..a9c57a4a15 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1326,7 +1326,7 @@ static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& sh } if (slabCount == (DOP14_COUNT / 2) && minDisplacementLen != FLT_MAX) { // we are within the k-dop so push the point along the minimum displacement found - displacementOut = shapePose.xformVector(minDisplacement); + displacementOut = shapePose.xformVectorFast(minDisplacement); return true; } else { // point is outside of kdop @@ -1335,7 +1335,7 @@ static bool findPointKDopDisplacement(const glm::vec3& point, const AnimPose& sh } else { // point is directly on top of shapeInfo.avgPoint. // push the point out along the x axis. - displacementOut = shapePose.xformVector(shapeInfo.points[0]); + displacementOut = shapePose.xformVectorFast(shapeInfo.points[0]); return true; } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index daef0e411a..1d62aed5b4 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1977,12 +1977,12 @@ float Avatar::getUnscaledEyeHeightFromSkeleton() const { auto& rig = _skeletonModel->getRig(); // Normally the model offset transform will contain the avatar scale factor, we explicitly remove it here. - AnimPose modelOffsetWithoutAvatarScale(1.0f, rig.getModelOffsetPose().rot(), rig.getModelOffsetPose().trans()); + AnimPose modelOffsetWithoutAvatarScale(glm::vec3(1.0f), rig.getModelOffsetPose().rot(), rig.getModelOffsetPose().trans()); AnimPose geomToRigWithoutAvatarScale = modelOffsetWithoutAvatarScale * rig.getGeometryOffsetPose(); // This factor can be used to scale distances in the geometry frame into the unscaled rig frame. // Typically it will be the unit conversion from cm to m. - float scaleFactor = geomToRigWithoutAvatarScale.scale(); + float scaleFactor = geomToRigWithoutAvatarScale.scale().x; // in practice this always a uniform scale factor. int headTopJoint = rig.indexOfJoint("HeadTop_End"); int headJoint = rig.indexOfJoint("Head"); diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 8944ae7996..bf528ee5f0 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -374,7 +374,7 @@ void AnimDebugDraw::update() { glm::vec4 color = std::get<3>(iter.second); for (int i = 0; i < skeleton->getNumJoints(); i++) { - const float radius = BONE_RADIUS / (absPoses[i].scale() * rootPose.scale()); + const float radius = BONE_RADIUS / (absPoses[i].scale().x * rootPose.scale().x); // draw bone addBone(rootPose, absPoses[i], radius, color, v); @@ -394,16 +394,16 @@ void AnimDebugDraw::update() { glm::vec3 pos = std::get<1>(iter.second); glm::vec4 color = std::get<2>(iter.second); const float radius = POSE_RADIUS; - addBone(AnimPose::identity, AnimPose(1.0f, rot, pos), radius, color, v); + addBone(AnimPose::identity, AnimPose(glm::vec3(1), rot, pos), radius, color, v); } - AnimPose myAvatarPose(1.0f, DebugDraw::getInstance().getMyAvatarRot(), DebugDraw::getInstance().getMyAvatarPos()); + AnimPose myAvatarPose(glm::vec3(1), DebugDraw::getInstance().getMyAvatarRot(), DebugDraw::getInstance().getMyAvatarPos()); for (auto& iter : myAvatarMarkerMap) { glm::quat rot = std::get<0>(iter.second); glm::vec3 pos = std::get<1>(iter.second); glm::vec4 color = std::get<2>(iter.second); const float radius = POSE_RADIUS; - addBone(myAvatarPose, AnimPose(1.0f, rot, pos), radius, color, v); + addBone(myAvatarPose, AnimPose(glm::vec3(1), rot, pos), radius, color, v); } // draw rays from shared DebugDraw singleton diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index b70925201a..81a81c5602 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -122,7 +122,7 @@ void CauterizedModel::updateClusterMatrices() { if (_useDualQuaternionSkinning) { auto jointPose = _rig.getJointPose(cluster.jointIndex); - Transform jointTransform(jointPose.rot(), glm::vec3(jointPose.scale()), jointPose.trans()); + Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans()); Transform clusterTransform; Transform::mult(clusterTransform, jointTransform, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindTransform); state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(clusterTransform); @@ -138,7 +138,7 @@ void CauterizedModel::updateClusterMatrices() { if (!_cauterizeBoneSet.empty()) { AnimPose cauterizePose = _rig.getJointPose(_rig.indexOfJoint("Neck")); - cauterizePose.scale() = 0.0001f; + cauterizePose.scale() = glm::vec3(0.0001f, 0.0001f, 0.0001f); static const glm::mat4 zeroScale( glm::vec4(0.0001f, 0.0f, 0.0f, 0.0f), @@ -161,7 +161,7 @@ void CauterizedModel::updateClusterMatrices() { // not cauterized so just copy the value from the non-cauterized version. state.clusterDualQuaternions[j] = _meshStates[i].clusterDualQuaternions[j]; } else { - Transform jointTransform(cauterizePose.rot(), glm::vec3(cauterizePose.scale()), cauterizePose.trans()); + Transform jointTransform(cauterizePose.rot(), cauterizePose.scale(), cauterizePose.trans()); Transform clusterTransform; Transform::mult(clusterTransform, jointTransform, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindTransform); state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(clusterTransform); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 260e25009e..0206bd6963 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1364,7 +1364,7 @@ void Model::updateClusterMatrices() { if (_useDualQuaternionSkinning) { auto jointPose = _rig.getJointPose(cluster.jointIndex); - Transform jointTransform(jointPose.rot(), glm::vec3(jointPose.scale()), jointPose.trans()); + Transform jointTransform(jointPose.rot(), jointPose.scale(), jointPose.trans()); Transform clusterTransform; Transform::mult(clusterTransform, jointTransform, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindTransform); state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(clusterTransform); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index c55178a21a..aadfca78ba 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -298,9 +298,9 @@ public: TransformDualQuaternion() {} TransformDualQuaternion(const glm::mat4& m) { AnimPose p(m); - _scale.x = p.scale(); - _scale.y = p.scale(); - _scale.z = p.scale(); + _scale.x = p.scale().x; + _scale.y = p.scale().y; + _scale.z = p.scale().z; _scale.w = 0.0f; _dq = DualQuaternion(p.rot(), p.trans()); } diff --git a/tests/animation/src/AnimTests.cpp b/tests/animation/src/AnimTests.cpp index 2a49846b6b..0cd9571e22 100644 --- a/tests/animation/src/AnimTests.cpp +++ b/tests/animation/src/AnimTests.cpp @@ -22,11 +22,9 @@ #include #include #include -#include QTEST_MAIN(AnimTests) - const float TEST_EPSILON = 0.001f; void AnimTests::initTestCase() { @@ -374,10 +372,16 @@ void AnimTests::testAnimPose() { const glm::quat ROT_Y_180 = glm::angleAxis(PI, glm::vec3(0.0f, 1.0, 0.0f)); const glm::quat ROT_Z_30 = glm::angleAxis(PI / 6.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - std::vector scaleVec = { - 1.0f, - 2.0f, - 0.5f + std::vector scaleVec = { + glm::vec3(1), + glm::vec3(2.0f, 1.0f, 1.0f), + glm::vec3(1.0f, 0.5f, 1.0f), + glm::vec3(1.0f, 1.0f, 1.5f), + glm::vec3(2.0f, 0.5f, 1.5f), + glm::vec3(-2.0f, 0.5f, 1.5f), + glm::vec3(2.0f, -0.5f, 1.5f), + glm::vec3(2.0f, 0.5f, -1.5f), + glm::vec3(-2.0f, -0.5f, -1.5f), }; std::vector rotVec = { @@ -407,7 +411,7 @@ void AnimTests::testAnimPose() { for (auto& trans : transVec) { // build a matrix the old fashioned way. - glm::mat4 scaleMat = glm::scale(glm::mat4(), glm::vec3(scale)); + glm::mat4 scaleMat = glm::scale(glm::mat4(), scale); glm::mat4 rotTransMat = createMatFromQuatAndPos(rot, trans); glm::mat4 rawMat = rotTransMat * scaleMat; @@ -425,7 +429,7 @@ void AnimTests::testAnimPose() { for (auto& trans : transVec) { // build a matrix the old fashioned way. - glm::mat4 scaleMat = glm::scale(glm::mat4(), glm::vec3(scale)); + glm::mat4 scaleMat = glm::scale(glm::mat4(), scale); glm::mat4 rotTransMat = createMatFromQuatAndPos(rot, trans); glm::mat4 rawMat = rotTransMat * scaleMat; @@ -441,91 +445,6 @@ void AnimTests::testAnimPose() { } } -void AnimTests::testAnimPoseMultiply() { - const float PI = (float)M_PI; - const glm::quat ROT_X_90 = glm::angleAxis(PI / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - const glm::quat ROT_Y_180 = glm::angleAxis(PI, glm::vec3(0.0f, 1.0, 0.0f)); - const glm::quat ROT_Z_30 = glm::angleAxis(PI / 6.0f, glm::vec3(1.0f, 0.0f, 0.0f)); - - std::vector scaleVec = { - 1.0f, - 2.0f, - 0.5f, - }; - - std::vector rotVec = { - glm::quat(), - ROT_X_90, - ROT_Y_180, - ROT_Z_30, - ROT_X_90 * ROT_Y_180 * ROT_Z_30, - -ROT_Y_180 - }; - - std::vector transVec = { - glm::vec3(), - glm::vec3(10.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 5.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 7.5f), - glm::vec3(10.0f, 5.0f, 7.5f), - glm::vec3(-10.0f, 5.0f, 7.5f), - glm::vec3(10.0f, -5.0f, 7.5f), - glm::vec3(10.0f, 5.0f, -7.5f) - }; - - const float TEST_EPSILON = 0.001f; - - std::vector matrixVec; - std::vector poseVec; - - for (auto& scale : scaleVec) { - for (auto& rot : rotVec) { - for (auto& trans : transVec) { - - // build a matrix the old fashioned way. - glm::mat4 scaleMat = glm::scale(glm::mat4(), glm::vec3(scale)); - glm::mat4 rotTransMat = createMatFromQuatAndPos(rot, trans); - glm::mat4 rawMat = rotTransMat * scaleMat; - - matrixVec.push_back(rawMat); - - // use an anim pose to build a matrix by parts. - AnimPose pose(scale, rot, trans); - poseVec.push_back(pose); - } - } - } - - for (int i = 0; i < matrixVec.size(); i++) { - for (int j = 0; j < matrixVec.size(); j++) { - - // multiply the matrices together - glm::mat4 matrix = matrixVec[i] * matrixVec[j]; - - // convert to matrix (note this will remove sheer from the matrix) - AnimPose resultA(matrix); - - // multiply the poses together directly - AnimPose resultB = poseVec[i] * poseVec[j]; - - /* - qDebug() << "matrixVec[" << i << "] =" << matrixVec[i]; - qDebug() << "matrixVec[" << j << "] =" << matrixVec[j]; - qDebug() << "matrixResult =" << resultA; - - qDebug() << "poseVec[" << i << "] =" << poseVec[i]; - qDebug() << "poseVec[" << j << "] =" << poseVec[j]; - qDebug() << "poseResult =" << resultB; - */ - - // compare results. - QCOMPARE_WITH_ABS_ERROR(resultA.scale(), resultB.scale(), TEST_EPSILON); - QCOMPARE_WITH_ABS_ERROR(resultA.rot(), resultB.rot(), TEST_EPSILON); - QCOMPARE_WITH_ABS_ERROR(resultA.trans(), resultB.trans(), TEST_EPSILON); - } - } -} - void AnimTests::testExpressionTokenizer() { QString str = "(10 + x) >= 20.1 && (y != !z)"; AnimExpression e("x"); diff --git a/tests/animation/src/AnimTests.h b/tests/animation/src/AnimTests.h index 637611e8c4..439793f21d 100644 --- a/tests/animation/src/AnimTests.h +++ b/tests/animation/src/AnimTests.h @@ -27,7 +27,6 @@ private slots: void testVariant(); void testAccumulateTime(); void testAnimPose(); - void testAnimPoseMultiply(); void testExpressionTokenizer(); void testExpressionParser(); void testExpressionEvaluator(); From 46ff3a84057dfd67813809b11f2d023cde5227da Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 14 Feb 2019 10:23:21 -0800 Subject: [PATCH 134/139] add select/clear all buttons to entity type dropdown --- scripts/system/html/css/edit-style.css | 20 ++++++++++ scripts/system/html/entityList.html | 4 ++ scripts/system/html/js/entityList.js | 54 ++++++++++++++++++++------ 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 6a0e7c8343..e9fa27d997 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1210,6 +1210,26 @@ div#grid-section, body#entity-list-body { width: 200px; padding-top: 1px; } +#filter-type-options-buttons { + top: -20px; + width: 224px; + z-index: 2; + background-color: #afafaf; +} +#filter-type-options input[type=button] { + position: relative; + top: 5px; + left: 15px; + z-index: 3; + height: 14px; + min-width: 60px; + font-size: 10px; + color: #000; + background: linear-gradient(#afafaf 20%, #808080 100%); +} +#filter-type-options input[type=button]:enabled:hover { + background: linear-gradient(#afafaf 20%, #575757 100%); +} #filter-search-and-icon { position: relative; diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index f525c84cbc..cfbce3c4d3 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -43,6 +43,10 @@
+
+ + +
diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index b19873a049..b487be0fd2 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -188,6 +188,7 @@ let renameTimeout = null; let renameLastBlur = null; let renameLastEntityID = null; let isRenameFieldBeingMoved = false; +let elFilterTypeInputs = {}; let elEntityTable, elEntityTableHeader, @@ -201,6 +202,8 @@ let elEntityTable, elFilterTypeMultiselectBox, elFilterTypeText, elFilterTypeOptions, + elFilterTypeSelectAll, + elFilterTypeClearAll, elFilterSearch, elFilterInView, elFilterRadius, @@ -243,6 +246,8 @@ function loaded() { elFilterTypeMultiselectBox = document.getElementById("filter-type-multiselect-box"); elFilterTypeText = document.getElementById("filter-type-text"); elFilterTypeOptions = document.getElementById("filter-type-options"); + elFilterTypeSelectAll = document.getElementById('filter-type-select-all'); + elFilterTypeClearAll = document.getElementById('filter-type-clear-all'); elFilterSearch = document.getElementById("filter-search"); elFilterInView = document.getElementById("filter-in-view"); elFilterRadius = document.getElementById("filter-radius"); @@ -276,6 +281,8 @@ function loaded() { }; elRefresh.onclick = refreshEntities; elFilterTypeMultiselectBox.onclick = onToggleTypeDropdown; + elFilterTypeSelectAll.onclick = onSelectAllTypes; + elFilterTypeClearAll.onclick = onClearAllTypes; elFilterSearch.onkeyup = refreshEntityList; elFilterSearch.onsearch = refreshEntityList; elFilterInView.onclick = onToggleFilterInView; @@ -297,6 +304,7 @@ function loaded() { elInput.setAttribute("id", typeFilterID); elInput.setAttribute("filterType", type); elInput.checked = true; // all types are checked initially + elFilterTypeInputs[type] = elInput; elDiv.appendChild(elInput); let elLabel = document.createElement('label'); @@ -1065,7 +1073,21 @@ function loaded() { event.stopPropagation(); } - function toggleTypeFilter(elInput, refresh) { + function refreshTypeFilter(refreshList) { + if (typeFilters.length === 0) { + elFilterTypeText.innerText = "No Types"; + } else if (typeFilters.length === FILTER_TYPES.length) { + elFilterTypeText.innerText = "All Types"; + } else { + elFilterTypeText.innerText = "Types..."; + } + + if (refreshList) { + refreshEntityList(); + } + } + + function toggleTypeFilter(elInput, refreshList) { let type = elInput.getAttribute("filterType"); let typeChecked = elInput.checked; @@ -1076,17 +1098,7 @@ function loaded() { typeFilters.push(type); } - if (typeFilters.length === 0) { - elFilterTypeText.innerText = "No Types"; - } else if (typeFilters.length === FILTER_TYPES.length) { - elFilterTypeText.innerText = "All Types"; - } else { - elFilterTypeText.innerText = "Types..."; - } - - if (refresh) { - refreshEntityList(); - } + refreshTypeFilter(refreshList); } function onToggleTypeFilter(event) { @@ -1097,6 +1109,24 @@ function loaded() { event.stopPropagation(); } + function onSelectAllTypes(event) { + for (let type in elFilterTypeInputs) { + elFilterTypeInputs[type].checked = true; + } + typeFilters = FILTER_TYPES; + refreshTypeFilter(true); + event.stopPropagation(); + } + + function onClearAllTypes(event) { + for (let type in elFilterTypeInputs) { + elFilterTypeInputs[type].checked = false; + } + typeFilters = []; + refreshTypeFilter(true); + event.stopPropagation(); + } + function onBodyClick(event) { // if clicking anywhere outside of the multiselect dropdowns (since click event bubbled up to onBodyClick and // propagation wasn't stopped in the toggle type/column callbacks) and the dropdown is open then close it From f6baa2432ab7870f689b2b4d6fd5339ef938b792 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 14 Feb 2019 17:27:05 -0800 Subject: [PATCH 135/139] design feedback --- scripts/system/html/css/edit-style.css | 6 +++--- scripts/system/html/entityList.html | 2 +- scripts/system/html/js/entityList.js | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index e9fa27d997..6870f18721 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1215,13 +1215,13 @@ div#grid-section, body#entity-list-body { width: 224px; z-index: 2; background-color: #afafaf; + padding-bottom: 2px; } #filter-type-options input[type=button] { position: relative; - top: 5px; - left: 15px; + left: 16px; z-index: 3; - height: 14px; + height: 19px; min-width: 60px; font-size: 10px; color: #000; diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index cfbce3c4d3..986e5c09b0 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -43,11 +43,11 @@
+
-
diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index b487be0fd2..8482591771 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -202,6 +202,7 @@ let elEntityTable, elFilterTypeMultiselectBox, elFilterTypeText, elFilterTypeOptions, + elFilterTypeOptionsButtons, elFilterTypeSelectAll, elFilterTypeClearAll, elFilterSearch, @@ -246,6 +247,7 @@ function loaded() { elFilterTypeMultiselectBox = document.getElementById("filter-type-multiselect-box"); elFilterTypeText = document.getElementById("filter-type-text"); elFilterTypeOptions = document.getElementById("filter-type-options"); + elFilterTypeOptionsButtons = document.getElementById("filter-type-options-buttons"); elFilterTypeSelectAll = document.getElementById('filter-type-select-all'); elFilterTypeClearAll = document.getElementById('filter-type-clear-all'); elFilterSearch = document.getElementById("filter-search"); @@ -297,7 +299,7 @@ function loaded() { let elDiv = document.createElement('div'); elDiv.onclick = onToggleTypeFilter; - elFilterTypeOptions.appendChild(elDiv); + elFilterTypeOptions.insertBefore(elDiv, elFilterTypeOptionsButtons); let elInput = document.createElement('input'); elInput.setAttribute("type", "checkbox"); From e944e284a6afeea9ca80a0734cd6eefcaf84f21d Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 14 Feb 2019 17:37:58 -0800 Subject: [PATCH 136/139] design feedback --- scripts/system/html/css/edit-style.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 6870f18721..926eeaeeb3 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1211,17 +1211,17 @@ div#grid-section, body#entity-list-body { padding-top: 1px; } #filter-type-options-buttons { - top: -20px; + top: -22px; width: 224px; z-index: 2; background-color: #afafaf; - padding-bottom: 2px; + padding-bottom: 6px; } #filter-type-options input[type=button] { position: relative; left: 16px; z-index: 3; - height: 19px; + height: 23px; min-width: 60px; font-size: 10px; color: #000; From 8b2d9c36af1447a6b4f6c1fcf63e7ca75d57f0e4 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 15 Feb 2019 08:39:29 -0800 Subject: [PATCH 137/139] Adding client profile combo. --- tools/nitpick/src/Nitpick.cpp | 8 ++++++-- tools/nitpick/src/Nitpick.h | 2 ++ tools/nitpick/src/Test.cpp | 2 +- tools/nitpick/src/Test.h | 2 +- tools/nitpick/ui/Nitpick.ui | 14 ++++++++++++-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/tools/nitpick/src/Nitpick.cpp b/tools/nitpick/src/Nitpick.cpp index d5bc6f6e5a..39800c6bc6 100644 --- a/tools/nitpick/src/Nitpick.cpp +++ b/tools/nitpick/src/Nitpick.cpp @@ -40,7 +40,11 @@ Nitpick::Nitpick(QWidget* parent) : QMainWindow(parent) { _ui.plainTextEdit->setReadOnly(true); - setWindowTitle("Nitpick - v2.1.2"); + setWindowTitle("Nitpick - v3.0.0"); + + clientProfiles << "VR-High" << "Desktop-High" << "Desktop-Low" << "Mobile-Touch" << "VR-Standalone"; + _ui.clientProfileComboBox->insertItems(0, clientProfiles); + } Nitpick::~Nitpick() { @@ -157,7 +161,7 @@ void Nitpick::on_createAllRecursiveScriptsPushbutton_clicked() { } void Nitpick::on_createTestsPushbutton_clicked() { - _test->createTests(); + _test->createTests(_ui.clientProfileComboBox->currentText()); } void Nitpick::on_createMDFilePushbutton_clicked() { diff --git a/tools/nitpick/src/Nitpick.h b/tools/nitpick/src/Nitpick.h index 36ec7e534b..80fef934d6 100644 --- a/tools/nitpick/src/Nitpick.h +++ b/tools/nitpick/src/Nitpick.h @@ -126,6 +126,8 @@ private: bool _isRunningFromCommandline{ false }; void* _caller; + + QStringList clientProfiles; }; #endif // hifi_Nitpick_h \ No newline at end of file diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp index f1e950db88..e8e284bf32 100644 --- a/tools/nitpick/src/Test.cpp +++ b/tools/nitpick/src/Test.cpp @@ -391,7 +391,7 @@ void Test::includeTest(QTextStream& textStream, const QString& testPathname) { textStream << "Script.include(testsRootPath + \"" << partialPathWithoutTests + "\");" << endl; } -void Test::createTests() { +void Test::createTests(const QString& clientProfile) { // Rename files sequentially, as ExpectedResult_00000.png, ExpectedResult_00001.png and so on // Any existing expected result images will be deleted QString previousSelection = _snapshotDirectory; diff --git a/tools/nitpick/src/Test.h b/tools/nitpick/src/Test.h index 166c71688d..23011d0c31 100644 --- a/tools/nitpick/src/Test.h +++ b/tools/nitpick/src/Test.h @@ -52,7 +52,7 @@ public: void finishTestsEvaluation(); - void createTests(); + void createTests(const QString& clientProfile); void createTestsOutline(); diff --git a/tools/nitpick/ui/Nitpick.ui b/tools/nitpick/ui/Nitpick.ui index 79bdfd158b..47471522db 100644 --- a/tools/nitpick/ui/Nitpick.ui +++ b/tools/nitpick/ui/Nitpick.ui @@ -52,8 +52,8 @@ - 210 - 60 + 70 + 40 220 40 @@ -153,6 +153,16 @@ Create all testAuto scripts + + + + 320 + 40 + 120 + 40 + + + From b77f40d300d8996adb6d318f38a0eeb9b1b44793 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 15 Feb 2019 09:52:57 -0800 Subject: [PATCH 138/139] Revert due to stable build problem on Ubuntu. --- tools/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index b9ae635a4f..6cda67db2d 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -20,7 +20,7 @@ endfunction() if (BUILD_TOOLS) # Allow different tools for stable builds - if (STABLE_BUILD) + if (RELEASE_TYPE STREQUAL "PRODUCTION") set(ALL_TOOLS udt-test vhacd-util From 54839718555c23f11afc322bd9c693844cae97e0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 15 Feb 2019 10:46:08 -0800 Subject: [PATCH 139/139] Fix crash in vive and interleaved stereo plugins --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 2 +- .../src/display-plugins/OpenGLDisplayPlugin.h | 5 +++++ libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index e4deaf8f4b..20fc9a2290 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -720,7 +720,7 @@ void OpenGLDisplayPlugin::present() { } gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory()); - } else { + } else if (alwaysPresent()) { internalPresent(); } _movingAveragePresent.addSample((float)(usecTimestampNow() - startPresent)); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 5c653f8a0a..49a38ecb4c 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -88,6 +88,11 @@ protected: glm::uvec2 getSurfaceSize() const; glm::uvec2 getSurfacePixels() const; + // Some display plugins require us to always execute some present logic, + // whether we have a frame or not (Oculus Mobile plugin) + // Such plugins must be prepared to do the right thing if the `_currentFrame` + // is not populated + virtual bool alwaysPresent() const { return false; } void updateCompositeFramebuffer(); diff --git a/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.h b/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.h index 4a0a21e995..a98989655e 100644 --- a/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.h +++ b/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.h @@ -57,6 +57,7 @@ protected: void internalPresent() override; void hmdPresent() override { throw std::runtime_error("Unused"); } bool isHmdMounted() const override; + bool alwaysPresent() const override { return true; } static const char* NAME; mutable gl::Context* _mainContext{ nullptr };
Print some nestable types.Create a Web entity displaying at 1920 x 1080 resolution.Create a cube overlay in front of your avatar. Report 3D overlay intersection details for mouse diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 4178cd4aec..a578ed0d97 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -170,8 +170,7 @@ WebTablet = function (url, width, dpi, hand, location, visible) { visible: visible }); - // FIXME: Circle3D overlays currently at the wrong dimensions, so we need to account for that here - var homeButtonDim = 4.0 * tabletScaleFactor / 3.0; + var homeButtonDim = 4.0 * tabletScaleFactor / 1.5; var HOME_BUTTON_X_OFFSET = 0.00079 * sensorScaleFactor; var HOME_BUTTON_Y_OFFSET = -1 * ((tabletHeight / 2) - (4.0 * tabletScaleFactor / 2)); var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleFactor; @@ -224,23 +223,6 @@ WebTablet = function (url, width, dpi, hand, location, visible) { } }; - this.myOnHoverEnterOverlay = function (overlayID, pointerEvent) { - _this.onHoverEnterOverlay(overlayID, pointerEvent); - }; - - Overlays.hoverEnterOverlay.connect(this.myOnHoverEnterOverlay); - - this.myOnHoverLeaveOverlay = function (overlayID, pointerEvent) { - _this.onHoverLeaveOverlay(overlayID, pointerEvent); - }; - - Overlays.hoverLeaveOverlay.connect(this.myOnHoverLeaveOverlay); - - this.myOnHoverOverOverlay = function (overlayID, pointerEvent) { - _this.onHoverOverOverlay(overlayID, pointerEvent); - }; - Overlays.hoverOverOverlay.connect(this.myOnHoverOverOverlay); - this.state = "idle"; this.getRoot = function() { @@ -350,10 +332,6 @@ WebTablet.prototype.setWidth = function (width) { }; WebTablet.prototype.destroy = function () { - Overlays.hoverEnterOverlay.disconnect(this.myOnHoverEnterOverlay); - Overlays.hoverLeaveOverlay.disconnect(this.myOnHoverLeaveOverlay); - Overlays.hoverOverOverlay.disconnect(this.myOnHoverOverOverlay); - Overlays.deleteOverlay(this.webOverlayID); Overlays.deleteOverlay(this.tabletEntityID); Overlays.deleteOverlay(this.homeButtonID); @@ -449,24 +427,6 @@ WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function (windowPos }; }; -WebTablet.prototype.onHoverEnterOverlay = function (overlayID, pointerEvent) { - if (overlayID === this.homeButtonID) { - Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 1.0 }); - } -}; - -WebTablet.prototype.onHoverOverOverlay = function (overlayID, pointerEvent) { - if (overlayID !== this.homeButtonID) { - Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 0.0 }); - } -}; - -WebTablet.prototype.onHoverLeaveOverlay = function (overlayID, pointerEvent) { - if (overlayID === this.homeButtonID) { - Overlays.editOverlay(this.homeButtonHighlightID, { alpha: 0.0 }); - } -}; - // compute position, rotation & parentJointIndex of the tablet WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMouse, tabletProperties) { if (HMD.active) { @@ -595,17 +555,8 @@ WebTablet.prototype.scheduleMouseMoveProcessor = function() { WebTablet.prototype.handleHomeButtonHover = function(x, y) { var pickRay = Camera.computePickRay(x, y); - var entityPickResults; - var homebuttonHovered = false; - entityPickResults = Overlays.findRayIntersection(pickRay, true, [this.tabletEntityID]); - if (entityPickResults.intersects && (entityPickResults.entityID === this.tabletEntityID || - entityPickResults.overlayID === this.tabletEntityID)) { - var overlayPickResults = Overlays.findRayIntersection(pickRay, true, [this.homeButtonID], []); - if (overlayPickResults.intersects && overlayPickResults.overlayID === this.homeButtonID) { - homebuttonHovered = true; - } - } - Overlays.editOverlay(this.homeButtonHighlightID, { alpha: homebuttonHovered ? 1.0 : 0.0 }); + var homePickResult = Overlays.findRayIntersection(pickRay, true, [this.homeButtonID]); + Overlays.editOverlay(this.homeButtonHighlightID, { alpha: homePickResult.intersects ? 1.0 : 0.0 }); }; WebTablet.prototype.mouseMoveEvent = function (event) { diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js index c0a52a45c6..931c346299 100644 --- a/scripts/system/libraries/utils.js +++ b/scripts/system/libraries/utils.js @@ -412,8 +412,7 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride) }); // update homeButton - // FIXME: Circle3D overlays currently at the wrong dimensions, so we need to account for that here - var homeButtonDim = 4.0 * tabletScaleFactor / 3.0; + var homeButtonDim = 4.0 * tabletScaleFactor / 1.5; var HOME_BUTTON_X_OFFSET = 0.00079 * sensorScaleOffsetOverride * sensorScaleFactor; var HOME_BUTTON_Y_OFFSET = -1 * ((tabletHeight / 2) - (4.0 * tabletScaleFactor / 2)) * sensorScaleOffsetOverride; var HOME_BUTTON_Z_OFFSET = (tabletDepth / 1.9) * sensorScaleOffsetOverride; From 7fa676a8460ac97fc5810215700a843bcba7590c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 28 Jan 2019 23:32:16 -0800 Subject: [PATCH 022/139] don't render text parts if alpha == 0 --- .../src/RenderableTextEntityItem.cpp | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 94ecf5d4eb..28879613f5 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -194,19 +194,22 @@ void TextEntityRenderer::doRender(RenderArgs* args) { transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed - batch.setModelTransform(transformToTopLeft); - auto geometryCache = DependencyManager::get(); - geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false); - geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID); + if (backgroundColor.a > 0.0f) { + batch.setModelTransform(transformToTopLeft); + auto geometryCache = DependencyManager::get(); + geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false); + geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID); + } - // FIXME: Factor out textRenderer so that text parts can be grouped by pipeline for a gpu performance increase. - float scale = _lineHeight / _textRenderer->getFontSize(); - transformToTopLeft.setScale(scale); // Scale to have the correct line height - batch.setModelTransform(transformToTopLeft); + if (textColor.a > 0.0f) { + // FIXME: Factor out textRenderer so that text parts can be grouped by pipeline for a gpu performance increase. + float scale = _lineHeight / _textRenderer->getFontSize(); + transformToTopLeft.setScale(scale); // Scale to have the correct line height + batch.setModelTransform(transformToTopLeft); - glm::vec2 bounds = glm::vec2(dimensions.x - (_leftMargin + _rightMargin), - dimensions.y - (_topMargin + _bottomMargin)); - _textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale); + glm::vec2 bounds = glm::vec2(dimensions.x - (_leftMargin + _rightMargin), dimensions.y - (_topMargin + _bottomMargin)); + _textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale); + } } QSizeF TextEntityRenderer::textSize(const QString& text) const { From 834e44dd3a6d91cf7dc4d4cb67c116d060f3416f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 30 Jan 2019 11:02:24 -0800 Subject: [PATCH 023/139] make polyline's with faceCamera not depend on normal --- interface/src/raypick/LaserPointer.cpp | 5 +++-- .../src/RenderablePolyLineEntityItem.cpp | 19 +++++++++++++------ .../entities-renderer/src/paintStroke.slv | 15 +++++++-------- .../system/libraries/entitySelectionTool.js | 4 +++- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 694c420426..aeed65fbad 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -165,8 +165,9 @@ void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& if (!getPathID().isNull()) { EntityItemProperties properties; QVector points; - points.append(origin); - points.append(end); + points.append(glm::vec3(0.0f)); + points.append(end - origin); + properties.setPosition(origin); properties.setLinePoints(points); properties.setVisible(true); properties.setIgnorePickIntersection(doesPathIgnorePicks()); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 68371e4e13..7ad050e86c 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -128,7 +128,8 @@ void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo } // Data - if (faceCamera != _faceCamera || glow != _glow) { + bool faceCameraChanged = faceCamera != _faceCamera; + if (faceCameraChanged || glow != _glow) { _faceCamera = faceCamera; _glow = glow; updateData(); @@ -148,7 +149,7 @@ void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPo _colors = entity->getStrokeColors(); _color = toGlm(entity->getColor()); } - if (_isUVModeStretch != isUVModeStretch || pointsChanged || widthsChanged || normalsChanged || colorsChanged || textureChanged) { + if (_isUVModeStretch != isUVModeStretch || pointsChanged || widthsChanged || normalsChanged || colorsChanged || textureChanged || faceCameraChanged) { _isUVModeStretch = isUVModeStretch; updateGeometry(); } @@ -220,11 +221,17 @@ void PolyLineEntityRenderer::updateGeometry() { // For last point we can assume binormals are the same since it represents the last two vertices of quad if (i < maxNumVertices - 1) { glm::vec3 tangent = _points[i + 1] - point; - binormal = glm::normalize(glm::cross(tangent, normal)); - // Check to make sure binormal is not a NAN. If it is, don't add to vertices vector - if (binormal.x != binormal.x) { - continue; + if (_faceCamera) { + // In faceCamera mode, we actually pass the tangent, and recompute the binormal in the shader + binormal = tangent; + } else { + binormal = glm::normalize(glm::cross(tangent, normal)); + + // Check to make sure binormal is not a NAN. If it is, don't add to vertices vector + if (binormal.x != binormal.x) { + continue; + } } } diff --git a/libraries/entities-renderer/src/paintStroke.slv b/libraries/entities-renderer/src/paintStroke.slv index c033d2c247..f591370186 100644 --- a/libraries/entities-renderer/src/paintStroke.slv +++ b/libraries/entities-renderer/src/paintStroke.slv @@ -36,24 +36,23 @@ void main(void) { TransformObject obj = getTransformObject(); _distanceFromCenter = -1.0 + 2.0 * evenVertex; vec4 position = vec4(vertex.positionAndUCoord.xyz, 1.0); - vec3 normal = vertex.normal.xyz; vec3 binormal = vertex.binormalAndHalfWidth.xyz; if (_polylineData.faceCameraGlow.x != 0.0) { vec4 posEye; - vec3 normalEye; - vec3 binormalEye; + vec3 tangentEye; <$transformModelToEyePos(cam, obj, position, posEye)$> - <$transformModelToEyeDir(cam, obj, normal, normalEye)$> - <$transformModelToEyeDir(cam, obj, binormal, binormalEye)$> + // See comment in RenderablePolyLineEntityItem.cpp: we actually pass in the tangent in faceCamera mode + <$transformModelToEyeDir(cam, obj, binormal, tangentEye)$> - vec3 tangentEye = cross(binormalEye, normalEye); // new normal faces the camera - normalEye = normalize(posEye.xyz); - binormalEye = normalize(cross(normalEye, tangentEye)); + vec3 normalEye = normalize(posEye.xyz); + + vec3 binormalEye = normalize(cross(normalEye, tangentEye)); posEye.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormalEye; <$transformEyeToClipPos(cam, posEye, gl_Position)$> <$transformEyeToWorldDir(cam, normalEye, _normalWS)$> } else { + vec3 normal = vertex.normal.xyz; position.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormal; <$transformModelToClipPos(cam, obj, position, gl_Position)$> <$transformModelToWorldDir(cam, obj, normal, _normalWS)$> diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 4cbc44bc2b..c9f171b0aa 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1013,6 +1013,8 @@ SelectionDisplay = (function() { return null; } + // We want to first check the drawInFront overlays (i.e. the handles, but really everything except the selectionBoxes) + // so that you can click on them even when they're behind things var overlayIncludesLayered = overlayIncludes.filter(function (value, index, arr) { return value != selectionBox && value != iconSelectionBox; }); @@ -1023,7 +1025,7 @@ SelectionDisplay = (function() { return value == selectionBox || value == iconSelectionBox; }); if (overlayIncludesNonLayered.length > 0) { - intersectObj = Overlays.findRayIntersection(queryRay, true, [], overlayExcludes); + intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludesNonLayered, overlayExcludes); } } From 57ee9786af5e1b57f2c65fd4e365afc103a0d704 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 30 Jan 2019 11:42:05 -0800 Subject: [PATCH 024/139] fix picks vs. local entities --- libraries/entities/src/EntityTreeElement.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 3b085457d1..abc4507fe0 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -141,14 +141,20 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3 bool checkFilterSettings(const EntityItemPointer& entity, PickFilter searchFilter) { bool visible = entity->isVisible(); - bool collidable = !entity->getCollisionless() && (entity->getShapeType() != SHAPE_TYPE_NONE); + entity::HostType hostType = entity->getEntityHostType(); if ((!searchFilter.doesPickVisible() && visible) || (!searchFilter.doesPickInvisible() && !visible) || - (!searchFilter.doesPickCollidable() && collidable) || (!searchFilter.doesPickNonCollidable() && !collidable) || - (!searchFilter.doesPickDomainEntities() && entity->isDomainEntity()) || - (!searchFilter.doesPickAvatarEntities() && entity->isAvatarEntity()) || - (!searchFilter.doesPickLocalEntities() && entity->isLocalEntity())) { + (!searchFilter.doesPickDomainEntities() && hostType == entity::HostType::DOMAIN) || + (!searchFilter.doesPickAvatarEntities() && hostType == entity::HostType::AVATAR) || + (!searchFilter.doesPickLocalEntities() && hostType == entity::HostType::LOCAL)) { return false; } + // We only check the collidable filters for non-local entities, because local entities are always collisionless + bool collidable = !entity->getCollisionless() && (entity->getShapeType() != SHAPE_TYPE_NONE); + if (hostType != entity::HostType::LOCAL) { + if ((!searchFilter.doesPickCollidable() && collidable) || (!searchFilter.doesPickNonCollidable() && !collidable)) { + return false; + } + } return true; } From 708da45ccc6f4f0d320b07d7f121b587b044bd38 Mon Sep 17 00:00:00 2001 From: amer cerkic Date: Wed, 30 Jan 2019 11:47:06 -0800 Subject: [PATCH 025/139] recreated changes due to CLA issue in previous pr. Adding args to intent so that app can parse as comamnd line args. --- .../hifiinterface/InterfaceActivity.java | 16 ++++++++++-- .../hifiinterface/PermissionChecker.java | 11 ++++++++ .../hifiinterface/SplashActivity.java | 26 ++++++++++++++----- interface/CMakeLists.txt | 6 ++++- 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index b7d2157737..fdc0ec3bd8 100644 --- a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -24,6 +24,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Vibrator; +import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -53,6 +54,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW public static final String DOMAIN_URL = "url"; public static final String EXTRA_GOTO_USERNAME = "gotousername"; private static final String TAG = "Interface"; + public static final String EXTRA_ARGS = "args"; private static final int WEB_DRAWER_RIGHT_MARGIN = 262; private static final int WEB_DRAWER_BOTTOM_MARGIN = 150; private static final int NORMAL_DPI = 160; @@ -77,6 +79,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW private boolean nativeEnterBackgroundCallEnqueued = false; private SlidingDrawer mWebSlidingDrawer; + private boolean mStartInDomain; // private GvrApi gvrApi; // Opaque native pointer to the Application C++ object. // This object is owned by the InterfaceActivity instance and passed to the native methods. @@ -92,8 +95,14 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW public void onCreate(Bundle savedInstanceState) { super.isLoading = true; Intent intent = getIntent(); - if (intent.hasExtra(DOMAIN_URL) && !intent.getStringExtra(DOMAIN_URL).isEmpty()) { + if (intent.hasExtra(DOMAIN_URL) && !TextUtils.isEmpty(intent.getStringExtra(DOMAIN_URL))) { intent.putExtra("applicationArguments", "--url " + intent.getStringExtra(DOMAIN_URL)); + } else if (intent.hasExtra(EXTRA_ARGS)) { + String args = intent.getStringExtra(EXTRA_ARGS); + if (!TextUtils.isEmpty(args)) { + mStartInDomain = true; + intent.putExtra("applicationArguments", args); + } } super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); @@ -124,7 +133,10 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW getActionBar().hide(); } }); - startActivity(new Intent(this, SplashActivity.class)); + Intent splashIntent = new Intent(this, SplashActivity.class); + splashIntent.putExtra(SplashActivity.EXTRA_START_IN_DOMAIN, mStartInDomain); + startActivity(splashIntent); + mVibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE); headsetStateReceiver = new HeadsetStateReceiver(); } diff --git a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java index 78a6421746..ef9876c71a 100644 --- a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java +++ b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/PermissionChecker.java @@ -9,6 +9,7 @@ import android.content.pm.PackageManager; import android.os.Bundle; import android.util.Log; import android.view.View; +import android.text.TextUtils; import org.json.JSONException; import org.json.JSONObject; @@ -27,9 +28,14 @@ public class PermissionChecker extends Activity { private static final boolean CHOOSE_AVATAR_ON_STARTUP = false; private static final String TAG = "Interface"; + private static final String EXTRA_ARGS = "args"; + private String mArgs; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mArgs =(getIntent().getStringExtra(EXTRA_ARGS)); + Intent myIntent = new Intent(this, BreakpadUploaderService.class); startService(myIntent); if (CHOOSE_AVATAR_ON_STARTUP) { @@ -76,6 +82,11 @@ public class PermissionChecker extends Activity { private void launchActivityWithPermissions(){ Intent i = new Intent(this, InterfaceActivity.class); + + if (!TextUtils.isEmpty(mArgs)) { + i.putExtra(EXTRA_ARGS, mArgs); + } + startActivity(i); finish(); } diff --git a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java index bb42467ace..9506a6a644 100644 --- a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java +++ b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java @@ -36,13 +36,27 @@ public class SplashActivity extends Activity { } public void onAppLoadedComplete() { - if (HifiUtils.getInstance().isUserLoggedIn()) { - startActivity(new Intent(this, MainActivity.class)); - } else { - Intent menuIntent = new Intent(this, LoginMenuActivity.class); - menuIntent.putExtra(LoginMenuActivity.EXTRA_FINISH_ON_BACK, true); - startActivity(menuIntent); + if (!mStartInDomain) { + if (HifiUtils.getInstance().isUserLoggedIn()) { + startActivity(new Intent(this, MainActivity.class)); + } else { + Intent menuIntent = new Intent(this, LoginMenuActivity.class); + menuIntent.putExtra(LoginMenuActivity.EXTRA_FINISH_ON_BACK, true); + startActivity(menuIntent); + } } SplashActivity.this.finish(); } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(EXTRA_START_IN_DOMAIN, mStartInDomain); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + mStartInDomain = savedInstanceState.getBoolean(EXTRA_START_IN_DOMAIN, false); + } } diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index c013cfacd3..019e20c7f7 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -330,7 +330,11 @@ if (APPLE) COMMAND "${CMAKE_COMMAND}" -E copy_directory "${PROJECT_SOURCE_DIR}/resources/fonts" "${RESOURCES_DEV_DIR}/fonts" - # add redirect json to macOS builds. + #copy serverless for android + COMMAND "${CMAKE_COMMAND}" -E copy_directory + "${PROJECT_SOURCE_DIR}/resources/serverless" + "${RESOURCES_DEV_DIR}/serverless" + # add redirect json to macOS builds. COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${PROJECT_SOURCE_DIR}/resources/serverless/redirect.json" "${RESOURCES_DEV_DIR}/serverless/redirect.json" From 7d47bfa2e44460f633567171131fe4c708e5c6dc Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 30 Jan 2019 11:50:32 -0800 Subject: [PATCH 026/139] david's comments --- .../system/libraries/entitySelectionTool.js | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index c9f171b0aa..38abac63fd 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -899,6 +899,9 @@ SelectionDisplay = (function() { yRailOverlay, zRailOverlay ]; + + const nonLayeredOverlays = [selectionBox, iconSelectionBox]; + var maximumHandleInAllOverlays = handleDuplicator; overlayNames[handleTranslateXCone] = "handleTranslateXCone"; @@ -1015,18 +1018,21 @@ SelectionDisplay = (function() { // We want to first check the drawInFront overlays (i.e. the handles, but really everything except the selectionBoxes) // so that you can click on them even when they're behind things - var overlayIncludesLayered = overlayIncludes.filter(function (value, index, arr) { - return value != selectionBox && value != iconSelectionBox; - }); + var overlayIncludesLayered = []; + var overlayIncludesNonLayered = []; + for (var i = 0; i < overlayIncludes.length; i++) { + var value = overlayIncludes[i]; + if (nonLayeredOverlays.includes(value)) { + overlayIncludesNonLayered.push(value); + } else { + overlayIncludesLayered.push(value); + } + } + var intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludesLayered, overlayExcludes); - if (!intersectObj.intersects) { - var overlayIncludesNonLayered = overlayIncludes.filter(function (value, index, arr) { - return value == selectionBox || value == iconSelectionBox; - }); - if (overlayIncludesNonLayered.length > 0) { - intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludesNonLayered, overlayExcludes); - } + if (!intersectObj.intersects && overlayIncludesNonLayered.length > 0) { + intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludesNonLayered, overlayExcludes); } if (wantDebug) { From d089bd5b8feb9200f1592406fa32acaaae1ab9db Mon Sep 17 00:00:00 2001 From: amer cerkic Date: Wed, 30 Jan 2019 12:40:09 -0800 Subject: [PATCH 027/139] missed variable declaration --- .../java/io/highfidelity/hifiinterface/SplashActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java index 9506a6a644..536bf23603 100644 --- a/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java +++ b/android/apps/interface/src/main/java/io/highfidelity/hifiinterface/SplashActivity.java @@ -7,6 +7,9 @@ import android.view.View; public class SplashActivity extends Activity { + public static final String EXTRA_START_IN_DOMAIN = "start-in-domain"; + private boolean mStartInDomain; + private native void registerLoadCompleteListener(); @Override From 0955512a80ab81d72ebc27d5bedbc5a13a2e9943 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 31 Jan 2019 15:22:09 -0800 Subject: [PATCH 028/139] add billboard mode to web entities and fix picking/culling --- interface/src/Application.cpp | 26 ++++++++++++- .../src/EntityTreeRenderer.cpp | 1 - .../src/EntityTreeRenderer.h | 4 -- .../src/RenderableImageEntityItem.cpp | 35 +++++++----------- .../src/RenderableImageEntityItem.h | 3 +- .../src/RenderableTextEntityItem.cpp | 33 ++++++----------- .../src/RenderableTextEntityItem.h | 8 ++-- .../src/RenderableWebEntityItem.cpp | 22 ++++++++++- .../src/RenderableWebEntityItem.h | 2 + libraries/entities/src/EntityItem.cpp | 2 + libraries/entities/src/EntityItem.h | 5 +++ .../entities/src/EntityItemProperties.cpp | 37 +++++++++++-------- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/EntityPropertyFlags.h | 10 ++--- libraries/entities/src/ImageEntityItem.cpp | 21 ++++++++--- libraries/entities/src/ImageEntityItem.h | 13 ++++--- libraries/entities/src/TextEntityItem.cpp | 23 +++++++++--- libraries/entities/src/TextEntityItem.h | 4 +- libraries/entities/src/WebEntityItem.cpp | 28 ++++++++++++++ libraries/entities/src/WebEntityItem.h | 5 +++ libraries/networking/src/udt/PacketHeaders.h | 1 + 21 files changed, 191 insertions(+), 94 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6b71c51a6e..c0b90899d6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2288,8 +2288,30 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); - EntityTreeRenderer::setGetAvatarUpOperator([] { - return DependencyManager::get()->getMyAvatar()->getWorldOrientation() * Vectors::UP; + EntityItem::setBillboardRotationOperator([this](const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode) { + if (billboardMode == BillboardMode::YAW) { + //rotate about vertical to face the camera + ViewFrustum frustum; + copyViewFrustum(frustum); + glm::vec3 dPosition = frustum.getPosition() - position; + // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees + float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z); + return glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); + } else if (billboardMode == BillboardMode::FULL) { + ViewFrustum frustum; + copyViewFrustum(frustum); + glm::vec3 cameraPos = frustum.getPosition(); + // use the referencial from the avatar, y isn't always up + glm::vec3 avatarUP = DependencyManager::get()->getMyAvatar()->getWorldOrientation() * Vectors::UP; + // check to see if glm::lookAt will work / using glm::lookAt variable name + glm::highp_vec3 s(glm::cross(position - cameraPos, avatarUP)); + + // make sure s is not NaN for any component + if (glm::length2(s) > 0.0f) { + return glm::conjugate(glm::toQuat(glm::lookAt(cameraPos, position, avatarUP))); + } + } + return rotation; }); render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([this](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 61344e3193..3da3693997 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -42,7 +42,6 @@ #include std::function EntityTreeRenderer::_entitiesShouldFadeFunction = []() { return true; }; -std::function EntityTreeRenderer::_getAvatarUpOperator = []() { return Vectors::UP; }; QString resolveScriptURL(const QString& scriptUrl) { auto normalizedScriptUrl = DependencyManager::get()->normalizeURL(scriptUrl); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index d9f594a20b..4a3c1c4b86 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -118,9 +118,6 @@ public: // Access the workload Space workload::SpacePointer getWorkloadSpace() const { return _space; } - static void setGetAvatarUpOperator(std::function getAvatarUpOperator) { _getAvatarUpOperator = getAvatarUpOperator; } - static glm::vec3 getAvatarUp() { return _getAvatarUpOperator(); } - EntityEditPacketSender* getPacketSender(); signals: @@ -258,7 +255,6 @@ private: workload::SpacePointer _space{ new workload::Space() }; workload::Transaction::Updates _spaceUpdates; - static std::function _getAvatarUpOperator; }; diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index c565eb1f0a..96dd1733e7 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -96,12 +96,12 @@ void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _emissive = entity->getEmissive(); _keepAspectRatio = entity->getKeepAspectRatio(); - _billboardMode = entity->getBillboardMode(); _subImage = entity->getSubImage(); _color = entity->getColor(); _alpha = entity->getAlpha(); _pulseProperties = entity->getPulseProperties(); + _billboardMode = entity->getBillboardMode(); if (!_textureIsLoaded && _texture && _texture->isLoaded()) { _textureIsLoaded = true; @@ -118,6 +118,17 @@ void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce }); } +Item::Bound ImageEntityRenderer::getBound() { + auto bound = Parent::getBound(); + if (_billboardMode != BillboardMode::NONE) { + glm::vec3 dimensions = bound.getScale(); + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); + } + return bound; +} + ShapeKey ImageEntityRenderer::getShapeKey() { auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (isTransparent()) { @@ -159,27 +170,7 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch* batch = args->_batch; - if (_billboardMode == BillboardMode::YAW) { - //rotate about vertical to face the camera - glm::vec3 dPosition = args->getViewFrustum().getPosition() - transform.getTranslation(); - // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees - float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z); - glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); - transform.setRotation(orientation); - } else if (_billboardMode == BillboardMode::FULL) { - glm::vec3 billboardPos = transform.getTranslation(); - glm::vec3 cameraPos = args->getViewFrustum().getPosition(); - // use the referencial from the avatar, y isn't always up - glm::vec3 avatarUP = EntityTreeRenderer::getAvatarUp(); - // check to see if glm::lookAt will work / using glm::lookAt variable name - glm::highp_vec3 s(glm::cross(billboardPos - cameraPos, avatarUP)); - - // make sure s is not NaN for any component - if (glm::length2(s) > 0.0f) { - glm::quat rotation(conjugate(toQuat(glm::lookAt(cameraPos, billboardPos, avatarUP)))); - transform.setRotation(rotation); - } - } + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode)); transform.postScale(dimensions); batch->setModelTransform(transform); diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.h b/libraries/entities-renderer/src/RenderableImageEntityItem.h index a20533cc8c..d60b38fe65 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.h +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.h @@ -23,6 +23,7 @@ public: ~ImageEntityRenderer(); protected: + Item::Bound getBound() override; ShapeKey getShapeKey() override; bool isTransparent() const override; @@ -39,12 +40,12 @@ private: bool _emissive; bool _keepAspectRatio; - BillboardMode _billboardMode; QRect _subImage; glm::u8vec3 _color; float _alpha; PulsePropertyGroup _pulseProperties; + BillboardMode _billboardMode; glm::vec3 _dimensions; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 28879613f5..48d39963dd 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -47,6 +47,17 @@ bool TextEntityRenderer::isTransparent() const { return Parent::isTransparent() || _textAlpha < 1.0f || _backgroundAlpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE; } +Item::Bound TextEntityRenderer::getBound() { + auto bound = Parent::getBound(); + if (_billboardMode != BillboardMode::NONE) { + glm::vec3 dimensions = bound.getScale(); + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); + } + return bound; +} + ShapeKey TextEntityRenderer::getShapeKey() { auto builder = render::ShapeKey::Builder().withOwnPipeline(); if (isTransparent()) { @@ -170,27 +181,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; auto transformToTopLeft = modelTransform; - if (_billboardMode == BillboardMode::YAW) { - //rotate about vertical to face the camera - glm::vec3 dPosition = args->getViewFrustum().getPosition() - modelTransform.getTranslation(); - // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees - float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z); - glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); - transformToTopLeft.setRotation(orientation); - } else if (_billboardMode == BillboardMode::FULL) { - glm::vec3 billboardPos = transformToTopLeft.getTranslation(); - glm::vec3 cameraPos = args->getViewFrustum().getPosition(); - // use the referencial from the avatar, y isn't always up - glm::vec3 avatarUP = EntityTreeRenderer::getAvatarUp(); - // check to see if glm::lookAt will work / using glm::lookAt variable name - glm::highp_vec3 s(glm::cross(billboardPos - cameraPos, avatarUP)); - - // make sure s is not NaN for any component - if (glm::length2(s) > 0.0f) { - glm::quat rotation(conjugate(toQuat(glm::lookAt(cameraPos, billboardPos, avatarUP)))); - transformToTopLeft.setRotation(rotation); - } - } + transformToTopLeft.setRotation(EntityItem::getBillboardRotation(transformToTopLeft.getTranslation(), transformToTopLeft.getRotation(), _billboardMode)); transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left transformToTopLeft.setScale(1.0f); // Use a scale of one so that the text is not deformed diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index a7c0b77974..e0306375a0 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -26,11 +26,13 @@ public: TextEntityRenderer(const EntityItemPointer& entity); ~TextEntityRenderer(); - bool isTransparent() const override; - ShapeKey getShapeKey() override; - QSizeF textSize(const QString& text) const; +protected: + bool isTransparent() const override; + Item::Bound getBound() override; + ShapeKey getShapeKey() override; + private: virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index ba136256cb..51f7be4cab 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -124,6 +124,10 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe return true; } + if (_billboardMode != entity->getBillboardMode()) { + return true; + } + if (_sourceURL != entity->getSourceUrl()) { return true; } @@ -209,6 +213,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene _color = entity->getColor(); _alpha = entity->getAlpha(); _pulseProperties = entity->getPulseProperties(); + _billboardMode = entity->getBillboardMode(); if (_contentType == ContentType::NoContent) { return; @@ -271,6 +276,17 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene }); } +Item::Bound WebEntityRenderer::getBound() { + auto bound = Parent::getBound(); + if (_billboardMode != BillboardMode::NONE) { + glm::vec3 dimensions = bound.getScale(); + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + bound.setScaleStayCentered(glm::vec3(SQRT_2 * max)); + } + return bound; +} + void WebEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("WebEntityRenderer::render"); withWriteLock([&] { @@ -298,14 +314,18 @@ void WebEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; glm::vec4 color; + Transform transform; withReadLock([&] { float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; color = glm::vec4(toGlm(_color), _alpha * fadeRatio); color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); - batch.setModelTransform(_renderTransform); + transform = _renderTransform; }); batch.setResourceTexture(0, _texture); + transform.setRotation(EntityItem::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode)); + batch.setModelTransform(transform); + // Turn off jitter for these entities batch.pushProjectionJitter(); DependencyManager::get()->bindWebBrowserProgram(batch, color.a < OPAQUE_ALPHA_THRESHOLD); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index e5eff5818b..30b63a72df 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -56,6 +56,7 @@ protected: virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; virtual bool isTransparent() const override; + Item::Bound getBound() override; virtual bool wantsHandControllerPointerEvents() const override { return true; } virtual bool wantsKeyboardFocus() const override { return true; } @@ -85,6 +86,7 @@ private: glm::u8vec3 _color; float _alpha { 1.0f }; PulsePropertyGroup _pulseProperties; + BillboardMode _billboardMode; QString _sourceURL; uint16_t _dpi; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 41e4f43a5d..b7d9355cd1 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -49,6 +49,8 @@ int EntityItem::_maxActionsDataSize = 800; quint64 EntityItem::_rememberDeletedActionTime = 20 * USECS_PER_SECOND; QString EntityItem::_marketplacePublicKey; +std::function EntityItem::_getBillboardRotationOperator = [](const glm::vec3&, const glm::quat& rotation, BillboardMode) { return rotation; }; + EntityItem::EntityItem(const EntityItemID& entityItemID) : SpatiallyNestable(NestableType::Entity, entityItemID) { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ec7ad78313..2351b5fbfb 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -562,6 +562,9 @@ public: virtual void addGrab(GrabPointer grab) override; virtual void removeGrab(GrabPointer grab) override; + static void setBillboardRotationOperator(std::function getBillboardRotationOperator) { _getBillboardRotationOperator = getBillboardRotationOperator; } + static glm::quat getBillboardRotation(const glm::vec3& position, const glm::quat& rotation, BillboardMode billboardMode) { return _getBillboardRotationOperator(position, rotation, billboardMode); } + signals: void requestRenderUpdate(); void spaceUpdate(std::pair data); @@ -753,6 +756,8 @@ private: std::unordered_map _materials; std::mutex _materialsLock; + static std::function _getBillboardRotationOperator; + }; #endif // hifi_EntityItem_h diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 9e087c3ac2..ed2a43c513 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -543,6 +543,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ALPHA, alpha); changedProperties += _pulse.getChangedProperties(); CHECK_PROPERTY_CHANGE(PROP_TEXTURES, textures); + CHECK_PROPERTY_CHANGE(PROP_BILLBOARD_MODE, billboardMode); // Particles CHECK_PROPERTY_CHANGE(PROP_MAX_PARTICLES, maxParticles); @@ -601,7 +602,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_TEXT_ALPHA, textAlpha); CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_COLOR, backgroundColor); CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_ALPHA, backgroundAlpha); - CHECK_PROPERTY_CHANGE(PROP_BILLBOARD_MODE, billboardMode); CHECK_PROPERTY_CHANGE(PROP_LEFT_MARGIN, leftMargin); CHECK_PROPERTY_CHANGE(PROP_RIGHT_MARGIN, rightMargin); CHECK_PROPERTY_CHANGE(PROP_TOP_MARGIN, topMargin); @@ -1337,6 +1337,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Vec3} dimensions=0.1,0.1,0.01 - The dimensions of the entity. * @property {Color} color=255,255,255 - The color of the web surface. * @property {number} alpha=1 - The alpha of the web surface. + * @property {BillboardMode} billboardMode="none" - If "none", the entity is not billboarded. If "yaw", the entity will be + * oriented to follow your camera around the y-axis. If "full" the entity will be oriented to face your camera. The following deprecated + * behavior is also supported: you can also set "faceCamera" to true to set billboardMode to "yaw", and you can set + * "isFacingAvatar" to true to set billboardMode to "full". Setting either to false sets the mode to "none" * @property {string} sourceUrl="" - The URL of the Web page to display. This value does not change as you or others navigate * on the Web entity. * @property {number} dpi=30 - The resolution to display the page at, in dots per inch. If you convert this to dots per meter @@ -1717,6 +1721,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool // Text only if (_type == EntityTypes::Text) { _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXT, text); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_HEIGHT, lineHeight); @@ -1724,7 +1729,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXT_ALPHA, textAlpha); COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_BACKGROUND_COLOR, backgroundColor, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_BACKGROUND_ALPHA, backgroundAlpha); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LEFT_MARGIN, leftMargin); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RIGHT_MARGIN, rightMargin); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TOP_MARGIN, topMargin); @@ -1760,6 +1764,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOURCE_URL, sourceUrl); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DPI, dpi); @@ -1826,11 +1831,11 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMISSIVE, emissive); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_KEEP_ASPECT_RATIO, keepAspectRatio); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BILLBOARD_MODE, billboardMode, getBillboardModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SUB_IMAGE, subImage); // Handle conversions to old 'textures' property from "imageURL" @@ -2035,6 +2040,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(alpha, float, setAlpha); _pulse.copyFromScriptValue(object, _defaultSettings); COPY_PROPERTY_FROM_QSCRIPTVALUE(textures, QString, setTextures); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(billboardMode, BillboardMode); // Particles COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, quint32, setMaxParticles); @@ -2093,7 +2099,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(textAlpha, float, setTextAlpha); COPY_PROPERTY_FROM_QSCRIPTVALUE(backgroundColor, u8vec3Color, setBackgroundColor); COPY_PROPERTY_FROM_QSCRIPTVALUE(backgroundAlpha, float, setBackgroundAlpha); - COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(billboardMode, BillboardMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(leftMargin, float, setLeftMargin); COPY_PROPERTY_FROM_QSCRIPTVALUE(rightMargin, float, setRightMargin); COPY_PROPERTY_FROM_QSCRIPTVALUE(topMargin, float, setTopMargin); @@ -2314,6 +2319,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(alpha); _pulse.merge(other._pulse); COPY_PROPERTY_IF_CHANGED(textures); + COPY_PROPERTY_IF_CHANGED(billboardMode); // Particles COPY_PROPERTY_IF_CHANGED(maxParticles); @@ -2372,7 +2378,6 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(textAlpha); COPY_PROPERTY_IF_CHANGED(backgroundColor); COPY_PROPERTY_IF_CHANGED(backgroundAlpha); - COPY_PROPERTY_IF_CHANGED(billboardMode); COPY_PROPERTY_IF_CHANGED(leftMargin); COPY_PROPERTY_IF_CHANGED(rightMargin); COPY_PROPERTY_IF_CHANGED(topMargin); @@ -2633,6 +2638,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_GROUP_PROPERTY_TO_MAP(PROP_PULSE_ALPHA_MODE, Pulse, pulse, AlphaMode, alphaMode); } ADD_PROPERTY_TO_MAP(PROP_TEXTURES, Textures, textures, QString); + ADD_PROPERTY_TO_MAP(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode); // Particles ADD_PROPERTY_TO_MAP_WITH_RANGE(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32, @@ -2726,7 +2732,6 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_TEXT_ALPHA, TextAlpha, textAlpha, float); ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, u8vec3Color); ADD_PROPERTY_TO_MAP(PROP_BACKGROUND_ALPHA, BackgroundAlpha, backgroundAlpha, float); - ADD_PROPERTY_TO_MAP(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode); ADD_PROPERTY_TO_MAP(PROP_LEFT_MARGIN, LeftMargin, leftMargin, float); ADD_PROPERTY_TO_MAP(PROP_RIGHT_MARGIN, RightMargin, rightMargin, float); ADD_PROPERTY_TO_MAP(PROP_TOP_MARGIN, TopMargin, topMargin, float); @@ -3136,6 +3141,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticPulse.setProperties(properties); _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight()); @@ -3143,7 +3149,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_TEXT_ALPHA, properties.getTextAlpha()); APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, properties.getBackgroundColor()); APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_ALPHA, properties.getBackgroundAlpha()); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_LEFT_MARGIN, properties.getLeftMargin()); APPEND_ENTITY_PROPERTY(PROP_RIGHT_MARGIN, properties.getRightMargin()); APPEND_ENTITY_PROPERTY(PROP_TOP_MARGIN, properties.getTopMargin()); @@ -3201,6 +3206,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticPulse.setProperties(properties); _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl()); APPEND_ENTITY_PROPERTY(PROP_DPI, properties.getDPI()); @@ -3262,11 +3268,11 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy _staticPulse.setProperties(properties); _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, properties.getImageURL()); APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, properties.getEmissive()); APPEND_ENTITY_PROPERTY(PROP_KEEP_ASPECT_RATIO, properties.getKeepAspectRatio()); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)properties.getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_SUB_IMAGE, properties.getSubImage()); } @@ -3608,6 +3614,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Text) { properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight); @@ -3615,7 +3622,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_ALPHA, float, setTextAlpha); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_COLOR, u8vec3Color, setBackgroundColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_ALPHA, float, setBackgroundAlpha); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LEFT_MARGIN, float, setLeftMargin); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RIGHT_MARGIN, float, setRightMargin); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TOP_MARGIN, float, setTopMargin); @@ -3662,6 +3668,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI); @@ -3720,11 +3727,11 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IMAGE_URL, QString, setImageURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMISSIVE, bool, setEmissive); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEEP_ASPECT_RATIO, bool, setKeepAspectRatio); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SUB_IMAGE, QRect, setSubImage); } @@ -3939,11 +3946,12 @@ void EntityItemProperties::markAllChanged() { // Common _shapeTypeChanged = true; + _compoundShapeURLChanged = true; _colorChanged = true; _alphaChanged = true; _pulse.markAllChanged(); _texturesChanged = true; - _compoundShapeURLChanged = true; + _billboardModeChanged = true; // Particles _maxParticlesChanged = true; @@ -4002,7 +4010,6 @@ void EntityItemProperties::markAllChanged() { _textAlphaChanged = true; _backgroundColorChanged = true; _backgroundAlphaChanged = true; - _billboardModeChanged = true; _leftMarginChanged = true; _rightMarginChanged = true; _topMarginChanged = true; @@ -4415,6 +4422,9 @@ QList EntityItemProperties::listChangedProperties() { if (texturesChanged()) { out += "textures"; } + if (billboardModeChanged()) { + out += "billboardMode"; + } // Particles if (maxParticlesChanged()) { @@ -4571,9 +4581,6 @@ QList EntityItemProperties::listChangedProperties() { if (backgroundAlphaChanged()) { out += "backgroundAlpha"; } - if (billboardModeChanged()) { - out += "billboardMode"; - } if (leftMarginChanged()) { out += "leftMargin"; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 58fe63cf40..712f2d120f 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -242,6 +242,7 @@ public: DEFINE_PROPERTY(PROP_ALPHA, Alpha, alpha, float, ENTITY_ITEM_DEFAULT_ALPHA); DEFINE_PROPERTY_GROUP(Pulse, pulse, PulsePropertyGroup); DEFINE_PROPERTY_REF(PROP_TEXTURES, Textures, textures, QString, ""); + DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE); // Particles DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32, particle::DEFAULT_MAX_PARTICLES); @@ -300,7 +301,6 @@ public: DEFINE_PROPERTY_REF(PROP_TEXT_ALPHA, TextAlpha, textAlpha, float, TextEntityItem::DEFAULT_TEXT_ALPHA); DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, u8vec3Color, TextEntityItem::DEFAULT_BACKGROUND_COLOR); DEFINE_PROPERTY_REF(PROP_BACKGROUND_ALPHA, BackgroundAlpha, backgroundAlpha, float, TextEntityItem::DEFAULT_TEXT_ALPHA); - DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE); DEFINE_PROPERTY_REF(PROP_LEFT_MARGIN, LeftMargin, leftMargin, float, TextEntityItem::DEFAULT_MARGIN); DEFINE_PROPERTY_REF(PROP_RIGHT_MARGIN, RightMargin, rightMargin, float, TextEntityItem::DEFAULT_MARGIN); DEFINE_PROPERTY_REF(PROP_TOP_MARGIN, TopMargin, topMargin, float, TextEntityItem::DEFAULT_MARGIN); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 5cf809e38e..093df92dc1 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -118,6 +118,7 @@ enum EntityPropertyList { PROP_PULSE_COLOR_MODE, PROP_PULSE_ALPHA_MODE, PROP_TEXTURES, + PROP_BILLBOARD_MODE, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new shared EntityItem properties to the list ABOVE this line @@ -232,11 +233,10 @@ enum EntityPropertyList { PROP_TEXT_ALPHA = PROP_DERIVED_3, PROP_BACKGROUND_COLOR = PROP_DERIVED_4, PROP_BACKGROUND_ALPHA = PROP_DERIVED_5, - PROP_BILLBOARD_MODE = PROP_DERIVED_6, - PROP_LEFT_MARGIN = PROP_DERIVED_7, - PROP_RIGHT_MARGIN = PROP_DERIVED_8, - PROP_TOP_MARGIN = PROP_DERIVED_9, - PROP_BOTTOM_MARGIN = PROP_DERIVED_10, + PROP_LEFT_MARGIN = PROP_DERIVED_6, + PROP_RIGHT_MARGIN = PROP_DERIVED_7, + PROP_TOP_MARGIN = PROP_DERIVED_8, + PROP_BOTTOM_MARGIN = PROP_DERIVED_9, // Zone // Keylight diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 1e8e4511cf..837e824f4a 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -35,11 +35,11 @@ EntityItemProperties ImageEntityItem::getProperties(const EntityPropertyFlags& d withReadLock([&] { _pulseProperties.getProperties(properties); }); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(imageURL, getImageURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emissive, getEmissive); COPY_ENTITY_PROPERTY_TO_PROPERTIES(keepAspectRatio, getKeepAspectRatio); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(subImage, getSubImage); return properties; @@ -54,11 +54,11 @@ bool ImageEntityItem::setProperties(const EntityItemProperties& properties) { bool pulsePropertiesChanged = _pulseProperties.setProperties(properties); somethingChanged |= pulsePropertiesChanged; }); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(imageURL, setImageURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emissive, setEmissive); SET_ENTITY_PROPERTY_FROM_PROPERTIES(keepAspectRatio, setKeepAspectRatio); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(subImage, setSubImage); if (somethingChanged) { @@ -91,11 +91,11 @@ int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, bytesRead += bytesFromPulse; dataAt += bytesFromPulse; }); + READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_IMAGE_URL, QString, setImageURL); READ_ENTITY_PROPERTY(PROP_EMISSIVE, bool, setEmissive); READ_ENTITY_PROPERTY(PROP_KEEP_ASPECT_RATIO, bool, setKeepAspectRatio); - READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_SUB_IMAGE, QRect, setSubImage); return bytesRead; @@ -107,11 +107,11 @@ EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; requestedProperties += _pulseProperties.getEntityProperties(params); + requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_IMAGE_URL; requestedProperties += PROP_EMISSIVE; requestedProperties += PROP_KEEP_ASPECT_RATIO; - requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_SUB_IMAGE; return requestedProperties; @@ -133,14 +133,24 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); }); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, getImageURL()); APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, getEmissive()); APPEND_ENTITY_PROPERTY(PROP_KEEP_ASPECT_RATIO, getKeepAspectRatio()); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_SUB_IMAGE, getSubImage()); } +glm::vec3 ImageEntityItem::getRaycastDimensions() const { + glm::vec3 dimensions = getScaledDimensions(); + if (getBillboardMode() != BillboardMode::NONE) { + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + return glm::vec3(SQRT_2 * max); + } + return dimensions; +} + bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, @@ -149,6 +159,7 @@ bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index 05218016b3..a1be5a0554 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -43,6 +43,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; + glm::vec3 getRaycastDimensions() const override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, @@ -77,15 +78,15 @@ public: PulsePropertyGroup getPulseProperties() const; protected: - QString _imageURL; - bool _emissive { false }; - bool _keepAspectRatio { true }; - BillboardMode _billboardMode; - QRect _subImage; - glm::u8vec3 _color; float _alpha; PulsePropertyGroup _pulseProperties; + BillboardMode _billboardMode; + + QString _imageURL; + bool _emissive { false }; + bool _keepAspectRatio { true }; + QRect _subImage; }; #endif // hifi_ImageEntityItem_h diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index a743d0a7a9..bc98c61ff7 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -52,6 +52,7 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de withReadLock([&] { _pulseProperties.getProperties(properties); }); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight); @@ -59,7 +60,6 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de COPY_ENTITY_PROPERTY_TO_PROPERTIES(textAlpha, getTextAlpha); COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundColor, getBackgroundColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundAlpha, getBackgroundAlpha); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(leftMargin, getLeftMargin); COPY_ENTITY_PROPERTY_TO_PROPERTIES(rightMargin, getRightMargin); COPY_ENTITY_PROPERTY_TO_PROPERTIES(topMargin, getTopMargin); @@ -75,6 +75,7 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) { bool pulsePropertiesChanged = _pulseProperties.setProperties(properties); somethingChanged |= pulsePropertiesChanged; }); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(text, setText); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight); @@ -82,7 +83,6 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(textAlpha, setTextAlpha); SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundColor, setBackgroundColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundAlpha, setBackgroundAlpha); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(leftMargin, setLeftMargin); SET_ENTITY_PROPERTY_FROM_PROPERTIES(rightMargin, setRightMargin); SET_ENTITY_PROPERTY_FROM_PROPERTIES(topMargin, setTopMargin); @@ -117,6 +117,7 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, bytesRead += bytesFromPulse; dataAt += bytesFromPulse; }); + READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, setLineHeight); @@ -124,7 +125,6 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_TEXT_ALPHA, float, setTextAlpha); READ_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, glm::u8vec3, setBackgroundColor); READ_ENTITY_PROPERTY(PROP_BACKGROUND_ALPHA, float, setBackgroundAlpha); - READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_LEFT_MARGIN, float, setLeftMargin); READ_ENTITY_PROPERTY(PROP_RIGHT_MARGIN, float, setRightMargin); READ_ENTITY_PROPERTY(PROP_TOP_MARGIN, float, setTopMargin); @@ -137,13 +137,14 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += _pulseProperties.getEntityProperties(params); + requestedProperties += PROP_BILLBOARD_MODE; + requestedProperties += PROP_TEXT; requestedProperties += PROP_LINE_HEIGHT; requestedProperties += PROP_TEXT_COLOR; requestedProperties += PROP_TEXT_ALPHA; requestedProperties += PROP_BACKGROUND_COLOR; requestedProperties += PROP_BACKGROUND_ALPHA; - requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_LEFT_MARGIN; requestedProperties += PROP_RIGHT_MARGIN; requestedProperties += PROP_TOP_MARGIN; @@ -166,6 +167,7 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); }); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_TEXT, getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, getLineHeight()); @@ -173,12 +175,20 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_TEXT_ALPHA, getTextAlpha()); APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, getBackgroundColor()); APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_ALPHA, getBackgroundAlpha()); - APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_LEFT_MARGIN, getLeftMargin()); APPEND_ENTITY_PROPERTY(PROP_RIGHT_MARGIN, getRightMargin()); APPEND_ENTITY_PROPERTY(PROP_TOP_MARGIN, getTopMargin()); APPEND_ENTITY_PROPERTY(PROP_BOTTOM_MARGIN, getBottomMargin()); - +} + +glm::vec3 TextEntityItem::getRaycastDimensions() const { + glm::vec3 dimensions = getScaledDimensions(); + if (getBillboardMode() != BillboardMode::NONE) { + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + return glm::vec3(SQRT_2 * max); + } + return dimensions; } bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, @@ -189,6 +199,7 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 5ca6823052..1ead9d3e15 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -47,6 +47,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; + glm::vec3 getRaycastDimensions() const override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, @@ -99,6 +100,8 @@ public: PulsePropertyGroup getPulseProperties() const; private: + BillboardMode _billboardMode; + QString _text; float _lineHeight; glm::u8vec3 _textColor; @@ -106,7 +109,6 @@ private: glm::u8vec3 _backgroundColor; float _backgroundAlpha; PulsePropertyGroup _pulseProperties; - BillboardMode _billboardMode; float _leftMargin; float _rightMargin; float _topMargin; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 51b78aaec7..2e5c3f1a6a 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -48,6 +48,7 @@ EntityItemProperties WebEntityItem::getProperties(const EntityPropertyFlags& des withReadLock([&] { _pulseProperties.getProperties(properties); }); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(sourceUrl, getSourceUrl); COPY_ENTITY_PROPERTY_TO_PROPERTIES(dpi, getDPI); @@ -68,6 +69,7 @@ bool WebEntityItem::setProperties(const EntityItemProperties& properties) { bool pulsePropertiesChanged = _pulseProperties.setProperties(properties); somethingChanged |= pulsePropertiesChanged; }); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(sourceUrl, setSourceUrl); SET_ENTITY_PROPERTY_FROM_PROPERTIES(dpi, setDPI); @@ -107,6 +109,7 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i bytesRead += bytesFromPulse; dataAt += bytesFromPulse; }); + READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode); READ_ENTITY_PROPERTY(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY(PROP_DPI, uint16_t, setDPI); @@ -123,6 +126,7 @@ EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& pa requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; requestedProperties += _pulseProperties.getEntityProperties(params); + requestedProperties += PROP_BILLBOARD_MODE; requestedProperties += PROP_SOURCE_URL; requestedProperties += PROP_DPI; @@ -148,6 +152,7 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); }); + APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode()); APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, getSourceUrl()); APPEND_ENTITY_PROPERTY(PROP_DPI, getDPI()); @@ -157,6 +162,16 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst APPEND_ENTITY_PROPERTY(PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT, getShowKeyboardFocusHighlight()); } +glm::vec3 WebEntityItem::getRaycastDimensions() const { + glm::vec3 dimensions = getScaledDimensions(); + if (getBillboardMode() != BillboardMode::NONE) { + float max = glm::max(dimensions.x, glm::max(dimensions.y, dimensions.z)); + const float SQRT_2 = 1.41421356237f; + return glm::vec3(SQRT_2 * max); + } + return dimensions; +} + bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, @@ -165,6 +180,7 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); + rotation = EntityItem::getBillboardRotation(position, rotation, _billboardMode); if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) { glm::vec3 forward = rotation * Vectors::FRONT; @@ -235,6 +251,18 @@ float WebEntityItem::getAlpha() const { }); } +BillboardMode WebEntityItem::getBillboardMode() const { + return resultWithReadLock([&] { + return _billboardMode; + }); +} + +void WebEntityItem::setBillboardMode(BillboardMode value) { + withWriteLock([&] { + _billboardMode = value; + }); +} + void WebEntityItem::setSourceUrl(const QString& value) { withWriteLock([&] { _sourceUrl = value; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 86b2377c90..bb1e527712 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -44,6 +44,7 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; + glm::vec3 getRaycastDimensions() const override; virtual bool supportsDetailedIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, @@ -60,6 +61,9 @@ public: float getAlpha() const; void setAlpha(float alpha); + void setBillboardMode(BillboardMode value); + BillboardMode getBillboardMode() const; + static const QString DEFAULT_SOURCE_URL; void setSourceUrl(const QString& value); QString getSourceUrl() const; @@ -86,6 +90,7 @@ protected: glm::u8vec3 _color; float _alpha { 1.0f }; PulsePropertyGroup _pulseProperties; + BillboardMode _billboardMode; QString _sourceUrl; uint16_t _dpi; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 0697fe8885..5f55c189ce 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -261,6 +261,7 @@ enum class EntityVersion : PacketVersion { PulseProperties, RingGizmoEntities, ShowKeyboardFocusHighlight, + WebBillboardMode, // Add new versions above here NUM_PACKET_TYPE, From 84db9f47290a847906acf9734db852d4d30510a8 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 31 Jan 2019 16:18:47 -0800 Subject: [PATCH 029/139] testing the water... --- interface/src/graphics/GraphicsEngine.cpp | 2 +- libraries/render-utils/src/ToneMappingEffect.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 861dfea7f8..fb3c5c3972 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -66,7 +66,7 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { } void GraphicsEngine::initializeRender(bool disableDeferred) { - disableDeferred = false; + disableDeferred = true; // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index 69694b13f5..2da5be8d10 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -51,7 +51,7 @@ private: float _exposure = 0.0f; float _twoPowExposure = 1.0f; glm::vec2 spareA; - int _toneCurve = Gamma22; + int _toneCurve = None; glm::vec3 spareB; Parameters() {} @@ -74,7 +74,7 @@ public: float exposure{ 0.0f }; - int curve{ ToneMappingEffect::Gamma22 }; + int curve{ ToneMappingEffect::None }; signals: void dirty(); }; From 50bfe84aa7422ffbd7a1195a5b7d3b2f6a66eaae Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 1 Feb 2019 12:11:00 -0800 Subject: [PATCH 030/139] fix keyboard intersection, laser alpha --- interface/src/raypick/StylusPick.cpp | 10 ++---- interface/src/ui/Keyboard.cpp | 4 +-- interface/src/ui/overlays/Overlays.cpp | 4 ++- .../src/RenderablePolyLineEntityItem.cpp | 33 +++++++++++++------ .../src/RenderablePolyLineEntityItem.h | 1 + libraries/entities/src/EntityTreeElement.cpp | 2 +- libraries/entities/src/EntityTreeElement.h | 1 + 7 files changed, 34 insertions(+), 21 deletions(-) diff --git a/interface/src/raypick/StylusPick.cpp b/interface/src/raypick/StylusPick.cpp index a9dbf9b950..0e95959566 100644 --- a/interface/src/raypick/StylusPick.cpp +++ b/interface/src/raypick/StylusPick.cpp @@ -18,6 +18,8 @@ #include #include +#include + using namespace bilateral; float StylusPick::WEB_STYLUS_LENGTH = 0.2f; @@ -146,13 +148,7 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) { continue; } - bool visible = entity->getVisible(); - bool collisionless = entity->getCollisionless(); - if ((!visible && !getFilter().doesPickInvisible()) || (visible && !getFilter().doesPickVisible()) || - (!collisionless && !getFilter().doesPickCollidable()) || (collisionless && !getFilter().doesPickNonCollidable()) || - (entity->isLocalEntity() && !getFilter().doesPickLocalEntities()) || - (entity->isAvatarEntity() && !getFilter().doesPickAvatarEntities()) || - (entity->isDomainEntity() && !getFilter().doesPickDomainEntities())) { + if (!EntityTreeElement::checkFilterSettings(entity, getFilter())) { continue; } diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 280c14167b..0a19ac7488 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -628,8 +628,8 @@ void Keyboard::handleTriggerContinue(const QUuid& id, const PointerEvent& event) auto stylusPickResult = std::dynamic_pointer_cast(pickResult); float distance = stylusPickResult->distance; - static const float PENATRATION_THRESHOLD = 0.025f; - if (distance < PENATRATION_THRESHOLD) { + static const float PENETRATION_THRESHOLD = 0.025f; + if (distance < PENETRATION_THRESHOLD) { static const float Z_OFFSET = 0.002f; auto entityScriptingInterface = DependencyManager::get(); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 13476e4841..a6d3d4fedb 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -514,7 +514,9 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove auto iter = overlayProps.find("lineWidth"); if (iter != overlayProps.end()) { QVariantList widths; - widths.append(iter.value()); + QVariant width = iter.value(); + widths.append(width); + widths.append(width); overlayProps["strokeWidths"] = widths; } } diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 7ad050e86c..bacb9adac6 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -25,6 +25,7 @@ using namespace render; using namespace render::entities; gpu::PipelinePointer PolyLineEntityRenderer::_pipeline = nullptr; +gpu::PipelinePointer PolyLineEntityRenderer::_glowPipeline = nullptr; static const QUrl DEFAULT_POLYLINE_TEXTURE = PathUtils::resourcesUrl("images/paintStroke.png"); @@ -44,14 +45,26 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity) void PolyLineEntityRenderer::buildPipeline() { // FIXME: opaque pipeline gpu::ShaderPointer program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke); - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setCullMode(gpu::State::CullMode::CULL_NONE); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - PrepareStencil::testMask(*state); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - _pipeline = gpu::Pipeline::create(program, state); + { + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setCullMode(gpu::State::CullMode::CULL_NONE); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + PrepareStencil::testMask(*state); + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + _pipeline = gpu::Pipeline::create(program, state); + } + { + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setCullMode(gpu::State::CullMode::CULL_NONE); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + PrepareStencil::testMask(*state); + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + _glowPipeline = gpu::Pipeline::create(program, state); + } } ItemKey PolyLineEntityRenderer::getKey() { @@ -257,11 +270,11 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; - if (!_pipeline) { + if (!_pipeline || !_glowPipeline) { buildPipeline(); } - batch.setPipeline(_pipeline); + batch.setPipeline(_glow ? _glowPipeline : _pipeline); batch.setModelTransform(_renderTransform); batch.setResourceTexture(0, _textureLoaded ? _texture->getGPUTexture() : DependencyManager::get()->getWhiteTexture()); batch.setResourceBuffer(0, _polylineGeometryBuffer); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index fd37a49598..b8a3ad3b3e 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -59,6 +59,7 @@ protected: gpu::BufferPointer _polylineDataBuffer; gpu::BufferPointer _polylineGeometryBuffer; static gpu::PipelinePointer _pipeline; + static gpu::PipelinePointer _glowPipeline; }; } } // namespace diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index abc4507fe0..a0fafbd8f9 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -139,7 +139,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3 return false; } -bool checkFilterSettings(const EntityItemPointer& entity, PickFilter searchFilter) { +bool EntityTreeElement::checkFilterSettings(const EntityItemPointer& entity, PickFilter searchFilter) { bool visible = entity->isVisible(); entity::HostType hostType = entity->getEntityHostType(); if ((!searchFilter.doesPickVisible() && visible) || (!searchFilter.doesPickInvisible() && !visible) || diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index 3f1fda57bd..f82eaa7fb1 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -134,6 +134,7 @@ public: virtual bool isRendered() const override { return getShouldRender(); } virtual bool deleteApproved() const override { return !hasEntities(); } + static bool checkFilterSettings(const EntityItemPointer& entity, PickFilter searchFilter); virtual bool canPickIntersect() const override { return hasEntities(); } virtual EntityItemID evalRayIntersection(const glm::vec3& origin, const glm::vec3& direction, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, From ba8320f5610e9ac4dc1e4fd46c732cd5087fcc72 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 1 Feb 2019 14:31:26 -0800 Subject: [PATCH 031/139] fix 2d overlay deletion --- interface/src/ui/overlays/Overlays.cpp | 15 ++++++++++++++- interface/src/ui/overlays/Overlays.h | 1 + scripts/system/libraries/entitySelectionTool.js | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index a6d3d4fedb..498ff78234 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -156,6 +156,19 @@ void Overlays::enable() { _enabled = true; } +Overlay::Pointer Overlays::take2DOverlay(const QUuid& id) { + if (_shuttingDown) { + return nullptr; + } + + QMutexLocker locker(&_mutex); + auto overlayIter = _overlays.find(id); + if (overlayIter != _overlays.end()) { + return _overlays.take(id); + } + return nullptr; +} + Overlay::Pointer Overlays::get2DOverlay(const QUuid& id) const { if (_shuttingDown) { return nullptr; @@ -808,7 +821,7 @@ void Overlays::deleteOverlay(const QUuid& id) { return; } - Overlay::Pointer overlay = get2DOverlay(id); + Overlay::Pointer overlay = take2DOverlay(id); if (overlay) { _overlaysToDelete.push_back(overlay); emit overlayDeleted(id); diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 992431f3ed..6f4bf210f1 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -94,6 +94,7 @@ public: void disable(); void enable(); + Overlay::Pointer take2DOverlay(const QUuid& id); Overlay::Pointer get2DOverlay(const QUuid& id) const; /// adds an overlay that's already been created diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 9b53cf85f3..2b12a03c00 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -926,7 +926,7 @@ SelectionDisplay = (function() { zRailOverlay ]; - const nonLayeredOverlays = [selectionBox, iconSelectionBox]; + var nonLayeredOverlays = [selectionBox, iconSelectionBox]; var maximumHandleInAllOverlays = handleDuplicator; From c6080d07954b81ba9ad628514b633b774b716d68 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 1 Feb 2019 14:37:42 -0800 Subject: [PATCH 032/139] fix edit selection + log problem --- scripts/system/libraries/entitySelectionTool.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 2b12a03c00..39796311a0 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -926,7 +926,7 @@ SelectionDisplay = (function() { zRailOverlay ]; - var nonLayeredOverlays = [selectionBox, iconSelectionBox]; + const nonLayeredOverlays = [selectionBox, iconSelectionBox]; var maximumHandleInAllOverlays = handleDuplicator; @@ -1048,7 +1048,14 @@ SelectionDisplay = (function() { var overlayIncludesNonLayered = []; for (var i = 0; i < overlayIncludes.length; i++) { var value = overlayIncludes[i]; - if (nonLayeredOverlays.includes(value)) { + var contains = false; + for (var j = 0; j < nonLayeredOverlays.length; j++) { + if (nonLayeredOverlays[j] === value) { + contains = true; + break; + } + } + if (contains) { overlayIncludesNonLayered.push(value); } else { overlayIncludesLayered.push(value); From 391cca787f78093a91a799f12fee2608e11f9589 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 1 Feb 2019 15:31:58 -0800 Subject: [PATCH 033/139] fix keyboard textures and text display --- interface/src/ui/Keyboard.cpp | 5 ++++- libraries/entities-renderer/src/RenderableTextEntityItem.cpp | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 0a19ac7488..32e6f9d186 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -325,6 +325,7 @@ void Keyboard::updateTextDisplay() { scaledDimensions *= sensorToWorldScale; float leftMargin = (scaledDimensions.x / 2); scaledDimensions.x += textWidth; + scaledDimensions.y *= 1.25f; EntityItemProperties properties; properties.setDimensions(scaledDimensions); @@ -817,7 +818,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setEmissive(true); properties.setParentID(_anchor.entityID); properties.setModelURL(url); - properties.setTextures(QVariant(textureMap).toString()); + properties.setTextures(QString(QJsonDocument::fromVariant(textureMap).toJson())); properties.getGrab().setGrabbable(false); properties.setLocalRotation(quatFromVariant(keyboardKeyValue["localOrientation"].toVariant())); QUuid id = entityScriptingInterface->addEntityInternal(properties, entity::HostType::LOCAL); @@ -868,6 +869,8 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { properties.setEmissive(true); properties.getGrab().setGrabbable(false); properties.setText(""); + properties.setTextAlpha(1.0f); + properties.setBackgroundAlpha(0.7f); properties.setParentID(_anchor.entityID); TextDisplay textDisplay; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 28879613f5..76d4711573 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -214,6 +214,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) { QSizeF TextEntityRenderer::textSize(const QString& text) const { auto extents = _textRenderer->computeExtent(text); + extents.y *= 2.0f; float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO; float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight; From 4b406bf41cc64e197ce163ba940bb347a799f752 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 1 Feb 2019 16:23:06 -0800 Subject: [PATCH 034/139] fix getEntityObject and tablet highlighting (Overlays.findOverlays) --- interface/src/Application.cpp | 8 ++++++++ interface/src/ui/overlays/Overlays.cpp | 2 ++ libraries/entities/src/EntityScriptingInterface.cpp | 9 +-------- libraries/entities/src/EntityTree.cpp | 8 ++++++++ libraries/entities/src/EntityTree.h | 4 ++++ 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 78e9bede07..df2761f259 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1955,6 +1955,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return false; }); + EntityTree::setGetEntityObjectOperator([this](const QUuid& id) -> QObject* { + auto entities = getEntities(); + if (auto entity = entities->renderableForEntityId(id)) { + return qobject_cast(entity.get()); + } + return nullptr; + }); + EntityTree::setTextSizeOperator([this](const QUuid& id, const QString& text) { auto entities = getEntities(); if (auto entity = entities->renderableForEntityId(id)) { diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 498ff78234..3a6dc71b1a 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -1326,6 +1326,8 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { auto entityTree = DependencyManager::get()->getEntityTree(); if (entityTree) { unsigned int searchFilter = PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES); + // For legacy reasons, this only finds visible objects + searchFilter = searchFilter | PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE); entityTree->withReadLock([&] { entityTree->evalEntitiesInSphere(center, radius, PickFilter(searchFilter), result); }); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 363f463eb7..852b5298b8 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1017,14 +1017,7 @@ QString EntityScriptingInterface::getEntityType(const QUuid& entityID) { } QObject* EntityScriptingInterface::getEntityObject(const QUuid& id) { - QObject* toReturn { nullptr }; - _entityTree->withReadLock([&] { - EntityItemPointer entity = _entityTree->findEntityByEntityItemID(id); - if (entity) { - toReturn = qobject_cast(&(*entity)); - } - }); - return toReturn; + return EntityTree::getEntityObject(id); } bool EntityScriptingInterface::isLoaded(const QUuid& id) { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 90f1044f5b..cfae8e250b 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2957,6 +2957,7 @@ std::function E std::function EntityTree::_removeMaterialFromEntityOperator = nullptr; std::function EntityTree::_addMaterialToAvatarOperator = nullptr; std::function EntityTree::_removeMaterialFromAvatarOperator = nullptr; +std::function EntityTree::_getEntityObjectOperator = nullptr; std::function EntityTree::_textSizeOperator = nullptr; bool EntityTree::addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { @@ -2987,6 +2988,13 @@ bool EntityTree::removeMaterialFromAvatar(const QUuid& avatarID, graphics::Mater return false; } +QObject* EntityTree::getEntityObject(const QUuid& id) { + if (_getEntityObjectOperator) { + return _getEntityObjectOperator(id); + } + return nullptr; +} + QSizeF EntityTree::textSize(const QUuid& id, const QString& text) { if (_textSizeOperator) { return _textSizeOperator(id, text); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index dda9ecaf17..9df01267ea 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -272,6 +272,9 @@ public: static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName); static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName); + static void setGetEntityObjectOperator(std::function getEntityObjectOperator) { _getEntityObjectOperator = getEntityObjectOperator; } + static QObject* getEntityObject(const QUuid& id); + static void setTextSizeOperator(std::function textSizeOperator) { _textSizeOperator = textSizeOperator; } static QSizeF textSize(const QUuid& id, const QString& text); @@ -387,6 +390,7 @@ private: static std::function _removeMaterialFromEntityOperator; static std::function _addMaterialToAvatarOperator; static std::function _removeMaterialFromAvatarOperator; + static std::function _getEntityObjectOperator; static std::function _textSizeOperator; std::vector _staleProxies; From b970c31c5c3cde76bebdf5ab69465d186ca23eb7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 1 Feb 2019 17:14:13 -0800 Subject: [PATCH 035/139] Correct gamma in oculus, yeah! --- interface/src/graphics/GraphicsEngine.cpp | 2 -- plugins/oculus/src/OculusDisplayPlugin.cpp | 20 +++++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index fb3c5c3972..bff778bd62 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -66,8 +66,6 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { } void GraphicsEngine::initializeRender(bool disableDeferred) { - disableDeferred = true; - // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; _renderEngine->addJob("UpdateScene"); diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index a34e647a5e..a34f068665 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -150,20 +150,26 @@ void OculusDisplayPlugin::hmdPresent() { // Manually bind the texture to the FBO // FIXME we should have a way of wrapping raw GL ids in GPU objects without // taking ownership of the object - auto fbo = getGLBackend()->getFramebufferID(_outputFramebuffer); - glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, curTexId, 0); - render([&](gpu::Batch& batch) { + auto srcfbo = getGLBackend()->getFramebufferID(_currentFrame->framebuffer); + auto dstfbo = getGLBackend()->getFramebufferID(_outputFramebuffer); + glNamedFramebufferTexture(dstfbo, GL_COLOR_ATTACHMENT0, curTexId, 0); + auto viewport = ivec4(uvec2(), _outputFramebuffer->getSize()); + /* render([&](gpu::Batch& batch) { batch.enableStereo(false); batch.setFramebuffer(_outputFramebuffer); batch.setViewportTransform(ivec4(uvec2(), _outputFramebuffer->getSize())); batch.setStateScissorRect(ivec4(uvec2(), _outputFramebuffer->getSize())); batch.resetViewTransform(); batch.setProjectionTransform(mat4()); - batch.setPipeline(_presentPipeline); - batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0)); + // batch.setPipeline(_presentPipeline); + batch.setPipeline(_simplePipeline); + // batch.setResourceTexture(0, _compositeFramebuffer->getRenderBuffer(0)); + batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0)); batch.draw(gpu::TRIANGLE_STRIP, 4); - }); - glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, 0, 0); + });*/ + glBlitNamedFramebuffer(srcfbo, dstfbo, viewport.x, viewport.y, viewport.z, viewport.w, viewport.x, viewport.y, + viewport.z, viewport.w, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glNamedFramebufferTexture(dstfbo, GL_COLOR_ATTACHMENT0, 0, 0); } { From d0a044120afc46b21f5d44c253ad7cc2bd004a4a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 3 Feb 2019 21:31:19 -0800 Subject: [PATCH 036/139] Adding the sub samples control --- .../render-utils/src/RenderForwardTask.cpp | 8 ++++++-- .../render-utils/src/RenderForwardTask.h | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index e6f687df59..01da7f73df 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -144,18 +144,22 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend task.addJob("Blit", framebuffer); } +void PrepareFramebuffer::configure(const PrepareFramebuffer::Config& config) { + _numSamples = config.getNumSamples(); +} + void PrepareFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w); // Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering - if (_framebuffer && _framebuffer->getSize() != frameSize) { + if (_framebuffer && (_framebuffer->getSize() != frameSize || _framebuffer->getNumSamples() != _numSamples)) { _framebuffer.reset(); } if (!_framebuffer) { _framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward")); - int numSamples = 8; + int numSamples = _numSamples; auto colorFormat = gpu::Element::COLOR_SRGBA_32; auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR); diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index e6a6008319..909e09452c 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -27,16 +27,33 @@ public: void build(JobModel& task, const render::Varying& input, render::Varying& output); }; +class PrepareFramebufferConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples NOTIFY dirty) +public: + int getNumSamples() const { return numSamples; } + void setNumSamples(int num) { numSamples = num; emit dirty(); } + +signals: + void dirty(); + +protected: + int numSamples{ 8 }; +}; + class PrepareFramebuffer { public: using Inputs = gpu::FramebufferPointer; - using JobModel = render::Job::ModelO; + using Config = PrepareFramebufferConfig; + using JobModel = render::Job::ModelO; + void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer); private: gpu::FramebufferPointer _framebuffer; + int _numSamples { 8 }; }; class PrepareForward { From 31cf623252cf910ed9a3a200411c649a2a99e996 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 4 Feb 2019 12:44:04 -0800 Subject: [PATCH 037/139] fix keyboard focus --- interface/src/Application.cpp | 107 ++++++++---------- interface/src/ui/overlays/Overlays.cpp | 8 +- interface/src/ui/overlays/Overlays.h | 2 +- .../src/EntityTreeRenderer.cpp | 9 +- .../src/EntityTreeRenderer.h | 2 +- .../entities/src/EntityScriptingInterface.cpp | 5 - 6 files changed, 59 insertions(+), 74 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index df2761f259..1cb63872e8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -348,6 +348,8 @@ static const QString ACTIVE_DISPLAY_PLUGIN_SETTING_NAME = "activeDisplayPlugin"; static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; static const QString KEEP_ME_LOGGED_IN_SETTING_NAME = "keepMeLoggedIn"; +static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f; + #if defined(Q_OS_ANDROID) static const QString TESTER_FILE = "/sdcard/_hifi_test_device.txt"; #endif @@ -1878,10 +1880,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo SpacemouseManager::getInstance().init(); #endif - // If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it - auto entityScriptingInterface = DependencyManager::get(); - connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity, - [this](const QUuid& id, const PointerEvent& event) { + // If the user clicks on an object, we will check that it's a web surface, and if so, set the focus to it + auto pointerManager = DependencyManager::get(); + auto keyboardFocusOperator = [this](const QUuid& id, const PointerEvent& event) { if (event.shouldFocus()) { if (getEntities()->wantsKeyboardFocus(id)) { setKeyboardFocusEntity(id); @@ -1889,8 +1890,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); } } - }); + }; + connect(pointerManager.data(), &PointerManager::triggerBeginEntity, keyboardFocusOperator); + connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, keyboardFocusOperator); + auto entityScriptingInterface = DependencyManager::get(); connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [this](const EntityItemID& entityItemID) { if (entityItemID == _keyboardFocusedEntity.get()) { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); @@ -1973,13 +1977,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return QSizeF(0.0f, 0.0f); }); - // Keyboard focus handling for local Web entities. - connect(&qApp->getOverlays(), &Overlays::overlayDeleted, [this](const QUuid& id) { - if (id == _keyboardFocusedEntity.get()) { - setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); - } - }); - connect(this, &Application::aboutToQuit, [this]() { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); }); @@ -4376,15 +4373,16 @@ void Application::mousePressEvent(QMouseEvent* event) { #else QPointF transformedPos; #endif - QMouseEvent mappedEvent(event->type(), - transformedPos, - event->screenPos(), event->button(), - event->buttons(), event->modifiers()); + QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), event->buttons(), event->modifiers()); + std::pair entityResult; if (!_controllerScriptingInterface->areEntityClicksCaptured()) { - getEntities()->mousePressEvent(&mappedEvent); + entityResult = getEntities()->mousePressEvent(&mappedEvent); } - getOverlays().mousePressEvent(&mappedEvent); + std::pair overlayResult = getOverlays().mousePressEvent(&mappedEvent); + + QUuid focusedEntity = entityResult.first < overlayResult.first ? entityResult.second : overlayResult.second; + setKeyboardFocusEntity(getEntities()->wantsKeyboardFocus(focusedEntity) ? focusedEntity : UNKNOWN_ENTITY_ID); _controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts @@ -4914,24 +4912,19 @@ void Application::idle() { update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS)); } - - // Update focus highlight for entities - { + { // Update keyboard focus highlight if (!_keyboardFocusedEntity.get().isInvalidID()) { const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus quint64 elapsedSinceAcceptedKeyPress = usecTimestampNow() - _lastAcceptedKeyPress; if (elapsedSinceAcceptedKeyPress > LOSE_FOCUS_AFTER_ELAPSED_TIME) { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); } else { - // update position of highlight object - if (!_keyboardFocusedEntity.get().isInvalidID()) { - auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get()); - if (entity && !_keyboardFocusHighlightID.isNull()) { - EntityItemProperties properties; - properties.setPosition(entity->getWorldPosition()); - properties.setRotation(entity->getWorldOrientation()); - DependencyManager::get()->editEntity(_keyboardFocusHighlightID, properties); - } + if (auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get())) { + EntityItemProperties properties; + properties.setPosition(entity->getWorldPosition()); + properties.setRotation(entity->getWorldOrientation()); + properties.setDimensions(entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); + DependencyManager::get()->editEntity(_keyboardFocusHighlightID, properties); } } } @@ -5729,11 +5722,10 @@ void Application::rotationModeChanged() const { } void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions) { - // Create focus if (qApp->getLoginDialogPoppedUp()) { return; } - + auto entityScriptingInterface = DependencyManager::get(); if (_keyboardFocusHighlightID == UNKNOWN_ENTITY_ID || !entityScriptingInterface->isAddedEntity(_keyboardFocusHighlightID)) { EntityItemProperties properties; @@ -5761,8 +5753,6 @@ QUuid Application::getKeyboardFocusEntity() const { return _keyboardFocusedEntity.get(); } -static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f; - void Application::setKeyboardFocusEntity(const QUuid& id) { if (_keyboardFocusedEntity.get() != id) { if (qApp->getLoginDialogPoppedUp() && !_loginDialogID.isNull()) { @@ -5777,34 +5767,35 @@ void Application::setKeyboardFocusEntity(const QUuid& id) { _keyboardFocusedEntity.set(id); auto entityScriptingInterface = DependencyManager::get(); - if (id == UNKNOWN_ENTITY_ID) { - EntityItemProperties properties; - properties.setVisible(false); - entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties); - return; - } + if (id != UNKNOWN_ENTITY_ID) { + EntityPropertyFlags desiredProperties; + desiredProperties += PROP_VISIBLE; + desiredProperties += PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT; + auto properties = entityScriptingInterface->getEntityProperties(id); + if (properties.getVisible()) { + auto entities = getEntities(); + auto entityId = _keyboardFocusedEntity.get(); + if (entities->wantsKeyboardFocus(entityId)) { + entities->setProxyWindow(entityId, _window->windowHandle()); + if (_keyboardMouseDevice->isActive()) { + _keyboardMouseDevice->pluginFocusOutEvent(); + } + _lastAcceptedKeyPress = usecTimestampNow(); - EntityPropertyFlags desiredProperties; - desiredProperties += PROP_VISIBLE; - desiredProperties += PROP_SHOW_KEYBOARD_FOCUS_HIGHLIGHT; - auto properties = entityScriptingInterface->getEntityProperties(id); - if (properties.getVisible() && properties.getShowKeyboardFocusHighlight()) { - auto entities = getEntities(); - auto entityId = _keyboardFocusedEntity.get(); - if (entities->wantsKeyboardFocus(entityId)) { - entities->setProxyWindow(entityId, _window->windowHandle()); - if (_keyboardMouseDevice->isActive()) { - _keyboardMouseDevice->pluginFocusOutEvent(); - } - _lastAcceptedKeyPress = usecTimestampNow(); - - auto entity = getEntities()->getEntity(entityId); - if (entity) { - setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), - entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); + if (properties.getShowKeyboardFocusHighlight()) { + if (auto entity = entities->getEntity(entityId)) { + setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), + entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); + return; + } + } } } } + + EntityItemProperties properties; + properties.setVisible(false); + entityScriptingInterface->editEntity(_keyboardFocusHighlightID, properties); } } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 3a6dc71b1a..a10bcc02b9 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -1209,7 +1209,7 @@ void Overlays::hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event } } -bool Overlays::mousePressEvent(QMouseEvent* event) { +std::pair Overlays::mousePressEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mousePressEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); @@ -1219,12 +1219,10 @@ bool Overlays::mousePressEvent(QMouseEvent* event) { PointerEvent pointerEvent = calculateOverlayPointerEvent(_currentClickingOnOverlayID, ray, rayPickResult, event, PointerEvent::Press); mousePressPointerEvent(_currentClickingOnOverlayID, pointerEvent); - return true; + return { rayPickResult.distance, rayPickResult.overlayID }; } - // if we didn't press on an overlay, disable overlay keyboard focus - setKeyboardFocusOverlay(UNKNOWN_ENTITY_ID); emit mousePressOffOverlay(); - return false; + return { FLT_MAX, UNKNOWN_ENTITY_ID }; } void Overlays::mousePressPointerEvent(const QUuid& id, const PointerEvent& event) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 6f4bf210f1..5a5e845a66 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -111,7 +111,7 @@ public: const QVector& discard, bool visibleOnly = false, bool collidableOnly = false); - bool mousePressEvent(QMouseEvent* event); + std::pair mousePressEvent(QMouseEvent* event); bool mouseDoublePressEvent(QMouseEvent* event); bool mouseReleaseEvent(QMouseEvent* event); bool mouseMoveEvent(QMouseEvent* event); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 61344e3193..3412772cae 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -798,11 +798,11 @@ static PointerEvent::Button toPointerButton(const QMouseEvent& event) { } } -void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { +std::pair EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { // If we don't have a tree, or we're in the process of shutting down, then don't // process these events. if (!_tree || _shuttingDown) { - return; + return { FLT_MAX, UNKNOWN_ENTITY_ID }; } PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent"); @@ -833,9 +833,10 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) { _lastPointerEvent = pointerEvent; _lastPointerEventValid = true; - } else { - emit entityScriptingInterface->mousePressOffEntity(); + return { rayPickResult.distance, rayPickResult.entityID }; } + emit entityScriptingInterface->mousePressOffEntity(); + return { FLT_MAX, UNKNOWN_ENTITY_ID }; } void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index d9f594a20b..4beee60ef8 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -93,8 +93,8 @@ public: void reloadEntityScripts(); // event handles which may generate entity related events + std::pair mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); - void mousePressEvent(QMouseEvent* event); void mouseDoublePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 852b5298b8..150aa6b0cf 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -57,11 +57,6 @@ EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership connect(nodeList.data(), &NodeList::canRezTmpCertifiedChanged, this, &EntityScriptingInterface::canRezTmpCertifiedChanged); connect(nodeList.data(), &NodeList::canWriteAssetsChanged, this, &EntityScriptingInterface::canWriteAssetsChanged); - // If the user clicks somewhere where there is no entity at all, we will release focus - connect(this, &EntityScriptingInterface::mousePressOffEntity, [this]() { - setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); - }); - auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::EntityScriptCallMethod, this, "handleEntityScriptCallMethodPacket"); } From 934abb3d52dac3789a215628044de9fcac78b403 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 4 Feb 2019 13:33:03 -0800 Subject: [PATCH 038/139] fix keyboard focus and image overlays --- interface/src/Application.cpp | 5 +-- interface/src/ui/Keyboard.cpp | 10 +++--- interface/src/ui/Keyboard.h | 4 +-- interface/src/ui/overlays/Overlays.cpp | 50 +++++++++----------------- 4 files changed, 26 insertions(+), 43 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1cb63872e8..fea58f558c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1884,9 +1884,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto pointerManager = DependencyManager::get(); auto keyboardFocusOperator = [this](const QUuid& id, const PointerEvent& event) { if (event.shouldFocus()) { + auto keyboard = DependencyManager::get(); if (getEntities()->wantsKeyboardFocus(id)) { setKeyboardFocusEntity(id); - } else { + } else if (!keyboard->getKeyIDs().contains(id)) { // FIXME: this is a hack to make the keyboard work for now, since the keys would otherwise steal focus setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); } } @@ -3794,7 +3795,7 @@ static inline bool isKeyEvent(QEvent::Type type) { } bool Application::handleKeyEventForFocusedEntity(QEvent* event) { - if (!_keyboardFocusedEntity.get().isInvalidID()) { + if (_keyboardFocusedEntity.get() != UNKNOWN_ENTITY_ID) { switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 32e6f9d186..8102df6dc6 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -841,7 +841,7 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { key.saveDimensionsAndLocalPosition(); includeItems.append(key.getID()); - _itemsToIgnore.append(key.getID()); + _itemsToIgnore.insert(key.getID()); keyboardLayerKeys.insert(id, key); } @@ -882,8 +882,8 @@ void Keyboard::loadKeyboardFile(const QString& keyboardFile) { } _ignoreItemsLock.withWriteLock([&] { - _itemsToIgnore.append(_textDisplay.entityID); - _itemsToIgnore.append(_anchor.entityID); + _itemsToIgnore.insert(_textDisplay.entityID); + _itemsToIgnore.insert(_anchor.entityID); }); _layerIndex = 0; auto pointerManager = DependencyManager::get(); @@ -905,8 +905,8 @@ bool Keyboard::shouldProcessEntity() const { return (!_keyboardLayers.empty() && isLayerSwitchTimerFinished()); } -QVector Keyboard::getKeysID() { - return _ignoreItemsLock.resultWithReadLock>([&] { +QSet Keyboard::getKeyIDs() { + return _ignoreItemsLock.resultWithReadLock>([&] { return _itemsToIgnore; }); } diff --git a/interface/src/ui/Keyboard.h b/interface/src/ui/Keyboard.h index 7056411578..958c862520 100644 --- a/interface/src/ui/Keyboard.h +++ b/interface/src/ui/Keyboard.h @@ -113,7 +113,7 @@ public: bool containsID(const QUuid& id) const; void loadKeyboardFile(const QString& keyboardFile); - QVector getKeysID(); + QSet getKeyIDs(); QUuid getAnchorID(); public slots: @@ -185,7 +185,7 @@ private: Anchor _anchor; BackPlate _backPlate; - QVector _itemsToIgnore; + QSet _itemsToIgnore; std::vector> _keyboardLayers; }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index a10bcc02b9..2580104d94 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -316,17 +316,6 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove RENAME_PROP(localOrientation, localRotation); RENAME_PROP(ignoreRayIntersection, ignorePickIntersection); - // Model overlays didn't support wireframe drawing - if (type != "Model") { - RENAME_PROP(solid, isSolid); - RENAME_PROP(isFilled, isSolid); - RENAME_PROP(filled, isSolid); - OVERLAY_TO_ENTITY_PROP_CONVERT_DEFAULT(isSolid, primitiveMode, false, [](const QVariant& v) { return v.toBool() ? "solid" : "lines"; }); - - RENAME_PROP(wire, isWire); - RENAME_PROP_CONVERT(isWire, primitiveMode, [](const QVariant& v) { return v.toBool() ? "lines" : "solid"; }); - } - RENAME_PROP_CONVERT(drawInFront, renderLayer, [](const QVariant& v) { return v.toBool() ? "front" : "world"; }); RENAME_PROP_CONVERT(drawHUDLayer, renderLayer, [=](const QVariant& v) { bool f = v.toBool(); @@ -362,6 +351,16 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove return "none"; }); + if (type == "Shape" || type == "Gizmo") { + RENAME_PROP(solid, isSolid); + RENAME_PROP(isFilled, isSolid); + RENAME_PROP(filled, isSolid); + OVERLAY_TO_ENTITY_PROP_CONVERT_DEFAULT(isSolid, primitiveMode, false, [](const QVariant& v) { return v.toBool() ? "solid" : "lines"; }); + + RENAME_PROP(wire, isWire); + RENAME_PROP_CONVERT(isWire, primitiveMode, [](const QVariant& v) { return v.toBool() ? "lines" : "solid"; }); + } + if (type == "Shape") { SET_OVERLAY_PROP_DEFAULT(shape, "Hexagon"); } else if (type == "Model") { @@ -1185,8 +1184,7 @@ PointerEvent Overlays::calculateOverlayPointerEvent(const QUuid& id, const PickR void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event) { auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(id)) { - // emit to scripts + if (!keyboard->getKeyIDs().contains(id)) { emit hoverEnterOverlay(id, event); } } @@ -1194,8 +1192,7 @@ void Overlays::hoverEnterPointerEvent(const QUuid& id, const PointerEvent& event void Overlays::hoverOverPointerEvent(const QUuid& id, const PointerEvent& event) { auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(id)) { - // emit to scripts + if (!keyboard->getKeyIDs().contains(id)) { emit hoverOverOverlay(id, event); } } @@ -1203,8 +1200,7 @@ void Overlays::hoverOverPointerEvent(const QUuid& id, const PointerEvent& event) void Overlays::hoverLeavePointerEvent(const QUuid& id, const PointerEvent& event) { auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(id)) { - // emit to scripts + if (!keyboard->getKeyIDs().contains(id)) { emit hoverLeaveOverlay(id, event); } } @@ -1228,8 +1224,7 @@ std::pair Overlays::mousePressEvent(QMouseEvent* event) { void Overlays::mousePressPointerEvent(const QUuid& id, const PointerEvent& event) { auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(id)) { - // emit to scripts + if (!keyboard->getKeyIDs().contains(id)) { emit mousePressOnOverlay(id, event); } } @@ -1267,7 +1262,7 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) { void Overlays::mouseReleasePointerEvent(const QUuid& id, const PointerEvent& event) { auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(id)) { + if (!keyboard->getKeyIDs().contains(id)) { emit mouseReleaseOnOverlay(id, event); } } @@ -1311,8 +1306,7 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { void Overlays::mouseMovePointerEvent(const QUuid& id, const PointerEvent& event) { auto keyboard = DependencyManager::get(); // Do not send keyboard key event to scripts to prevent malignant scripts from gathering what you typed - if (!keyboard->getKeysID().contains(id)) { - // emit to scripts + if (!keyboard->getKeyIDs().contains(id)) { emit mouseMoveOnOverlay(id, event); } } @@ -1649,8 +1643,6 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * parentID set, otherwise the same value as position. * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a * parentID set, otherwise the same value as rotation. Synonym: localOrientation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. @@ -1708,8 +1700,6 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * parentID set, otherwise the same value as position. * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a * parentID set, otherwise the same value as rotation. Synonym: localOrientation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. @@ -1758,8 +1748,6 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * parentID set, otherwise the same value as position. * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a * parentID set, otherwise the same value as rotation. Synonym: localOrientation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. @@ -1804,8 +1792,6 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * parentID set, otherwise the same value as position. * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a * parentID set, otherwise the same value as rotation. Synonym: localOrientation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. @@ -1838,8 +1824,6 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * parentID set, otherwise the same value as position. * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a * parentID set, otherwise the same value as rotation. Synonym: localOrientation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. @@ -1890,8 +1874,6 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * parentID set, otherwise the same value as position. * @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a * parentID set, otherwise the same value as rotation. Synonym: localOrientation. - * @property {boolean} isSolid=false - Synonyms: solid, isFilled, and filled. - * Antonyms: isWire and wire. * @property {boolean} ignorePickIntersection=false - If true, picks ignore the overlay. ignoreRayIntersection is a synonym. * @property {boolean} drawInFront=false - If true, the overlay is rendered in front of objects in the world, but behind the HUD. * @property {boolean} drawHUDLayer=false - If true, the overlay is rendered in front of everything, including the HUD. From 4089f8c5b0b50426ff9dc9ad49d243913db0b715 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 4 Feb 2019 23:45:35 -0800 Subject: [PATCH 039/139] Adding Color filter to the tone mapper --- libraries/render-utils/src/ToneMappingEffect.cpp | 15 ++++++++++----- libraries/render-utils/src/ToneMappingEffect.h | 10 +++++++++- libraries/render-utils/src/toneMapping.slf | 6 +++++- .../utilities/render/deferredLighting.qml | 16 ++++++++++++++++ 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index d192266d7e..c40505917c 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -40,6 +40,13 @@ void ToneMappingEffect::setExposure(float exposure) { } } +void ToneMappingEffect::setColorFilter(const glm::vec3& colorFilter) { + auto& params = _parametersBuffer.get(); + if (params._colorFilter != colorFilter) { + _parametersBuffer.edit()._colorFilter = colorFilter; + } +} + void ToneMappingEffect::setToneCurve(ToneCurve curve) { auto& params = _parametersBuffer.get(); if (params._toneCurve != curve) { @@ -62,9 +69,6 @@ void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& ligh batch.enableStereo(false); batch.setFramebuffer(destinationFramebuffer); - // FIXME: Generate the Luminosity map - //batch.generateTextureMips(lightingBuffer); - batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); @@ -79,8 +83,9 @@ void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& ligh void ToneMappingDeferred::configure(const Config& config) { - _toneMappingEffect.setExposure(config.exposure); - _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)config.curve); + _toneMappingEffect.setExposure(config.exposure); + _toneMappingEffect.setColorFilter(config.colorFilter); + _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)config.curve); } void ToneMappingDeferred::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index 2da5be8d10..ae394c4dc3 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -31,6 +31,9 @@ public: void setExposure(float exposure); float getExposure() const { return _parametersBuffer.get()._exposure; } + void setColorFilter(const glm::vec3& colorFilter); + glm::vec3 getColorFIlter() const { return _parametersBuffer.get()._colorFilter; } + // Different tone curve available enum ToneCurve { None = 0, @@ -51,8 +54,10 @@ private: float _exposure = 0.0f; float _twoPowExposure = 1.0f; glm::vec2 spareA; + glm::vec3 _colorFilter{ 1.0f }; + float spareB; int _toneCurve = None; - glm::vec3 spareB; + glm::vec3 spareC; Parameters() {} }; @@ -65,15 +70,18 @@ private: class ToneMappingConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(float exposure MEMBER exposure WRITE setExposure); + Q_PROPERTY(glm::vec3 colorFilter MEMBER colorFilter WRITE setColorFilter); Q_PROPERTY(int curve MEMBER curve WRITE setCurve); public: ToneMappingConfig() : render::Job::Config(true) {} void setExposure(float newExposure) { exposure = newExposure; emit dirty(); } + void setColorFilter(const glm::vec3& newColorFilter) { colorFilter = newColorFilter; emit dirty(); } void setCurve(int newCurve) { curve = std::max((int)ToneMappingEffect::None, std::min((int)ToneMappingEffect::Filmic, newCurve)); emit dirty(); } float exposure{ 0.0f }; + glm::vec3 colorFilter { 1.0f }; int curve{ ToneMappingEffect::None }; signals: void dirty(); diff --git a/libraries/render-utils/src/toneMapping.slf b/libraries/render-utils/src/toneMapping.slf index cb3e73dd4d..3b13425816 100644 --- a/libraries/render-utils/src/toneMapping.slf +++ b/libraries/render-utils/src/toneMapping.slf @@ -17,6 +17,7 @@ struct ToneMappingParams { vec4 _exp_2powExp_s0_s1; + vec4 _colorFilter_s0; ivec4 _toneCurve_s0_s1_s2; }; @@ -32,6 +33,9 @@ LAYOUT(binding=RENDER_UTILS_BUFFER_TM_PARAMS) uniform toneMappingParamsBuffer { float getTwoPowExposure() { return params._exp_2powExp_s0_s1.y; } +vec3 getColorFilter() { + return params._colorFilter_s0.xyz; +} int getToneCurve() { return params._toneCurve_s0_s1_s2.x; } @@ -45,7 +49,7 @@ void main(void) { vec4 fragColorRaw = texture(colorMap, varTexCoord0); vec3 fragColor = fragColorRaw.xyz; - vec3 srcColor = fragColor * getTwoPowExposure(); + vec3 srcColor = fragColor * getColorFilter() * getTwoPowExposure(); int toneCurve = getToneCurve(); vec3 tonedColor = srcColor; diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index aef533b7a3..8c3e0fce94 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -14,6 +14,7 @@ import QtQuick.Layouts 1.3 import stylesUit 1.0 import controlsUit 1.0 as HifiControls import "configSlider" +import "../lib/plotperf" Rectangle { HifiConstants { id: hifi;} @@ -123,7 +124,22 @@ Rectangle { anchors.right: parent.right } } + Item { + HifiControls.Label { + text: "Color filter" + anchors.left: parent.left + } + Color { + height: 20 + anchors.right: parent.right + width: parent.width / 2 + _color: render.mainViewTask.getConfig("ToneMapping")["colorFilter"] + onNewColor: { + render.mainViewTask.getConfig("ToneMapping")["colorFilter"] = getXColor() + } + } + } Item { height: childrenRect.height anchors.left: parent.left From e62f67a847e65b36425929f4caf01e31a9a7ad9d Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 5 Feb 2019 10:31:59 -0800 Subject: [PATCH 040/139] Don't remove unselected component in Win installer --- cmake/templates/NSIS.template.in | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 9ce11ca032..cc7a6929a2 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -300,6 +300,8 @@ Var substringResult SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags ;Checking lowest bit: IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED} + !insertmacro LoadVar ${SecName}_was_installed + IntOp $AR_SecFlags $AR_SecFlags | $R0 IntCmp $AR_SecFlags 1 "leave_${SecName}" ;Section is not selected: @@ -478,18 +480,6 @@ Var GAClientID ;-------------------------------- ; Installation types -Section "-Previous Install Cleanup" - ; Remove the resources folder so we don't end up including removed QML files - RMDir /r "$INSTDIR\resources" - - ; delete old assignment-client and domain-server so they're no longer present - ; in client only installs. - Delete "$INSTDIR\@DS_EXEC_NAME@" - Delete "$INSTDIR\@AC_EXEC_NAME@" - - ; delete interface so it's not there for server-only installs - Delete "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@" -SectionEnd @CPACK_NSIS_INSTALLATION_TYPES@ From 5945823606a9fd0494fc96f80edbf851ffe25ff5 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 5 Feb 2019 17:02:00 -0800 Subject: [PATCH 041/139] Honor full scene resends --- assignment-client/src/entities/EntityTreeSendThread.cpp | 7 ++++--- assignment-client/src/entities/EntityTreeSendThread.h | 2 +- libraries/entities/src/DiffTraversal.cpp | 5 +++-- libraries/entities/src/DiffTraversal.h | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index 8b7c8771e8..a6542689e0 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -111,7 +111,7 @@ bool EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST); newView.lodScaleFactor = powf(2.0f, lodLevelOffset); - startNewTraversal(newView, root); + startNewTraversal(newView, root, isFullScene); // When the viewFrustum changed the sort order may be incorrect, so we re-sort // and also use the opportunity to cull anything no longer in view @@ -220,9 +220,10 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil return hasNewChild || hasNewDescendants; } -void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root) { +void EntityTreeSendThread::startNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root, + bool forceFirstPass) { - DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root); + DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, forceFirstPass); // there are three types of traversal: // // (1) FirstTime = at login --> find everything in view diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h index 199769ca09..7eedc2f1ba 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.h +++ b/assignment-client/src/entities/EntityTreeSendThread.h @@ -42,7 +42,7 @@ private: bool addAncestorsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); - void startNewTraversal(const DiffTraversal::View& viewFrustum, EntityTreeElementPointer root); + void startNewTraversal(const DiffTraversal::View& viewFrustum, EntityTreeElementPointer root, bool forceFirstPass = false); bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override; void preDistributionProcessing() override; diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp index 36d1f41267..dc32419ed0 100644 --- a/libraries/entities/src/DiffTraversal.cpp +++ b/libraries/entities/src/DiffTraversal.cpp @@ -193,7 +193,8 @@ DiffTraversal::DiffTraversal() { _path.reserve(MIN_PATH_DEPTH); } -DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root) { +DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root, + bool forceFirstPass) { assert(root); // there are three types of traversal: // @@ -212,7 +213,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const DiffTraversal::View Type type; // If usesViewFrustum changes, treat it as a First traversal - if (_completedView.startTime == 0 || _currentView.usesViewFrustums() != _completedView.usesViewFrustums()) { + if (forceFirstPass || _completedView.startTime == 0 || _currentView.usesViewFrustums() != _completedView.usesViewFrustums()) { type = Type::First; _currentView.viewFrustums = view.viewFrustums; _currentView.lodScaleFactor = view.lodScaleFactor; diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h index d62c7b8ee1..e1107ec930 100644 --- a/libraries/entities/src/DiffTraversal.h +++ b/libraries/entities/src/DiffTraversal.h @@ -61,7 +61,7 @@ public: DiffTraversal(); - Type prepareNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root); + Type prepareNewTraversal(const DiffTraversal::View& view, EntityTreeElementPointer root, bool forceFirstPass = false); const View& getCurrentView() const { return _currentView; } From 8b32a62e2fc251ea9e26ccab2a2490c595052622 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 5 Feb 2019 17:02:19 -0800 Subject: [PATCH 042/139] Simplify filter check --- libraries/entities/src/EntityItem.cpp | 11 ++--------- .../src/model-networking/TextureCache.cpp | 1 - 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1640e97ff4..79b7eb27a1 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2635,15 +2635,8 @@ bool EntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const { static const QString SERVER_SCRIPTS_PROPERTY = "serverScripts"; - foreach(const auto& property, jsonFilters.keys()) { - if (property == SERVER_SCRIPTS_PROPERTY && jsonFilters[property] == EntityQueryFilterSymbol::NonDefault) { - // check if this entity has a non-default value for serverScripts - if (_serverScripts != ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS) { - return true; - } else { - return false; - } - } + if (jsonFilters[SERVER_SCRIPTS_PROPERTY] == EntityQueryFilterSymbol::NonDefault) { + return _serverScripts != ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS; } // the json filter syntax did not match what we expected, return a match diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 4c30dc6d93..37e8ad3f56 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -493,7 +493,6 @@ void NetworkTexture::makeRequest() { } else { qWarning(networking) << "NetworkTexture::makeRequest() called while not in a valid state: " << _ktxResourceState; } - } void NetworkTexture::handleLocalRequestCompleted() { From 3ee448a89a91b3737b316ad693964fa789342d72 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 5 Feb 2019 17:32:15 -0800 Subject: [PATCH 043/139] fix scattering and working on resource cache bug --- libraries/animation/src/AnimationCache.cpp | 7 +- libraries/animation/src/AnimationCache.h | 7 +- libraries/audio/src/SoundCache.cpp | 7 +- libraries/audio/src/SoundCache.h | 5 +- .../src/RenderableModelEntityItem.cpp | 6 +- libraries/fbx/src/FBXSerializer_Material.cpp | 13 ++- libraries/fbx/src/FSTReader.cpp | 4 +- libraries/graphics/src/graphics/Material.cpp | 2 +- .../src/model-networking/MaterialCache.cpp | 8 +- .../src/model-networking/MaterialCache.h | 3 +- .../src/model-networking/ModelCache.cpp | 32 +++++-- .../src/model-networking/ModelCache.h | 12 ++- .../src/model-networking/ShaderCache.cpp | 8 +- .../src/model-networking/ShaderCache.h | 5 +- .../src/model-networking/TextureCache.cpp | 51 ++++++---- .../src/model-networking/TextureCache.h | 8 +- libraries/networking/src/ResourceCache.cpp | 95 ++++++++++++++----- libraries/networking/src/ResourceCache.h | 19 ++-- .../recording/src/recording/ClipCache.cpp | 5 +- libraries/recording/src/recording/ClipCache.h | 5 +- .../render-utils/src/RenderPipelines.cpp | 2 +- 21 files changed, 199 insertions(+), 105 deletions(-) diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index f7a7dd861a..4e988334f9 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -36,12 +36,13 @@ AnimationPointer AnimationCache::getAnimation(const QUrl& url) { return getResource(url).staticCast(); } -QSharedPointer AnimationCache::createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) { +QSharedPointer AnimationCache::createResource(const QUrl& url) { return QSharedPointer(new Animation(url), &Resource::deleter); } -Animation::Animation(const QUrl& url) : Resource(url) {} +QSharedPointer AnimationCache::createResourceCopy(const QSharedPointer& resource) { + return QSharedPointer(new Animation(*resource.staticCast().data()), &Resource::deleter); +} AnimationReader::AnimationReader(const QUrl& url, const QByteArray& data) : _url(url), diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 2f8168625e..eea64475df 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -34,9 +34,9 @@ public: Q_INVOKABLE AnimationPointer getAnimation(const QUrl& url); protected: + virtual QSharedPointer createResource(const QUrl& url) override; + QSharedPointer createResourceCopy(const QSharedPointer& resource) override; - virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) override; private: explicit AnimationCache(QObject* parent = NULL); virtual ~AnimationCache() { } @@ -62,7 +62,8 @@ class Animation : public Resource { public: - explicit Animation(const QUrl& url); + Animation(const Animation& other) : Resource(other), _hfmModel(other._hfmModel) {} + Animation(const QUrl& url) : Resource(url) {} QString getType() const override { return "Animation"; } diff --git a/libraries/audio/src/SoundCache.cpp b/libraries/audio/src/SoundCache.cpp index 845fd6ab4f..343de46e9a 100644 --- a/libraries/audio/src/SoundCache.cpp +++ b/libraries/audio/src/SoundCache.cpp @@ -33,9 +33,12 @@ SharedSoundPointer SoundCache::getSound(const QUrl& url) { return getResource(url).staticCast(); } -QSharedPointer SoundCache::createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) { +QSharedPointer SoundCache::createResource(const QUrl& url) { auto resource = QSharedPointer(new Sound(url), &Resource::deleter); resource->setLoadPriority(this, SOUNDS_LOADING_PRIORITY); return resource; } + +QSharedPointer SoundCache::createResourceCopy(const QSharedPointer& resource) { + return QSharedPointer(new Sound(*resource.staticCast().data()), &Resource::deleter); +} \ No newline at end of file diff --git a/libraries/audio/src/SoundCache.h b/libraries/audio/src/SoundCache.h index 64d392a41d..48c3354877 100644 --- a/libraries/audio/src/SoundCache.h +++ b/libraries/audio/src/SoundCache.h @@ -24,8 +24,9 @@ public: Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url); protected: - virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) override; + virtual QSharedPointer createResource(const QUrl& url) override; + QSharedPointer createResourceCopy(const QSharedPointer& resource) override; + private: SoundCache(QObject* parent = NULL); }; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 7e01af04dd..9515ef94b5 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -280,11 +280,7 @@ bool RenderableModelEntityItem::findDetailedParabolaIntersection(const glm::vec3 } void RenderableModelEntityItem::fetchCollisionGeometryResource() { - QUrl hullURL(getCollisionShapeURL()); - QUrlQuery queryArgs(hullURL); - queryArgs.addQueryItem("collision-hull", ""); - hullURL.setQuery(queryArgs); - _compoundShapeResource = DependencyManager::get()->getCollisionGeometryResource(hullURL); + _compoundShapeResource = DependencyManager::get()->getCollisionGeometryResource(getCollisionShapeURL()); } bool RenderableModelEntityItem::computeShapeFailedToLoad() { diff --git a/libraries/fbx/src/FBXSerializer_Material.cpp b/libraries/fbx/src/FBXSerializer_Material.cpp index 0a1d15b72a..9caf713e75 100644 --- a/libraries/fbx/src/FBXSerializer_Material.cpp +++ b/libraries/fbx/src/FBXSerializer_Material.cpp @@ -76,13 +76,12 @@ HFMTexture FBXSerializer::getTexture(const QString& textureID, const QString& ma } void FBXSerializer::consolidateHFMMaterials(const QVariantHash& mapping) { - - QString materialMapString = mapping.value("materialMap").toString(); - QJsonDocument materialMapDocument = QJsonDocument::fromJson(materialMapString.toUtf8()); - QJsonObject materialMap = materialMapDocument.object(); - if (!materialMapString.isEmpty()) { - if (materialMapDocument.isEmpty() || materialMap.isEmpty()) { - qCDebug(modelformat) << "fbx Material Map found but did not produce valid JSON:" << materialMapString; + QJsonObject materialMap; + if (mapping.contains("materialMap")) { + QByteArray materialMapValue = mapping.value("materialMap").toByteArray(); + materialMap = QJsonDocument::fromJson(materialMapValue).object(); + if (materialMap.isEmpty()) { + qCDebug(modelformat) << "fbx Material Map found but did not produce valid JSON:" << materialMapValue; } } for (QHash::iterator it = _hfmMaterials.begin(); it != _hfmMaterials.end(); it++) { diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index 43806560dc..0ca1c6c9e6 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -88,7 +88,7 @@ QByteArray FSTReader::writeMapping(const QVariantHash& mapping) { << BLENDSHAPE_FIELD << JOINT_INDEX_FIELD; QBuffer buffer; buffer.open(QIODevice::WriteOnly); - + for (auto key : PREFERED_ORDER) { auto it = mapping.find(key); if (it != mapping.constEnd()) { @@ -104,7 +104,7 @@ QByteArray FSTReader::writeMapping(const QVariantHash& mapping) { } } } - + for (auto it = mapping.constBegin(); it != mapping.constEnd(); it++) { if (!PREFERED_ORDER.contains(it.key())) { writeVariant(buffer, it); diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index 7befb7e053..c19b139936 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -105,7 +105,7 @@ void Material::setMetallic(float metallic) { void Material::setScattering(float scattering) { scattering = glm::clamp(scattering, 0.0f, 1.0f); - _key.setMetallic(scattering > 0.0f); + _key.setScattering(scattering > 0.0f); _scattering = scattering; } diff --git a/libraries/model-networking/src/model-networking/MaterialCache.cpp b/libraries/model-networking/src/model-networking/MaterialCache.cpp index b6550a5e9e..7dcd7b8a61 100644 --- a/libraries/model-networking/src/model-networking/MaterialCache.cpp +++ b/libraries/model-networking/src/model-networking/MaterialCache.cpp @@ -417,9 +417,13 @@ MaterialCache& MaterialCache::instance() { } NetworkMaterialResourcePointer MaterialCache::getMaterial(const QUrl& url) { - return ResourceCache::getResource(url, QUrl(), nullptr).staticCast(); + return ResourceCache::getResource(url, QUrl()).staticCast(); } -QSharedPointer MaterialCache::createResource(const QUrl& url, const QSharedPointer& fallback, const void* extra) { +QSharedPointer MaterialCache::createResource(const QUrl& url) { return QSharedPointer(new NetworkMaterialResource(url), &Resource::deleter); +} + +QSharedPointer MaterialCache::createResourceCopy(const QSharedPointer& resource) { + return QSharedPointer(new NetworkMaterialResource(*resource.staticCast().data()), &Resource::deleter); } \ No newline at end of file diff --git a/libraries/model-networking/src/model-networking/MaterialCache.h b/libraries/model-networking/src/model-networking/MaterialCache.h index 074cd6c98d..6abadfc030 100644 --- a/libraries/model-networking/src/model-networking/MaterialCache.h +++ b/libraries/model-networking/src/model-networking/MaterialCache.h @@ -53,7 +53,8 @@ public: NetworkMaterialResourcePointer getMaterial(const QUrl& url); protected: - virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, const void* extra) override; + virtual QSharedPointer createResource(const QUrl& url) override; + QSharedPointer createResourceCopy(const QSharedPointer& resource) override; }; #endif diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 8c541040a7..7515dad256 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -107,7 +107,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { } auto modelCache = DependencyManager::get(); - GeometryExtra extra{ _mapping, _textureBaseUrl, false }; + GeometryExtra extra { _mapping, _textureBaseUrl, false }; // Get the raw GeometryResource _geometryResource = modelCache->getResource(url, QUrl(), &extra).staticCast(); @@ -253,13 +253,19 @@ void GeometryReader::run() { class GeometryDefinitionResource : public GeometryResource { Q_OBJECT public: - GeometryDefinitionResource(const ModelLoader& modelLoader, const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl, bool combineParts) : - GeometryResource(url, resolveTextureBaseUrl(url, textureBaseUrl)), _modelLoader(modelLoader), _mapping(mapping), _combineParts(combineParts) {} + GeometryDefinitionResource(const ModelLoader& modelLoader, const QUrl& url) : GeometryResource(url), _modelLoader(modelLoader) {} + GeometryDefinitionResource(const GeometryDefinitionResource& other) : + GeometryResource(other), + _modelLoader(other._modelLoader), + _mapping(other._mapping), + _combineParts(other._combineParts) {} QString getType() const override { return "GeometryDefinition"; } virtual void downloadFinished(const QByteArray& data) override; + void setExtra(void* extra) override; + protected: Q_INVOKABLE void setGeometryDefinition(HFMModel::Pointer hfmModel); @@ -269,6 +275,13 @@ private: bool _combineParts; }; +void GeometryDefinitionResource::setExtra(void* extra) { + const GeometryExtra* geometryExtra = static_cast(extra); + _mapping = geometryExtra ? geometryExtra->mapping : QVariantHash(); + _textureBaseUrl = resolveTextureBaseUrl(_url, geometryExtra ? geometryExtra->textureBaseUrl : QUrl()); + _combineParts = geometryExtra ? geometryExtra->combineParts : true; +} + void GeometryDefinitionResource::downloadFinished(const QByteArray& data) { if (_url != _effectiveBaseURL) { _url = _effectiveBaseURL; @@ -323,22 +336,21 @@ ModelCache::ModelCache() { modelFormatRegistry->addFormat(GLTFSerializer()); } -QSharedPointer ModelCache::createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) { +QSharedPointer ModelCache::createResource(const QUrl& url) { Resource* resource = nullptr; if (url.path().toLower().endsWith(".fst")) { resource = new GeometryMappingResource(url); } else { - const GeometryExtra* geometryExtra = static_cast(extra); - auto mapping = geometryExtra ? geometryExtra->mapping : QVariantHash(); - auto textureBaseUrl = geometryExtra ? geometryExtra->textureBaseUrl : QUrl(); - bool combineParts = geometryExtra ? geometryExtra->combineParts : true; - resource = new GeometryDefinitionResource(_modelLoader, url, mapping, textureBaseUrl, combineParts); + resource = new GeometryDefinitionResource(_modelLoader, url); } return QSharedPointer(resource, &Resource::deleter); } +QSharedPointer ModelCache::createResourceCopy(const QSharedPointer& resource) { + return QSharedPointer(new GeometryDefinitionResource(*resource.staticCast().data()), &Resource::deleter); +} + GeometryResource::Pointer ModelCache::getGeometryResource(const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl) { bool combineParts = true; diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 1018bdecd5..497cae86a3 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -82,8 +82,12 @@ class GeometryResource : public Resource, public Geometry { public: using Pointer = QSharedPointer; - GeometryResource(const QUrl& url, const QUrl& textureBaseUrl = QUrl()) : - Resource(url), _textureBaseUrl(textureBaseUrl) {} + GeometryResource(const QUrl& url) : Resource(url) {} + GeometryResource(const GeometryResource& other) : + Resource(other), + Geometry(other), + _textureBaseUrl(other._textureBaseUrl), + _isCacheable(other._isCacheable) {} virtual bool areTexturesLoaded() const override { return isLoaded() && Geometry::areTexturesLoaded(); } @@ -153,8 +157,8 @@ public: protected: friend class GeometryMappingResource; - virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) override; + virtual QSharedPointer createResource(const QUrl& url) override; + QSharedPointer createResourceCopy(const QSharedPointer& resource) override; private: ModelCache(); diff --git a/libraries/model-networking/src/model-networking/ShaderCache.cpp b/libraries/model-networking/src/model-networking/ShaderCache.cpp index bf7ade07f7..b774ca36c5 100644 --- a/libraries/model-networking/src/model-networking/ShaderCache.cpp +++ b/libraries/model-networking/src/model-networking/ShaderCache.cpp @@ -21,11 +21,13 @@ ShaderCache& ShaderCache::instance() { } NetworkShaderPointer ShaderCache::getShader(const QUrl& url) { - return ResourceCache::getResource(url, QUrl(), nullptr).staticCast(); + return ResourceCache::getResource(url, QUrl()).staticCast(); } -QSharedPointer ShaderCache::createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) { +QSharedPointer ShaderCache::createResource(const QUrl& url) { return QSharedPointer(new NetworkShader(url), &Resource::deleter); } +QSharedPointer ShaderCache::createResourceCopy(const QSharedPointer& resource) { + return QSharedPointer(new NetworkShader(*resource.staticCast().data()), &Resource::deleter); +} diff --git a/libraries/model-networking/src/model-networking/ShaderCache.h b/libraries/model-networking/src/model-networking/ShaderCache.h index bd78e6e7e3..fe9edd7ddf 100644 --- a/libraries/model-networking/src/model-networking/ShaderCache.h +++ b/libraries/model-networking/src/model-networking/ShaderCache.h @@ -14,6 +14,7 @@ class NetworkShader : public Resource { public: NetworkShader(const QUrl& url); + NetworkShader(const NetworkShader& other) : Resource(other), _source(other._source) {} QString getType() const override { return "NetworkShader"; } @@ -31,8 +32,8 @@ public: NetworkShaderPointer getShader(const QUrl& url); protected: - virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) override; + virtual QSharedPointer createResource(const QUrl& url) override; + QSharedPointer createResourceCopy(const QSharedPointer& resource) override; }; #endif diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 4c30dc6d93..2f29eaf385 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -305,42 +305,52 @@ gpu::TexturePointer TextureCache::getImageTexture(const QString& path, image::Te return gpu::TexturePointer(loader(std::move(image), path.toStdString(), shouldCompress, target, false)); } -QSharedPointer TextureCache::createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) { - const TextureExtra* textureExtra = static_cast(extra); - auto type = textureExtra ? textureExtra->type : image::TextureUsage::DEFAULT_TEXTURE; - auto content = textureExtra ? textureExtra->content : QByteArray(); - auto maxNumPixels = textureExtra ? textureExtra->maxNumPixels : ABSOLUTE_MAX_TEXTURE_NUM_PIXELS; - NetworkTexture* texture = new NetworkTexture(url, type, content, maxNumPixels); - return QSharedPointer(texture, &Resource::deleter); +QSharedPointer TextureCache::createResource(const QUrl& url) { + return QSharedPointer(new NetworkTexture(url), &Resource::deleter); +} + +QSharedPointer TextureCache::createResourceCopy(const QSharedPointer& resource) { + return QSharedPointer(new NetworkTexture(*resource.staticCast().data()), &Resource::deleter); } int networkTexturePointerMetaTypeId = qRegisterMetaType>(); NetworkTexture::NetworkTexture(const QUrl& url) : -Resource(url), -_type(), -_maxNumPixels(100) + Resource(url), + _type(), + _maxNumPixels(100) { _textureSource = std::make_shared(url); _lowestRequestedMipLevel = 0; _loaded = true; } +NetworkTexture::NetworkTexture(const NetworkTexture& other) : + Resource(other), + _type(other._type), + _currentlyLoadingResourceType(other._currentlyLoadingResourceType), + _originalWidth(other._originalWidth), + _originalHeight(other._originalHeight), + _width(other._width), + _height(other._height), + _maxNumPixels(other._maxNumPixels) +{ +} + static bool isLocalUrl(const QUrl& url) { auto scheme = url.scheme(); return (scheme == HIFI_URL_SCHEME_FILE || scheme == URL_SCHEME_QRC || scheme == RESOURCE_SCHEME); } -NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) : - Resource(url), - _type(type), - _maxNumPixels(maxNumPixels) -{ - _textureSource = std::make_shared(url, (int)type); +void NetworkTexture::setExtra(void* extra) { + const TextureExtra* textureExtra = static_cast(extra); + _type = textureExtra ? textureExtra->type : image::TextureUsage::DEFAULT_TEXTURE; + _maxNumPixels = textureExtra ? textureExtra->maxNumPixels : ABSOLUTE_MAX_TEXTURE_NUM_PIXELS; + + _textureSource = std::make_shared(_url, (int)_type); _lowestRequestedMipLevel = 0; - auto fileNameLowercase = url.fileName().toLower(); + auto fileNameLowercase = _url.fileName().toLower(); if (fileNameLowercase.endsWith(TEXTURE_META_EXTENSION)) { _currentlyLoadingResourceType = ResourceType::META; } else if (fileNameLowercase.endsWith(".ktx")) { @@ -351,17 +361,18 @@ NetworkTexture::NetworkTexture(const QUrl& url, image::TextureUsage::Type type, _shouldFailOnRedirect = _currentlyLoadingResourceType != ResourceType::KTX; - if (type == image::TextureUsage::CUBE_TEXTURE) { + if (_type == image::TextureUsage::CUBE_TEXTURE) { setLoadPriority(this, SKYBOX_LOAD_PRIORITY); } else if (_currentlyLoadingResourceType == ResourceType::KTX) { setLoadPriority(this, HIGH_MIPS_LOAD_PRIORITY); } - if (!url.isValid()) { + if (!_url.isValid()) { _loaded = true; } // if we have content, load it after we have our self pointer + auto content = textureExtra ? textureExtra->content : QByteArray(); if (!content.isEmpty()) { _startedLoading = true; QMetaObject::invokeMethod(this, "downloadFinished", Qt::QueuedConnection, Q_ARG(const QByteArray&, content)); diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 3933e3ae56..d744d060b6 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -46,7 +46,7 @@ class NetworkTexture : public Resource, public Texture { public: NetworkTexture(const QUrl& url); - NetworkTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels); + NetworkTexture(const NetworkTexture& other); ~NetworkTexture() override; QString getType() const override { return "NetworkTexture"; } @@ -63,6 +63,8 @@ public: Q_INVOKABLE void setOriginalDescriptor(ktx::KTXDescriptor* descriptor) { _originalKtxDescriptor.reset(descriptor); } + void setExtra(void* extra) override; + signals: void networkTextureCreated(const QWeakPointer& self); @@ -201,8 +203,8 @@ protected: // Overload ResourceCache::prefetch to allow specifying texture type for loads Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS); - virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) override; + virtual QSharedPointer createResource(const QUrl& url) override; + QSharedPointer createResourceCopy(const QSharedPointer& resource) override; private: friend class ImageReader; diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 20fe05e7b8..43fc93ffc5 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -265,16 +265,17 @@ ResourceCache::~ResourceCache() { void ResourceCache::clearATPAssets() { { QWriteLocker locker(&_resourcesLock); - for (auto& url : _resources.keys()) { + QList urls = _resources.keys(); + for (auto& url : urls) { // If this is an ATP resource if (url.scheme() == URL_SCHEME_ATP) { - - // Remove it from the resource hash - auto resource = _resources.take(url); - if (auto strongRef = resource.lock()) { - // Make sure the resource won't reinsert itself - strongRef->setCache(nullptr); - _totalResourcesSize -= strongRef->getBytes(); + auto resourcesWithExtraHash = _resources.take(url); + for (auto& resource : resourcesWithExtraHash) { + if (auto strongRef = resource.lock()) { + // Make sure the resource won't reinsert itself + strongRef->setCache(nullptr); + _totalResourcesSize -= strongRef->getBytes(); + } } } } @@ -297,16 +298,20 @@ void ResourceCache::refreshAll() { clearUnusedResources(); resetUnusedResourceCounter(); - QHash> resources; + QHash>> allResources; { QReadLocker locker(&_resourcesLock); - resources = _resources; + allResources = _resources; } // Refresh all remaining resources in use - foreach (QSharedPointer resource, resources) { - if (resource) { - resource->refresh(); + // FIXME: this will trigger multiple refreshes for the same resource if they have different hashes + for (auto& resourcesWithExtraHash : allResources) { + for (auto& resourceWeak : resourcesWithExtraHash) { + auto resource = resourceWeak.lock(); + if (resource) { + resource->refresh(); + } } } } @@ -338,39 +343,59 @@ void ResourceCache::setRequestLimit(uint32_t limit) { } } -QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& fallback, void* extra) { +QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& fallback, void* extra, int extraHash) { QSharedPointer resource; + if (extra && extraHash < 0) { + qDebug() << "ResourceCache::getResource: ERROR! Non-null extra, but invalid extraHash"; + return resource; + } + { QReadLocker locker(&_resourcesLock); - resource = _resources.value(url).lock(); + auto& resourcesWithExtraHash = _resources[url]; + auto resourcesWithExtraHashIter = resourcesWithExtraHash.find(extraHash); + if (resourcesWithExtraHashIter != resourcesWithExtraHash.end()) { + // We've seen this extra info before + resource = resourcesWithExtraHashIter.value().lock(); + } else if (resourcesWithExtraHash.size() > 0.0f) { + // We haven't seen this extra info before, but we've already downloaded the resource. We need a new copy of this object (with any old hash). + resource = createResourceCopy(resourcesWithExtraHash.begin().value().lock()); + resource->setExtra(extra); + resource->setExtraHash(extraHash); + resource->setSelf(resource); + resource->setCache(this); + resource->moveToThread(qApp->thread()); + connect(resource.data(), &Resource::updateSize, this, &ResourceCache::updateTotalSize); + resourcesWithExtraHash.insert(extraHash, resource); + removeUnusedResource(resource); + resource->ensureLoading(); + } } if (resource) { removeUnusedResource(resource); } - if (!resource && !url.isValid() && !url.isEmpty() && fallback.isValid()) { - resource = getResource(fallback, QUrl()); + if (!resource && (!url.isValid() || url.isEmpty()) && fallback.isValid()) { + resource = getResource(fallback, QUrl(), extra, extraHash); } if (!resource) { - resource = createResource( - url, - fallback.isValid() ? getResource(fallback, QUrl()) : QSharedPointer(), - extra); + resource = createResource(url); + resource->setExtra(extra); + resource->setExtraHash(extraHash); resource->setSelf(resource); resource->setCache(this); resource->moveToThread(qApp->thread()); connect(resource.data(), &Resource::updateSize, this, &ResourceCache::updateTotalSize); { QWriteLocker locker(&_resourcesLock); - _resources.insert(url, resource); + _resources[url].insert(extraHash, resource); } removeUnusedResource(resource); resource->ensureLoading(); } - DependencyManager::get()->update( - resource->getURL(), -1, "ResourceCache::getResource"); + DependencyManager::get()->update(resource->getURL(), -1, "ResourceCache::getResource"); return resource; } @@ -527,6 +552,26 @@ bool ResourceCache::attemptHighestPriorityRequest() { static int requestID = 0; +Resource::Resource(const Resource& other) : + _url(other._url), + _extraHash(other._extraHash), + _effectiveBaseURL(other._effectiveBaseURL), + _activeUrl(other._activeUrl), + _requestByteRange(other._requestByteRange), + _shouldFailOnRedirect(other._shouldFailOnRedirect), + _startedLoading(other._startedLoading), + _failedToLoad(other._failedToLoad), + _loaded(other._loaded), + _loadPriorities(other._loadPriorities), + _bytesReceived(other._bytesReceived), + _bytesTotal(other._bytesTotal), + _bytes(other._bytes), + _requestID(++requestID) { + if (!other._loaded) { + _startedLoading = false; + } +} + Resource::Resource(const QUrl& url) : _url(url), _activeUrl(url), @@ -678,7 +723,7 @@ void Resource::setSize(const qint64& bytes) { void Resource::reinsert() { QWriteLocker locker(&_cache->_resourcesLock); - _cache->_resources.insert(_url, _self); + _cache->_resources[_url].insert(_extraHash, _self); } diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 275684f73e..dd60e3c110 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -239,8 +239,7 @@ protected slots: /// returns an empty smart pointer and loads its asynchronously. /// \param fallback a fallback URL to load if the desired one is unavailable /// \param extra extra data to pass to the creator, if appropriate - QSharedPointer getResource(const QUrl& url, const QUrl& fallback = QUrl(), - void* extra = NULL); + QSharedPointer getResource(const QUrl& url, const QUrl& fallback = QUrl(), void* extra = NULL, int extraHash = -1); private slots: void clearATPAssets(); @@ -254,8 +253,8 @@ protected: Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr); } /// Creates a new resource. - virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra) = 0; + virtual QSharedPointer createResource(const QUrl& url) = 0; + virtual QSharedPointer createResourceCopy(const QSharedPointer& resource) = 0; void addUnusedResource(const QSharedPointer& resource); void removeUnusedResource(const QSharedPointer& resource); @@ -278,7 +277,7 @@ private: void resetResourceCounters(); // Resources - QHash> _resources; + QHash>> _resources; QReadWriteLock _resourcesLock { QReadWriteLock::Recursive }; int _lastLRUKey = 0; @@ -359,7 +358,8 @@ class Resource : public QObject { Q_OBJECT public: - + + Resource(const Resource& other); Resource(const QUrl& url); virtual ~Resource(); @@ -415,6 +415,9 @@ public: unsigned int getDownloadAttempts() { return _attempts; } unsigned int getDownloadAttemptsRemaining() { return _attemptsRemaining; } + virtual void setExtra(void* extra) {}; + void setExtraHash(int extraHash) { _extraHash = extraHash; } + signals: /// Fired when the resource begins downloading. void loading(); @@ -469,7 +472,7 @@ protected: virtual bool handleFailedRequest(ResourceRequest::Result result); QUrl _url; - QUrl _effectiveBaseURL{ _url }; + QUrl _effectiveBaseURL { _url }; QUrl _activeUrl; ByteRange _requestByteRange; bool _shouldFailOnRedirect { false }; @@ -492,6 +495,8 @@ protected: int _requestID; ResourceRequest* _request{ nullptr }; + int _extraHash { -1 }; + public slots: void handleDownloadProgress(uint64_t bytesReceived, uint64_t bytesTotal); void handleReplyFinished(); diff --git a/libraries/recording/src/recording/ClipCache.cpp b/libraries/recording/src/recording/ClipCache.cpp index c63350de7f..c08dd40ad8 100644 --- a/libraries/recording/src/recording/ClipCache.cpp +++ b/libraries/recording/src/recording/ClipCache.cpp @@ -48,8 +48,11 @@ NetworkClipLoaderPointer ClipCache::getClipLoader(const QUrl& url) { return getResource(url).staticCast(); } -QSharedPointer ClipCache::createResource(const QUrl& url, const QSharedPointer& fallback, const void* extra) { +QSharedPointer ClipCache::createResource(const QUrl& url) { qCDebug(recordingLog) << "Loading recording at" << url; return QSharedPointer(new NetworkClipLoader(url), &Resource::deleter); } +QSharedPointer ClipCache::createResourceCopy(const QSharedPointer& resource) { + return QSharedPointer(new NetworkClipLoader(*resource.staticCast().data()), &Resource::deleter); +} \ No newline at end of file diff --git a/libraries/recording/src/recording/ClipCache.h b/libraries/recording/src/recording/ClipCache.h index 2c3465e725..202cd2f00e 100644 --- a/libraries/recording/src/recording/ClipCache.h +++ b/libraries/recording/src/recording/ClipCache.h @@ -33,6 +33,8 @@ class NetworkClipLoader : public Resource { Q_OBJECT public: NetworkClipLoader(const QUrl& url); + NetworkClipLoader(const NetworkClipLoader& other) : Resource(other), _clip(other._clip) {} + virtual void downloadFinished(const QByteArray& data) override; ClipPointer getClip() { return _clip; } bool completed() { return _failedToLoad || isLoaded(); } @@ -54,7 +56,8 @@ public slots: NetworkClipLoaderPointer getClipLoader(const QUrl& url); protected: - virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, const void* extra) override; + virtual QSharedPointer createResource(const QUrl& url) override; + QSharedPointer createResourceCopy(const QSharedPointer& resource) override; private: ClipCache(QObject* parent = nullptr); diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 85bdf0fadc..5f3763ac2a 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -579,7 +579,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial } else { forceDefault = true; } - schemaKey.setScattering(true); + schemaKey.setScatteringMap(true); } break; case graphics::MaterialKey::EMISSIVE_MAP_BIT: From b1b6533295ca48b55bd5979c84fd66239452e47e Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 5 Feb 2019 18:01:41 -0800 Subject: [PATCH 044/139] Restore clear --- .../display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 44110b2c99..ffd51cd61f 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -510,7 +510,7 @@ void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::Textur batch.enableStereo(false); batch.resetViewTransform(); batch.setFramebuffer(fbo); -// batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); batch.setStateScissorRect(scissor); batch.setViewportTransform(viewport); batch.setResourceTexture(0, texture); From bc11d80a52b9728b0a5a0cab24b1b037744c50d2 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Tue, 5 Feb 2019 23:07:57 -0800 Subject: [PATCH 045/139] fix create selectionBox wireframe --- interface/src/ui/overlays/Overlays.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 2580104d94..150fa22cd5 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -351,7 +351,7 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove return "none"; }); - if (type == "Shape" || type == "Gizmo") { + if (type == "Shape" || type == "Box" || type == "Sphere" || type == "Gizmo") { RENAME_PROP(solid, isSolid); RENAME_PROP(isFilled, isSolid); RENAME_PROP(filled, isSolid); @@ -1967,4 +1967,4 @@ QVector Overlays::findOverlays(const glm::vec3& center, float radius) { * outwards from the inner radius; a negative value draws tick marks inwards from the outer radius. * @property {Color} majorTickMarksColor = 0, 0, 0 - The color of the major tick marks. * @property {Color} minorTickMarksColor = 0, 0, 0 - The color of the minor tick marks. - */ \ No newline at end of file + */ From 35491bf5b0e074cbb0bd39268ccd39cba3583e95 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 6 Feb 2019 00:05:17 -0800 Subject: [PATCH 046/139] Multisampling works in 4.1 --- .../gpu-gl-common/src/gpu/gl/GLTexture.cpp | 13 ++++--- .../gpu-gl/src/gpu/gl41/GL41BackendOutput.cpp | 4 +++ .../src/gpu/gl41/GL41BackendTexture.cpp | 28 ++++++++++----- .../render-utils/src/ToneMappingEffect.cpp | 2 +- .../render-utils/src/ToneMappingEffect.h | 6 ++-- .../utilities/lib/plotperf/Color.qml | 1 + .../utilities/render/deferredLighting.qml | 35 +++++-------------- 7 files changed, 46 insertions(+), 43 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLTexture.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLTexture.cpp index c8d6dbfdf0..082edd47bc 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLTexture.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLTexture.cpp @@ -106,15 +106,20 @@ const std::vector& GLTexture::getFaceTargets(GLenum target) { GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; - static const std::vector faceTargets { + static const std::vector face2DTargets { GL_TEXTURE_2D }; - static const std::vector arrayFaceTargets{ + static const std::vector face2DMSTargets{ + GL_TEXTURE_2D_MULTISAMPLE + }; + static const std::vector arrayFaceTargets{ GL_TEXTURE_2D_ARRAY }; switch (target) { case GL_TEXTURE_2D: - return faceTargets; + return face2DTargets; + case GL_TEXTURE_2D_MULTISAMPLE: + return face2DMSTargets; case GL_TEXTURE_2D_ARRAY: return arrayFaceTargets; case GL_TEXTURE_CUBE_MAP: @@ -124,7 +129,7 @@ const std::vector& GLTexture::getFaceTargets(GLenum target) { break; } Q_UNREACHABLE(); - return faceTargets; + return face2DTargets; } GLTexture::GLTexture(const std::weak_ptr& backend, const Texture& texture, GLuint id) : diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendOutput.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendOutput.cpp index 1d512103bd..0f50b0724e 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendOutput.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendOutput.cpp @@ -66,6 +66,8 @@ public: if (gltexture) { if (gltexture->_target == GL_TEXTURE_2D) { glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[unit], GL_TEXTURE_2D, gltexture->_texture, 0); + } else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) { + glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[unit], GL_TEXTURE_2D_MULTISAMPLE, gltexture->_texture, 0); } else { glFramebufferTextureLayer(GL_FRAMEBUFFER, colorAttachments[unit], gltexture->_texture, 0, b._subresource); @@ -98,6 +100,8 @@ public: if (gltexture) { if (gltexture->_target == GL_TEXTURE_2D) { glFramebufferTexture2D(GL_FRAMEBUFFER, attachement, GL_TEXTURE_2D, gltexture->_texture, 0); + } else if (gltexture->_target == GL_TEXTURE_2D_MULTISAMPLE) { + glFramebufferTexture2D(GL_FRAMEBUFFER, attachement, GL_TEXTURE_2D_MULTISAMPLE, gltexture->_texture, 0); } else { glFramebufferTextureLayer(GL_FRAMEBUFFER, attachement, gltexture->_texture, 0, _gpuObject.getDepthStencilBufferSubresource()); diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index 4068865274..f47211555a 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -216,19 +216,29 @@ void GL41FixedAllocationTexture::allocateStorage() const { const GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat()); const auto numMips = _gpuObject.getNumMips(); const auto numSlices = _gpuObject.getNumSlices(); + const auto numSamples = _gpuObject.getNumSamples(); // glTextureStorage2D(_id, mips, texelFormat.internalFormat, dimensions.x, dimensions.y); - for (GLint level = 0; level < numMips; level++) { - Vec3u dimensions = _gpuObject.evalMipDimensions(level); - for (GLenum target : getFaceTargets(_target)) { - if (!_gpuObject.isArray()) { - glTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, - texelFormat.type, nullptr); - } else { - glTexImage3D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, numSlices, 0, - texelFormat.format, texelFormat.type, nullptr); + if (!_gpuObject.isMultisample()) { + for (GLint level = 0; level < numMips; level++) { + Vec3u dimensions = _gpuObject.evalMipDimensions(level); + for (GLenum target : getFaceTargets(_target)) { + if (!_gpuObject.isArray()) { + glTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, + texelFormat.type, nullptr); + } else { + glTexImage3D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, numSlices, 0, + texelFormat.format, texelFormat.type, nullptr); + } } } + } else { + const auto dimensions = _gpuObject.getDimensions(); + if (!_gpuObject.isArray()) { + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, texelFormat.internalFormat, dimensions.x, dimensions.y, GL_FALSE); + } else { + glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, numSamples, texelFormat.internalFormat, dimensions.x, dimensions.y, dimensions.z, GL_FALSE); + } } glTexParameteri(_target, GL_TEXTURE_BASE_LEVEL, 0); diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index c40505917c..c631ae4383 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -84,7 +84,7 @@ void ToneMappingEffect::render(RenderArgs* args, const gpu::TexturePointer& ligh void ToneMappingDeferred::configure(const Config& config) { _toneMappingEffect.setExposure(config.exposure); - _toneMappingEffect.setColorFilter(config.colorFilter); + _toneMappingEffect.setColorFilter(toGlm(config.colorFilter)); _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)config.curve); } diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index ae394c4dc3..163805ae91 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -70,18 +70,18 @@ private: class ToneMappingConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(float exposure MEMBER exposure WRITE setExposure); - Q_PROPERTY(glm::vec3 colorFilter MEMBER colorFilter WRITE setColorFilter); + Q_PROPERTY(QColor colorFilter MEMBER colorFilter WRITE setColorFilter); Q_PROPERTY(int curve MEMBER curve WRITE setCurve); public: ToneMappingConfig() : render::Job::Config(true) {} void setExposure(float newExposure) { exposure = newExposure; emit dirty(); } - void setColorFilter(const glm::vec3& newColorFilter) { colorFilter = newColorFilter; emit dirty(); } + void setColorFilter(const QColor& newColorFilter) { colorFilter = newColorFilter; emit dirty(); } void setCurve(int newCurve) { curve = std::max((int)ToneMappingEffect::None, std::min((int)ToneMappingEffect::Filmic, newCurve)); emit dirty(); } float exposure{ 0.0f }; - glm::vec3 colorFilter { 1.0f }; + QColor colorFilter { 255, 255, 255 }; int curve{ ToneMappingEffect::None }; signals: void dirty(); diff --git a/scripts/developer/utilities/lib/plotperf/Color.qml b/scripts/developer/utilities/lib/plotperf/Color.qml index 1ad72fe2e6..64a3980947 100644 --- a/scripts/developer/utilities/lib/plotperf/Color.qml +++ b/scripts/developer/utilities/lib/plotperf/Color.qml @@ -23,6 +23,7 @@ Item { height: 24 property var _color: Qt.rgba(1.0, 1.0, 1.0, 1.0 ); + property var _lcolor: Qt.vec4(1.0, 1.0, 1.0, 1.0 ); property var zoneWidth: width / 3; property var hoveredOn: 0.0; property var sliderHeight: height / 2; diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 8c3e0fce94..d3cc7adca3 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -124,22 +124,6 @@ Rectangle { anchors.right: parent.right } } - Item { - HifiControls.Label { - text: "Color filter" - anchors.left: parent.left - } - - Color { - height: 20 - anchors.right: parent.right - width: parent.width / 2 - _color: render.mainViewTask.getConfig("ToneMapping")["colorFilter"] - onNewColor: { - render.mainViewTask.getConfig("ToneMapping")["colorFilter"] = getXColor() - } - } - } Item { height: childrenRect.height anchors.left: parent.left @@ -150,18 +134,17 @@ Rectangle { anchors.left: parent.left } - HifiControls.ComboBox { + ComboBox { anchors.right: parent.right currentIndex: 1 - model: ListModel { - id: cbItems - ListElement { text: "RGB"; color: "Yellow" } - ListElement { text: "SRGB"; color: "Green" } - ListElement { text: "Reinhard"; color: "Yellow" } - ListElement { text: "Filmic"; color: "White" } - } + model: [ + "RGB", + "SRGB", + "Reinhard", + "Filmic", + ] width: 200 - onCurrentIndexChanged: { render.mainViewTask.getConfig("ToneMapping")["curve"] = currentIndex } + onCurrentIndexChanged: { render.mainViewTask.getConfig("ToneMapping")["curve"] = currentIndex; } } } } @@ -186,7 +169,7 @@ Rectangle { framebuffer.config.mode = mode; } - HifiControls.ComboBox { + ComboBox { anchors.right: parent.right currentIndex: 0 model: ListModel { From a2da59271df5a90fe47896cb0f80718b758b83b0 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 6 Feb 2019 11:38:48 -0800 Subject: [PATCH 047/139] If sorting PAL by loudness re-sort upon loudness updates --- interface/resources/qml/hifi/Pal.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index b7b412b577..9fe5ac3ac2 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -1247,6 +1247,9 @@ Rectangle { } } } + if (nearbyTable.sortIndicatorColumn == 0) { // Current sort by loudness so re-sort. + sortModel(); + } break; case 'clearLocalQMLData': ignored = {}; From 91937041731f2908df99afffccace23db729189b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 5 Feb 2019 18:27:27 -0800 Subject: [PATCH 048/139] trying to get hashes working --- .../src/model-networking/MaterialCache.cpp | 2 +- .../src/model-networking/ModelCache.cpp | 50 +++++++++++++++++-- .../src/model-networking/ShaderCache.cpp | 2 +- .../src/model-networking/TextureCache.cpp | 22 +++++++- libraries/networking/src/ResourceCache.cpp | 24 ++++----- libraries/networking/src/ResourceCache.h | 19 +++---- 6 files changed, 89 insertions(+), 30 deletions(-) diff --git a/libraries/model-networking/src/model-networking/MaterialCache.cpp b/libraries/model-networking/src/model-networking/MaterialCache.cpp index 7dcd7b8a61..aaa9767397 100644 --- a/libraries/model-networking/src/model-networking/MaterialCache.cpp +++ b/libraries/model-networking/src/model-networking/MaterialCache.cpp @@ -417,7 +417,7 @@ MaterialCache& MaterialCache::instance() { } NetworkMaterialResourcePointer MaterialCache::getMaterial(const QUrl& url) { - return ResourceCache::getResource(url, QUrl()).staticCast(); + return ResourceCache::getResource(url).staticCast(); } QSharedPointer MaterialCache::createResource(const QUrl& url) { diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 7515dad256..1535f5cfad 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -40,6 +40,50 @@ public: bool combineParts; }; +// From: https://stackoverflow.com/questions/41145012/how-to-hash-qvariant +class QVariantHasher { +public: + QVariantHasher() : buff(&bb), ds(&buff) { + bb.reserve(1000); + buff.open(QIODevice::WriteOnly); + } + uint hash(const QVariant& v) { + buff.seek(0); + ds << v; + return qHashBits(bb.constData(), buff.pos()); + } +private: + QByteArray bb; + QBuffer buff; + QDataStream ds; +}; + +namespace std { + template <> + struct hash { + size_t operator()(const QVariantHash& a) const { + QVariantHasher hasher; + return hasher.hash(a); + } + }; + + template <> + struct hash { + size_t operator()(const QUrl& a) const { + return qHash(a); + } + }; + + template <> + struct hash { + size_t operator()(const GeometryExtra& a) const { + size_t result = 0; + hash_combine(result, a.mapping, a.textureBaseUrl, a.combineParts); + return result; + } + }; +} + QUrl resolveTextureBaseUrl(const QUrl& url, const QUrl& textureBaseUrl) { return textureBaseUrl.isValid() ? textureBaseUrl : url; } @@ -110,7 +154,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { GeometryExtra extra { _mapping, _textureBaseUrl, false }; // Get the raw GeometryResource - _geometryResource = modelCache->getResource(url, QUrl(), &extra).staticCast(); + _geometryResource = modelCache->getResource(url, QUrl(), &extra, std::hash()(extra)).staticCast(); // Avoid caching nested resources - their references will be held by the parent _geometryResource->_isCacheable = false; @@ -355,7 +399,7 @@ GeometryResource::Pointer ModelCache::getGeometryResource(const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl) { bool combineParts = true; GeometryExtra geometryExtra = { mapping, textureBaseUrl, combineParts }; - GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra).staticCast(); + GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra, std::hash()(geometryExtra)).staticCast(); if (resource) { if (resource->isLoaded() && resource->shouldSetTextures()) { resource->setTextures(); @@ -368,7 +412,7 @@ GeometryResource::Pointer ModelCache::getCollisionGeometryResource(const QUrl& u const QVariantHash& mapping, const QUrl& textureBaseUrl) { bool combineParts = false; GeometryExtra geometryExtra = { mapping, textureBaseUrl, combineParts }; - GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra).staticCast(); + GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra, std::hash()(geometryExtra)).staticCast(); if (resource) { if (resource->isLoaded() && resource->shouldSetTextures()) { resource->setTextures(); diff --git a/libraries/model-networking/src/model-networking/ShaderCache.cpp b/libraries/model-networking/src/model-networking/ShaderCache.cpp index b774ca36c5..8d060c42f2 100644 --- a/libraries/model-networking/src/model-networking/ShaderCache.cpp +++ b/libraries/model-networking/src/model-networking/ShaderCache.cpp @@ -21,7 +21,7 @@ ShaderCache& ShaderCache::instance() { } NetworkShaderPointer ShaderCache::getShader(const QUrl& url) { - return ResourceCache::getResource(url, QUrl()).staticCast(); + return ResourceCache::getResource(url).staticCast(); } QSharedPointer ShaderCache::createResource(const QUrl& url) { diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 2f29eaf385..910de258f9 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -194,10 +194,28 @@ public: int maxNumPixels; }; +namespace std { + template <> + struct hash { + size_t operator()(const QByteArray& a) const { + return qHash(a); + } + }; + + template <> + struct hash { + size_t operator()(const TextureExtra& a) const { + size_t result = 0; + hash_combine(result, (int)a.type, a.content, a.maxNumPixels); + return result; + } + }; +} + ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels) { auto byteArray = QByteArray(); TextureExtra extra = { (image::TextureUsage::Type)type, byteArray, maxNumPixels }; - return ResourceCache::prefetch(url, &extra); + return ResourceCache::prefetch(url, &extra, std::hash()(extra)); } NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) { @@ -211,7 +229,7 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUs modifiedUrl.setQuery(query.toString()); } TextureExtra extra = { type, content, maxNumPixels }; - return ResourceCache::getResource(modifiedUrl, QUrl(), &extra).staticCast(); + return ResourceCache::getResource(modifiedUrl, QUrl(), &extra, std::hash()(extra)).staticCast(); } gpu::TexturePointer TextureCache::getTextureByHash(const std::string& hash) { diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 43fc93ffc5..cb7b8c7c82 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -158,8 +158,8 @@ void ScriptableResourceCache::updateTotalSize(const qint64& deltaSize) { _resourceCache->updateTotalSize(deltaSize); } -ScriptableResource* ScriptableResourceCache::prefetch(const QUrl& url, void* extra) { - return _resourceCache->prefetch(url, extra); +ScriptableResource* ScriptableResourceCache::prefetch(const QUrl& url, void* extra, size_t extraHash) { + return _resourceCache->prefetch(url, extra, extraHash); } @@ -211,20 +211,20 @@ void ScriptableResource::disconnectHelper() { } } -ScriptableResource* ResourceCache::prefetch(const QUrl& url, void* extra) { +ScriptableResource* ResourceCache::prefetch(const QUrl& url, void* extra, size_t extraHash) { ScriptableResource* result = nullptr; if (QThread::currentThread() != thread()) { // Must be called in thread to ensure getResource returns a valid pointer BLOCKING_INVOKE_METHOD(this, "prefetch", Q_RETURN_ARG(ScriptableResource*, result), - Q_ARG(QUrl, url), Q_ARG(void*, extra)); + Q_ARG(QUrl, url), Q_ARG(void*, extra), Q_ARG(size_t, extraHash)); return result; } result = new ScriptableResource(url); - auto resource = getResource(url, QUrl(), extra); + auto resource = getResource(url, QUrl(), extra, extraHash); result->_resource = resource; result->setObjectName(url.toString()); @@ -298,7 +298,7 @@ void ResourceCache::refreshAll() { clearUnusedResources(); resetUnusedResourceCounter(); - QHash>> allResources; + QHash>> allResources; { QReadLocker locker(&_resourcesLock); allResources = _resources; @@ -343,13 +343,8 @@ void ResourceCache::setRequestLimit(uint32_t limit) { } } -QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& fallback, void* extra, int extraHash) { +QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& fallback, void* extra, size_t extraHash) { QSharedPointer resource; - if (extra && extraHash < 0) { - qDebug() << "ResourceCache::getResource: ERROR! Non-null extra, but invalid extraHash"; - return resource; - } - { QReadLocker locker(&_resourcesLock); auto& resourcesWithExtraHash = _resources[url]; @@ -553,8 +548,8 @@ bool ResourceCache::attemptHighestPriorityRequest() { static int requestID = 0; Resource::Resource(const Resource& other) : + QObject(), _url(other._url), - _extraHash(other._extraHash), _effectiveBaseURL(other._effectiveBaseURL), _activeUrl(other._activeUrl), _requestByteRange(other._requestByteRange), @@ -566,7 +561,8 @@ Resource::Resource(const Resource& other) : _bytesReceived(other._bytesReceived), _bytesTotal(other._bytesTotal), _bytes(other._bytes), - _requestID(++requestID) { + _requestID(++requestID), + _extraHash(other._extraHash) { if (!other._loaded) { _startedLoading = false; } diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index dd60e3c110..740bdadc48 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -231,15 +231,16 @@ protected slots: // Prefetches a resource to be held by the QScriptEngine. // Left as a protected member so subclasses can overload prefetch // and delegate to it (see TextureCache::prefetch(const QUrl&, int). - ScriptableResource* prefetch(const QUrl& url, void* extra); + ScriptableResource* prefetch(const QUrl& url, void* extra, size_t extraHash); // FIXME: The return type is not recognized by JavaScript. /// Loads a resource from the specified URL and returns it. /// If the caller is on a different thread than the ResourceCache, /// returns an empty smart pointer and loads its asynchronously. /// \param fallback a fallback URL to load if the desired one is unavailable - /// \param extra extra data to pass to the creator, if appropriate - QSharedPointer getResource(const QUrl& url, const QUrl& fallback = QUrl(), void* extra = NULL, int extraHash = -1); + // FIXME: std::numeric_limits::max() could be a valid extraHash + QSharedPointer getResource(const QUrl& url, const QUrl& fallback = QUrl()) { return getResource(url, fallback, nullptr, std::numeric_limits::max()); } + QSharedPointer getResource(const QUrl& url, const QUrl& fallback, void* extra, size_t extraHash); private slots: void clearATPAssets(); @@ -250,7 +251,7 @@ protected: // which should be a QScriptEngine with ScriptableResource registered, so that // the QScriptEngine will delete the pointer when it is garbage collected. // JSDoc is provided on more general function signature. - Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr); } + Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr, std::numeric_limits::max()); } /// Creates a new resource. virtual QSharedPointer createResource(const QUrl& url) = 0; @@ -277,7 +278,7 @@ private: void resetResourceCounters(); // Resources - QHash>> _resources; + QHash>> _resources; QReadWriteLock _resourcesLock { QReadWriteLock::Recursive }; int _lastLRUKey = 0; @@ -331,10 +332,10 @@ public: * Prefetches a resource. * @function ResourceCache.prefetch * @param {string} url - URL of the resource to prefetch. - * @param {object} [extra=null] * @returns {ResourceObject} */ - Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, void* extra = nullptr); + Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url) { return prefetch(url, nullptr, std::numeric_limits::max()); } + Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, void* extra, size_t extraHash); signals: @@ -416,7 +417,7 @@ public: unsigned int getDownloadAttemptsRemaining() { return _attemptsRemaining; } virtual void setExtra(void* extra) {}; - void setExtraHash(int extraHash) { _extraHash = extraHash; } + void setExtraHash(size_t extraHash) { _extraHash = extraHash; } signals: /// Fired when the resource begins downloading. @@ -495,7 +496,7 @@ protected: int _requestID; ResourceRequest* _request{ nullptr }; - int _extraHash { -1 }; + size_t _extraHash; public slots: void handleDownloadProgress(uint64_t bytesReceived, uint64_t bytesTotal); From 58d8945aa5df46978147dfdbec80106310e5d92d Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 6 Feb 2019 14:41:27 -0800 Subject: [PATCH 049/139] Limit re-sort rate to 2 Hz. --- interface/resources/qml/hifi/Pal.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 9fe5ac3ac2..92c608fa3c 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -42,6 +42,8 @@ Rectangle { property var activeTab: "nearbyTab"; property bool currentlyEditingDisplayName: false property bool punctuationMode: false; + property double loudSortTime: 0.0; + readonly property double kLOUD_SORT_PERIOD_MS: 500.0; HifiConstants { id: hifi; } RootHttpRequest { id: http; } @@ -1247,8 +1249,10 @@ Rectangle { } } } - if (nearbyTable.sortIndicatorColumn == 0) { // Current sort by loudness so re-sort. + if (nearbyTable.sortIndicatorColumn == 0 && Date.now() - pal.loudSortTime >= pal.kLOUD_SORT_PERIOD_MS) { + // Current sort by loudness so re-sort. sortModel(); + pal.loudSortTime = Date.now(); } break; case 'clearLocalQMLData': From b1e7c3d4fd770f04450feae1dea54d1999598854 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 6 Feb 2019 16:04:40 -0800 Subject: [PATCH 050/139] allow negative dimensions for planar overlays via HACK, set default texture for line overlays to white pixel --- interface/resources/images/whitePixel.png | Bin 0 -> 155 bytes interface/src/ui/overlays/Overlays.cpp | 66 +++++++++++++++++++++- interface/src/ui/overlays/Overlays.h | 3 +- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 interface/resources/images/whitePixel.png diff --git a/interface/resources/images/whitePixel.png b/interface/resources/images/whitePixel.png new file mode 100644 index 0000000000000000000000000000000000000000..fe2ec44cb704a92cedd8ffd53be63b92b34a2a75 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0y~yU|O>_%)r2R7=#&*=dVa%U|^6aag8Vm&QB{TPb^AhC`ioAE78kK zEm1JhGt@IpagP95!{h1V7$Om#{Nw+Bdj{5jO#hafHnuP@Ffe$!`njxgN@xNA#_B0L literal 0 HcmV?d00001 diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 150fa22cd5..8a0f3cfd8b 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -301,7 +301,14 @@ QString Overlays::overlayToEntityType(const QString& type) { } \ } +static QHash savedRotations = QHash(); + EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id) { + glm::quat rotation; + return convertOverlayToEntityProperties(overlayProps, rotation, type, add, id); +} + +EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& overlayProps, glm::quat& rotationToSave, const QString& type, bool add, const QUuid& id) { overlayProps["type"] = type; SET_OVERLAY_PROP_DEFAULT(alpha, 0.7); @@ -541,6 +548,58 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove normals.append(vec3toVariant(Vectors::UP)); SET_OVERLAY_PROP_DEFAULT(normals, normals); } + + SET_OVERLAY_PROP_DEFAULT(textures, PathUtils::resourcesUrl() + "images/whitePixel.png"); + } + + if (type == "Text" || type == "Image" || type == "Grid" || type == "Web") { + glm::quat originalRotation = ENTITY_ITEM_DEFAULT_ROTATION; + { + auto iter = overlayProps.find("rotation"); + if (iter != overlayProps.end()) { + originalRotation = quatFromVariant(iter.value()); + } else { + iter = overlayProps.find("localRotation"); + if (iter != overlayProps.end()) { + originalRotation = quatFromVariant(iter.value()); + } else if (!add) { + auto iter2 = savedRotations.find(id); + if (iter2 != savedRotations.end()) { + originalRotation = iter2.value(); + } + } + } + } + + if (!add) { + savedRotations[id] = originalRotation; + } else { + rotationToSave = originalRotation; + } + + glm::vec3 dimensions = ENTITY_ITEM_DEFAULT_DIMENSIONS; + { + auto iter = overlayProps.find("dimensions"); + if (iter != overlayProps.end()) { + dimensions = vec3FromVariant(iter.value()); + } + } + + bool rotateX = dimensions.y < 0.0f; + bool rotateY = dimensions.x < 0.0f; + + { + glm::quat rotation = originalRotation; + if (rotateX) { + rotation = glm::angleAxis((float)M_PI, rotation * Vectors::RIGHT) * rotation; + } + if (rotateY) { + rotation = glm::angleAxis((float)M_PI, rotation * Vectors::UP) * rotation; + } + + overlayProps["localRotation"] = quatToVariant(rotation); + overlayProps["dimensions"] = vec3toVariant(glm::abs(dimensions)); + } } QScriptEngine scriptEngine; @@ -714,7 +773,12 @@ QUuid Overlays::addOverlay(const QString& type, const QVariant& properties) { if (type == "rectangle3d") { propertyMap["shape"] = "Quad"; } - return DependencyManager::get()->addEntityInternal(convertOverlayToEntityProperties(propertyMap, entityType, true), entity::HostType::LOCAL); + glm::quat rotationToSave; + QUuid id = DependencyManager::get()->addEntityInternal(convertOverlayToEntityProperties(propertyMap, rotationToSave, entityType, true), entity::HostType::LOCAL); + if (entityType == "Text" || entityType == "Image" || entityType == "Grid" || entityType == "Web") { + savedRotations[id] = rotationToSave; + } + return id; } QUuid Overlays::add2DOverlay(const Overlay::Pointer& overlay) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 5a5e845a66..6e88397967 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -728,7 +728,8 @@ private: static std::unordered_map _overlayToEntityTypes; QVariantMap convertEntityToOverlayProperties(const EntityItemProperties& entityProps); - EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id = QUuid()); + EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, const QString& type, bool add, const QUuid& id); + EntityItemProperties convertOverlayToEntityProperties(QVariantMap& overlayProps, glm::quat& rotationToSave, const QString& type, bool add, const QUuid& id = QUuid()); private slots: void mousePressPointerEvent(const QUuid& id, const PointerEvent& event); From a665664fd5dd022d998325dda766f39662fab5ad Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 6 Feb 2019 16:13:40 -0800 Subject: [PATCH 051/139] fix double lasers --- interface/src/Application.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fea58f558c..78e7b611bc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6173,6 +6173,19 @@ void Application::update(float deltaTime) { auto grabManager = DependencyManager::get(); grabManager->simulateGrabs(); + // TODO: break these out into distinct perfTimers when they prove interesting + { + PROFILE_RANGE(app, "PickManager"); + PerformanceTimer perfTimer("pickManager"); + DependencyManager::get()->update(); + } + + { + PROFILE_RANGE(app, "PointerManager"); + PerformanceTimer perfTimer("pointerManager"); + DependencyManager::get()->update(); + } + QSharedPointer avatarManager = DependencyManager::get(); { @@ -6325,19 +6338,6 @@ void Application::update(float deltaTime) { updateLoginDialogPosition(); } - // TODO: break these out into distinct perfTimers when they prove interesting - { - PROFILE_RANGE(app, "PickManager"); - PerformanceTimer perfTimer("pickManager"); - DependencyManager::get()->update(); - } - - { - PROFILE_RANGE(app, "PointerManager"); - PerformanceTimer perfTimer("pointerManager"); - DependencyManager::get()->update(); - } - { PROFILE_RANGE_EX(app, "Overlays", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); PerformanceTimer perfTimer("overlays"); From e601f6c59f798c1730fe24c54abc27842e451b6b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 7 Feb 2019 14:10:09 -0800 Subject: [PATCH 052/139] move material mapping to hfm prep step --- libraries/fbx/src/FBXSerializer.cpp | 2 +- libraries/fbx/src/FBXSerializer.h | 2 +- libraries/fbx/src/FBXSerializer_Material.cpp | 27 +-------- .../model-baker/ApplyMaterialMappingTask.cpp | 55 +++++++++++++++++++ .../model-baker/ApplyMaterialMappingTask.h | 27 +++++++++ .../model-baker/src/model-baker/Baker.cpp | 10 +++- 6 files changed, 93 insertions(+), 30 deletions(-) create mode 100644 libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp create mode 100644 libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.h diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index 207ee2982d..9e7f422b40 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -1326,7 +1326,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr hfmModel.meshExtents.reset(); // Create the Material Library - consolidateHFMMaterials(mapping); + consolidateHFMMaterials(); // We can't allow the scaling of a given image to different sizes, because the hash used for the KTX cache is based on the original image // Allowing scaling of the same image to different sizes would cause different KTX files to target the same cache key diff --git a/libraries/fbx/src/FBXSerializer.h b/libraries/fbx/src/FBXSerializer.h index b95bb729e7..379b1ac743 100644 --- a/libraries/fbx/src/FBXSerializer.h +++ b/libraries/fbx/src/FBXSerializer.h @@ -153,7 +153,7 @@ public: QHash _hfmMaterials; QHash _materialParams; - void consolidateHFMMaterials(const QVariantHash& mapping); + void consolidateHFMMaterials(); bool _loadLightmaps { true }; float _lightmapOffset { 0.0f }; diff --git a/libraries/fbx/src/FBXSerializer_Material.cpp b/libraries/fbx/src/FBXSerializer_Material.cpp index 9caf713e75..b47329e483 100644 --- a/libraries/fbx/src/FBXSerializer_Material.cpp +++ b/libraries/fbx/src/FBXSerializer_Material.cpp @@ -75,15 +75,7 @@ HFMTexture FBXSerializer::getTexture(const QString& textureID, const QString& ma return texture; } -void FBXSerializer::consolidateHFMMaterials(const QVariantHash& mapping) { - QJsonObject materialMap; - if (mapping.contains("materialMap")) { - QByteArray materialMapValue = mapping.value("materialMap").toByteArray(); - materialMap = QJsonDocument::fromJson(materialMapValue).object(); - if (materialMap.isEmpty()) { - qCDebug(modelformat) << "fbx Material Map found but did not produce valid JSON:" << materialMapValue; - } - } +void FBXSerializer::consolidateHFMMaterials() { for (QHash::iterator it = _hfmMaterials.begin(); it != _hfmMaterials.end(); it++) { HFMMaterial& material = (*it); @@ -266,23 +258,6 @@ void FBXSerializer::consolidateHFMMaterials(const QVariantHash& mapping) { } qCDebug(modelformat) << " fbx material Name:" << material.name; - if (materialMap.contains(material.name)) { - QJsonObject materialOptions = materialMap.value(material.name).toObject(); - qCDebug(modelformat) << "Mapping fbx material:" << material.name << " with HifiMaterial: " << materialOptions; - - if (materialOptions.contains("scattering")) { - float scattering = (float) materialOptions.value("scattering").toDouble(); - material._material->setScattering(scattering); - } - - if (materialOptions.contains("scatteringMap")) { - QByteArray scatteringMap = materialOptions.value("scatteringMap").toVariant().toByteArray(); - material.scatteringTexture = HFMTexture(); - material.scatteringTexture.name = material.name + ".scatteringMap"; - material.scatteringTexture.filename = scatteringMap; - } - } - if (material.opacity <= 0.0f) { material._material->setOpacity(1.0f); } else { diff --git a/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp b/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp new file mode 100644 index 0000000000..c9b4fec1e1 --- /dev/null +++ b/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp @@ -0,0 +1,55 @@ +// +// Created by Sam Gondelman on 2/7/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ApplyMaterialMappingTask.h" + +#include "ModelBakerLogging.h" + +void ApplyMaterialMappingTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) { + const auto& materialsIn = input.get0(); + const auto& mapping = input.get1(); + + auto materialsOut = materialsIn; + + auto mappingIter = mapping.find("materialMap"); + if (mappingIter != mapping.end()) { + QByteArray materialMapValue = mappingIter.value().toByteArray(); + QJsonObject materialMap = QJsonDocument::fromJson(materialMapValue).object(); + if (materialMap.isEmpty()) { + qCDebug(model_baker) << "Material Map found but did not produce valid JSON:" << materialMapValue; + } else { + for (auto& material : materialsOut) { + auto materialMapIter = materialMap.find(material.name); + if (materialMapIter != materialMap.end()) { + QJsonObject materialOptions = materialMapIter.value().toObject(); + qCDebug(model_baker) << "Mapping material:" << material.name << " with HFMaterial: " << materialOptions; + + { + auto scatteringIter = materialOptions.find("scattering"); + if (scatteringIter != materialOptions.end()) { + float scattering = (float)scatteringIter.value().toDouble(); + material._material->setScattering(scattering); + } + } + + { + auto scatteringMapIter = materialOptions.find("scatteringMap"); + if (scatteringMapIter != materialOptions.end()) { + QByteArray scatteringMap = scatteringMapIter.value().toVariant().toByteArray(); + material.scatteringTexture = HFMTexture(); + material.scatteringTexture.name = material.name + ".scatteringMap"; + material.scatteringTexture.filename = scatteringMap; + } + } + } + } + } + } + + output = materialsOut; +} diff --git a/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.h b/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.h new file mode 100644 index 0000000000..271c80fe67 --- /dev/null +++ b/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.h @@ -0,0 +1,27 @@ +// +// Created by Sam Gondelman on 2/7/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ApplyMaterialMappingTask_h +#define hifi_ApplyMaterialMappingTask_h + +#include + +#include + +#include "Engine.h" + +class ApplyMaterialMappingTask { +public: + using Input = baker::VaryingSet2, QVariantHash>; + using Output = QHash; + using JobModel = baker::Job::ModelIO; + + void run(const baker::BakeContextPointer& context, const Input& input, Output& output); +}; + +#endif // hifi_ApplyMaterialMappingTask_h \ No newline at end of file diff --git a/libraries/model-baker/src/model-baker/Baker.cpp b/libraries/model-baker/src/model-baker/Baker.cpp index 1c2a2f5c63..981d799f12 100644 --- a/libraries/model-baker/src/model-baker/Baker.cpp +++ b/libraries/model-baker/src/model-baker/Baker.cpp @@ -20,6 +20,7 @@ #include "CalculateBlendshapeNormalsTask.h" #include "CalculateBlendshapeTangentsTask.h" #include "PrepareJointsTask.h" +#include "ApplyMaterialMappingTask.h" namespace baker { @@ -101,7 +102,7 @@ namespace baker { class BuildModelTask { public: - using Input = VaryingSet5, std::vector, QMap /*jointRotationOffsets*/, QHash /*jointIndices*/>; + using Input = VaryingSet6, std::vector, QMap, QHash, QHash>; using Output = hfm::Model::Pointer; using JobModel = Job::ModelIO; @@ -111,6 +112,7 @@ namespace baker { hfmModelOut->joints = QVector::fromStdVector(input.get2()); hfmModelOut->jointRotationOffsets = input.get3(); hfmModelOut->jointIndices = input.get4(); + hfmModelOut->materials = input.get5(); output = hfmModelOut; } }; @@ -154,12 +156,16 @@ namespace baker { const auto jointRotationOffsets = jointInfoOut.getN(1); const auto jointIndices = jointInfoOut.getN(2); + // Apply material mapping + const auto materialMappingInputs = ApplyMaterialMappingTask::Input(materials, mapping).asVarying(); + const auto materialsOut = model.addJob("ApplyMaterialMapping", materialMappingInputs); + // Combine the outputs into a new hfm::Model const auto buildBlendshapesInputs = BuildBlendshapesTask::Input(blendshapesPerMeshIn, normalsPerBlendshapePerMesh, tangentsPerBlendshapePerMesh).asVarying(); const auto blendshapesPerMeshOut = model.addJob("BuildBlendshapes", buildBlendshapesInputs); const auto buildMeshesInputs = BuildMeshesTask::Input(meshesIn, graphicsMeshes, normalsPerMesh, tangentsPerMesh, blendshapesPerMeshOut).asVarying(); const auto meshesOut = model.addJob("BuildMeshes", buildMeshesInputs); - const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices).asVarying(); + const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices, materialsOut).asVarying(); hfmModelOut = model.addJob("BuildModel", buildModelInputs); } }; From c217f8d80f8d819fab509ad2fef990e3d8d72583 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 7 Feb 2019 14:23:34 -0800 Subject: [PATCH 053/139] remove overlay picks from stats qml --- interface/resources/qml/Stats.qml | 10 +++++----- interface/src/ui/Stats.cpp | 2 +- interface/src/ui/Stats.h | 16 ++++++++-------- libraries/pointers/src/PickManager.h | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index a65170ee3b..3b703d72e6 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -129,11 +129,11 @@ Item { } StatText { visible: root.expanded - text: "Intersection calls: Entities/Overlays/Avatars/HUD\n " + - "Styluses:\t" + root.stylusPicksUpdated.x + "/" + root.stylusPicksUpdated.y + "/" + root.stylusPicksUpdated.z + "/" + root.stylusPicksUpdated.w + "\n " + - "Rays:\t" + root.rayPicksUpdated.x + "/" + root.rayPicksUpdated.y + "/" + root.rayPicksUpdated.z + "/" + root.rayPicksUpdated.w + "\n " + - "Parabolas:\t" + root.parabolaPicksUpdated.x + "/" + root.parabolaPicksUpdated.y + "/" + root.parabolaPicksUpdated.z + "/" + root.parabolaPicksUpdated.w + "\n " + - "Colliders:\t" + root.collisionPicksUpdated.x + "/" + root.collisionPicksUpdated.y + "/" + root.collisionPicksUpdated.z + "/" + root.collisionPicksUpdated.w + text: "Intersection calls: Entities/Avatars/HUD\n " + + "Styluses:\t" + root.stylusPicksUpdated.x + "/" + root.stylusPicksUpdated.y + "/" + root.stylusPicksUpdated.z + "\n " + + "Rays:\t" + root.rayPicksUpdated.x + "/" + root.rayPicksUpdated.y + "/" + root.rayPicksUpdated.z + "\n " + + "Parabolas:\t" + root.parabolaPicksUpdated.x + "/" + root.parabolaPicksUpdated.y + "/" + root.parabolaPicksUpdated.z + "\n " + + "Colliders:\t" + root.collisionPicksUpdated.x + "/" + root.collisionPicksUpdated.y + "/" + root.collisionPicksUpdated.z } } } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index cb204c9772..e3697ee8ec 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -158,7 +158,7 @@ void Stats::updateStats(bool force) { STAT_UPDATE(rayPicksCount, totalPicks[PickQuery::Ray]); STAT_UPDATE(parabolaPicksCount, totalPicks[PickQuery::Parabola]); STAT_UPDATE(collisionPicksCount, totalPicks[PickQuery::Collision]); - std::vector updatedPicks = pickManager->getUpdatedPickCounts(); + std::vector updatedPicks = pickManager->getUpdatedPickCounts(); STAT_UPDATE(stylusPicksUpdated, updatedPicks[PickQuery::Stylus]); STAT_UPDATE(rayPicksUpdated, updatedPicks[PickQuery::Ray]); STAT_UPDATE(parabolaPicksUpdated, updatedPicks[PickQuery::Parabola]); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index ae608cfddb..20b6ed9919 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -171,10 +171,10 @@ private: \ * @property {number} rayPicksCount - Read-only. * @property {number} parabolaPicksCount - Read-only. * @property {number} collisionPicksCount - Read-only. - * @property {Vec4} stylusPicksUpdated - Read-only. - * @property {Vec4} rayPicksUpdated - Read-only. - * @property {Vec4} parabolaPicksUpdated - Read-only. - * @property {Vec4} collisionPicksUpdated - Read-only. + * @property {Vec3} stylusPicksUpdated - Read-only. + * @property {Vec3} rayPicksUpdated - Read-only. + * @property {Vec3} parabolaPicksUpdated - Read-only. + * @property {Vec3} collisionPicksUpdated - Read-only. */ // Properties from x onwards are QQuickItem properties. @@ -296,10 +296,10 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, rayPicksCount, 0) STATS_PROPERTY(int, parabolaPicksCount, 0) STATS_PROPERTY(int, collisionPicksCount, 0) - STATS_PROPERTY(QVector4D, stylusPicksUpdated, QVector4D(0, 0, 0, 0)) - STATS_PROPERTY(QVector4D, rayPicksUpdated, QVector4D(0, 0, 0, 0)) - STATS_PROPERTY(QVector4D, parabolaPicksUpdated, QVector4D(0, 0, 0, 0)) - STATS_PROPERTY(QVector4D, collisionPicksUpdated, QVector4D(0, 0, 0, 0)) + STATS_PROPERTY(QVector3D, stylusPicksUpdated, QVector3D(0, 0, 0)) + STATS_PROPERTY(QVector3D, rayPicksUpdated, QVector3D(0, 0, 0)) + STATS_PROPERTY(QVector3D, parabolaPicksUpdated, QVector3D(0, 0, 0)) + STATS_PROPERTY(QVector3D, collisionPicksUpdated, QVector3D(0, 0, 0)) public: static Stats* getInstance(); diff --git a/libraries/pointers/src/PickManager.h b/libraries/pointers/src/PickManager.h index 9d5971078d..8f5aa5caf8 100644 --- a/libraries/pointers/src/PickManager.h +++ b/libraries/pointers/src/PickManager.h @@ -61,14 +61,14 @@ public: bool getForceCoarsePicking() { return _forceCoarsePicking; } - const std::vector& getUpdatedPickCounts() { return _updatedPickCounts; } + const std::vector& getUpdatedPickCounts() { return _updatedPickCounts; } const std::vector& getTotalPickCounts() { return _totalPickCounts; } public slots: void setForceCoarsePicking(bool forceCoarsePicking) { _forceCoarsePicking = forceCoarsePicking; } protected: - std::vector _updatedPickCounts { PickQuery::NUM_PICK_TYPES }; + std::vector _updatedPickCounts { PickQuery::NUM_PICK_TYPES }; std::vector _totalPickCounts { 0, 0, 0, 0 }; bool _forceCoarsePicking { false }; From 446176d3a516d81dc100789c04cccc021c2d6aa1 Mon Sep 17 00:00:00 2001 From: raveenajain Date: Thu, 7 Feb 2019 15:08:04 -0800 Subject: [PATCH 054/139] update to parse glb files --- libraries/fbx/src/GLTFSerializer.cpp | 67 +++++++++++++++++++++++++--- libraries/fbx/src/GLTFSerializer.h | 3 ++ 2 files changed, 64 insertions(+), 6 deletions(-) mode change 100644 => 100755 libraries/fbx/src/GLTFSerializer.cpp mode change 100644 => 100755 libraries/fbx/src/GLTFSerializer.h diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp old mode 100644 new mode 100755 index 96c236f703..f2ea16aa31 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -124,6 +124,31 @@ bool GLTFSerializer::getObjectArrayVal(const QJsonObject& object, const QString& return _defined; } +QByteArray GLTFSerializer::setGLBChunks(const QByteArray& data) { + int byte = 4; + int jsonStart = data.indexOf("JSON", Qt::CaseSensitive); + int binStart = data.indexOf("BIN", Qt::CaseSensitive); + int jsonLength, binLength; + QByteArray jsonLengthChunk, binLengthChunk; + + jsonLengthChunk = data.mid(jsonStart - byte, byte); + QDataStream tempJsonLen(jsonLengthChunk); + tempJsonLen.setByteOrder(QDataStream::LittleEndian); + tempJsonLen >> jsonLength; + QByteArray jsonChunk = data.mid(jsonStart + byte, jsonLength); + + if (binStart != -1) { + binLengthChunk = data.mid(binStart - byte, byte); + + QDataStream tempBinLen(binLengthChunk); + tempBinLen.setByteOrder(QDataStream::LittleEndian); + tempBinLen >> binLength; + + _glbBinary = data.mid(binStart + byte, binLength); + } + return jsonChunk; +} + int GLTFSerializer::getMeshPrimitiveRenderingMode(const QString& type) { if (type == "POINTS") { @@ -309,6 +334,14 @@ bool GLTFSerializer::addBuffer(const QJsonObject& object) { GLTFBuffer buffer; getIntVal(object, "byteLength", buffer.byteLength, buffer.defined); + + if (_url.toString().endsWith("glb")) { + if (!_glbBinary.isEmpty()) { + buffer.blob = _glbBinary; + } else { + return false; + } + } if (getStringVal(object, "uri", buffer.uri, buffer.defined)) { if (!readBinary(buffer.uri, buffer.blob)) { return false; @@ -530,9 +563,16 @@ bool GLTFSerializer::addTexture(const QJsonObject& object) { bool GLTFSerializer::parseGLTF(const QByteArray& data) { PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr); - - QJsonDocument d = QJsonDocument::fromJson(data); + + QByteArray jsonChunk = data; + + if (_url.toString().endsWith("glb") && data.indexOf("glTF") == 0 && data.contains("JSON")) { + jsonChunk = setGLBChunks(data); + } + + QJsonDocument d = QJsonDocument::fromJson(jsonChunk); QJsonObject jsFile = d.object(); + bool success = setAsset(jsFile); if (success) { QJsonArray accessors; @@ -904,6 +944,10 @@ MediaType GLTFSerializer::getMediaType() const { MediaType mediaType("gltf"); mediaType.extensions.push_back("gltf"); mediaType.webMediaTypes.push_back("model/gltf+json"); + + mediaType.extensions.push_back("glb"); + mediaType.webMediaTypes.push_back("model/gltf-binary"); + return mediaType; } @@ -912,9 +956,9 @@ std::unique_ptr GLTFSerializer::getFactory() const { } HFMModel::Pointer GLTFSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) { - - _url = url; + _url = url; + // Normalize url for local files QUrl normalizeUrl = DependencyManager::get()->normalizeURL(_url); if (normalizeUrl.scheme().isEmpty() || (normalizeUrl.scheme() == "file")) { @@ -943,7 +987,7 @@ bool GLTFSerializer::readBinary(const QString& url, QByteArray& outdata) { bool success; std::tie(success, outdata) = requestData(binaryUrl); - + return success; } @@ -1003,7 +1047,7 @@ QNetworkReply* GLTFSerializer::request(QUrl& url, bool isTest) { HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) { HFMTexture fbxtex = HFMTexture(); fbxtex.texcoordSet = 0; - + if (texture.defined["source"]) { QString url = _file.images[texture.source].uri; QString fname = QUrl(url).fileName(); @@ -1011,6 +1055,17 @@ HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) { qCDebug(modelformat) << "fname: " << fname; fbxtex.name = fname; fbxtex.filename = textureUrl.toEncoded(); + + if (_url.toString().endsWith("glb") && !_glbBinary.isEmpty()) { + int bufferView = _file.images[texture.source].bufferView; + + GLTFBufferView& imagesBufferview = _file.bufferviews[bufferView]; + int offset = imagesBufferview.byteOffset; + int length = imagesBufferview.byteLength; + + fbxtex.content = _glbBinary.mid(offset, length); + fbxtex.filename = textureUrl.toEncoded().append(texture.source); + } } return fbxtex; } diff --git a/libraries/fbx/src/GLTFSerializer.h b/libraries/fbx/src/GLTFSerializer.h old mode 100644 new mode 100755 index 5fca77c4fd..fe1dea49e0 --- a/libraries/fbx/src/GLTFSerializer.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -709,6 +709,7 @@ public: private: GLTFFile _file; QUrl _url; + QByteArray _glbBinary; glm::mat4 getModelTransform(const GLTFNode& node); @@ -731,6 +732,8 @@ private: QVector& values, QMap& defined); bool getObjectArrayVal(const QJsonObject& object, const QString& fieldname, QJsonArray& objects, QMap& defined); + + QByteArray setGLBChunks(const QByteArray& data); int getMaterialAlphaMode(const QString& type); int getAccessorType(const QString& type); From d3301803d35c91627442757702ed69e8a233389e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 6 Feb 2019 14:28:45 -0800 Subject: [PATCH 055/139] Support custom display / input plugin lists and small tweaks --- CMakeLists.txt | 19 ++++++++++ android/apps/framePlayer/build.gradle | 25 ++++--------- android/apps/questFramePlayer/build.gradle | 24 ++++-------- .../qt5/android/bindings/QtActivity.java | 2 + interface/CMakeLists.txt | 3 ++ .../resources/qml/hifi/avatarapp/Spinner.qml | 1 - interface/src/Application.cpp | 13 ++++++- interface/src/Application.h | 4 ++ .../src/octree/OctreePacketProcessor.cpp | 2 + .../src/display-plugins/DisplayPlugin.cpp | 2 + .../display-plugins/OpenGLDisplayPlugin.cpp | 2 + .../hmd/DebugHmdDisplayPlugin.cpp | 18 ++++----- .../display-plugins/hmd/HmdDisplayPlugin.h | 1 - .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 4 ++ .../gpu-gl-common/src/gpu/gl/GLBackend.h | 2 +- .../src/input-plugins/InputPlugin.cpp | 2 + .../src/OculusMobileControllerManager.cpp | 37 ++++++++++++++++++- .../src/OculusMobileDisplayPlugin.cpp | 2 +- libraries/qml/src/qml/OffscreenSurface.cpp | 15 ++++++++ libraries/qml/src/qml/OffscreenSurface.h | 2 + libraries/ui/src/ui/OffscreenQmlSurface.cpp | 6 ++- plugins/oculus/src/OculusDisplayPlugin.cpp | 4 ++ tools/gpu-frame-player/CMakeLists.txt | 2 +- 23 files changed, 139 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d616e1f3a..12c92182b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,25 @@ if (ANDROID) set(GLES_OPTION ON) set(PLATFORM_QT_COMPONENTS AndroidExtras WebView) add_definitions(-DHIFI_ANDROID_APP=\"${HIFI_ANDROID_APP}\") + if ( + (${HIFI_ANDROID_APP} STREQUAL "questInterface") OR + (${HIFI_ANDROID_APP} STREQUAL "questFramePlayer") OR + (${HIFI_ANDROID_APP} STREQUAL "framePlayer") + ) + # We know the quest hardware has this extension, so we can force the use of instanced stereo + add_definitions(-DHAVE_EXT_clip_cull_distance) + # We can also use multiview stereo techniques + add_definitions(-DHAVE_OVR_multiview2) + add_definitions(-DHAVE_OVR_multiview) + # We can also use our own foveated textures + add_definitions(-DHAVE_QCOM_texture_foveated) + + # if set, the application itself or some library it depends on MUST implement + # `DisplayPluginList getDisplayPlugins()` and `InputPluginList getInputPlugins()` + add_definitions(-DCUSTOM_INPUT_PLUGINS) + add_definitions(-DCUSTOM_DISPLAY_PLUGINS) + set(PLATFORM_PLUGIN_LIBRARIES oculusMobile oculusMobilePlugin) + endif() else () set(PLATFORM_QT_COMPONENTS WebEngine) endif () diff --git a/android/apps/framePlayer/build.gradle b/android/apps/framePlayer/build.gradle index a210c8300e..5bf8176863 100644 --- a/android/apps/framePlayer/build.gradle +++ b/android/apps/framePlayer/build.gradle @@ -1,15 +1,8 @@ +import com.android.builder.core.BuilderConstants + apply plugin: 'com.android.application' android { - signingConfigs { - release { - storeFile project.hasProperty("HIFI_ANDROID_KEYSTORE") ? file(HIFI_ANDROID_KEYSTORE) : null - storePassword project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") ? HIFI_ANDROID_KEYSTORE_PASSWORD : '' - keyAlias project.hasProperty("HIFI_ANDROID_KEY_ALIAS") ? HIFI_ANDROID_KEY_ALIAS : '' - keyPassword project.hasProperty("HIFI_ANDROID_KEY_PASSWORD") ? HIFI_ANDROID_KEY_PASSWORD : '' - } - } - compileSdkVersion 28 defaultConfig { applicationId "io.highfidelity.frameplayer" @@ -32,19 +25,17 @@ android { targetCompatibility JavaVersion.VERSION_1_8 } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.release + externalNativeBuild.cmake.path '../../../CMakeLists.txt' + + variantFilter { variant -> + def build = variant.buildType.name + if (build == BuilderConstants.RELEASE) { + variant.setIgnore(true) } } - - externalNativeBuild.cmake.path '../../../CMakeLists.txt' } dependencies { implementation fileTree(include: ['*.jar'], dir: '../../libraries/qt/libs') - //implementation project(':oculus') implementation project(':qt') } diff --git a/android/apps/questFramePlayer/build.gradle b/android/apps/questFramePlayer/build.gradle index 899f9cb955..0b153af0a9 100644 --- a/android/apps/questFramePlayer/build.gradle +++ b/android/apps/questFramePlayer/build.gradle @@ -1,15 +1,8 @@ +import com.android.builder.core.BuilderConstants + apply plugin: 'com.android.application' android { - signingConfigs { - release { - storeFile project.hasProperty("HIFI_ANDROID_KEYSTORE") ? file(HIFI_ANDROID_KEYSTORE) : null - storePassword project.hasProperty("HIFI_ANDROID_KEYSTORE_PASSWORD") ? HIFI_ANDROID_KEYSTORE_PASSWORD : '' - keyAlias project.hasProperty("HIFI_ANDROID_KEY_ALIAS") ? HIFI_ANDROID_KEY_ALIAS : '' - keyPassword project.hasProperty("HIFI_ANDROID_KEY_PASSWORD") ? HIFI_ANDROID_KEY_PASSWORD : '' - } - } - compileSdkVersion 28 defaultConfig { applicationId "io.highfidelity.frameplayer" @@ -33,15 +26,14 @@ android { targetCompatibility JavaVersion.VERSION_1_8 } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.release + externalNativeBuild.cmake.path '../../../CMakeLists.txt' + + variantFilter { variant -> + def build = variant.buildType.name + if (build == BuilderConstants.RELEASE) { + variant.setIgnore(true) } } - - externalNativeBuild.cmake.path '../../../CMakeLists.txt' } dependencies { diff --git a/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java b/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java index 40e1863d69..6a6688ac41 100644 --- a/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/android/libraries/qt/src/main/java/org/qtproject/qt5/android/bindings/QtActivity.java @@ -650,6 +650,8 @@ public class QtActivity extends Activity { if (!keepInterfaceRunning) { QtApplication.invokeDelegate(); } + QtNative.terminateQt(); + QtNative.setActivity(null,null); } //--------------------------------------------------------------------------- diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 81b9935aa5..0bfed88d9c 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -211,7 +211,10 @@ link_hifi_libraries( render-utils entities-renderer avatars-renderer ui qml auto-updater midi controllers plugins image trackers ui-plugins display-plugins input-plugins + # Platform specific GL libraries ${PLATFORM_GL_BACKEND} + # Plaform specific input & display plugin libraries + ${PLATFORM_PLUGIN_LIBRARIES} shaders ) diff --git a/interface/resources/qml/hifi/avatarapp/Spinner.qml b/interface/resources/qml/hifi/avatarapp/Spinner.qml index 3fc331346d..14f8e922d7 100644 --- a/interface/resources/qml/hifi/avatarapp/Spinner.qml +++ b/interface/resources/qml/hifi/avatarapp/Spinner.qml @@ -1,5 +1,4 @@ import QtQuick 2.5 -import QtWebEngine 1.5 AnimatedImage { source: "../../../icons/loader-snake-64-w.gif" diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e16a54ec74..1029398794 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -603,8 +603,9 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt __android_log_write(ANDROID_LOG_FATAL,"Interface",local); abort(); } -#endif +#else qApp->getLogger()->addMessage(qPrintable(logMessage)); +#endif } } @@ -989,7 +990,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QApplication(argc, argv), _window(new MainWindow(desktop())), _sessionRunTimer(startupTimer), +#ifndef Q_OS_ANDROID _logger(new FileLogger(this)), +#endif _previousSessionCrashed(setupEssentials(argc, argv, runningMarkerExisted)), _entitySimulation(new PhysicalEntitySimulation()), _physicsEngine(new PhysicsEngine(Vectors::ZERO)), @@ -1123,7 +1126,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } auto accountManager = DependencyManager::get(); +#ifndef Q_OS_ANDROID _logger->setSessionID(accountManager->getSessionID()); +#endif setCrashAnnotation("metaverse_session_id", accountManager->getSessionID().toString().toStdString()); setCrashAnnotation("main_thread_id", std::to_string((size_t)QThread::currentThreadId())); @@ -4963,7 +4968,11 @@ void Application::idle() { // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing // details normally. +#ifdef Q_OS_ANDROID + bool showWarnings = false; +#else bool showWarnings = getLogger()->extraDebugging(); +#endif PerformanceWarning warn(showWarnings, "idle()"); { @@ -8306,7 +8315,7 @@ void Application::toggleLogDialog() { bool keepOnTop =_keepLogWindowOnTop.get(); #ifdef Q_OS_WIN _logDialog = new LogDialog(keepOnTop ? qApp->getWindow() : nullptr, getLogger()); -#else +#elif !defined(Q_OS_ANDROID) _logDialog = new LogDialog(nullptr, getLogger()); if (keepOnTop) { diff --git a/interface/src/Application.h b/interface/src/Application.h index de79e91cb2..2b4902f72e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -251,7 +251,9 @@ public: void setActiveDisplayPlugin(const QString& pluginName); +#ifndef Q_OS_ANDROID FileLogger* getLogger() const { return _logger; } +#endif float getRenderResolutionScale() const; @@ -599,7 +601,9 @@ private: bool _aboutToQuit { false }; +#ifndef Q_OS_ANDROID FileLogger* _logger { nullptr }; +#endif bool _previousSessionCrashed; diff --git a/interface/src/octree/OctreePacketProcessor.cpp b/interface/src/octree/OctreePacketProcessor.cpp index 5c8868abdb..6b07e6717c 100644 --- a/interface/src/octree/OctreePacketProcessor.cpp +++ b/interface/src/octree/OctreePacketProcessor.cpp @@ -38,11 +38,13 @@ void OctreePacketProcessor::processPacket(QSharedPointer messag PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "OctreePacketProcessor::processPacket()"); +#ifndef Q_OS_ANDROID const int WAY_BEHIND = 300; if (packetsToProcessCount() > WAY_BEHIND && qApp->getLogger()->extraDebugging()) { qDebug("OctreePacketProcessor::processPacket() packets to process=%d", packetsToProcessCount()); } +#endif bool wasStatsPacket = false; diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp index da226d146b..69590aae82 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp @@ -20,6 +20,7 @@ const QString& DisplayPlugin::MENU_PATH() { return value; } +#if !defined(CUSTOM_DISPLAY_PLUGINS) // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class DisplayPluginList getDisplayPlugins() { DisplayPlugin* PLUGIN_POOL[] = { @@ -49,3 +50,4 @@ DisplayPluginList getDisplayPlugins() { } return result; } +#endif \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 6c59dbd861..e4deaf8f4b 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -720,6 +720,8 @@ void OpenGLDisplayPlugin::present() { } gpu::Backend::freeGPUMemSize.set(gpu::gl::getFreeDedicatedMemory()); + } else { + internalPresent(); } _movingAveragePresent.addSample((float)(usecTimestampNow() - startPresent)); } diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp index 9eafe381ab..b4527ff90c 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp @@ -51,15 +51,15 @@ bool DebugHmdDisplayPlugin::internalActivate() { }, true, _isAutoRotateEnabled); _ipd = 0.0327499993f * 2.0f; - // Would be nice to know why the left and right projection matrices are slightly dissymetrical - _eyeProjections[0][0] = vec4{ 0.759056330, 0.000000000, 0.000000000, 0.000000000 }; - _eyeProjections[0][1] = vec4{ 0.000000000, 0.682773232, 0.000000000, 0.000000000 }; - _eyeProjections[0][2] = vec4{ -0.0580431037, -0.00619550655, -1.00000489, -1.00000000 }; - _eyeProjections[0][3] = vec4{ 0.000000000, 0.000000000, -0.0800003856, 0.000000000 }; - _eyeProjections[1][0] = vec4{ 0.752847493, 0.000000000, 0.000000000, 0.000000000 }; - _eyeProjections[1][1] = vec4{ 0.000000000, 0.678060353, 0.000000000, 0.000000000 }; - _eyeProjections[1][2] = vec4{ 0.0578232110, -0.00669418881, -1.00000489, -1.000000000 }; - _eyeProjections[1][3] = vec4{ 0.000000000, 0.000000000, -0.0800003856, 0.000000000 }; + // Quest + _eyeProjections[0][0] = vec4{ 0.91729, 0.0, -0.17407, 0.0 }; + _eyeProjections[0][1] = vec4{ 0.0, 0.083354, -0.106141, 0.0 }; + _eyeProjections[0][2] = vec4{ 0.0, 0.0, -1.0, -0.2 }; + _eyeProjections[0][3] = vec4{ 0.0, 0.0, -1.0, 0.0 }; + _eyeProjections[1][0] = vec4{ 0.91729, 0.0, 0.17407, 0.0 }; + _eyeProjections[1][1] = vec4{ 0.0, 0.083354, -0.106141, 0.0 }; + _eyeProjections[1][2] = vec4{ 0.0, 0.0, -1.0, -0.2 }; + _eyeProjections[1][3] = vec4{ 0.0, 0.0, -1.0, 0.0 }; // No need to do so here as this will done in Parent::internalActivate //_eyeInverseProjections[0] = glm::inverse(_eyeProjections[0]); //_eyeInverseProjections[1] = glm::inverse(_eyeProjections[1]); diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 4aeacbe05c..d8c0ce8e1d 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -81,7 +81,6 @@ protected: mat4 presentPose; double sensorSampleTime { 0 }; double predictedDisplayTime { 0 }; - mat3 presentReprojection; }; QMap _frameInfos; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index 1cf331cd1a..fef458f536 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -418,6 +418,10 @@ public: #endif }; +#if defined(GPU_STEREO_DRAWCALL_INSTANCED) && !defined(GL_CLIP_DISTANCE0) +#define GL_CLIP_DISTANCE0 GL_CLIP_DISTANCE0_EXT +#endif + #define GL_PROFILE_RANGE(category, name) \ PROFILE_RANGE(category, name); \ GlDuration glProfileRangeThis(name); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 671d4e11d7..ffd0466b79 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -32,7 +32,7 @@ // Different versions for the stereo drawcall // Current preferred is "instanced" which draw the shape twice but instanced and rely on clipping plane to draw left/right side only -#if defined(USE_GLES) +#if defined(USE_GLES) && !defined(HAVE_EXT_clip_cull_distance) #define GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE #else //#define GPU_STEREO_TECHNIQUE_DOUBLED_SMARTER diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index 6f94e7592c..c18c4cde65 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -16,6 +16,7 @@ #include "TouchscreenDevice.h" #include "TouchscreenVirtualPadDevice.h" +#if !defined(CUSTOM_INPUT_PLUGINS) // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class InputPluginList getInputPlugins() { InputPlugin* PLUGIN_POOL[] = { @@ -37,6 +38,7 @@ InputPluginList getInputPlugins() { } return result; } +#endif void saveInputPluginSettings(const InputPluginList& plugins) { foreach (auto inputPlugin, plugins) { diff --git a/libraries/oculusMobilePlugin/src/OculusMobileControllerManager.cpp b/libraries/oculusMobilePlugin/src/OculusMobileControllerManager.cpp index 8de563ee4c..705045b517 100644 --- a/libraries/oculusMobilePlugin/src/OculusMobileControllerManager.cpp +++ b/libraries/oculusMobilePlugin/src/OculusMobileControllerManager.cpp @@ -171,6 +171,8 @@ private: void handleHeadPose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const ovrRigidBodyPosef& headPose); + void reconnectTouchControllers(ovrMobile* session); + // perform an action when the TouchDevice mutex is acquired. using Locker = std::unique_lock; @@ -637,7 +639,6 @@ controller::Input::NamedVector OculusMobileInputDevice::getAvailableInputs() con makePair(RIGHT_THUMB_UP, "RightThumbUp"), makePair(LEFT_INDEX_POINT, "LeftIndexPoint"), makePair(RIGHT_INDEX_POINT, "RightIndexPoint"), - makePair(BACK, "LeftApplicationMenu"), makePair(START, "RightApplicationMenu"), }; @@ -665,8 +666,40 @@ OculusMobileInputDevice::OculusMobileInputDevice(ovrMobile* session, const std:: void OculusMobileInputDevice::updateHands(ovrMobile* session) { _headTracking = vrapi_GetPredictedTracking2(session, 0.0); + + bool touchControllerNotConnected = false; for (auto& hand : _hands) { hand.update(session); + + if (hand.stateResult < 0 || hand.trackingResult < 0) { + touchControllerNotConnected = true; + } + } + + if (touchControllerNotConnected) { + reconnectTouchControllers(session); + } +} + +void OculusMobileInputDevice::reconnectTouchControllers(ovrMobile* session) { + uint32_t deviceIndex { 0 }; + ovrInputCapabilityHeader capsHeader; + while (vrapi_EnumerateInputDevices(session, deviceIndex, &capsHeader) >= 0) { + if (capsHeader.Type == ovrControllerType_TrackedRemote) { + ovrInputTrackedRemoteCapabilities caps; + caps.Header = capsHeader; + vrapi_GetInputDeviceCapabilities(session, &caps.Header); + + if (caps.ControllerCapabilities & ovrControllerCaps_LeftHand || caps.ControllerCapabilities & ovrControllerCaps_RightHand) { + size_t handIndex = caps.ControllerCapabilities & ovrControllerCaps_LeftHand ? 0 : 1; + HandData& handData = _hands[handIndex]; + handData.state.Header.ControllerType = ovrControllerType_TrackedRemote; + handData.valid = true; + handData.caps = caps; + handData.update(session); + } + } + ++deviceIndex; } } @@ -691,4 +724,4 @@ InputPluginList getInputPlugins() { } } return result; -} \ No newline at end of file +} diff --git a/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.cpp b/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.cpp index 34ba130c71..78d80443d8 100644 --- a/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.cpp +++ b/libraries/oculusMobilePlugin/src/OculusMobileDisplayPlugin.cpp @@ -63,7 +63,7 @@ bool OculusMobileDisplayPlugin::internalActivate() { withOvrJava([&](const ovrJava* java){ _renderTargetSize = glm::uvec2{ - vrapi_GetSystemPropertyInt(java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_WIDTH), + 2 * vrapi_GetSystemPropertyInt(java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_WIDTH), vrapi_GetSystemPropertyInt(java, VRAPI_SYS_PROP_SUGGESTED_EYE_TEXTURE_HEIGHT), }; }); diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index abab5391e2..69e6c833ee 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,21 @@ static QSize clampSize(const QSize& qsize, uint32_t maxDimension) { const QmlContextObjectCallback OffscreenSurface::DEFAULT_CONTEXT_OBJECT_CALLBACK = [](QQmlContext*, QQuickItem*) {}; const QmlContextCallback OffscreenSurface::DEFAULT_CONTEXT_CALLBACK = [](QQmlContext*) {}; +QQmlFileSelector* OffscreenSurface::getFileSelector() { + auto context = getSurfaceContext(); + if (!context) { + return nullptr; + } + auto engine = context->engine(); + if (!engine) { + return nullptr; + } + + return QQmlFileSelector::get(engine); +} + void OffscreenSurface::initializeEngine(QQmlEngine* engine) { + new QQmlFileSelector(engine); } using namespace hifi::qml::impl; diff --git a/libraries/qml/src/qml/OffscreenSurface.h b/libraries/qml/src/qml/OffscreenSurface.h index b3539e7709..18d24c93f7 100644 --- a/libraries/qml/src/qml/OffscreenSurface.h +++ b/libraries/qml/src/qml/OffscreenSurface.h @@ -30,6 +30,7 @@ class QQmlComponent; class QQuickWindow; class QQuickItem; class OffscreenQmlSharedObject; +class QQmlFileSelector; namespace hifi { namespace qml { @@ -72,6 +73,7 @@ public: QQuickWindow* getWindow(); QObject* getEventHandler(); QQmlContext* getSurfaceContext(); + QQmlFileSelector* getFileSelector(); // Checks to see if a new texture is available. If one is, the function returns true and // textureAndFence will be populated with the texture ID and a fence which will be signalled diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 71bb65509f..7fd60a0b1d 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -238,8 +238,10 @@ void OffscreenQmlSurface::clearFocusItem() { void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) { Parent::initializeEngine(engine); - QQmlFileSelector* fileSelector = new QQmlFileSelector(engine); - fileSelector->setExtraSelectors(FileUtils::getFileSelectors()); + auto fileSelector = getFileSelector(); + if (fileSelector) { + fileSelector->setExtraSelectors(FileUtils::getFileSelectors()); + } static std::once_flag once; std::call_once(once, [] { diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index a34e647a5e..df01591639 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -138,6 +138,10 @@ void OculusDisplayPlugin::hmdPresent() { return; } + if (!_currentFrame) { + return; + } + PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) { diff --git a/tools/gpu-frame-player/CMakeLists.txt b/tools/gpu-frame-player/CMakeLists.txt index bd50839f9c..996fc859d8 100644 --- a/tools/gpu-frame-player/CMakeLists.txt +++ b/tools/gpu-frame-player/CMakeLists.txt @@ -7,7 +7,7 @@ setup_hifi_project(Gui Widgets) # link in the shared libraries link_hifi_libraries( - shared ktx shaders gpu + shared ktx shaders gpu # vk gpu-vk gl ${PLATFORM_GL_BACKEND} ) From 79bf26ee27332aa8a94af93b9fc2ff39a9be423d Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Thu, 7 Feb 2019 15:57:14 -0800 Subject: [PATCH 056/139] Add prebuild metrics logging for CI system Metric about the times various parts of the build take are great to have. This change takes us a step in that direction by adding metrics to the prebuild step of the build process. These metrics are off by default; use the `--ci-build` option of `prebuild.py` to enable them. --- prebuild.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/prebuild.py b/prebuild.py index fb54b8d6fe..060e1fd3b0 100644 --- a/prebuild.py +++ b/prebuild.py @@ -35,9 +35,50 @@ import re import tempfile import time import functools +import subprocess +import logging + +from uuid import uuid4 +from contextlib import contextmanager print = functools.partial(print, flush=True) +class TrackableLogger(logging.Logger): + guid = str(uuid4()) + + def _log(self, msg, *args, **kwargs): + x = {'guid': self.guid} + if 'extra' in kwargs: + kwargs['extra'].update(x) + else: + kwargs['extra'] = x + super()._log(msg, *args, **kwargs) + +logging.setLoggerClass(TrackableLogger) +logger = logging.getLogger('prebuild') + +def headSha(): + repo_dir = os.path.dirname(os.path.abspath(__file__)) + git = subprocess.Popen( + 'git rev-parse --short HEAD', + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + shell=True, cwd=repo_dir, universal_newlines=True, + ) + stdout, _ = git.communicate() + sha = stdout.split('\n')[0] + if not sha: + raise RuntimeError("couldn't find git sha") + return sha + +@contextmanager +def timer(name): + ''' Print the elapsed time a context's execution takes to execute ''' + start = time.time() + yield + # Please take care when modifiying this print statement. + # Log parsing logic may depend on it. + logger.info('%s took %.3f secs' % (name, time.time() - start)) + def parse_args(): # our custom ports, relative to the script location defaultPortsPath = hifi_utils.scriptRelative('cmake', 'ports') @@ -50,6 +91,7 @@ def parse_args(): parser.add_argument('--vcpkg-root', type=str, help='The location of the vcpkg distribution') parser.add_argument('--build-root', required=True, type=str, help='The location of the cmake build') parser.add_argument('--ports-path', type=str, default=defaultPortsPath) + parser.add_argument('--ci-build', action='store_true') if True: args = parser.parse_args() else: @@ -66,11 +108,19 @@ def main(): del os.environ[var] args = parse_args() + + if args.ci_build: + logging.basicConfig(datefmt='%s', format='%(asctime)s %(guid)s %(message)s', level=logging.INFO) + + logger.info('sha=%s' % headSha()) + logger.info('start') + # Only allow one instance of the program to run at a time pm = hifi_vcpkg.VcpkgRepo(args) with hifi_singleton.Singleton(pm.lockFile) as lock: - if not pm.upToDate(): - pm.bootstrap() + with timer('Bootstraping'): + if not pm.upToDate(): + pm.bootstrap() # Always write the tag, even if we changed nothing. This # allows vcpkg to reclaim disk space by identifying directories with @@ -80,11 +130,13 @@ def main(): # Grab our required dependencies: # * build host tools, like spirv-cross and scribe # * build client dependencies like openssl and nvtt - pm.setupDependencies() + with timer('Setting up dependencies'): + pm.setupDependencies() # wipe out the build directories (after writing the tag, since failure # here shouldn't invalidte the vcpkg install) - pm.cleanBuilds() + with timer('Cleaning builds'): + pm.cleanBuilds() # If we're running in android mode, we also need to grab a bunch of additional binaries # (this logic is all migrated from the old setupDependencies tasks in gradle) @@ -98,7 +150,10 @@ def main(): hifi_android.QtPackager(appPath, qtPath).bundle() # Write the vcpkg config to the build directory last - pm.writeConfig() + with timer('Writing configuration'): + pm.writeConfig() + + logger.info('end') print(sys.argv) main() From f7a487a02060cdb9ea5c9468cc48c1b1f4001808 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 8 Feb 2019 10:28:07 -0800 Subject: [PATCH 057/139] move materialcache et al to material-networking library --- assignment-client/CMakeLists.txt | 2 +- interface/CMakeLists.txt | 4 +- interface/src/Application.cpp | 4 +- libraries/avatars-renderer/CMakeLists.txt | 2 +- libraries/display-plugins/CMakeLists.txt | 1 + libraries/entities-renderer/CMakeLists.txt | 2 +- libraries/entities/CMakeLists.txt | 2 +- libraries/entities/src/MaterialEntityItem.h | 2 +- libraries/graphics-scripting/CMakeLists.txt | 2 +- libraries/material-networking/CMakeLists.txt | 5 + .../src/material-networking}/KTXCache.cpp | 0 .../src/material-networking}/KTXCache.h | 0 .../material-networking}/MaterialCache.cpp | 306 ++++++++++++++++++ .../src/material-networking/MaterialCache.h | 115 +++++++ .../MaterialNetworkingLogging.cpp | 11 + .../MaterialNetworkingLogging.h | 11 + .../src/material-networking}/ShaderCache.cpp | 0 .../src/material-networking}/ShaderCache.h | 0 .../src/material-networking}/TextureCache.cpp | 8 +- .../src/material-networking}/TextureCache.h | 0 .../TextureCacheScriptingInterface.cpp | 0 .../TextureCacheScriptingInterface.h | 0 libraries/model-baker/CMakeLists.txt | 3 +- .../model-baker/ApplyMaterialMappingTask.cpp | 2 + libraries/model-networking/CMakeLists.txt | 3 +- .../src/model-networking/MaterialCache.h | 60 ---- .../src/model-networking/ModelCache.cpp | 306 ------------------ .../src/model-networking/ModelCache.h | 61 +--- .../ModelNetworkingLogging.cpp | 2 +- libraries/physics/CMakeLists.txt | 1 + libraries/procedural/CMakeLists.txt | 2 +- .../procedural/src/procedural/Procedural.h | 4 +- libraries/render-utils/CMakeLists.txt | 2 +- .../render-utils/src/RenderPipelines.cpp | 2 +- libraries/render-utils/src/TextureCache.h | 2 +- libraries/script-engine/CMakeLists.txt | 2 +- plugins/openvr/CMakeLists.txt | 2 +- 37 files changed, 480 insertions(+), 451 deletions(-) create mode 100644 libraries/material-networking/CMakeLists.txt rename libraries/{model-networking/src/model-networking => material-networking/src/material-networking}/KTXCache.cpp (100%) rename libraries/{model-networking/src/model-networking => material-networking/src/material-networking}/KTXCache.h (100%) rename libraries/{model-networking/src/model-networking => material-networking/src/material-networking}/MaterialCache.cpp (63%) create mode 100644 libraries/material-networking/src/material-networking/MaterialCache.h create mode 100644 libraries/material-networking/src/material-networking/MaterialNetworkingLogging.cpp create mode 100644 libraries/material-networking/src/material-networking/MaterialNetworkingLogging.h rename libraries/{model-networking/src/model-networking => material-networking/src/material-networking}/ShaderCache.cpp (100%) rename libraries/{model-networking/src/model-networking => material-networking/src/material-networking}/ShaderCache.h (100%) rename libraries/{model-networking/src/model-networking => material-networking/src/material-networking}/TextureCache.cpp (99%) rename libraries/{model-networking/src/model-networking => material-networking/src/material-networking}/TextureCache.h (100%) rename libraries/{model-networking/src/model-networking => material-networking/src/material-networking}/TextureCacheScriptingInterface.cpp (100%) rename libraries/{model-networking/src/model-networking => material-networking/src/material-networking}/TextureCacheScriptingInterface.h (100%) delete mode 100644 libraries/model-networking/src/model-networking/MaterialCache.h diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index f28dc90b7d..b7afc3ed9e 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -14,7 +14,7 @@ link_hifi_libraries( audio avatars octree gpu graphics shaders fbx hfm entities networking animation recording shared script-engine embedded-webserver controllers physics plugins midi image - model-networking ktx shaders + material-networking model-networking ktx shaders ) add_dependencies(${TARGET_NAME} oven) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index c013cfacd3..d5dfce957f 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -205,8 +205,8 @@ endif() # link required hifi libraries link_hifi_libraries( shared workload task octree ktx gpu gl procedural graphics graphics-scripting render - pointers - recording hfm fbx networking model-networking model-baker entities avatars trackers + pointers recording hfm fbx networking material-networking + model-networking model-baker entities avatars trackers audio audio-client animation script-engine physics render-utils entities-renderer avatars-renderer ui qml auto-updater midi controllers plugins image trackers diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index daf2dd6363..03b2e6c18e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -102,7 +102,7 @@ #include #include #include -#include +#include #include #include #include @@ -153,7 +153,7 @@ #include #include #include -#include +#include #include "recording/ClipCache.h" #include "AudioClient.h" diff --git a/libraries/avatars-renderer/CMakeLists.txt b/libraries/avatars-renderer/CMakeLists.txt index 06a3804ece..de1ac1a7c2 100644 --- a/libraries/avatars-renderer/CMakeLists.txt +++ b/libraries/avatars-renderer/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME avatars-renderer) setup_hifi_library(Network Script) -link_hifi_libraries(shared shaders gpu graphics animation model-networking script-engine render render-utils image trackers entities-renderer) +link_hifi_libraries(shared shaders gpu graphics animation material-networking model-networking script-engine render render-utils image trackers entities-renderer) include_hifi_library_headers(avatars) include_hifi_library_headers(networking) include_hifi_library_headers(hfm) diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt index 8e966ed9ea..ad6503b22d 100644 --- a/libraries/display-plugins/CMakeLists.txt +++ b/libraries/display-plugins/CMakeLists.txt @@ -2,6 +2,7 @@ set(TARGET_NAME display-plugins) setup_hifi_library(Gui) link_hifi_libraries(shared shaders plugins ui-plugins gl ui render-utils ${PLATFORM_GL_BACKEND}) include_hifi_library_headers(gpu) +include_hifi_library_headers(material-networking) include_hifi_library_headers(model-networking) include_hifi_library_headers(networking) include_hifi_library_headers(graphics) diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index b08856e8a8..e1896cf674 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -1,6 +1,6 @@ set(TARGET_NAME entities-renderer) setup_hifi_library(Network Script) -link_hifi_libraries(shared workload gpu shaders procedural graphics model-networking script-engine render render-utils image qml ui pointers) +link_hifi_libraries(shared workload gpu shaders procedural graphics material-networking model-networking script-engine render render-utils image qml ui pointers) include_hifi_library_headers(networking) include_hifi_library_headers(gl) include_hifi_library_headers(ktx) diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index fcbe563f88..044d25f77e 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -6,4 +6,4 @@ include_hifi_library_headers(fbx) include_hifi_library_headers(gpu) include_hifi_library_headers(image) include_hifi_library_headers(ktx) -link_hifi_libraries(shared shaders networking octree avatars graphics model-networking) +link_hifi_libraries(shared shaders networking octree avatars graphics material-networking model-networking) diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index ba142d7719..069c71c1d6 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -13,7 +13,7 @@ #include "MaterialMappingMode.h" #include -#include +#include class MaterialEntityItem : public EntityItem { using Pointer = std::shared_ptr; diff --git a/libraries/graphics-scripting/CMakeLists.txt b/libraries/graphics-scripting/CMakeLists.txt index 0f59fb41f8..9bb34adda1 100644 --- a/libraries/graphics-scripting/CMakeLists.txt +++ b/libraries/graphics-scripting/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME graphics-scripting) setup_hifi_library() -link_hifi_libraries(shared networking graphics fbx image model-networking script-engine) +link_hifi_libraries(shared networking graphics fbx image material-networking model-networking script-engine) include_hifi_library_headers(gpu) diff --git a/libraries/material-networking/CMakeLists.txt b/libraries/material-networking/CMakeLists.txt new file mode 100644 index 0000000000..4ade61230a --- /dev/null +++ b/libraries/material-networking/CMakeLists.txt @@ -0,0 +1,5 @@ +set(TARGET_NAME material-networking) +setup_hifi_library() +link_hifi_libraries(shared shaders networking graphics fbx ktx image gl) +include_hifi_library_headers(gpu) +include_hifi_library_headers(hfm) \ No newline at end of file diff --git a/libraries/model-networking/src/model-networking/KTXCache.cpp b/libraries/material-networking/src/material-networking/KTXCache.cpp similarity index 100% rename from libraries/model-networking/src/model-networking/KTXCache.cpp rename to libraries/material-networking/src/material-networking/KTXCache.cpp diff --git a/libraries/model-networking/src/model-networking/KTXCache.h b/libraries/material-networking/src/material-networking/KTXCache.h similarity index 100% rename from libraries/model-networking/src/model-networking/KTXCache.h rename to libraries/material-networking/src/material-networking/KTXCache.h diff --git a/libraries/model-networking/src/model-networking/MaterialCache.cpp b/libraries/material-networking/src/material-networking/MaterialCache.cpp similarity index 63% rename from libraries/model-networking/src/model-networking/MaterialCache.cpp rename to libraries/material-networking/src/material-networking/MaterialCache.cpp index aaa9767397..bccf1ca0c4 100644 --- a/libraries/model-networking/src/model-networking/MaterialCache.cpp +++ b/libraries/material-networking/src/material-networking/MaterialCache.cpp @@ -426,4 +426,310 @@ QSharedPointer MaterialCache::createResource(const QUrl& url) { QSharedPointer MaterialCache::createResourceCopy(const QSharedPointer& resource) { return QSharedPointer(new NetworkMaterialResource(*resource.staticCast().data()), &Resource::deleter); +} + +NetworkMaterial::NetworkMaterial(const NetworkMaterial& m) : + Material(m), + _textures(m._textures), + _albedoTransform(m._albedoTransform), + _lightmapTransform(m._lightmapTransform), + _lightmapParams(m._lightmapParams), + _isOriginal(m._isOriginal) +{} + +const QString NetworkMaterial::NO_TEXTURE = QString(); + +const QString& NetworkMaterial::getTextureName(MapChannel channel) { + if (_textures[channel].texture) { + return _textures[channel].name; + } + return NO_TEXTURE; +} + +QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const HFMTexture& texture) { + if (texture.content.isEmpty()) { + // External file: search relative to the baseUrl, in case filename is relative + return baseUrl.resolved(QUrl(texture.filename)); + } else { + // Inlined file: cache under the fbx file to avoid namespace clashes + // NOTE: We cannot resolve the path because filename may be an absolute path + assert(texture.filename.size() > 0); + auto baseUrlStripped = baseUrl.toDisplayString(QUrl::RemoveFragment | QUrl::RemoveQuery | QUrl::RemoveUserInfo); + if (texture.filename.at(0) == '/') { + return baseUrlStripped + texture.filename; + } else { + return baseUrlStripped + '/' + texture.filename; + } + } +} + +graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture, + image::TextureUsage::Type type, MapChannel channel) { + + if (baseUrl.isEmpty()) { + return nullptr; + } + + const auto url = getTextureUrl(baseUrl, hfmTexture); + const auto texture = DependencyManager::get()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels); + _textures[channel] = Texture { hfmTexture.name, texture }; + + auto map = std::make_shared(); + if (texture) { + map->setTextureSource(texture->_textureSource); + } + map->setTextureTransform(hfmTexture.transform); + + return map; +} + +graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel) { + auto textureCache = DependencyManager::get(); + if (textureCache && !url.isEmpty()) { + auto texture = textureCache->getTexture(url, type); + _textures[channel].texture = texture; + + auto map = std::make_shared(); + if (texture) { + map->setTextureSource(texture->_textureSource); + } + + return map; + } + return nullptr; +} + +void NetworkMaterial::setAlbedoMap(const QUrl& url, bool useAlphaChannel) { + auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + if (map) { + map->setUseAlphaChannel(useAlphaChannel); + setTextureMap(MapChannel::ALBEDO_MAP, map); + } +} + +void NetworkMaterial::setNormalMap(const QUrl& url, bool isBumpmap) { + auto map = fetchTextureMap(url, isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); + if (map) { + setTextureMap(MapChannel::NORMAL_MAP, map); + } +} + +void NetworkMaterial::setRoughnessMap(const QUrl& url, bool isGloss) { + auto map = fetchTextureMap(url, isGloss ? image::TextureUsage::GLOSS_TEXTURE : image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + if (map) { + setTextureMap(MapChannel::ROUGHNESS_MAP, map); + } +} + +void NetworkMaterial::setMetallicMap(const QUrl& url, bool isSpecular) { + auto map = fetchTextureMap(url, isSpecular ? image::TextureUsage::SPECULAR_TEXTURE : image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + if (map) { + setTextureMap(MapChannel::METALLIC_MAP, map); + } +} + +void NetworkMaterial::setOcclusionMap(const QUrl& url) { + auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + if (map) { + setTextureMap(MapChannel::OCCLUSION_MAP, map); + } +} + +void NetworkMaterial::setEmissiveMap(const QUrl& url) { + auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + if (map) { + setTextureMap(MapChannel::EMISSIVE_MAP, map); + } +} + +void NetworkMaterial::setScatteringMap(const QUrl& url) { + auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); + if (map) { + setTextureMap(MapChannel::SCATTERING_MAP, map); + } +} + +void NetworkMaterial::setLightmapMap(const QUrl& url) { + auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + if (map) { + //map->setTextureTransform(_lightmapTransform); + //map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); + setTextureMap(MapChannel::LIGHTMAP_MAP, map); + } +} + +NetworkMaterial::NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl) : + graphics::Material(*material._material), + _textures(MapChannel::NUM_MAP_CHANNELS) +{ + _name = material.name.toStdString(); + if (!material.albedoTexture.filename.isEmpty()) { + auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + if (map) { + _albedoTransform = material.albedoTexture.transform; + map->setTextureTransform(_albedoTransform); + + if (!material.opacityTexture.filename.isEmpty()) { + if (material.albedoTexture.filename == material.opacityTexture.filename) { + // Best case scenario, just indicating that the albedo map contains transparency + // TODO: Different albedo/opacity maps are not currently supported + map->setUseAlphaChannel(true); + } + } + } + + setTextureMap(MapChannel::ALBEDO_MAP, map); + } + + + if (!material.normalTexture.filename.isEmpty()) { + auto type = (material.normalTexture.isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE); + auto map = fetchTextureMap(textureBaseUrl, material.normalTexture, type, MapChannel::NORMAL_MAP); + setTextureMap(MapChannel::NORMAL_MAP, map); + } + + if (!material.roughnessTexture.filename.isEmpty()) { + auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + setTextureMap(MapChannel::ROUGHNESS_MAP, map); + } else if (!material.glossTexture.filename.isEmpty()) { + auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, image::TextureUsage::GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP); + setTextureMap(MapChannel::ROUGHNESS_MAP, map); + } + + if (!material.metallicTexture.filename.isEmpty()) { + auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + setTextureMap(MapChannel::METALLIC_MAP, map); + } else if (!material.specularTexture.filename.isEmpty()) { + auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, image::TextureUsage::SPECULAR_TEXTURE, MapChannel::METALLIC_MAP); + setTextureMap(MapChannel::METALLIC_MAP, map); + } + + if (!material.occlusionTexture.filename.isEmpty()) { + auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + if (map) { + map->setTextureTransform(material.occlusionTexture.transform); + } + setTextureMap(MapChannel::OCCLUSION_MAP, map); + } + + if (!material.emissiveTexture.filename.isEmpty()) { + auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + setTextureMap(MapChannel::EMISSIVE_MAP, map); + } + + if (!material.scatteringTexture.filename.isEmpty()) { + auto map = fetchTextureMap(textureBaseUrl, material.scatteringTexture, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); + setTextureMap(MapChannel::SCATTERING_MAP, map); + } + + if (!material.lightmapTexture.filename.isEmpty()) { + auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + if (map) { + _lightmapTransform = material.lightmapTexture.transform; + _lightmapParams = material.lightmapParams; + map->setTextureTransform(_lightmapTransform); + map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); + } + setTextureMap(MapChannel::LIGHTMAP_MAP, map); + } +} + +void NetworkMaterial::setTextures(const QVariantMap& textureMap) { + _isOriginal = false; + + const auto& albedoName = getTextureName(MapChannel::ALBEDO_MAP); + const auto& normalName = getTextureName(MapChannel::NORMAL_MAP); + const auto& roughnessName = getTextureName(MapChannel::ROUGHNESS_MAP); + const auto& metallicName = getTextureName(MapChannel::METALLIC_MAP); + const auto& occlusionName = getTextureName(MapChannel::OCCLUSION_MAP); + const auto& emissiveName = getTextureName(MapChannel::EMISSIVE_MAP); + const auto& lightmapName = getTextureName(MapChannel::LIGHTMAP_MAP); + const auto& scatteringName = getTextureName(MapChannel::SCATTERING_MAP); + + if (!albedoName.isEmpty()) { + auto url = textureMap.contains(albedoName) ? textureMap[albedoName].toUrl() : QUrl(); + auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + if (map) { + map->setTextureTransform(_albedoTransform); + // when reassigning the albedo texture we also check for the alpha channel used as opacity + map->setUseAlphaChannel(true); + } + setTextureMap(MapChannel::ALBEDO_MAP, map); + } + + if (!normalName.isEmpty()) { + auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl(); + auto map = fetchTextureMap(url, image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); + setTextureMap(MapChannel::NORMAL_MAP, map); + } + + if (!roughnessName.isEmpty()) { + auto url = textureMap.contains(roughnessName) ? textureMap[roughnessName].toUrl() : QUrl(); + // FIXME: If passing a gloss map instead of a roughmap how do we know? + auto map = fetchTextureMap(url, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + setTextureMap(MapChannel::ROUGHNESS_MAP, map); + } + + if (!metallicName.isEmpty()) { + auto url = textureMap.contains(metallicName) ? textureMap[metallicName].toUrl() : QUrl(); + // FIXME: If passing a specular map instead of a metallic how do we know? + auto map = fetchTextureMap(url, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + setTextureMap(MapChannel::METALLIC_MAP, map); + } + + if (!occlusionName.isEmpty()) { + auto url = textureMap.contains(occlusionName) ? textureMap[occlusionName].toUrl() : QUrl(); + // FIXME: we need to handle the occlusion map transform here + auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + setTextureMap(MapChannel::OCCLUSION_MAP, map); + } + + if (!emissiveName.isEmpty()) { + auto url = textureMap.contains(emissiveName) ? textureMap[emissiveName].toUrl() : QUrl(); + auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + setTextureMap(MapChannel::EMISSIVE_MAP, map); + } + + if (!scatteringName.isEmpty()) { + auto url = textureMap.contains(scatteringName) ? textureMap[scatteringName].toUrl() : QUrl(); + auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); + setTextureMap(MapChannel::SCATTERING_MAP, map); + } + + if (!lightmapName.isEmpty()) { + auto url = textureMap.contains(lightmapName) ? textureMap[lightmapName].toUrl() : QUrl(); + auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + if (map) { + map->setTextureTransform(_lightmapTransform); + map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); + } + setTextureMap(MapChannel::LIGHTMAP_MAP, map); + } +} + +bool NetworkMaterial::isMissingTexture() { + for (auto& networkTexture : _textures) { + auto& texture = networkTexture.texture; + if (!texture) { + continue; + } + // Failed texture downloads need to be considered as 'loaded' + // or the object will never fade in + bool finished = texture->isFailed() || (texture->isLoaded() && texture->getGPUTexture() && texture->getGPUTexture()->isDefined()); + if (!finished) { + return true; + } + } + return false; +} + +void NetworkMaterial::checkResetOpacityMap() { + // If material textures are loaded, check the material translucency + // FIXME: This should not be done here. The opacity map should already be reset in Material::setTextureMap. + // However, currently that code can be called before the albedo map is defined, so resetOpacityMap will fail. + // Geometry::areTexturesLoaded() is called repeatedly until it returns true, so we do the check here for now + const auto& albedoTexture = _textures[NetworkMaterial::MapChannel::ALBEDO_MAP]; + if (albedoTexture.texture) { + resetOpacityMap(); + } } \ No newline at end of file diff --git a/libraries/material-networking/src/material-networking/MaterialCache.h b/libraries/material-networking/src/material-networking/MaterialCache.h new file mode 100644 index 0000000000..4e6805ca39 --- /dev/null +++ b/libraries/material-networking/src/material-networking/MaterialCache.h @@ -0,0 +1,115 @@ +// +// Created by Sam Gondelman on 2/9/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_MaterialCache_h +#define hifi_MaterialCache_h + +#include "glm/glm.hpp" + +#include +#include +#include + +#include "TextureCache.h" + +class NetworkMaterial : public graphics::Material { +public: + using MapChannel = graphics::Material::MapChannel; + + NetworkMaterial() : _textures(MapChannel::NUM_MAP_CHANNELS) {} + NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl); + NetworkMaterial(const NetworkMaterial& material); + + void setAlbedoMap(const QUrl& url, bool useAlphaChannel); + void setNormalMap(const QUrl& url, bool isBumpmap); + void setRoughnessMap(const QUrl& url, bool isGloss); + void setMetallicMap(const QUrl& url, bool isSpecular); + void setOcclusionMap(const QUrl& url); + void setEmissiveMap(const QUrl& url); + void setScatteringMap(const QUrl& url); + void setLightmapMap(const QUrl& url); + + bool isMissingTexture(); + void checkResetOpacityMap(); + +protected: + friend class Geometry; + + class Texture { + public: + QString name; + NetworkTexturePointer texture; + }; + using Textures = std::vector; + + Textures _textures; + + static const QString NO_TEXTURE; + const QString& getTextureName(MapChannel channel); + + void setTextures(const QVariantMap& textureMap); + + const bool& isOriginal() const { return _isOriginal; } + +private: + // Helpers for the ctors + QUrl getTextureUrl(const QUrl& baseUrl, const HFMTexture& hfmTexture); + graphics::TextureMapPointer fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture, + image::TextureUsage::Type type, MapChannel channel); + graphics::TextureMapPointer fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel); + + Transform _albedoTransform; + Transform _lightmapTransform; + vec2 _lightmapParams; + + bool _isOriginal { true }; +}; + +class NetworkMaterialResource : public Resource { +public: + NetworkMaterialResource(const QUrl& url); + + QString getType() const override { return "NetworkMaterial"; } + + virtual void downloadFinished(const QByteArray& data) override; + + typedef struct ParsedMaterials { + uint version { 1 }; + std::vector names; + std::unordered_map> networkMaterials; + + void reset() { + version = 1; + names.clear(); + networkMaterials.clear(); + } + + } ParsedMaterials; + + ParsedMaterials parsedMaterials; + + static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl); + static std::pair> parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl); + +private: + static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB); +}; + +using NetworkMaterialResourcePointer = QSharedPointer; + +class MaterialCache : public ResourceCache { +public: + static MaterialCache& instance(); + + NetworkMaterialResourcePointer getMaterial(const QUrl& url); + +protected: + virtual QSharedPointer createResource(const QUrl& url) override; + QSharedPointer createResourceCopy(const QSharedPointer& resource) override; +}; + +#endif diff --git a/libraries/material-networking/src/material-networking/MaterialNetworkingLogging.cpp b/libraries/material-networking/src/material-networking/MaterialNetworkingLogging.cpp new file mode 100644 index 0000000000..9a99c21240 --- /dev/null +++ b/libraries/material-networking/src/material-networking/MaterialNetworkingLogging.cpp @@ -0,0 +1,11 @@ +// +// Created by Sam Gondelman on 2/7/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "MaterialNetworkingLogging.h" + +Q_LOGGING_CATEGORY(materialnetworking, "hifi.gpu-material-network") diff --git a/libraries/material-networking/src/material-networking/MaterialNetworkingLogging.h b/libraries/material-networking/src/material-networking/MaterialNetworkingLogging.h new file mode 100644 index 0000000000..a3f220d027 --- /dev/null +++ b/libraries/material-networking/src/material-networking/MaterialNetworkingLogging.h @@ -0,0 +1,11 @@ +// +// Created by Sam Gondelman on 2/7/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +Q_DECLARE_LOGGING_CATEGORY(materialnetworking) diff --git a/libraries/model-networking/src/model-networking/ShaderCache.cpp b/libraries/material-networking/src/material-networking/ShaderCache.cpp similarity index 100% rename from libraries/model-networking/src/model-networking/ShaderCache.cpp rename to libraries/material-networking/src/material-networking/ShaderCache.cpp diff --git a/libraries/model-networking/src/model-networking/ShaderCache.h b/libraries/material-networking/src/material-networking/ShaderCache.h similarity index 100% rename from libraries/model-networking/src/model-networking/ShaderCache.h rename to libraries/material-networking/src/material-networking/ShaderCache.h diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/material-networking/src/material-networking/TextureCache.cpp similarity index 99% rename from libraries/model-networking/src/model-networking/TextureCache.cpp rename to libraries/material-networking/src/material-networking/TextureCache.cpp index 910de258f9..0e7d50a2e5 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/material-networking/src/material-networking/TextureCache.cpp @@ -44,7 +44,7 @@ #include #include "NetworkLogging.h" -#include "ModelNetworkingLogging.h" +#include "MaterialNetworkingLogging.h" #include "NetworkingConstants.h" #include #include @@ -938,7 +938,7 @@ void NetworkTexture::handleFinishedInitialLoad() { cache::FilePointer file; auto& ktxCache = textureCache->_ktxCache; if (!memKtx || !(file = ktxCache->writeFile(data, KTXCache::Metadata(filename, length)))) { - qCWarning(modelnetworking) << url << " failed to write cache file"; + qCWarning(materialnetworking) << url << " failed to write cache file"; QMetaObject::invokeMethod(resource.data(), "setImage", Q_ARG(gpu::TexturePointer, nullptr), Q_ARG(int, 0), @@ -1126,7 +1126,7 @@ void ImageReader::listSupportedImageFormats() { static std::once_flag once; std::call_once(once, []{ auto supportedFormats = QImageReader::supportedImageFormats(); - qCDebug(modelnetworking) << "List of supported Image formats:" << supportedFormats.join(", "); + qCDebug(materialnetworking) << "List of supported Image formats:" << supportedFormats.join(", "); }); } @@ -1174,7 +1174,7 @@ void ImageReader::read() { if (texture) { texture = textureCache->cacheTextureByHash(hash, texture); } else { - qCWarning(modelnetworking) << "Invalid cached KTX " << _url << " under hash " << hash.c_str() << ", recreating..."; + qCWarning(materialnetworking) << "Invalid cached KTX " << _url << " under hash " << hash.c_str() << ", recreating..."; } } } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/material-networking/src/material-networking/TextureCache.h similarity index 100% rename from libraries/model-networking/src/model-networking/TextureCache.h rename to libraries/material-networking/src/material-networking/TextureCache.h diff --git a/libraries/model-networking/src/model-networking/TextureCacheScriptingInterface.cpp b/libraries/material-networking/src/material-networking/TextureCacheScriptingInterface.cpp similarity index 100% rename from libraries/model-networking/src/model-networking/TextureCacheScriptingInterface.cpp rename to libraries/material-networking/src/material-networking/TextureCacheScriptingInterface.cpp diff --git a/libraries/model-networking/src/model-networking/TextureCacheScriptingInterface.h b/libraries/material-networking/src/material-networking/TextureCacheScriptingInterface.h similarity index 100% rename from libraries/model-networking/src/model-networking/TextureCacheScriptingInterface.h rename to libraries/material-networking/src/material-networking/TextureCacheScriptingInterface.h diff --git a/libraries/model-baker/CMakeLists.txt b/libraries/model-baker/CMakeLists.txt index 6fa7c1815a..1e67d04bc1 100644 --- a/libraries/model-baker/CMakeLists.txt +++ b/libraries/model-baker/CMakeLists.txt @@ -1,4 +1,5 @@ set(TARGET_NAME model-baker) setup_hifi_library() -link_hifi_libraries(shared task gpu graphics hfm) +link_hifi_libraries(shared shaders task gpu graphics hfm material-networking) +include_hifi_library_headers(networking) \ No newline at end of file diff --git a/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp b/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp index c9b4fec1e1..37ea184360 100644 --- a/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp +++ b/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp @@ -10,6 +10,8 @@ #include "ModelBakerLogging.h" +#include + void ApplyMaterialMappingTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) { const auto& materialsIn = input.get0(); const auto& mapping = input.get1(); diff --git a/libraries/model-networking/CMakeLists.txt b/libraries/model-networking/CMakeLists.txt index 6a7182cc33..7701f54d43 100644 --- a/libraries/model-networking/CMakeLists.txt +++ b/libraries/model-networking/CMakeLists.txt @@ -1,6 +1,5 @@ set(TARGET_NAME model-networking) setup_hifi_library() -link_hifi_libraries(shared shaders networking graphics fbx ktx image gl model-baker) -include_hifi_library_headers(gpu) +link_hifi_libraries(shared shaders networking graphics fbx material-networking model-baker) include_hifi_library_headers(hfm) include_hifi_library_headers(task) diff --git a/libraries/model-networking/src/model-networking/MaterialCache.h b/libraries/model-networking/src/model-networking/MaterialCache.h deleted file mode 100644 index 6abadfc030..0000000000 --- a/libraries/model-networking/src/model-networking/MaterialCache.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Created by Sam Gondelman on 2/9/2018 -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -#ifndef hifi_MaterialCache_h -#define hifi_MaterialCache_h - -#include - -#include "glm/glm.hpp" - -#include "ModelCache.h" - -class NetworkMaterialResource : public Resource { -public: - NetworkMaterialResource(const QUrl& url); - - QString getType() const override { return "NetworkMaterial"; } - - virtual void downloadFinished(const QByteArray& data) override; - - typedef struct ParsedMaterials { - uint version { 1 }; - std::vector names; - std::unordered_map> networkMaterials; - - void reset() { - version = 1; - names.clear(); - networkMaterials.clear(); - } - - } ParsedMaterials; - - ParsedMaterials parsedMaterials; - - static ParsedMaterials parseJSONMaterials(const QJsonDocument& materialJSON, const QUrl& baseUrl); - static std::pair> parseJSONMaterial(const QJsonObject& materialJSON, const QUrl& baseUrl); - -private: - static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB); -}; - -using NetworkMaterialResourcePointer = QSharedPointer; - -class MaterialCache : public ResourceCache { -public: - static MaterialCache& instance(); - - NetworkMaterialResourcePointer getMaterial(const QUrl& url); - -protected: - virtual QSharedPointer createResource(const QUrl& url) override; - QSharedPointer createResourceCopy(const QSharedPointer& resource) override; -}; - -#endif diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index a4eba0c7a9..20ca97a681 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -556,310 +556,4 @@ void GeometryResourceWatcher::resourceRefreshed() { // _instance.reset(); } -NetworkMaterial::NetworkMaterial(const NetworkMaterial& m) : - Material(m), - _textures(m._textures), - _albedoTransform(m._albedoTransform), - _lightmapTransform(m._lightmapTransform), - _lightmapParams(m._lightmapParams), - _isOriginal(m._isOriginal) -{} - -const QString NetworkMaterial::NO_TEXTURE = QString(); - -const QString& NetworkMaterial::getTextureName(MapChannel channel) { - if (_textures[channel].texture) { - return _textures[channel].name; - } - return NO_TEXTURE; -} - -QUrl NetworkMaterial::getTextureUrl(const QUrl& baseUrl, const HFMTexture& texture) { - if (texture.content.isEmpty()) { - // External file: search relative to the baseUrl, in case filename is relative - return baseUrl.resolved(QUrl(texture.filename)); - } else { - // Inlined file: cache under the fbx file to avoid namespace clashes - // NOTE: We cannot resolve the path because filename may be an absolute path - assert(texture.filename.size() > 0); - auto baseUrlStripped = baseUrl.toDisplayString(QUrl::RemoveFragment | QUrl::RemoveQuery | QUrl::RemoveUserInfo); - if (texture.filename.at(0) == '/') { - return baseUrlStripped + texture.filename; - } else { - return baseUrlStripped + '/' + texture.filename; - } - } -} - -graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture, - image::TextureUsage::Type type, MapChannel channel) { - - if (baseUrl.isEmpty()) { - return nullptr; - } - - const auto url = getTextureUrl(baseUrl, hfmTexture); - const auto texture = DependencyManager::get()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels); - _textures[channel] = Texture { hfmTexture.name, texture }; - - auto map = std::make_shared(); - if (texture) { - map->setTextureSource(texture->_textureSource); - } - map->setTextureTransform(hfmTexture.transform); - - return map; -} - -graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel) { - auto textureCache = DependencyManager::get(); - if (textureCache && !url.isEmpty()) { - auto texture = textureCache->getTexture(url, type); - _textures[channel].texture = texture; - - auto map = std::make_shared(); - if (texture) { - map->setTextureSource(texture->_textureSource); - } - - return map; - } - return nullptr; -} - -void NetworkMaterial::setAlbedoMap(const QUrl& url, bool useAlphaChannel) { - auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); - if (map) { - map->setUseAlphaChannel(useAlphaChannel); - setTextureMap(MapChannel::ALBEDO_MAP, map); - } -} - -void NetworkMaterial::setNormalMap(const QUrl& url, bool isBumpmap) { - auto map = fetchTextureMap(url, isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); - if (map) { - setTextureMap(MapChannel::NORMAL_MAP, map); - } -} - -void NetworkMaterial::setRoughnessMap(const QUrl& url, bool isGloss) { - auto map = fetchTextureMap(url, isGloss ? image::TextureUsage::GLOSS_TEXTURE : image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); - if (map) { - setTextureMap(MapChannel::ROUGHNESS_MAP, map); - } -} - -void NetworkMaterial::setMetallicMap(const QUrl& url, bool isSpecular) { - auto map = fetchTextureMap(url, isSpecular ? image::TextureUsage::SPECULAR_TEXTURE : image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); - if (map) { - setTextureMap(MapChannel::METALLIC_MAP, map); - } -} - -void NetworkMaterial::setOcclusionMap(const QUrl& url) { - auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); - if (map) { - setTextureMap(MapChannel::OCCLUSION_MAP, map); - } -} - -void NetworkMaterial::setEmissiveMap(const QUrl& url) { - auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); - if (map) { - setTextureMap(MapChannel::EMISSIVE_MAP, map); - } -} - -void NetworkMaterial::setScatteringMap(const QUrl& url) { - auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); - if (map) { - setTextureMap(MapChannel::SCATTERING_MAP, map); - } -} - -void NetworkMaterial::setLightmapMap(const QUrl& url) { - auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); - if (map) { - //map->setTextureTransform(_lightmapTransform); - //map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); - setTextureMap(MapChannel::LIGHTMAP_MAP, map); - } -} - -NetworkMaterial::NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl) : - graphics::Material(*material._material), - _textures(MapChannel::NUM_MAP_CHANNELS) -{ - _name = material.name.toStdString(); - if (!material.albedoTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); - if (map) { - _albedoTransform = material.albedoTexture.transform; - map->setTextureTransform(_albedoTransform); - - if (!material.opacityTexture.filename.isEmpty()) { - if (material.albedoTexture.filename == material.opacityTexture.filename) { - // Best case scenario, just indicating that the albedo map contains transparency - // TODO: Different albedo/opacity maps are not currently supported - map->setUseAlphaChannel(true); - } - } - } - - setTextureMap(MapChannel::ALBEDO_MAP, map); - } - - - if (!material.normalTexture.filename.isEmpty()) { - auto type = (material.normalTexture.isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE); - auto map = fetchTextureMap(textureBaseUrl, material.normalTexture, type, MapChannel::NORMAL_MAP); - setTextureMap(MapChannel::NORMAL_MAP, map); - } - - if (!material.roughnessTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.roughnessTexture, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); - setTextureMap(MapChannel::ROUGHNESS_MAP, map); - } else if (!material.glossTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.glossTexture, image::TextureUsage::GLOSS_TEXTURE, MapChannel::ROUGHNESS_MAP); - setTextureMap(MapChannel::ROUGHNESS_MAP, map); - } - - if (!material.metallicTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.metallicTexture, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); - setTextureMap(MapChannel::METALLIC_MAP, map); - } else if (!material.specularTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.specularTexture, image::TextureUsage::SPECULAR_TEXTURE, MapChannel::METALLIC_MAP); - setTextureMap(MapChannel::METALLIC_MAP, map); - } - - if (!material.occlusionTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.occlusionTexture, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); - if (map) { - map->setTextureTransform(material.occlusionTexture.transform); - } - setTextureMap(MapChannel::OCCLUSION_MAP, map); - } - - if (!material.emissiveTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.emissiveTexture, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); - setTextureMap(MapChannel::EMISSIVE_MAP, map); - } - - if (!material.scatteringTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.scatteringTexture, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); - setTextureMap(MapChannel::SCATTERING_MAP, map); - } - - if (!material.lightmapTexture.filename.isEmpty()) { - auto map = fetchTextureMap(textureBaseUrl, material.lightmapTexture, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); - if (map) { - _lightmapTransform = material.lightmapTexture.transform; - _lightmapParams = material.lightmapParams; - map->setTextureTransform(_lightmapTransform); - map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); - } - setTextureMap(MapChannel::LIGHTMAP_MAP, map); - } -} - -void NetworkMaterial::setTextures(const QVariantMap& textureMap) { - _isOriginal = false; - - const auto& albedoName = getTextureName(MapChannel::ALBEDO_MAP); - const auto& normalName = getTextureName(MapChannel::NORMAL_MAP); - const auto& roughnessName = getTextureName(MapChannel::ROUGHNESS_MAP); - const auto& metallicName = getTextureName(MapChannel::METALLIC_MAP); - const auto& occlusionName = getTextureName(MapChannel::OCCLUSION_MAP); - const auto& emissiveName = getTextureName(MapChannel::EMISSIVE_MAP); - const auto& lightmapName = getTextureName(MapChannel::LIGHTMAP_MAP); - const auto& scatteringName = getTextureName(MapChannel::SCATTERING_MAP); - - if (!albedoName.isEmpty()) { - auto url = textureMap.contains(albedoName) ? textureMap[albedoName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); - if (map) { - map->setTextureTransform(_albedoTransform); - // when reassigning the albedo texture we also check for the alpha channel used as opacity - map->setUseAlphaChannel(true); - } - setTextureMap(MapChannel::ALBEDO_MAP, map); - } - - if (!normalName.isEmpty()) { - auto url = textureMap.contains(normalName) ? textureMap[normalName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); - setTextureMap(MapChannel::NORMAL_MAP, map); - } - - if (!roughnessName.isEmpty()) { - auto url = textureMap.contains(roughnessName) ? textureMap[roughnessName].toUrl() : QUrl(); - // FIXME: If passing a gloss map instead of a roughmap how do we know? - auto map = fetchTextureMap(url, image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); - setTextureMap(MapChannel::ROUGHNESS_MAP, map); - } - - if (!metallicName.isEmpty()) { - auto url = textureMap.contains(metallicName) ? textureMap[metallicName].toUrl() : QUrl(); - // FIXME: If passing a specular map instead of a metallic how do we know? - auto map = fetchTextureMap(url, image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); - setTextureMap(MapChannel::METALLIC_MAP, map); - } - - if (!occlusionName.isEmpty()) { - auto url = textureMap.contains(occlusionName) ? textureMap[occlusionName].toUrl() : QUrl(); - // FIXME: we need to handle the occlusion map transform here - auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); - setTextureMap(MapChannel::OCCLUSION_MAP, map); - } - - if (!emissiveName.isEmpty()) { - auto url = textureMap.contains(emissiveName) ? textureMap[emissiveName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); - setTextureMap(MapChannel::EMISSIVE_MAP, map); - } - - if (!scatteringName.isEmpty()) { - auto url = textureMap.contains(scatteringName) ? textureMap[scatteringName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); - setTextureMap(MapChannel::SCATTERING_MAP, map); - } - - if (!lightmapName.isEmpty()) { - auto url = textureMap.contains(lightmapName) ? textureMap[lightmapName].toUrl() : QUrl(); - auto map = fetchTextureMap(url, image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); - if (map) { - map->setTextureTransform(_lightmapTransform); - map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); - } - setTextureMap(MapChannel::LIGHTMAP_MAP, map); - } -} - -bool NetworkMaterial::isMissingTexture() { - for (auto& networkTexture : _textures) { - auto& texture = networkTexture.texture; - if (!texture) { - continue; - } - // Failed texture downloads need to be considered as 'loaded' - // or the object will never fade in - bool finished = texture->isFailed() || (texture->isLoaded() && texture->getGPUTexture() && texture->getGPUTexture()->isDefined()); - if (!finished) { - return true; - } - } - return false; -} - -void NetworkMaterial::checkResetOpacityMap() { - // If material textures are loaded, check the material translucency - // FIXME: This should not be done here. The opacity map should already be reset in Material::setTextureMap. - // However, currently that code can be called before the albedo map is defined, so resetOpacityMap will fail. - // Geometry::areTexturesLoaded() is called repeatedly until it returns true, so we do the check here for now - const auto& albedoTexture = _textures[NetworkMaterial::MapChannel::ALBEDO_MAP]; - if (albedoTexture.texture) { - resetOpacityMap(); - } -} - #include "ModelCache.moc" diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 497cae86a3..59fd6a4b74 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -15,17 +15,13 @@ #include #include -#include #include #include "FBXSerializer.h" -#include "TextureCache.h" +#include +#include #include "ModelLoader.h" -// Alias instead of derive to avoid copying - -class NetworkTexture; -class NetworkMaterial; class MeshPart; class GeometryMappingResource; @@ -166,59 +162,6 @@ private: ModelLoader _modelLoader; }; -class NetworkMaterial : public graphics::Material { -public: - using MapChannel = graphics::Material::MapChannel; - - NetworkMaterial() : _textures(MapChannel::NUM_MAP_CHANNELS) {} - NetworkMaterial(const HFMMaterial& material, const QUrl& textureBaseUrl); - NetworkMaterial(const NetworkMaterial& material); - - void setAlbedoMap(const QUrl& url, bool useAlphaChannel); - void setNormalMap(const QUrl& url, bool isBumpmap); - void setRoughnessMap(const QUrl& url, bool isGloss); - void setMetallicMap(const QUrl& url, bool isSpecular); - void setOcclusionMap(const QUrl& url); - void setEmissiveMap(const QUrl& url); - void setScatteringMap(const QUrl& url); - void setLightmapMap(const QUrl& url); - - bool isMissingTexture(); - void checkResetOpacityMap(); - -protected: - friend class Geometry; - - class Texture { - public: - QString name; - NetworkTexturePointer texture; - }; - using Textures = std::vector; - - Textures _textures; - - static const QString NO_TEXTURE; - const QString& getTextureName(MapChannel channel); - - void setTextures(const QVariantMap& textureMap); - - const bool& isOriginal() const { return _isOriginal; } - -private: - // Helpers for the ctors - QUrl getTextureUrl(const QUrl& baseUrl, const HFMTexture& hfmTexture); - graphics::TextureMapPointer fetchTextureMap(const QUrl& baseUrl, const HFMTexture& hfmTexture, - image::TextureUsage::Type type, MapChannel channel); - graphics::TextureMapPointer fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel); - - Transform _albedoTransform; - Transform _lightmapTransform; - vec2 _lightmapParams; - - bool _isOriginal { true }; -}; - class MeshPart { public: MeshPart(int mesh, int part, int material) : meshID { mesh }, partID { part }, materialID { material } {} diff --git a/libraries/model-networking/src/model-networking/ModelNetworkingLogging.cpp b/libraries/model-networking/src/model-networking/ModelNetworkingLogging.cpp index 0c44fa33eb..d76efec31a 100644 --- a/libraries/model-networking/src/model-networking/ModelNetworkingLogging.cpp +++ b/libraries/model-networking/src/model-networking/ModelNetworkingLogging.cpp @@ -8,4 +8,4 @@ #include "ModelNetworkingLogging.h" -Q_LOGGING_CATEGORY(modelnetworking, "hifi.gpu-network") +Q_LOGGING_CATEGORY(modelnetworking, "hifi.gpu-model-network") diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index 5249ed2950..d7ce40641d 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -7,6 +7,7 @@ include_hifi_library_headers(avatars) include_hifi_library_headers(audio) include_hifi_library_headers(octree) include_hifi_library_headers(animation) +include_hifi_library_headers(material-networking) include_hifi_library_headers(model-networking) include_hifi_library_headers(image) include_hifi_library_headers(ktx) diff --git a/libraries/procedural/CMakeLists.txt b/libraries/procedural/CMakeLists.txt index 6d6610a323..06d2a3d1ed 100644 --- a/libraries/procedural/CMakeLists.txt +++ b/libraries/procedural/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME procedural) setup_hifi_library() -link_hifi_libraries(shared gpu shaders networking graphics model-networking ktx image) +link_hifi_libraries(shared gpu shaders networking graphics material-networking ktx image) diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 3e10678ba7..8477e69afc 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -19,8 +19,8 @@ #include #include #include -#include -#include +#include +#include using UniformLambdas = std::list>; const size_t MAX_PROCEDURAL_TEXTURE_CHANNELS{ 4 }; diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 2b092bff2a..833d78bb74 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME render-utils) # pull in the resources.qrc file qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc") setup_hifi_library(Gui Network Qml Quick Script) -link_hifi_libraries(shared task ktx gpu shaders graphics graphics-scripting model-networking render animation fbx image procedural) +link_hifi_libraries(shared task ktx gpu shaders graphics graphics-scripting material-networking model-networking render animation fbx image procedural) include_hifi_library_headers(audio) include_hifi_library_headers(networking) include_hifi_library_headers(octree) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 5f3763ac2a..6f6f2ab856 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index d6c1e419b9..f010666e19 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -1,2 +1,2 @@ // Compatibility -#include +#include diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 346c6e50f6..82c408f386 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -17,6 +17,6 @@ if (NOT ANDROID) endif () -link_hifi_libraries(shared networking octree shaders gpu procedural graphics model-networking ktx recording avatars fbx hfm entities controllers animation audio physics image midi) +link_hifi_libraries(shared networking octree shaders gpu procedural graphics material-networking model-networking ktx recording avatars fbx hfm entities controllers animation audio physics image midi) # ui includes gl, but link_hifi_libraries does not use transitive includes, so gl must be explicit include_hifi_library_headers(gl) diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt index 8e43397c19..dcb2e39e1b 100644 --- a/plugins/openvr/CMakeLists.txt +++ b/plugins/openvr/CMakeLists.txt @@ -11,7 +11,7 @@ if (WIN32 AND (NOT USE_GLES)) setup_hifi_plugin(Gui Qml Multimedia) link_hifi_libraries(shared task gl qml networking controllers ui plugins display-plugins ui-plugins input-plugins script-engine - audio-client render-utils graphics shaders gpu render model-networking model-baker hfm fbx ktx image procedural ${PLATFORM_GL_BACKEND}) + audio-client render-utils graphics shaders gpu render material-networking model-networking model-baker hfm fbx ktx image procedural ${PLATFORM_GL_BACKEND}) include_hifi_library_headers(octree) target_openvr() From 709f784feacdf5d8d8abbce276b6c9f519d94ddc Mon Sep 17 00:00:00 2001 From: raveenajain Date: Fri, 8 Feb 2019 16:51:18 -0800 Subject: [PATCH 058/139] :} --- libraries/fbx/src/GLTFSerializer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 9a23a9428f..d6de3d4b25 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1095,6 +1095,7 @@ HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) { fbxtex.content = _glbBinary.mid(offset, length); fbxtex.filename = textureUrl.toEncoded().append(texture.source); + } if (url.contains("data:image/jpeg;base64,") || url.contains("data:image/png;base64,")) { fbxtex.content = requestEmbeddedData(url); From 23806ed67d73bf870b0a98a336581679bd94e165 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Fri, 8 Feb 2019 14:33:55 -0800 Subject: [PATCH 059/139] Add support for GLTF roughness/metallic --- libraries/fbx/src/GLTFSerializer.cpp | 2 + libraries/hfm/src/hfm/HFM.h | 2 + libraries/image/src/image/Image.cpp | 46 ++++++++++++++++++- libraries/image/src/image/Image.h | 3 +- .../src/model-networking/ModelCache.cpp | 2 +- .../src/model-networking/TextureCache.cpp | 36 ++++++++++----- .../src/model-networking/TextureCache.h | 6 ++- .../shared/src/shared/ColorChannelMapping.h | 37 +++++++++++++++ 8 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 libraries/shared/src/shared/ColorChannelMapping.h diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 96c236f703..f7493ad88b 100644 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1057,8 +1057,10 @@ void GLTFSerializer::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& mat } if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) { fbxmat.roughnessTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); + fbxmat.roughnessTexture.channelMapping = ColorChannelMapping::GREEN; fbxmat.useRoughnessMap = true; fbxmat.metallicTexture = getHFMTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); + fbxmat.metallicTexture.channelMapping = ColorChannelMapping::BLUE; fbxmat.useMetallicMap = true; } if (material.pbrMetallicRoughness.defined["roughnessFactor"]) { diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 1bd87332a1..f733e4ef69 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -24,6 +24,7 @@ #include #include +#include #if defined(Q_OS_ANDROID) #define HFM_PACK_NORMALS 0 @@ -125,6 +126,7 @@ public: QString name; QByteArray filename; QByteArray content; + ColorChannelMapping channelMapping { ColorChannelMapping::NONE }; Transform transform; int maxNumPixels { MAX_NUM_PIXELS_FOR_FBX_TEXTURE }; diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index ac2813667f..0f7acabf85 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -221,7 +222,45 @@ QImage processRawImageData(QIODevice& content, const std::string& filename) { return QImage(); } -gpu::TexturePointer processImage(std::shared_ptr content, const std::string& filename, +void mapToRedChannel(QImage& image, ColorChannelMapping sourceChannel) { + // Change format of image so we know exactly how to process it + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + + for (int i = 0; i < image.height(); i++) { + QRgb* pixel = reinterpret_cast(image.scanLine(i)); + // Past end pointer + QRgb* lineEnd = pixel + image.width(); + + // Transfer channel data from source to target + for (; pixel < lineEnd; pixel++) { + int colorValue; + switch (sourceChannel) { + case ColorChannelMapping::RED: + colorValue = qRed(*pixel); + break; + case ColorChannelMapping::GREEN: + colorValue = qGreen(*pixel); + break; + case ColorChannelMapping::BLUE: + colorValue = qBlue(*pixel); + break; + case ColorChannelMapping::ALPHA: + colorValue = qAlpha(*pixel); + break; + default: + colorValue = qRed(*pixel); + break; + } + + // Dump the color in the red channel, ignore the rest + *pixel = qRgba(colorValue, 0, 0, 0); + } + } +} + +gpu::TexturePointer processImage(std::shared_ptr content, const std::string& filename, ColorChannelMapping channelMapping, int maxNumPixels, TextureUsage::Type textureType, bool compress, BackendTarget target, const std::atomic& abortProcessing) { @@ -252,6 +291,11 @@ gpu::TexturePointer processImage(std::shared_ptr content, const std:: QSize(originalWidth, originalHeight) << " to " << QSize(imageWidth, imageHeight) << ")"; } + + // Re-map to image with single red channel texture if requested + if (channelMapping != ColorChannelMapping::NONE) { + mapToRedChannel(image, channelMapping); + } auto loader = TextureUsage::getTextureLoaderForType(textureType); auto texture = loader(std::move(image), filename, compress, target, abortProcessing); diff --git a/libraries/image/src/image/Image.h b/libraries/image/src/image/Image.h index ae72a183b3..cc68ef6718 100644 --- a/libraries/image/src/image/Image.h +++ b/libraries/image/src/image/Image.h @@ -15,6 +15,7 @@ #include #include +#include class QByteArray; class QImage; @@ -81,7 +82,7 @@ gpu::TexturePointer processCubeTextureColorFromImage(QImage&& srcImage, const st const QStringList getSupportedFormats(); -gpu::TexturePointer processImage(std::shared_ptr content, const std::string& url, +gpu::TexturePointer processImage(std::shared_ptr content, const std::string& url, ColorChannelMapping channelMapping, int maxNumPixels, TextureUsage::Type textureType, bool compress, gpu::BackendTarget target, const std::atomic& abortProcessing = false); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 1535f5cfad..0da683789e 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -599,7 +599,7 @@ graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl } const auto url = getTextureUrl(baseUrl, hfmTexture); - const auto texture = DependencyManager::get()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels); + const auto texture = DependencyManager::get()->getTexture(url, type, hfmTexture.content, hfmTexture.maxNumPixels, hfmTexture.channelMapping); _textures[channel] = Texture { hfmTexture.name, texture }; auto map = std::make_shared(); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 910de258f9..fe68c4ca6e 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -192,6 +192,7 @@ public: image::TextureUsage::Type type; const QByteArray& content; int maxNumPixels; + ColorChannelMapping channelMapping; }; namespace std { @@ -206,19 +207,19 @@ namespace std { struct hash { size_t operator()(const TextureExtra& a) const { size_t result = 0; - hash_combine(result, (int)a.type, a.content, a.maxNumPixels); + hash_combine(result, (int)a.type, a.content, a.maxNumPixels, a.channelMapping); return result; } }; } -ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels) { +ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNumPixels, ColorChannelMapping channelMapping) { auto byteArray = QByteArray(); - TextureExtra extra = { (image::TextureUsage::Type)type, byteArray, maxNumPixels }; + TextureExtra extra = { (image::TextureUsage::Type)type, byteArray, maxNumPixels, channelMapping }; return ResourceCache::prefetch(url, &extra, std::hash()(extra)); } -NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) { +NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels, ColorChannelMapping channelMapping) { if (url.scheme() == RESOURCE_SCHEME) { return getResourceTexture(url); } @@ -228,7 +229,7 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUs query.addQueryItem("skybox", ""); modifiedUrl.setQuery(query.toString()); } - TextureExtra extra = { type, content, maxNumPixels }; + TextureExtra extra = { type, content, maxNumPixels, channelMapping }; return ResourceCache::getResource(modifiedUrl, QUrl(), &extra, std::hash()(extra)).staticCast(); } @@ -346,6 +347,7 @@ NetworkTexture::NetworkTexture(const QUrl& url) : NetworkTexture::NetworkTexture(const NetworkTexture& other) : Resource(other), _type(other._type), + _channelMapping(other._channelMapping), _currentlyLoadingResourceType(other._currentlyLoadingResourceType), _originalWidth(other._originalWidth), _originalHeight(other._originalHeight), @@ -353,6 +355,11 @@ NetworkTexture::NetworkTexture(const NetworkTexture& other) : _height(other._height), _maxNumPixels(other._maxNumPixels) { + if (_width == 0 || _height == 0 || + other._currentlyLoadingResourceType == ResourceType::META || + (other._currentlyLoadingResourceType == ResourceType::KTX && other._ktxResourceState != KTXResourceState::WAITING_FOR_MIP_REQUEST)) { + _startedLoading = false; + } } static bool isLocalUrl(const QUrl& url) { @@ -364,6 +371,7 @@ void NetworkTexture::setExtra(void* extra) { const TextureExtra* textureExtra = static_cast(extra); _type = textureExtra ? textureExtra->type : image::TextureUsage::DEFAULT_TEXTURE; _maxNumPixels = textureExtra ? textureExtra->maxNumPixels : ABSOLUTE_MAX_TEXTURE_NUM_PIXELS; + _channelMapping = textureExtra ? textureExtra->channelMapping : ColorChannelMapping::NONE; _textureSource = std::make_shared(_url, (int)_type); _lowestRequestedMipLevel = 0; @@ -425,7 +433,8 @@ gpu::TexturePointer NetworkTexture::getFallbackTexture() const { class ImageReader : public QRunnable { public: ImageReader(const QWeakPointer& resource, const QUrl& url, - const QByteArray& data, int maxNumPixels); + const QByteArray& data, size_t extraHash, int maxNumPixels, + ColorChannelMapping channelMapping); void run() override final; void read(); @@ -435,7 +444,9 @@ private: QWeakPointer _resource; QUrl _url; QByteArray _content; + size_t _extraHash; int _maxNumPixels; + ColorChannelMapping _channelMapping; }; NetworkTexture::~NetworkTexture() { @@ -1068,7 +1079,7 @@ void NetworkTexture::loadTextureContent(const QByteArray& content) { return; } - QThreadPool::globalInstance()->start(new ImageReader(_self, _url, content, _maxNumPixels)); + QThreadPool::globalInstance()->start(new ImageReader(_self, _url, content, _extraHash, _maxNumPixels, _channelMapping)); } void NetworkTexture::refresh() { @@ -1093,11 +1104,13 @@ void NetworkTexture::refresh() { Resource::refresh(); } -ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, int maxNumPixels) : +ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, size_t extraHash, int maxNumPixels, const ColorChannelMapping channelMapping) : _resource(resource), _url(url), _content(data), - _maxNumPixels(maxNumPixels) + _extraHash(extraHash), + _maxNumPixels(maxNumPixels), + _channelMapping(channelMapping) { DependencyManager::get()->incrementStat("PendingProcessing"); listSupportedImageFormats(); @@ -1152,11 +1165,12 @@ void ImageReader::read() { } auto networkTexture = resource.staticCast(); - // Hash the source image to for KTX caching + // Hash the source image and extra to for KTX caching std::string hash; { QCryptographicHash hasher(QCryptographicHash::Md5); hasher.addData(_content); + hasher.addData(std::to_string(_extraHash).c_str()); hash = hasher.result().toHex().toStdString(); } @@ -1204,7 +1218,7 @@ void ImageReader::read() { constexpr bool shouldCompress = false; #endif auto target = getBackendTarget(); - texture = image::processImage(std::move(buffer), _url.toString().toStdString(), _maxNumPixels, networkTexture->getTextureType(), shouldCompress, target); + texture = image::processImage(std::move(buffer), _url.toString().toStdString(), _channelMapping, _maxNumPixels, networkTexture->getTextureType(), shouldCompress, target); if (!texture) { QMetaObject::invokeMethod(resource.data(), "setImage", diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index d744d060b6..44f7a0034c 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -96,6 +96,7 @@ private: friend class ImageReader; image::TextureUsage::Type _type; + ColorChannelMapping _channelMapping; enum class ResourceType { META, @@ -178,7 +179,8 @@ public: /// Loads a texture from the specified URL. NetworkTexturePointer getTexture(const QUrl& url, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE, - const QByteArray& content = QByteArray(), int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS); + const QByteArray& content = QByteArray(), int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, + ColorChannelMapping channelMapping = ColorChannelMapping::NONE); gpu::TexturePointer getTextureByHash(const std::string& hash); gpu::TexturePointer cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture); @@ -201,7 +203,7 @@ signals: protected: // Overload ResourceCache::prefetch to allow specifying texture type for loads - Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS); + Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, ColorChannelMapping channelMapping = ColorChannelMapping::NONE); virtual QSharedPointer createResource(const QUrl& url) override; QSharedPointer createResourceCopy(const QSharedPointer& resource) override; diff --git a/libraries/shared/src/shared/ColorChannelMapping.h b/libraries/shared/src/shared/ColorChannelMapping.h new file mode 100644 index 0000000000..c400ec1414 --- /dev/null +++ b/libraries/shared/src/shared/ColorChannelMapping.h @@ -0,0 +1,37 @@ +// +// ColorChannelMapping.h +// libraries/shared/src +// +// Created by Sabrina Shanman on 2019/02/05. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_ColorChannelMapping_h +#define hifi_ColorChannelMapping_h + +#include "../RegisteredMetaTypes.h" + +enum class ColorChannelMapping { + NONE, + RED, + GREEN, + BLUE, + ALPHA, + COUNT +}; + +namespace std { + template <> + struct hash { + size_t operator()(const ColorChannelMapping& a) const { + size_t result = 0; + hash_combine(result, (int)a); + return result; + } + }; +}; + +#endif // hifi_ColorChannelMapping_h From dff98f462f621493fa31c61df033cdb13b3fe79c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sat, 9 Feb 2019 13:13:13 -0800 Subject: [PATCH 060/139] Removed unnecessary of spaces. --- tools/nitpick/ui/Nitpick.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/nitpick/ui/Nitpick.ui b/tools/nitpick/ui/Nitpick.ui index 319452233f..16aaa9594d 100644 --- a/tools/nitpick/ui/Nitpick.ui +++ b/tools/nitpick/ui/Nitpick.ui @@ -43,7 +43,7 @@ - 3 + 0 @@ -85,7 +85,7 @@ - Create all MD files + Create all MD files @@ -124,7 +124,7 @@ - Create all Recursive Scripts + Create all Recursive Scripts From b2fb7a737be139b4a53f586d6e2550b8187c03bf Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sat, 9 Feb 2019 13:21:36 -0800 Subject: [PATCH 061/139] Ready for testing. --- tools/nitpick/src/Nitpick.cpp | 2 +- tools/nitpick/src/Test.cpp | 154 +++++++++++++--------------------- tools/nitpick/src/Test.h | 9 +- 3 files changed, 65 insertions(+), 100 deletions(-) diff --git a/tools/nitpick/src/Nitpick.cpp b/tools/nitpick/src/Nitpick.cpp index 78ed0ca0af..fa53730ce0 100644 --- a/tools/nitpick/src/Nitpick.cpp +++ b/tools/nitpick/src/Nitpick.cpp @@ -40,7 +40,7 @@ Nitpick::Nitpick(QWidget* parent) : QMainWindow(parent) { _ui.plainTextEdit->setReadOnly(true); - setWindowTitle("Nitpick - v2.0.1"); + setWindowTitle("Nitpick - v2.1.0"); } Nitpick::~Nitpick() { diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp index 2e62296146..59583cda8b 100644 --- a/tools/nitpick/src/Test.cpp +++ b/tools/nitpick/src/Test.cpp @@ -758,47 +758,66 @@ void Test::createAllRecursiveScripts() { return; } + createAllRecursiveScripts(_testsRootDirectory); createRecursiveScript(_testsRootDirectory, false); - - QDirIterator it(_testsRootDirectory, QDirIterator::Subdirectories); - while (it.hasNext()) { - QString directory = it.next(); - - // Only process directories - QDir dir; - if (!isAValidDirectory(directory)) { - continue; - } - - // Only process directories that have sub-directories - bool hasNoSubDirectories{ true }; - QDirIterator it2(directory, QDirIterator::Subdirectories); - while (it2.hasNext()) { - QString directory2 = it2.next(); - - // Only process directories - QDir dir; - if (isAValidDirectory(directory2)) { - hasNoSubDirectories = false; - break; - } - } - - if (!hasNoSubDirectories) { - createRecursiveScript(directory, false); - } - } - QMessageBox::information(0, "Success", "Scripts have been created"); } -void Test::createRecursiveScript(const QString& topLevelDirectory, bool interactiveMode) { - const QString recursiveTestsScriptName("testRecursive.js"); - const QString recursiveTestsFilename(topLevelDirectory + "/" + recursiveTestsScriptName); +void Test::createAllRecursiveScripts(const QString& directory) { + QDirIterator it(directory, QDirIterator::Subdirectories); + + while (it.hasNext()) { + QString nextDirectory = it.next(); + if (isAValidDirectory(nextDirectory)) { + createAllRecursiveScripts(nextDirectory); + createRecursiveScript(nextDirectory, false); + } + } +} + +void Test::createRecursiveScript(const QString& directory, bool interactiveMode) { + // If folder contains a test, then we are at a leaf + const QString testPathname{ directory + "/" + TEST_FILENAME }; + if (QFileInfo(testPathname).exists()) { + return; + } + + // Directories are included in reverse order. The nitpick scripts use a stack mechanism, + // so this ensures that the tests run in alphabetical order (a convenience when debugging) + QStringList directories; + QDirIterator it(directory); + while (it.hasNext()) { + QString subDirectory = it.next(); + + // Only process directories + if (!isAValidDirectory(subDirectory)) { + continue; + } + + const QString testPathname{ subDirectory + "/" + TEST_FILENAME }; + if (QFileInfo(testPathname).exists()) { + // Current folder contains a test script + directories.push_front(testPathname); + } + + const QString testRecursivePathname{ subDirectory + "/" + TEST_RECURSIVE_FILENAME }; + if (QFileInfo(testRecursivePathname).exists()) { + // Current folder contains a recursive script + directories.push_front(testRecursivePathname); + } + } + + // If 'directories' is empty, this means that this recursive script has no tests to call, so it is redundant + if (directories.length() == 0) { + return; + } + + // Open the recursive script file + const QString recursiveTestsFilename(directory + "/" + TEST_RECURSIVE_FILENAME); QFile recursiveTestsFile(recursiveTestsFilename); if (!recursiveTestsFile.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Failed to create \"" + recursiveTestsScriptName + "\" in directory \"" + topLevelDirectory + "\""); + "Failed to create \"" + TEST_RECURSIVE_FILENAME + "\" in directory \"" + directory + "\""); exit(-1); } @@ -812,72 +831,16 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact QString user = nitpick->getSelectedUser(); textStream << "PATH_TO_THE_REPO_PATH_UTILS_FILE = \"https://raw.githubusercontent.com/" + user + "/hifi_tests/" + branch + - "/tests/utils/branchUtils.js\";" - << endl; - textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl; - textStream << "var nitpick = createNitpick(Script.resolvePath(\".\"));" << endl << endl; + "/tests/utils/branchUtils.js\";" + << endl; + textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl << endl; - textStream << "var testsRootPath = nitpick.getTestsRootPath();" << endl << endl; - - // Wait 10 seconds before starting - textStream << "if (typeof Test !== 'undefined') {" << endl; - textStream << " Test.wait(10000);" << endl; - textStream << "};" << endl << endl; + textStream << "if (typeof nitpick === 'undefined') var nitpick = createNitpick(Script.resolvePath(\".\"));" << endl; + textStream << "if (typeof testsRootPath === 'undefined') var testsRootPath = nitpick.getTestsRootPath();" << endl << endl; textStream << "nitpick.enableRecursive();" << endl; textStream << "nitpick.enableAuto();" << endl << endl; - // This is used to verify that the recursive test contains at least one test - bool testFound{ false }; - - // Directories are included in reverse order. The nitpick scripts use a stack mechanism, - // so this ensures that the tests run in alphabetical order (a convenience when debugging) - QStringList directories; - - // First test if top-level folder has a test.js file - const QString testPathname{ topLevelDirectory + "/" + TEST_FILENAME }; - QFileInfo fileInfo(testPathname); - if (fileInfo.exists()) { - // Current folder contains a test - directories.push_front(testPathname); - - testFound = true; - } - - QDirIterator it(topLevelDirectory, QDirIterator::Subdirectories); - while (it.hasNext()) { - QString directory = it.next(); - - // Only process directories - QDir dir(directory); - if (!isAValidDirectory(directory)) { - continue; - } - - const QString testPathname{ directory + "/" + TEST_FILENAME }; - QFileInfo fileInfo(testPathname); - if (fileInfo.exists()) { - // Current folder contains a test - directories.push_front(testPathname); - - testFound = true; - } - } - - if (interactiveMode && !testFound) { - QMessageBox::information(0, "Failure", "No \"" + TEST_FILENAME + "\" files found"); - recursiveTestsFile.close(); - return; - } - - // If 'directories' is empty, this means that this recursive script has no tests to call, so it is redundant - // The script will be closed and deleted - if (directories.length() == 0) { - recursiveTestsFile.close(); - QFile::remove(recursiveTestsFilename); - return; - } - // Now include the test scripts for (int i = 0; i < directories.length(); ++i) { includeTest(textStream, directories.at(i)); @@ -928,7 +891,6 @@ void Test::createTestsOutline() { QString directory = it.next(); // Only process directories - QDir dir; if (!isAValidDirectory(directory)) { continue; } diff --git a/tools/nitpick/src/Test.h b/tools/nitpick/src/Test.h index aafd2f5711..842e4bdb48 100644 --- a/tools/nitpick/src/Test.h +++ b/tools/nitpick/src/Test.h @@ -72,9 +72,11 @@ public: void updateTestRailRunResult(); - void createRecursiveScript(); void createAllRecursiveScripts(); - void createRecursiveScript(const QString& topLevelDirectory, bool interactiveMode); + void createAllRecursiveScripts(const QString& directory); + + void createRecursiveScript(); + void createRecursiveScript(const QString& directory, bool interactiveMode); int compareImageLists(); int checkTextResults(); @@ -109,7 +111,8 @@ private: bool _isRunningFromCommandLine{ false }; bool _isRunningInAutomaticTestRun{ false }; - const QString TEST_FILENAME { "test.js" }; + const QString TEST_FILENAME{ "test.js" }; + const QString TEST_RECURSIVE_FILENAME{ "testRecursive.js" }; const QString TEST_RESULTS_FOLDER { "TestResults" }; const QString TEST_RESULTS_FILENAME { "TestResults.txt" }; From 20841a0eea1237dc8278f506ec18150e8245547a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Sat, 9 Feb 2019 16:42:34 -0800 Subject: [PATCH 062/139] fix skybox loading I think and pull in sabrina's ktx caching fix --- .../src/model-networking/TextureCache.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 910de258f9..c7235337c2 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -335,12 +335,8 @@ int networkTexturePointerMetaTypeId = qRegisterMetaType(url); - _lowestRequestedMipLevel = 0; - _loaded = true; } NetworkTexture::NetworkTexture(const NetworkTexture& other) : @@ -425,7 +421,7 @@ gpu::TexturePointer NetworkTexture::getFallbackTexture() const { class ImageReader : public QRunnable { public: ImageReader(const QWeakPointer& resource, const QUrl& url, - const QByteArray& data, int maxNumPixels); + const QByteArray& data, size_t extraHash, int maxNumPixels); void run() override final; void read(); @@ -435,6 +431,7 @@ private: QWeakPointer _resource; QUrl _url; QByteArray _content; + size_t _extraHash; int _maxNumPixels; }; @@ -1068,7 +1065,7 @@ void NetworkTexture::loadTextureContent(const QByteArray& content) { return; } - QThreadPool::globalInstance()->start(new ImageReader(_self, _url, content, _maxNumPixels)); + QThreadPool::globalInstance()->start(new ImageReader(_self, _url, content, _extraHash, _maxNumPixels)); } void NetworkTexture::refresh() { @@ -1093,10 +1090,11 @@ void NetworkTexture::refresh() { Resource::refresh(); } -ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, int maxNumPixels) : +ImageReader::ImageReader(const QWeakPointer& resource, const QUrl& url, const QByteArray& data, size_t extraHash, int maxNumPixels) : _resource(resource), _url(url), _content(data), + _extraHash(extraHash), _maxNumPixels(maxNumPixels) { DependencyManager::get()->incrementStat("PendingProcessing"); @@ -1152,11 +1150,12 @@ void ImageReader::read() { } auto networkTexture = resource.staticCast(); - // Hash the source image to for KTX caching + // Hash the source image and extraHash for KTX caching std::string hash; { QCryptographicHash hasher(QCryptographicHash::Md5); hasher.addData(_content); + hasher.addData(std::to_string(_extraHash).c_str()); hash = hasher.result().toHex().toStdString(); } From d3e0aa5d8cd2cb69afb1afadadb17b29a9187a5b Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sun, 10 Feb 2019 20:32:38 -0800 Subject: [PATCH 063/139] Make sure only top-level recursive script runs recursively. --- tools/nitpick/src/Test.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp index 59583cda8b..20d5ad89a6 100644 --- a/tools/nitpick/src/Test.cpp +++ b/tools/nitpick/src/Test.cpp @@ -835,8 +835,8 @@ void Test::createRecursiveScript(const QString& directory, bool interactiveMode) << endl; textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl << endl; - textStream << "if (typeof nitpick === 'undefined') var nitpick = createNitpick(Script.resolvePath(\".\"));" << endl; - textStream << "if (typeof testsRootPath === 'undefined') var testsRootPath = nitpick.getTestsRootPath();" << endl << endl; + textStream << "if (typeof nitpick === 'undefined') nitpick = createNitpick(Script.resolvePath(\".\"));" << endl; + textStream << "if (typeof testsRootPath === 'undefined') testsRootPath = nitpick.getTestsRootPath();" << endl << endl; textStream << "nitpick.enableRecursive();" << endl; textStream << "nitpick.enableAuto();" << endl << endl; @@ -847,7 +847,10 @@ void Test::createRecursiveScript(const QString& directory, bool interactiveMode) } textStream << endl; - textStream << "nitpick.runRecursive();" << endl; + textStream << "if (typeof runningRecursive === 'undefined') {" << endl; + textStream << " runningRecursive = true;" << endl; + textStream << " nitpick.runRecursive();" << endl; + textStream << "}" << endl << endl; recursiveTestsFile.close(); } From 0f291612c3b92dcce2d0d323234e896824fbd448 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Mon, 11 Feb 2019 09:04:41 -0800 Subject: [PATCH 064/139] Fix invalid processImage calls in TextureBaker.cpp --- libraries/baking/src/TextureBaker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/baking/src/TextureBaker.cpp b/libraries/baking/src/TextureBaker.cpp index 2516323c37..b9e476b714 100644 --- a/libraries/baking/src/TextureBaker.cpp +++ b/libraries/baking/src/TextureBaker.cpp @@ -154,7 +154,7 @@ void TextureBaker::processTexture() { gpu::BackendTarget::GLES32 }}; for (auto target : BACKEND_TARGETS) { - auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(), + auto processedTexture = image::processImage(buffer, _textureURL.toString().toStdString(), ColorChannelMapping::NONE, ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, true, target, _abortProcessing); if (!processedTexture) { @@ -197,7 +197,7 @@ void TextureBaker::processTexture() { // Uncompressed KTX if (_textureType == image::TextureUsage::Type::CUBE_TEXTURE) { buffer->reset(); - auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), + auto processedTexture = image::processImage(std::move(buffer), _textureURL.toString().toStdString(), ColorChannelMapping::NONE, ABSOLUTE_MAX_TEXTURE_NUM_PIXELS, _textureType, false, gpu::BackendTarget::GL45, _abortProcessing); if (!processedTexture) { handleError("Could not process texture " + _textureURL.toString()); From f7d7136b3ea9dc98e8b715072210d1ab47d7e263 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Mon, 11 Feb 2019 09:06:26 -0800 Subject: [PATCH 065/139] Do not have hash specialization just for ColorChannelMapping --- .../src/model-networking/TextureCache.cpp | 2 +- libraries/shared/src/shared/ColorChannelMapping.h | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index fe68c4ca6e..36893b4280 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -207,7 +207,7 @@ namespace std { struct hash { size_t operator()(const TextureExtra& a) const { size_t result = 0; - hash_combine(result, (int)a.type, a.content, a.maxNumPixels, a.channelMapping); + hash_combine(result, (int)a.type, a.content, a.maxNumPixels, (int)a.channelMapping); return result; } }; diff --git a/libraries/shared/src/shared/ColorChannelMapping.h b/libraries/shared/src/shared/ColorChannelMapping.h index c400ec1414..0f70b9d9f7 100644 --- a/libraries/shared/src/shared/ColorChannelMapping.h +++ b/libraries/shared/src/shared/ColorChannelMapping.h @@ -23,15 +23,4 @@ enum class ColorChannelMapping { COUNT }; -namespace std { - template <> - struct hash { - size_t operator()(const ColorChannelMapping& a) const { - size_t result = 0; - hash_combine(result, (int)a); - return result; - } - }; -}; - #endif // hifi_ColorChannelMapping_h From 5840f272ede0b261f997d29a8bb18687e4aa2887 Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Mon, 11 Feb 2019 09:07:45 -0800 Subject: [PATCH 066/139] Store mapped single channel texture with alpha of 255 just to be safe --- libraries/image/src/image/Image.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 0f7acabf85..bce322c9ee 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -255,7 +255,7 @@ void mapToRedChannel(QImage& image, ColorChannelMapping sourceChannel) { } // Dump the color in the red channel, ignore the rest - *pixel = qRgba(colorValue, 0, 0, 0); + *pixel = qRgba(colorValue, 0, 0, 255); } } } From 4f03157f3989afb4d337bc951f1a2c8dfd70af19 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 11 Feb 2019 10:20:55 -0800 Subject: [PATCH 067/139] working on fst material mapping --- libraries/material-networking/CMakeLists.txt | 2 +- .../src/material-networking/MaterialCache.h | 2 + .../model-baker/ApplyMaterialMappingTask.cpp | 57 ----------------- .../model-baker/src/model-baker/Baker.cpp | 23 +++---- libraries/model-baker/src/model-baker/Baker.h | 3 + .../model-baker/ParseMaterialMappingTask.cpp | 63 +++++++++++++++++++ ...ppingTask.h => ParseMaterialMappingTask.h} | 14 +++-- .../src/model-networking/ModelCache.cpp | 3 + .../src/model-networking/ModelCache.h | 2 + libraries/networking/src/ResourceCache.h | 2 +- .../render-utils/src/CauterizedModel.cpp | 1 + libraries/render-utils/src/Model.cpp | 50 ++++++++++++++- libraries/render-utils/src/Model.h | 3 + 13 files changed, 146 insertions(+), 79 deletions(-) delete mode 100644 libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp create mode 100644 libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp rename libraries/model-baker/src/model-baker/{ApplyMaterialMappingTask.h => ParseMaterialMappingTask.h} (62%) diff --git a/libraries/material-networking/CMakeLists.txt b/libraries/material-networking/CMakeLists.txt index 4ade61230a..2bf8ea213d 100644 --- a/libraries/material-networking/CMakeLists.txt +++ b/libraries/material-networking/CMakeLists.txt @@ -1,5 +1,5 @@ set(TARGET_NAME material-networking) setup_hifi_library() -link_hifi_libraries(shared shaders networking graphics fbx ktx image gl) +link_hifi_libraries(shared shaders networking graphics ktx image gl) include_hifi_library_headers(gpu) include_hifi_library_headers(hfm) \ No newline at end of file diff --git a/libraries/material-networking/src/material-networking/MaterialCache.h b/libraries/material-networking/src/material-networking/MaterialCache.h index 4e6805ca39..d327aedb22 100644 --- a/libraries/material-networking/src/material-networking/MaterialCache.h +++ b/libraries/material-networking/src/material-networking/MaterialCache.h @@ -71,6 +71,7 @@ private: class NetworkMaterialResource : public Resource { public: + NetworkMaterialResource() : Resource() {} NetworkMaterialResource(const QUrl& url); QString getType() const override { return "NetworkMaterial"; } @@ -100,6 +101,7 @@ private: }; using NetworkMaterialResourcePointer = QSharedPointer; +using MaterialMapping = std::vector>; class MaterialCache : public ResourceCache { public: diff --git a/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp b/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp deleted file mode 100644 index 37ea184360..0000000000 --- a/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// Created by Sam Gondelman on 2/7/2019 -// Copyright 2019 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "ApplyMaterialMappingTask.h" - -#include "ModelBakerLogging.h" - -#include - -void ApplyMaterialMappingTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) { - const auto& materialsIn = input.get0(); - const auto& mapping = input.get1(); - - auto materialsOut = materialsIn; - - auto mappingIter = mapping.find("materialMap"); - if (mappingIter != mapping.end()) { - QByteArray materialMapValue = mappingIter.value().toByteArray(); - QJsonObject materialMap = QJsonDocument::fromJson(materialMapValue).object(); - if (materialMap.isEmpty()) { - qCDebug(model_baker) << "Material Map found but did not produce valid JSON:" << materialMapValue; - } else { - for (auto& material : materialsOut) { - auto materialMapIter = materialMap.find(material.name); - if (materialMapIter != materialMap.end()) { - QJsonObject materialOptions = materialMapIter.value().toObject(); - qCDebug(model_baker) << "Mapping material:" << material.name << " with HFMaterial: " << materialOptions; - - { - auto scatteringIter = materialOptions.find("scattering"); - if (scatteringIter != materialOptions.end()) { - float scattering = (float)scatteringIter.value().toDouble(); - material._material->setScattering(scattering); - } - } - - { - auto scatteringMapIter = materialOptions.find("scatteringMap"); - if (scatteringMapIter != materialOptions.end()) { - QByteArray scatteringMap = scatteringMapIter.value().toVariant().toByteArray(); - material.scatteringTexture = HFMTexture(); - material.scatteringTexture.name = material.name + ".scatteringMap"; - material.scatteringTexture.filename = scatteringMap; - } - } - } - } - } - } - - output = materialsOut; -} diff --git a/libraries/model-baker/src/model-baker/Baker.cpp b/libraries/model-baker/src/model-baker/Baker.cpp index 981d799f12..037cfb7912 100644 --- a/libraries/model-baker/src/model-baker/Baker.cpp +++ b/libraries/model-baker/src/model-baker/Baker.cpp @@ -20,7 +20,6 @@ #include "CalculateBlendshapeNormalsTask.h" #include "CalculateBlendshapeTangentsTask.h" #include "PrepareJointsTask.h" -#include "ApplyMaterialMappingTask.h" namespace baker { @@ -102,7 +101,7 @@ namespace baker { class BuildModelTask { public: - using Input = VaryingSet6, std::vector, QMap, QHash, QHash>; + using Input = VaryingSet5, std::vector, QMap, QHash>; using Output = hfm::Model::Pointer; using JobModel = Job::ModelIO; @@ -112,7 +111,6 @@ namespace baker { hfmModelOut->joints = QVector::fromStdVector(input.get2()); hfmModelOut->jointRotationOffsets = input.get3(); hfmModelOut->jointIndices = input.get4(); - hfmModelOut->materials = input.get5(); output = hfmModelOut; } }; @@ -120,9 +118,9 @@ namespace baker { class BakerEngineBuilder { public: using Input = VaryingSet2; - using Output = hfm::Model::Pointer; + using Output = VaryingSet2; using JobModel = Task::ModelIO; - void build(JobModel& model, const Varying& input, Varying& hfmModelOut) { + void build(JobModel& model, const Varying& input, Varying& output) { const auto& hfmModelIn = input.getN(0); const auto& mapping = input.getN(1); @@ -156,17 +154,19 @@ namespace baker { const auto jointRotationOffsets = jointInfoOut.getN(1); const auto jointIndices = jointInfoOut.getN(2); - // Apply material mapping - const auto materialMappingInputs = ApplyMaterialMappingTask::Input(materials, mapping).asVarying(); - const auto materialsOut = model.addJob("ApplyMaterialMapping", materialMappingInputs); + // Parse material mapping + const auto materialMappingInputs = ParseMaterialMappingTask::Input(materials, mapping).asVarying(); + const auto materialMapping = model.addJob("ParseMaterialMapping", materialMappingInputs); // Combine the outputs into a new hfm::Model const auto buildBlendshapesInputs = BuildBlendshapesTask::Input(blendshapesPerMeshIn, normalsPerBlendshapePerMesh, tangentsPerBlendshapePerMesh).asVarying(); const auto blendshapesPerMeshOut = model.addJob("BuildBlendshapes", buildBlendshapesInputs); const auto buildMeshesInputs = BuildMeshesTask::Input(meshesIn, graphicsMeshes, normalsPerMesh, tangentsPerMesh, blendshapesPerMeshOut).asVarying(); const auto meshesOut = model.addJob("BuildMeshes", buildMeshesInputs); - const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices, materialsOut).asVarying(); - hfmModelOut = model.addJob("BuildModel", buildModelInputs); + const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices).asVarying(); + const auto hfmModelOut = model.addJob("BuildModel", buildModelInputs); + + output = Output(hfmModelOut, materialMapping); } }; @@ -178,7 +178,8 @@ namespace baker { void Baker::run() { _engine->run(); - hfmModel = _engine->getOutput().get(); + hfmModel = _engine->getOutput().get().get0(); + materialMapping = _engine->getOutput().get().get1(); } }; diff --git a/libraries/model-baker/src/model-baker/Baker.h b/libraries/model-baker/src/model-baker/Baker.h index 41989d73df..542be0b559 100644 --- a/libraries/model-baker/src/model-baker/Baker.h +++ b/libraries/model-baker/src/model-baker/Baker.h @@ -18,6 +18,8 @@ #include "Engine.h" +#include "ParseMaterialMappingTask.h" + namespace baker { class Baker { public: @@ -27,6 +29,7 @@ namespace baker { // Outputs, available after run() is called hfm::Model::Pointer hfmModel; + MaterialMapping materialMapping; protected: EnginePointer _engine; diff --git a/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp new file mode 100644 index 0000000000..7a4acb595a --- /dev/null +++ b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.cpp @@ -0,0 +1,63 @@ +// +// Created by Sam Gondelman on 2/7/2019 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ParseMaterialMappingTask.h" + +#include "ModelBakerLogging.h" + +void ParseMaterialMappingTask::run(const baker::BakeContextPointer& context, const Input& input, Output& output) { + const auto& materialsIn = input.get0(); + const auto& mapping = input.get1(); + + MaterialMapping materialMapping; + + auto mappingIter = mapping.find("materialMap"); + if (mappingIter != mapping.end()) { + QByteArray materialMapValue = mappingIter.value().toByteArray(); + QJsonObject materialMap = QJsonDocument::fromJson(materialMapValue).object(); + if (materialMap.isEmpty()) { + qCDebug(model_baker) << "Material Map found but did not produce valid JSON:" << materialMapValue; + } else { + auto mappingKeys = materialMap.keys(); + for (auto mapping : mappingKeys) { + auto mappingValue = materialMap[mapping].toObject(); + + // Old subsurface scattering mapping + { + auto scatteringIter = mappingValue.find("scattering"); + auto scatteringMapIter = mappingValue.find("scatteringMap"); + if (scatteringIter != mappingValue.end() || scatteringMapIter != mappingValue.end()) { + std::shared_ptr material = std::make_shared(); + + if (scatteringIter != mappingValue.end()) { + float scattering = (float)scatteringIter.value().toDouble(); + material->setScattering(scattering); + } + + if (scatteringMapIter != mappingValue.end()) { + QString scatteringMap = scatteringMapIter.value().toString(); + material->setScatteringMap(scatteringMap); + } + + material->setDefaultFallthrough(true); + + NetworkMaterialResourcePointer materialResource = NetworkMaterialResourcePointer(new NetworkMaterialResource(), [](NetworkMaterialResource* ptr) { ptr->deleteLater(); }); + materialResource->moveToThread(qApp->thread()); + materialResource->parsedMaterials.names.push_back("scattering"); + materialResource->parsedMaterials.networkMaterials["scattering"] = material; + + materialMapping.push_back(std::pair("mat::" + mapping.toStdString(), materialResource)); + continue; + } + } + } + } + } + + output = materialMapping; +} diff --git a/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.h b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h similarity index 62% rename from libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.h rename to libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h index 271c80fe67..3e48c00acf 100644 --- a/libraries/model-baker/src/model-baker/ApplyMaterialMappingTask.h +++ b/libraries/model-baker/src/model-baker/ParseMaterialMappingTask.h @@ -6,8 +6,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_ApplyMaterialMappingTask_h -#define hifi_ApplyMaterialMappingTask_h +#ifndef hifi_ParseMaterialMappingTask_h +#define hifi_ParseMaterialMappingTask_h #include @@ -15,13 +15,15 @@ #include "Engine.h" -class ApplyMaterialMappingTask { +#include + +class ParseMaterialMappingTask { public: using Input = baker::VaryingSet2, QVariantHash>; - using Output = QHash; - using JobModel = baker::Job::ModelIO; + using Output = MaterialMapping; + using JobModel = baker::Job::ModelIO; void run(const baker::BakeContextPointer& context, const Input& input, Output& output); }; -#endif // hifi_ApplyMaterialMappingTask_h \ No newline at end of file +#endif // hifi_ParseMaterialMappingTask_h \ No newline at end of file diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 20ca97a681..0ed518937d 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -174,6 +174,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { void GeometryMappingResource::onGeometryMappingLoaded(bool success) { if (success && _geometryResource) { _hfmModel = _geometryResource->_hfmModel; + _materialMapping = _geometryResource->_materialMapping; _meshParts = _geometryResource->_meshParts; _meshes = _geometryResource->_meshes; _materials = _geometryResource->_materials; @@ -341,6 +342,7 @@ void GeometryDefinitionResource::setGeometryDefinition(HFMModel::Pointer hfmMode // Assume ownership of the processed HFMModel _hfmModel = modelBaker.hfmModel; + _materialMapping = modelBaker.materialMapping; // Copy materials QHash materialIDAtlas; @@ -437,6 +439,7 @@ const QVariantMap Geometry::getTextures() const { // FIXME: The materials should only be copied when modified, but the Model currently caches the original Geometry::Geometry(const Geometry& geometry) { _hfmModel = geometry._hfmModel; + _materialMapping = geometry._materialMapping; _meshes = geometry._meshes; _meshParts = geometry._meshParts; diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 59fd6a4b74..4cd7048dca 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -45,6 +45,7 @@ public: bool isHFMModelLoaded() const { return (bool)_hfmModel; } const HFMModel& getHFMModel() const { return *_hfmModel; } + const MaterialMapping& getMaterialMapping() const { return _materialMapping; } const GeometryMeshes& getMeshes() const { return *_meshes; } const std::shared_ptr getShapeMaterial(int shapeID) const; @@ -60,6 +61,7 @@ protected: // Shared across all geometries, constant throughout lifetime std::shared_ptr _hfmModel; + MaterialMapping _materialMapping; std::shared_ptr _meshes; std::shared_ptr _meshParts; diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 740bdadc48..4693bc0613 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -359,7 +359,7 @@ class Resource : public QObject { Q_OBJECT public: - + Resource() : QObject(), _loaded(true) {} Resource(const Resource& other); Resource(const QUrl& url); virtual ~Resource(); diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 81a81c5602..691dae0339 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -97,6 +97,7 @@ void CauterizedModel::createRenderItemSet() { } } _blendshapeOffsetsInitialized = true; + applyMaterialMapping(); } else { Model::createRenderItemSet(); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 0206bd6963..722f12eceb 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1465,6 +1465,7 @@ void Model::createRenderItemSet() { } } _blendshapeOffsetsInitialized = true; + applyMaterialMapping(); } bool Model::isRenderable() const { @@ -1519,17 +1520,60 @@ std::set Model::getMeshIDsFromMaterialID(QString parentMaterialNam return toReturn; } +void Model::applyMaterialMapping() { + auto renderItemsKey = _renderItemKeyGlobalFlags; + PrimitiveMode primitiveMode = getPrimitiveMode(); + bool useDualQuaternionSkinning = _useDualQuaternionSkinning; + + render::Transaction transaction; + std::unordered_map priorityMap; + auto& materialMapping = getMaterialMapping(); + qDebug() << "boop" << materialMapping.size(); + for (auto& mapping : materialMapping) { + std::set shapeIDs = getMeshIDsFromMaterialID(QString(mapping.first.c_str())); + + qDebug() << "boop2" << mapping.first.c_str() << shapeIDs.size(); + if (shapeIDs.size() == 0) { + continue; + } + + auto networkMaterialResource = mapping.second; + qDebug() << (bool)networkMaterialResource; + if (networkMaterialResource && networkMaterialResource->isLoaded() && networkMaterialResource->parsedMaterials.names.size() > 0) { + auto networkMaterial = networkMaterialResource->parsedMaterials.networkMaterials[networkMaterialResource->parsedMaterials.names[0]]; + for (auto shapeID : shapeIDs) { + if (shapeID < _modelMeshRenderItemIDs.size()) { + auto itemID = _modelMeshRenderItemIDs[shapeID]; + auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; + bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + graphics::MaterialLayer material = graphics::MaterialLayer(networkMaterial, ++priorityMap[shapeID]); + transaction.updateItem(itemID, [material, renderItemsKey, + invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) { + data.addMaterial(material); + // if the material changed, we might need to update our item key or shape key + data.updateKey(renderItemsKey); + data.setShapeKey(invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning); + }); + } + } + } + } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +} + void Model::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) { std::set shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str())); + + auto renderItemsKey = _renderItemKeyGlobalFlags; + PrimitiveMode primitiveMode = getPrimitiveMode(); + bool useDualQuaternionSkinning = _useDualQuaternionSkinning; + render::Transaction transaction; for (auto shapeID : shapeIDs) { if (shapeID < _modelMeshRenderItemIDs.size()) { auto itemID = _modelMeshRenderItemIDs[shapeID]; - auto renderItemsKey = _renderItemKeyGlobalFlags; - PrimitiveMode primitiveMode = getPrimitiveMode(); auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); - bool useDualQuaternionSkinning = _useDualQuaternionSkinning; transaction.updateItem(itemID, [material, renderItemsKey, invalidatePayloadShapeKey, primitiveMode, useDualQuaternionSkinning](ModelMeshPartPayload& data) { data.addMaterial(material); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index aadfca78ba..672a4c61eb 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -183,6 +183,7 @@ public: /// Provided as a convenience, will crash if !isLoaded() // And so that getHFMModel() isn't chained everywhere const HFMModel& getHFMModel() const { assert(isLoaded()); return _renderGeometry->getHFMModel(); } + const MaterialMapping& getMaterialMapping() const { assert(isLoaded()); return _renderGeometry->getMaterialMapping(); } bool isActive() const { return isLoaded(); } @@ -373,6 +374,8 @@ signals: protected: + void applyMaterialMapping(); + void setBlendshapeCoefficients(const QVector& coefficients) { _blendshapeCoefficients = coefficients; } const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } From 44c163b7cc95c7e681d76378031c0386a56cb60e Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 11 Feb 2019 10:30:51 -0800 Subject: [PATCH 068/139] Tweak inventory-delete message to be more accurate --- interface/resources/qml/hifi/commerce/purchases/Purchases.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index bcc2a2821c..dc892e6640 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -607,7 +607,7 @@ Rectangle { } else if (msg.method === "showTrashLightbox") { lightboxPopup.titleText = "Send \"" + msg.itemName + "\" to Trash"; lightboxPopup.bodyText = "Sending this item to the Trash means you will no longer own this item " + - "and it will be inaccessible to you from Purchases.\n\nThis action cannot be undone."; + "and it will be inaccessible to you from Inventory.\n\nThis action cannot be undone."; lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = function() { lightboxPopup.visible = false; From 4f2223ced3452f9aaeb2b60ba92372e3cb3bc44c Mon Sep 17 00:00:00 2001 From: Simon Walton <36682372+SimonWalton-HiFi@users.noreply.github.com> Date: Mon, 11 Feb 2019 14:17:55 -0800 Subject: [PATCH 069/139] Change max update to 10 Hz --- interface/resources/qml/hifi/Pal.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 92c608fa3c..7c22b98dc2 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -43,7 +43,7 @@ Rectangle { property bool currentlyEditingDisplayName: false property bool punctuationMode: false; property double loudSortTime: 0.0; - readonly property double kLOUD_SORT_PERIOD_MS: 500.0; + readonly property double kLOUD_SORT_PERIOD_MS: 100.0; HifiConstants { id: hifi; } RootHttpRequest { id: http; } From 5428bb19dcd186fea35cbd9e764e54d0262049bb Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 12 Feb 2019 11:49:49 +1300 Subject: [PATCH 070/139] Add "Avatar Script" JSDoc API classification --- interface/src/AboutUtil.h | 3 ++- interface/src/AvatarBookmarks.h | 1 + interface/src/LODManager.h | 1 + interface/src/LocationBookmarks.h | 1 + interface/src/SpeechRecognizer.h | 1 + interface/src/audio/AudioScope.h | 1 + interface/src/avatar/AvatarManager.h | 1 + interface/src/avatar/MyAvatar.h | 1 + interface/src/devices/DdeFaceTracker.h | 1 + .../src/raypick/LaserPointerScriptingInterface.h | 1 + interface/src/raypick/PickScriptingInterface.h | 1 + interface/src/raypick/PointerScriptingInterface.h | 1 + interface/src/raypick/RayPickScriptingInterface.h | 1 + .../src/scripting/AccountServicesScriptingInterface.h | 1 + interface/src/scripting/Audio.h | 1 + interface/src/scripting/ClipboardScriptingInterface.h | 1 + .../src/scripting/ControllerScriptingInterface.h | 1 + interface/src/scripting/DesktopScriptingInterface.h | 3 ++- .../src/scripting/GooglePolyScriptingInterface.h | 1 + interface/src/scripting/HMDScriptingInterface.h | 1 + interface/src/scripting/KeyboardScriptingInterface.h | 1 + interface/src/scripting/MenuScriptingInterface.h | 1 + interface/src/scripting/SelectionScriptingInterface.h | 1 + interface/src/scripting/SettingsScriptingInterface.h | 1 + interface/src/scripting/WalletScriptingInterface.h | 1 + interface/src/scripting/WindowScriptingInterface.h | 1 + interface/src/ui/AvatarInputs.h | 1 + interface/src/ui/Snapshot.h | 1 + interface/src/ui/Stats.h | 1 + interface/src/ui/overlays/Overlays.h | 1 + libraries/animation/src/AnimationCache.h | 1 + .../animation/src/AnimationCacheScriptingInterface.h | 1 + libraries/audio-client/src/AudioIOStats.h | 2 ++ libraries/audio/src/AudioEffectOptions.h | 1 + libraries/audio/src/Sound.h | 1 + libraries/audio/src/SoundCacheScriptingInterface.h | 1 + .../src/controllers/impl/MappingBuilderProxy.h | 1 + .../src/controllers/impl/RouteBuilderProxy.h | 1 + .../src/display-plugins/CompositorHelper.h | 1 + libraries/entities/src/EntityScriptingInterface.h | 1 + .../graphics-scripting/GraphicsScriptingInterface.h | 1 + libraries/midi/src/Midi.h | 1 + .../model-networking/ModelCacheScriptingInterface.h | 1 + .../model-networking/TextureCacheScriptingInterface.h | 1 + libraries/networking/src/AddressManager.h | 1 + libraries/networking/src/MessagesClient.h | 1 + libraries/networking/src/ResourceCache.h | 1 + libraries/networking/src/ResourceScriptingInterface.h | 1 + libraries/plugins/src/plugins/SteamClientPlugin.h | 1 + libraries/pointers/src/Pick.h | 1 + libraries/script-engine/src/AssetScriptingInterface.h | 1 + libraries/script-engine/src/FileScriptingInterface.h | 1 + libraries/script-engine/src/Mat4.h | 1 + libraries/script-engine/src/Quat.h | 1 + .../script-engine/src/RecordingScriptingInterface.h | 1 + libraries/script-engine/src/SceneScriptingInterface.h | 2 ++ libraries/script-engine/src/ScriptAudioInjector.h | 1 + libraries/script-engine/src/ScriptEngine.cpp | 1 + libraries/script-engine/src/ScriptEngine.h | 1 + libraries/script-engine/src/ScriptEngines.h | 1 + libraries/script-engine/src/ScriptUUID.h | 1 + libraries/script-engine/src/ScriptsModel.h | 1 + libraries/script-engine/src/ScriptsModelFilter.h | 1 + libraries/script-engine/src/UsersScriptingInterface.h | 1 + libraries/script-engine/src/Vec3.h | 1 + libraries/shared/src/DebugDraw.h | 1 + libraries/shared/src/PathUtils.h | 1 + libraries/shared/src/RegisteredMetaTypes.h | 1 + libraries/shared/src/shared/Camera.h | 1 + libraries/task/src/task/Config.h | 1 + libraries/ui/src/InteractiveWindow.h | 1 + libraries/ui/src/OffscreenUi.cpp | 1 + libraries/ui/src/QmlWebWindowClass.h | 1 + libraries/ui/src/QmlWindowClass.h | 1 + libraries/ui/src/ui/TabletScriptingInterface.h | 4 ++++ libraries/ui/src/ui/ToolbarScriptingInterface.h | 3 +++ tools/jsdoc/plugins/hifi.js | 11 +++++++++++ 77 files changed, 96 insertions(+), 2 deletions(-) diff --git a/interface/src/AboutUtil.h b/interface/src/AboutUtil.h index 767e69842d..1495045b85 100644 --- a/interface/src/AboutUtil.h +++ b/interface/src/AboutUtil.h @@ -20,7 +20,8 @@ * * @hifi-interface * @hifi-client-entity - * + * @hifi-avatar + * * @property {string} buildDate * @property {string} buildVersion * @property {string} qtVersion diff --git a/interface/src/AvatarBookmarks.h b/interface/src/AvatarBookmarks.h index f1bc6820eb..4623e7d929 100644 --- a/interface/src/AvatarBookmarks.h +++ b/interface/src/AvatarBookmarks.h @@ -21,6 +21,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * */ diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 6206fd3539..559bae1779 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -36,6 +36,7 @@ class AABox; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} presentTime Read-only. * @property {number} engineRunTime Read-only. diff --git a/interface/src/LocationBookmarks.h b/interface/src/LocationBookmarks.h index 70ea50e2e7..8cd8e40634 100644 --- a/interface/src/LocationBookmarks.h +++ b/interface/src/LocationBookmarks.h @@ -21,6 +21,7 @@ * * @hifi-client-entity * @hifi-interface + * @hifi-avatar */ class LocationBookmarks : public Bookmarks, public Dependency { diff --git a/interface/src/SpeechRecognizer.h b/interface/src/SpeechRecognizer.h index b22ab73837..7e2acdb8ac 100644 --- a/interface/src/SpeechRecognizer.h +++ b/interface/src/SpeechRecognizer.h @@ -27,6 +27,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class SpeechRecognizer : public QObject, public Dependency { Q_OBJECT diff --git a/interface/src/audio/AudioScope.h b/interface/src/audio/AudioScope.h index 41cee8d17d..912e337670 100644 --- a/interface/src/audio/AudioScope.h +++ b/interface/src/audio/AudioScope.h @@ -31,6 +31,7 @@ class AudioScope : public QObject, public Dependency { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} scopeInput Read-only. * @property {number} scopeOutputLeft Read-only. diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 50d9e80e8b..51352ec861 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -46,6 +46,7 @@ using SortedAvatar = std::pair>; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @borrows AvatarList.getAvatarIdentifiers as getAvatarIdentifiers * @borrows AvatarList.getAvatarsInRange as getAvatarsInRange diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c53eae65d4..1a6833b988 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -66,6 +66,7 @@ class MyAvatar : public Avatar { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {Vec3} qmlPosition - A synonym for position for use by QML. * @property {boolean} shouldRenderLocally=true - If true then your avatar is rendered for you in Interface, diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index 4fe36b582e..282a347dcc 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -32,6 +32,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class DdeFaceTracker : public FaceTracker, public Dependency { diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index d85e329e9a..b02213340c 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -27,6 +27,7 @@ class LaserPointerScriptingInterface : public QObject, public Dependency { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ public: diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h index e795068cd3..1c7c8cc6d6 100644 --- a/interface/src/raypick/PickScriptingInterface.h +++ b/interface/src/raypick/PickScriptingInterface.h @@ -23,6 +23,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} PICK_ENTITIES A filter flag. Include domain and avatar entities when intersecting. Read-only.. Deprecated. * @property {number} PICK_OVERLAYS A filter flag. Include local entities when intersecting. Read-only.. Deprecated. diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h index a21c1f2470..49b13d6ce6 100644 --- a/interface/src/raypick/PointerScriptingInterface.h +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -22,6 +22,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class PointerScriptingInterface : public QObject, public Dependency { diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index 3ad0efd439..2311cd21c8 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -25,6 +25,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {number} PICK_ENTITIES Read-only. * @property {number} PICK_OVERLAYS Read-only. diff --git a/interface/src/scripting/AccountServicesScriptingInterface.h b/interface/src/scripting/AccountServicesScriptingInterface.h index fb3c329def..55445a864d 100644 --- a/interface/src/scripting/AccountServicesScriptingInterface.h +++ b/interface/src/scripting/AccountServicesScriptingInterface.h @@ -42,6 +42,7 @@ class AccountServicesScriptingInterface : public QObject { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @namespace AccountServices * @property {string} username Read-only. diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index 63758d0633..e4dcba9130 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -32,6 +32,7 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable { * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * @hifi-server-entity * @hifi-assignment-client * diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index f6a0b29779..42f2205861 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -24,6 +24,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class ClipboardScriptingInterface : public QObject { Q_OBJECT diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index b063e98992..f8adbd5c12 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -199,6 +199,7 @@ class ScriptEngine; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {Controller.Actions} Actions - Predefined actions on Interface and the user's avatar. These can be used as end * points in a {@link RouteObject} mapping. A synonym for Controller.Hardware.Actions. diff --git a/interface/src/scripting/DesktopScriptingInterface.h b/interface/src/scripting/DesktopScriptingInterface.h index db42b5ca54..c8e251eb3e 100644 --- a/interface/src/scripting/DesktopScriptingInterface.h +++ b/interface/src/scripting/DesktopScriptingInterface.h @@ -24,7 +24,8 @@ * * @hifi-interface * @hifi-client-entity - * + * @hifi-avatar + * * @property {number} width * @property {number} height * @property {number} ALWAYS_ON_TOP - InteractiveWindow flag for always showing a window on top diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index fb5aed9759..ad44ad6223 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -21,6 +21,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ class GooglePolyScriptingInterface : public QObject, public Dependency { diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 81f85409cc..f00e600858 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -31,6 +31,7 @@ class QScriptEngine; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise * {@link Vec3(0)|Vec3.ZERO}. Read-only. diff --git a/interface/src/scripting/KeyboardScriptingInterface.h b/interface/src/scripting/KeyboardScriptingInterface.h index acee10669e..68582d9bd9 100644 --- a/interface/src/scripting/KeyboardScriptingInterface.h +++ b/interface/src/scripting/KeyboardScriptingInterface.h @@ -24,6 +24,7 @@ * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @property {bool} raised - true If the keyboard is visible false otherwise * @property {bool} password - true Will show * instead of characters in the text display false otherwise diff --git a/interface/src/scripting/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h index 81cf775de8..02d5c84138 100644 --- a/interface/src/scripting/MenuScriptingInterface.h +++ b/interface/src/scripting/MenuScriptingInterface.h @@ -35,6 +35,7 @@ class MenuItemProperties; * * @hifi-interface * @hifi-client-entity + * @hifi-avatar */ /** diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index 83aec63ee2..3217efd10a 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -88,6 +88,7 @@ protected: * * @hifi-interface * @hifi-client-entity + * @hifi-avatar * * @example Outline an entity when it is grabbed by a controller.