diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 06ce6c3d6c..5c8d18cf4a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2155,6 +2155,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return QSizeF(0.0f, 0.0f); }); + Texture::setUnboundTextureForUUIDOperator([this](const QUuid& entityID) -> gpu::TexturePointer { + if (_aboutToQuit) { + return nullptr; + } + + auto renderable = getEntities()->renderableForEntityId(entityID); + if (renderable) { + return renderable->getTexture(); + } + + return nullptr; + }); + connect(this, &Application::aboutToQuit, [this]() { setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); }); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index b521ee29c4..29351cb25a 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -63,6 +63,7 @@ public: virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); static Pipeline getPipelineType(const graphics::MultiMaterial& materials); + virtual gpu::TexturePointer getTexture() { return nullptr; } virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); } diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.h b/libraries/entities-renderer/src/RenderableImageEntityItem.h index ff82dc157a..cc923daf4b 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.h +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.h @@ -24,6 +24,8 @@ public: ImageEntityRenderer(const EntityItemPointer& entity); ~ImageEntityRenderer(); + gpu::TexturePointer getTexture() override { return _texture ? _texture->getGPUTexture() : nullptr; } + protected: Item::Bound getBound(RenderArgs* args) override; ShapeKey getShapeKey() override; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 1ac415e5e5..fb04e08ec7 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -55,6 +55,8 @@ public: virtual void setProxyWindow(QWindow* proxyWindow) override; virtual QObject* getEventHandler() override; + gpu::TexturePointer getTexture() override { return _texture; } + protected: virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; diff --git a/libraries/gpu/src/gpu/Texture.cpp b/libraries/gpu/src/gpu/Texture.cpp index 1edd7d33cf..28d68f6271 100755 --- a/libraries/gpu/src/gpu/Texture.cpp +++ b/libraries/gpu/src/gpu/Texture.cpp @@ -887,16 +887,29 @@ void SphericalHarmonics::evalFromTexture(const Texture& texture, gpu::BackendTar // TextureSource +const gpu::TexturePointer TextureSource::getGPUTexture() const { + if (_gpuTextureOperator) { + return _gpuTextureOperator(); + } + return _gpuTexture; +} + void TextureSource::resetTexture(gpu::TexturePointer texture) { _gpuTexture = texture; + _gpuTextureOperator = nullptr; +} + +void TextureSource::resetTextureOperator(std::function textureOperator) { + _gpuTexture = nullptr; + _gpuTextureOperator = textureOperator; } bool TextureSource::isDefined() const { - if (_gpuTexture) { - return _gpuTexture->isDefined(); - } else { - return false; + if (_gpuTextureOperator) { + auto gpuTexture = _gpuTextureOperator(); + return gpuTexture && gpuTexture->isDefined(); } + return _gpuTexture && _gpuTexture->isDefined(); } bool Texture::setMinMip(uint16 newMinMip) { @@ -930,6 +943,7 @@ void Texture::setExternalTexture(uint32 externalId, void* externalFence) { Lock lock(_externalMutex); assert(_externalRecycler); _externalUpdates.push_back({ externalId, externalFence }); + _defined = true; } Texture::ExternalUpdates Texture::getUpdates() const { diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 54c7d49421..18df2e5d3f 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -700,16 +700,18 @@ public: void setUrl(const QUrl& url) { _imageUrl = url; } const QUrl& getUrl() const { return _imageUrl; } - const gpu::TexturePointer getGPUTexture() const { return _gpuTexture; } + const gpu::TexturePointer getGPUTexture() const; void setType(int type) { _type = type; } int getType() const { return _type; } void resetTexture(gpu::TexturePointer texture); + void resetTextureOperator(std::function textureOperator); bool isDefined() const; protected: gpu::TexturePointer _gpuTexture; + std::function _gpuTextureOperator { nullptr }; QUrl _imageUrl; int _type { 0 }; }; diff --git a/libraries/graphics/src/graphics/TextureMap.cpp b/libraries/graphics/src/graphics/TextureMap.cpp index e2f24d68ff..69e182fc9d 100755 --- a/libraries/graphics/src/graphics/TextureMap.cpp +++ b/libraries/graphics/src/graphics/TextureMap.cpp @@ -18,11 +18,7 @@ void TextureMap::setTextureSource(TextureSourcePointer& textureSource) { } bool TextureMap::isDefined() const { - if (_textureSource) { - return _textureSource->isDefined(); - } else { - return false; - } + return _textureSource && _textureSource->isDefined(); } gpu::TextureView TextureMap::getTextureView() const { diff --git a/libraries/material-networking/src/material-networking/TextureCache.cpp b/libraries/material-networking/src/material-networking/TextureCache.cpp index 64c3abb0d8..288d35c0f6 100644 --- a/libraries/material-networking/src/material-networking/TextureCache.cpp +++ b/libraries/material-networking/src/material-networking/TextureCache.cpp @@ -98,6 +98,8 @@ static const QUrl HMD_PREVIEW_FRAME_URL("resource://hmdPreviewFrame"); static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads first static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models +std::function Texture::_unboundTextureForUUIDOperator { nullptr }; + TextureCache::TextureCache() { _ktxCache->initialize(); #if defined(DISABLE_KTX_CACHE) @@ -252,6 +254,10 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUs if (url.scheme() == RESOURCE_SCHEME) { return getResourceTexture(url); } + QString decodedURL = url.toDisplayString(QUrl::FullyDecoded); + if (decodedURL.startsWith("{")) { + return getTextureByUUID(decodedURL); + } auto modifiedUrl = url; if (type == image::TextureUsage::SKY_TEXTURE) { QUrlQuery query { url.query() }; @@ -480,6 +486,12 @@ void NetworkTexture::setImage(gpu::TexturePointer texture, int originalWidth, emit networkTextureCreated(qWeakPointerCast (_self)); } +void NetworkTexture::setImageOperator(std::function textureOperator) { + _textureSource->resetTextureOperator(textureOperator); + finishedLoading((bool)textureOperator); + emit networkTextureCreated(qWeakPointerCast (_self)); +} + gpu::TexturePointer NetworkTexture::getFallbackTexture() const { return getFallbackTextureForType(_type); } @@ -1311,7 +1323,6 @@ void ImageReader::read() { } NetworkTexturePointer TextureCache::getResourceTexture(const QUrl& resourceTextureUrl) { - gpu::TexturePointer texture; if (resourceTextureUrl == SPECTATOR_CAMERA_FRAME_URL) { if (!_spectatorCameraNetworkTexture) { _spectatorCameraNetworkTexture.reset(new NetworkTexture(resourceTextureUrl, true)); @@ -1328,6 +1339,7 @@ NetworkTexturePointer TextureCache::getResourceTexture(const QUrl& resourceTextu _hmdPreviewNetworkTexture.reset(new NetworkTexture(resourceTextureUrl, true)); } if (_hmdPreviewFramebuffer) { + gpu::TexturePointer texture; texture = _hmdPreviewFramebuffer->getRenderBuffer(0); if (texture) { texture->setSource(HMD_PREVIEW_FRAME_URL.toString().toStdString()); @@ -1374,3 +1386,22 @@ void TextureCache::updateSpectatorCameraNetworkTexture() { } } } + +NetworkTexturePointer TextureCache::getTextureByUUID(const QString& uuid) { + QUuid quuid = QUuid(uuid); + if (!quuid.isNull()) { + // We mark this as a resource texture because it's just a reference to another texture. The source + // texture will be marked properly + NetworkTexturePointer toReturn = NetworkTexturePointer(new NetworkTexture(uuid, true)); + toReturn->setImageOperator(Texture::getTextureForUUIDOperator(uuid)); + return toReturn; + } + return NetworkTexturePointer(); +} + +std::function Texture::getTextureForUUIDOperator(const QUuid& uuid) { + if (_unboundTextureForUUIDOperator) { + return std::bind(_unboundTextureForUUIDOperator, uuid); + } + return nullptr; +} \ No newline at end of file diff --git a/libraries/material-networking/src/material-networking/TextureCache.h b/libraries/material-networking/src/material-networking/TextureCache.h index 754263566b..adf600d810 100644 --- a/libraries/material-networking/src/material-networking/TextureCache.h +++ b/libraries/material-networking/src/material-networking/TextureCache.h @@ -39,6 +39,12 @@ class Texture { public: gpu::TexturePointer getGPUTexture() const { return _textureSource->getGPUTexture(); } gpu::TextureSourcePointer _textureSource; + + static std::function getTextureForUUIDOperator(const QUuid& uuid); + static void setUnboundTextureForUUIDOperator(std::function textureForUUIDOperator) { _unboundTextureForUUIDOperator = textureForUUIDOperator; } + +private: + static std::function _unboundTextureForUUIDOperator; }; /// A texture loaded from the network. @@ -86,6 +92,7 @@ protected: Q_INVOKABLE void loadTextureContent(const QByteArray& content); Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight); + void setImageOperator(std::function textureOperator); Q_INVOKABLE void startRequestForNextMipLevel(); @@ -192,6 +199,8 @@ public: const gpu::FramebufferPointer& getSpectatorCameraFramebuffer(int width, int height); void updateSpectatorCameraNetworkTexture(); + NetworkTexturePointer getTextureByUUID(const QString& uuid); + static const int DEFAULT_SPECTATOR_CAM_WIDTH { 2048 }; static const int DEFAULT_SPECTATOR_CAM_HEIGHT { 1024 };