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;