mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
web entity fixes
This commit is contained in:
parent
6fd34bf1f0
commit
1d2270e9c7
6 changed files with 69 additions and 94 deletions
|
@ -2317,7 +2317,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;
|
return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;
|
||||||
});
|
});
|
||||||
|
|
||||||
render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([](const QString& url, bool htmlContent, QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface) {
|
render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([this](const QString& url, bool htmlContent, QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface) {
|
||||||
bool isTablet = url == TabletScriptingInterface::QML;
|
bool isTablet = url == TabletScriptingInterface::QML;
|
||||||
if (htmlContent) {
|
if (htmlContent) {
|
||||||
webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(render::entities::WebEntityRenderer::QML);
|
webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(render::entities::WebEntityRenderer::QML);
|
||||||
|
@ -2328,7 +2328,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
if (webSurface->getRootItem()) {
|
if (webSurface->getRootItem()) {
|
||||||
rootItemLoadedFunctor();
|
rootItemLoadedFunctor();
|
||||||
} else {
|
} else {
|
||||||
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
|
QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// FIXME: the tablet should use the OffscreenQmlSurfaceCache
|
// FIXME: the tablet should use the OffscreenQmlSurfaceCache
|
||||||
|
@ -2345,7 +2345,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
if (webSurface->getRootItem()) {
|
if (webSurface->getRootItem()) {
|
||||||
rootItemLoadedFunctor();
|
rootItemLoadedFunctor();
|
||||||
} else {
|
} else {
|
||||||
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
|
QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
|
||||||
}
|
}
|
||||||
webSurface->load(url);
|
webSurface->load(url);
|
||||||
cachedWebSurface = false;
|
cachedWebSurface = false;
|
||||||
|
@ -2354,7 +2354,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
const uint8_t TABLET_FPS = 90;
|
const uint8_t TABLET_FPS = 90;
|
||||||
webSurface->setMaxFps(isTablet ? TABLET_FPS : DEFAULT_MAX_FPS);
|
webSurface->setMaxFps(isTablet ? TABLET_FPS : DEFAULT_MAX_FPS);
|
||||||
});
|
});
|
||||||
render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([](QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface, std::vector<QMetaObject::Connection>& connections) {
|
render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([this](QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface, std::vector<QMetaObject::Connection>& connections) {
|
||||||
QQuickItem* rootItem = webSurface->getRootItem();
|
QQuickItem* rootItem = webSurface->getRootItem();
|
||||||
if (rootItem && rootItem->objectName() == "tabletRoot") {
|
if (rootItem && rootItem->objectName() == "tabletRoot") {
|
||||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
|
|
|
@ -82,8 +82,7 @@ Web3DOverlay::Web3DOverlay() {
|
||||||
connect(this, &Web3DOverlay::requestWebSurface, this, &Web3DOverlay::buildWebSurface);
|
connect(this, &Web3DOverlay::requestWebSurface, this, &Web3DOverlay::buildWebSurface);
|
||||||
connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface);
|
connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface);
|
||||||
|
|
||||||
render::entities::WebEntityRenderer::acquireWebSurface("", true, _webSurface, _cachedWebSurface);
|
buildWebSurface(true);
|
||||||
_webSurface->resume();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) :
|
Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) :
|
||||||
|
@ -114,12 +113,12 @@ void Web3DOverlay::destroyWebSurface() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Web3DOverlay::buildWebSurface() {
|
void Web3DOverlay::buildWebSurface(bool overrideWeb) {
|
||||||
if (_webSurface) {
|
if (_webSurface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
render::entities::WebEntityRenderer::acquireWebSurface(_url, isWebContent(), _webSurface, _cachedWebSurface);
|
render::entities::WebEntityRenderer::acquireWebSurface(_url, overrideWeb || isWebContent(), _webSurface, _cachedWebSurface);
|
||||||
onResizeWebSurface();
|
onResizeWebSurface();
|
||||||
_webSurface->resume();
|
_webSurface->resume();
|
||||||
|
|
||||||
|
@ -172,7 +171,7 @@ void Web3DOverlay::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_webSurface) {
|
if (!_webSurface) {
|
||||||
emit requestWebSurface();
|
emit requestWebSurface(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
Mouse
|
Mouse
|
||||||
};
|
};
|
||||||
|
|
||||||
void buildWebSurface();
|
void buildWebSurface(bool overrideWeb = false);
|
||||||
void destroyWebSurface();
|
void destroyWebSurface();
|
||||||
void onResizeWebSurface();
|
void onResizeWebSurface();
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ signals:
|
||||||
void scriptEventReceived(const QVariant& message);
|
void scriptEventReceived(const QVariant& message);
|
||||||
void webEventReceived(const QVariant& message);
|
void webEventReceived(const QVariant& message);
|
||||||
void resizeWebSurface();
|
void resizeWebSurface();
|
||||||
void requestWebSurface();
|
void requestWebSurface(bool overrideWeb);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Transform evalRenderTransform() override;
|
Transform evalRenderTransform() override;
|
||||||
|
|
|
@ -79,14 +79,8 @@ WebEntityRenderer::WebEntityRenderer(const EntityItemPointer& entity) : Parent(e
|
||||||
_texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda());
|
_texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda());
|
||||||
_texture->setSource(__FUNCTION__);
|
_texture->setSource(__FUNCTION__);
|
||||||
|
|
||||||
if (_currentWebCount < MAX_CONCURRENT_WEB_VIEWS) {
|
_contentType = ContentType::HtmlContent;
|
||||||
_currentWebCount++;
|
buildWebSurface(entity, "");
|
||||||
WebEntityRenderer::acquireWebSurface("", true, _webSurface, _cachedWebSurface);
|
|
||||||
_contentType = ContentType::HtmlContent;
|
|
||||||
_fadeStartTime = usecTimestampNow();
|
|
||||||
_webSurface->resume();
|
|
||||||
qDebug() << "boop" << this << _webSurface << _webSurface->getRootItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
_timer.setInterval(MSECS_PER_SECOND);
|
_timer.setInterval(MSECS_PER_SECOND);
|
||||||
connect(&_timer, &QTimer::timeout, this, &WebEntityRenderer::onTimeout);
|
connect(&_timer, &QTimer::timeout, this, &WebEntityRenderer::onTimeout);
|
||||||
|
@ -154,7 +148,7 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe
|
||||||
|
|
||||||
bool WebEntityRenderer::needsRenderUpdate() const {
|
bool WebEntityRenderer::needsRenderUpdate() const {
|
||||||
if (resultWithReadLock<bool>([this] {
|
if (resultWithReadLock<bool>([this] {
|
||||||
return _prevHasWebSurface != hasWebSurface() || _needsURLUpdate;
|
return !_webSurface;
|
||||||
})) {
|
})) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -181,30 +175,22 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
|
||||||
// destroy the existing surface (because surfaces don't support changing the root
|
// destroy the existing surface (because surfaces don't support changing the root
|
||||||
// object, so subsequent loads of content just overlap the existing content
|
// object, so subsequent loads of content just overlap the existing content
|
||||||
bool urlChanged = false;
|
bool urlChanged = false;
|
||||||
|
auto newSourceURL = entity->getSourceUrl();
|
||||||
{
|
{
|
||||||
auto newSourceUrl = entity->getSourceUrl();
|
auto newContentType = getContentType(newSourceURL);
|
||||||
auto newContentType = getContentType(newSourceUrl);
|
|
||||||
ContentType currentContentType;
|
ContentType currentContentType;
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
urlChanged = _sourceURL != newSourceUrl;
|
urlChanged = _sourceURL != newSourceURL;
|
||||||
currentContentType = _contentType;
|
currentContentType = _contentType;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (urlChanged) {
|
if (urlChanged) {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_needsURLUpdate = true;
|
|
||||||
_sourceURL = newSourceUrl;
|
|
||||||
_contentType = newContentType;
|
_contentType = newContentType;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) {
|
if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) {
|
||||||
qDebug() << "boop2" << this << _webSurface << _webSurface->getRootItem();
|
|
||||||
destroyWebSurface();
|
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();
|
_alpha = entity->getAlpha();
|
||||||
|
|
||||||
if (_contentType == ContentType::NoContent) {
|
if (_contentType == ContentType::NoContent) {
|
||||||
_prevHasWebSurface = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This work must be done on the main thread
|
// This work must be done on the main thread
|
||||||
// If we couldn't create a new web surface, exit
|
|
||||||
if (!_webSurface) {
|
if (!_webSurface) {
|
||||||
qDebug() << "boop3" << this << _webSurface << _webSurface->getRootItem();
|
buildWebSurface(entity, newSourceURL);
|
||||||
buildWebSurface(entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_prevHasWebSurface = hasWebSurface();
|
if (_webSurface && _webSurface->getRootItem()) {
|
||||||
if (!_prevHasWebSurface) {
|
if (_webSurface->getRootItem()) {
|
||||||
qDebug() << "boop4" << this << _webSurface << _webSurface->getRootItem();
|
if (_contentType == ContentType::HtmlContent && urlChanged) {
|
||||||
return;
|
_webSurface->getRootItem()->setProperty(URL_PROPERTY, newSourceURL);
|
||||||
}
|
_sourceURL = newSourceURL;
|
||||||
|
}
|
||||||
qDebug() << "boop6" << this << _webSurface << _webSurface->getRootItem();
|
|
||||||
if (_needsURLUpdate && _contentType == ContentType::HtmlContent) {
|
{
|
||||||
qDebug() << "boop7" << this << _webSurface << _webSurface->getRootItem();
|
auto scriptURL = entity->getScriptURL();
|
||||||
_webSurface->getRootItem()->setProperty(URL_PROPERTY, _sourceURL);
|
if (_scriptURL != scriptURL) {
|
||||||
_needsURLUpdate = false;
|
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
|
||||||
}
|
_scriptURL = scriptURL;
|
||||||
|
}
|
||||||
{
|
}
|
||||||
auto scriptURL = entity->getScriptURL();
|
|
||||||
if (_scriptURL != scriptURL) {
|
{
|
||||||
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
|
auto maxFPS = entity->getMaxFPS();
|
||||||
_scriptURL = scriptURL;
|
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);
|
||||||
auto maxFPS = entity->getMaxFPS();
|
} else {
|
||||||
if (_maxFPS != maxFPS) {
|
_webSurface->setMaxFps(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
|
_maxFPS = maxFPS;
|
||||||
if (QUrl(_sourceURL).host().endsWith("youtube.com", Qt::CaseInsensitive)) {
|
}
|
||||||
_webSurface->setMaxFps(YOUTUBE_MAX_FPS);
|
}
|
||||||
} else {
|
|
||||||
_webSurface->setMaxFps(_maxFPS);
|
{
|
||||||
|
auto contextPosition = entity->getWorldPosition();
|
||||||
|
if (_contextPosition != contextPosition) {
|
||||||
|
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(contextPosition));
|
||||||
|
_contextPosition = contextPosition;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_maxFPS = maxFPS;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (_contextPosition != entity->getWorldPosition()) {
|
void* key = (void*)this;
|
||||||
_contextPosition = entity->getWorldPosition();
|
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() {
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
|
withWriteLock([&] {
|
||||||
}
|
glm::vec2 windowSize = getWindowSize(entity);
|
||||||
|
_webSurface->resize(QSize(windowSize.x, windowSize.y));
|
||||||
void* key = (void*)this;
|
updateModelTransformAndBound();
|
||||||
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
|
_renderTransform = getModelTransform();
|
||||||
withWriteLock([&] {
|
_renderTransform.postScale(entity->getScaledDimensions());
|
||||||
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);
|
batch.setResourceTexture(0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebEntityRenderer::hasWebSurface() const {
|
void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const QString& newSourceURL) {
|
||||||
return (bool)_webSurface && _webSurface->getRootItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
|
||||||
if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) {
|
if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) {
|
||||||
qWarning() << "Too many concurrent web views to create new view";
|
qWarning() << "Too many concurrent web views to create new view";
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
++_currentWebCount;
|
++_currentWebCount;
|
||||||
WebEntityRenderer::acquireWebSurface(_sourceURL, _contentType == ContentType::HtmlContent, _webSurface, _cachedWebSurface);
|
WebEntityRenderer::acquireWebSurface(newSourceURL, _contentType == ContentType::HtmlContent, _webSurface, _cachedWebSurface);
|
||||||
_fadeStartTime = usecTimestampNow();
|
_fadeStartTime = usecTimestampNow();
|
||||||
_webSurface->resume();
|
_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) {
|
_connections.push_back(QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, [entityItemID](const QVariant& message) {
|
||||||
emit DependencyManager::get<EntityScriptingInterface>()->webEventReceived(entityItemID, message);
|
emit DependencyManager::get<EntityScriptingInterface>()->webEventReceived(entityItemID, message);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return _webSurface->getRootItem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebEntityRenderer::destroyWebSurface() {
|
void WebEntityRenderer::destroyWebSurface() {
|
||||||
|
|
|
@ -65,9 +65,8 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onTimeout();
|
void onTimeout();
|
||||||
bool buildWebSurface(const TypedEntityPointer& entity);
|
void buildWebSurface(const EntityItemPointer& entity, const QString& newSourceURL);
|
||||||
void destroyWebSurface();
|
void destroyWebSurface();
|
||||||
bool hasWebSurface() const;
|
|
||||||
glm::vec2 getWindowSize(const TypedEntityPointer& entity) const;
|
glm::vec2 getWindowSize(const TypedEntityPointer& entity) const;
|
||||||
|
|
||||||
int _geometryId{ 0 };
|
int _geometryId{ 0 };
|
||||||
|
@ -80,8 +79,6 @@ private:
|
||||||
ContentType _contentType { ContentType::NoContent };
|
ContentType _contentType { ContentType::NoContent };
|
||||||
|
|
||||||
QSharedPointer<OffscreenQmlSurface> _webSurface { nullptr };
|
QSharedPointer<OffscreenQmlSurface> _webSurface { nullptr };
|
||||||
bool _prevHasWebSurface { false };
|
|
||||||
bool _needsURLUpdate { false };
|
|
||||||
bool _cachedWebSurface { false };
|
bool _cachedWebSurface { false };
|
||||||
gpu::TexturePointer _texture;
|
gpu::TexturePointer _texture;
|
||||||
|
|
||||||
|
|
|
@ -3496,6 +3496,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties.getType() == EntityTypes::Web) {
|
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_SOURCE_URL, QString, setSourceUrl);
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI);
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_URL, QString, setScriptURL);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_URL, QString, setScriptURL);
|
||||||
|
|
Loading…
Reference in a new issue