From 1d2270e9c70435b19223d0313129115f97248ca1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 14 Jan 2019 15:40:37 -0800 Subject: [PATCH] web entity fixes --- interface/src/Application.cpp | 8 +- interface/src/ui/overlays/Web3DOverlay.cpp | 9 +- interface/src/ui/overlays/Web3DOverlay.h | 4 +- .../src/RenderableWebEntityItem.cpp | 134 +++++++----------- .../src/RenderableWebEntityItem.h | 5 +- .../entities/src/EntityItemProperties.cpp | 3 + 6 files changed, 69 insertions(+), 94 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3d0e135fed..e016b4afc7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2317,7 +2317,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return DependencyManager::get()->getMyAvatar()->getWorldOrientation() * Vectors::UP; }); - render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { + render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([this](const QString& url, bool htmlContent, QSharedPointer& webSurface, bool& cachedWebSurface) { bool isTablet = url == TabletScriptingInterface::QML; if (htmlContent) { webSurface = DependencyManager::get()->acquire(render::entities::WebEntityRenderer::QML); @@ -2328,7 +2328,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (webSurface->getRootItem()) { rootItemLoadedFunctor(); } else { - connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor); + QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor); } } else { // FIXME: the tablet should use the OffscreenQmlSurfaceCache @@ -2345,7 +2345,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (webSurface->getRootItem()) { rootItemLoadedFunctor(); } else { - connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor); + QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor); } webSurface->load(url); cachedWebSurface = false; @@ -2354,7 +2354,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo const uint8_t TABLET_FPS = 90; webSurface->setMaxFps(isTablet ? TABLET_FPS : DEFAULT_MAX_FPS); }); - render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([](QSharedPointer& webSurface, bool& cachedWebSurface, std::vector& connections) { + render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([this](QSharedPointer& webSurface, bool& cachedWebSurface, std::vector& connections) { QQuickItem* rootItem = webSurface->getRootItem(); if (rootItem && rootItem->objectName() == "tabletRoot") { auto tabletScriptingInterface = DependencyManager::get(); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index de7ed45819..eb61ca7281 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -82,8 +82,7 @@ Web3DOverlay::Web3DOverlay() { connect(this, &Web3DOverlay::requestWebSurface, this, &Web3DOverlay::buildWebSurface); connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface); - render::entities::WebEntityRenderer::acquireWebSurface("", true, _webSurface, _cachedWebSurface); - _webSurface->resume(); + buildWebSurface(true); } Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) : @@ -114,12 +113,12 @@ void Web3DOverlay::destroyWebSurface() { } } -void Web3DOverlay::buildWebSurface() { +void Web3DOverlay::buildWebSurface(bool overrideWeb) { if (_webSurface) { return; } - render::entities::WebEntityRenderer::acquireWebSurface(_url, isWebContent(), _webSurface, _cachedWebSurface); + render::entities::WebEntityRenderer::acquireWebSurface(_url, overrideWeb || isWebContent(), _webSurface, _cachedWebSurface); onResizeWebSurface(); _webSurface->resume(); @@ -172,7 +171,7 @@ void Web3DOverlay::render(RenderArgs* args) { } if (!_webSurface) { - emit requestWebSurface(); + emit requestWebSurface(false); return; } diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 632b9cda3f..4265c35699 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -57,7 +57,7 @@ public: Mouse }; - void buildWebSurface(); + void buildWebSurface(bool overrideWeb = false); void destroyWebSurface(); void onResizeWebSurface(); @@ -68,7 +68,7 @@ signals: void scriptEventReceived(const QVariant& message); void webEventReceived(const QVariant& message); void resizeWebSurface(); - void requestWebSurface(); + void requestWebSurface(bool overrideWeb); protected: Transform evalRenderTransform() override; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index c45f09757b..38d1320aa2 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -79,14 +79,8 @@ WebEntityRenderer::WebEntityRenderer(const EntityItemPointer& entity) : Parent(e _texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); _texture->setSource(__FUNCTION__); - if (_currentWebCount < MAX_CONCURRENT_WEB_VIEWS) { - _currentWebCount++; - WebEntityRenderer::acquireWebSurface("", true, _webSurface, _cachedWebSurface); - _contentType = ContentType::HtmlContent; - _fadeStartTime = usecTimestampNow(); - _webSurface->resume(); - qDebug() << "boop" << this << _webSurface << _webSurface->getRootItem(); - } + _contentType = ContentType::HtmlContent; + buildWebSurface(entity, ""); _timer.setInterval(MSECS_PER_SECOND); connect(&_timer, &QTimer::timeout, this, &WebEntityRenderer::onTimeout); @@ -154,7 +148,7 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe bool WebEntityRenderer::needsRenderUpdate() const { if (resultWithReadLock([this] { - return _prevHasWebSurface != hasWebSurface() || _needsURLUpdate; + return !_webSurface; })) { return true; } @@ -181,30 +175,22 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene // destroy the existing surface (because surfaces don't support changing the root // object, so subsequent loads of content just overlap the existing content bool urlChanged = false; + auto newSourceURL = entity->getSourceUrl(); { - auto newSourceUrl = entity->getSourceUrl(); - auto newContentType = getContentType(newSourceUrl); + auto newContentType = getContentType(newSourceURL); ContentType currentContentType; withReadLock([&] { - urlChanged = _sourceURL != newSourceUrl; + urlChanged = _sourceURL != newSourceURL; currentContentType = _contentType; }); if (urlChanged) { withWriteLock([&] { - _needsURLUpdate = true; - _sourceURL = newSourceUrl; _contentType = newContentType; }); if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) { - qDebug() << "boop2" << this << _webSurface << _webSurface->getRootItem(); destroyWebSurface(); - // If we destroyed the surface, the URL change will be implicitly handled by the re-creation - urlChanged = false; - withWriteLock([&] { - _needsURLUpdate = false; - }); } } } @@ -217,67 +203,63 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene _alpha = entity->getAlpha(); if (_contentType == ContentType::NoContent) { - _prevHasWebSurface = false; return; } // This work must be done on the main thread - // If we couldn't create a new web surface, exit if (!_webSurface) { - qDebug() << "boop3" << this << _webSurface << _webSurface->getRootItem(); - buildWebSurface(entity); + buildWebSurface(entity, newSourceURL); } - _prevHasWebSurface = hasWebSurface(); - if (!_prevHasWebSurface) { - qDebug() << "boop4" << this << _webSurface << _webSurface->getRootItem(); - return; - } - - qDebug() << "boop6" << this << _webSurface << _webSurface->getRootItem(); - if (_needsURLUpdate && _contentType == ContentType::HtmlContent) { - qDebug() << "boop7" << this << _webSurface << _webSurface->getRootItem(); - _webSurface->getRootItem()->setProperty(URL_PROPERTY, _sourceURL); - _needsURLUpdate = false; - } - - { - auto scriptURL = entity->getScriptURL(); - if (_scriptURL != scriptURL) { - _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); - _scriptURL = scriptURL; - } - } - - { - auto maxFPS = entity->getMaxFPS(); - if (_maxFPS != maxFPS) { - // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. - // FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the web entity - if (QUrl(_sourceURL).host().endsWith("youtube.com", Qt::CaseInsensitive)) { - _webSurface->setMaxFps(YOUTUBE_MAX_FPS); - } else { - _webSurface->setMaxFps(_maxFPS); + if (_webSurface && _webSurface->getRootItem()) { + if (_webSurface->getRootItem()) { + if (_contentType == ContentType::HtmlContent && urlChanged) { + _webSurface->getRootItem()->setProperty(URL_PROPERTY, newSourceURL); + _sourceURL = newSourceURL; + } + + { + auto scriptURL = entity->getScriptURL(); + if (_scriptURL != scriptURL) { + _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); + _scriptURL = scriptURL; + } + } + + { + auto maxFPS = entity->getMaxFPS(); + if (_maxFPS != maxFPS) { + // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. + // FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the web entity + if (QUrl(_sourceURL).host().endsWith("youtube.com", Qt::CaseInsensitive)) { + _webSurface->setMaxFps(YOUTUBE_MAX_FPS); + } else { + _webSurface->setMaxFps(maxFPS); + } + _maxFPS = maxFPS; + } + } + + { + auto contextPosition = entity->getWorldPosition(); + if (_contextPosition != contextPosition) { + _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(contextPosition)); + _contextPosition = contextPosition; + } } - _maxFPS = maxFPS; } - } - if (_contextPosition != entity->getWorldPosition()) { - _contextPosition = entity->getWorldPosition(); - _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition)); - } - - void* key = (void*)this; - AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () { - withWriteLock([&] { - glm::vec2 windowSize = getWindowSize(entity); - _webSurface->resize(QSize(windowSize.x, windowSize.y)); - updateModelTransformAndBound(); - _renderTransform = getModelTransform(); - _renderTransform.postScale(entity->getScaledDimensions()); + void* key = (void*)this; + AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() { + withWriteLock([&] { + glm::vec2 windowSize = getWindowSize(entity); + _webSurface->resize(QSize(windowSize.x, windowSize.y)); + updateModelTransformAndBound(); + _renderTransform = getModelTransform(); + _renderTransform.postScale(entity->getScaledDimensions()); + }); }); - }); + } }); } @@ -323,18 +305,14 @@ void WebEntityRenderer::doRender(RenderArgs* args) { batch.setResourceTexture(0, nullptr); } -bool WebEntityRenderer::hasWebSurface() const { - return (bool)_webSurface && _webSurface->getRootItem(); -} - -bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { +void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const QString& newSourceURL) { if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) { qWarning() << "Too many concurrent web views to create new view"; - return false; + return; } ++_currentWebCount; - WebEntityRenderer::acquireWebSurface(_sourceURL, _contentType == ContentType::HtmlContent, _webSurface, _cachedWebSurface); + WebEntityRenderer::acquireWebSurface(newSourceURL, _contentType == ContentType::HtmlContent, _webSurface, _cachedWebSurface); _fadeStartTime = usecTimestampNow(); _webSurface->resume(); @@ -344,8 +322,6 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { _connections.push_back(QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, [entityItemID](const QVariant& message) { emit DependencyManager::get()->webEventReceived(entityItemID, message); })); - - return _webSurface->getRootItem(); } void WebEntityRenderer::destroyWebSurface() { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 545a6c878a..4affb5819d 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -65,9 +65,8 @@ protected: private: void onTimeout(); - bool buildWebSurface(const TypedEntityPointer& entity); + void buildWebSurface(const EntityItemPointer& entity, const QString& newSourceURL); void destroyWebSurface(); - bool hasWebSurface() const; glm::vec2 getWindowSize(const TypedEntityPointer& entity) const; int _geometryId{ 0 }; @@ -80,8 +79,6 @@ private: ContentType _contentType { ContentType::NoContent }; QSharedPointer _webSurface { nullptr }; - bool _prevHasWebSurface { false }; - bool _needsURLUpdate { false }; bool _cachedWebSurface { false }; gpu::TexturePointer _texture; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index dfdc7933a9..c2928d8cd0 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -3496,6 +3496,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int } if (properties.getType() == EntityTypes::Web) { + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_URL, QString, setScriptURL);