diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 2d5f77f006..9589c842e6 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -33,15 +33,19 @@ Rectangle { property bool balanceReceived: false; property bool availableUpdatesReceived: false; property bool itemInfoReceived: false; + property bool dataReady: itemInfoReceived && ownershipStatusReceived && balanceReceived && availableUpdatesReceived; property string baseItemName: ""; property string itemName; property string itemId; property string itemHref; property string itemAuthor; property int itemEdition: -1; + property bool hasSomethingToTradeIn: alreadyOwned && (itemEdition > 0); // i.e., don't trade in your artist's proof + property bool isTradingIn: isUpdating && hasSomethingToTradeIn; + property bool isStocking: availability === 'not for sale' && creator === Account.username; property string certificateId; property double balanceAfterPurchase; - property bool alreadyOwned: false; + property bool alreadyOwned: false; // Including proofs property int itemPrice: -1; property bool isCertified; property string itemType: "unknown"; @@ -56,6 +60,8 @@ Rectangle { property string referrer; property bool isInstalled; property bool isUpdating; + property string availability: "available"; + property string creator: ""; property string baseAppURL; property int currentUpdatesPage: 1; // Style @@ -434,7 +440,7 @@ Rectangle { anchors.top: parent.top; anchors.left: itemPreviewImage.right; anchors.leftMargin: 12; - anchors.right: itemPriceContainer.left; + anchors.right: parent.right; anchors.rightMargin: 8; height: 30; // Style @@ -449,21 +455,22 @@ Rectangle { Item { id: itemPriceContainer; // Anchors - anchors.top: parent.top; - anchors.right: parent.right; + anchors.top: itemNameText.bottom; + anchors.topMargin: 8; + anchors.left: itemNameText.left; height: 30; - width: itemPriceTextLabel.width + itemPriceText.width + 20; + width: itemPriceText.width + 20; - // "HFC" balance label + // "HFC" label HiFiGlyphs { id: itemPriceTextLabel; - visible: !(root.isUpdating && root.itemEdition > 0) && (root.itemPrice > 0); + visible: !isTradingIn && (root.itemPrice > 0); text: hifi.glyphs.hfc; // Size size: 30; // Anchors - anchors.right: itemPriceText.left; - anchors.rightMargin: 4; + anchors.right: parent.right; + //anchors.rightMargin: 4; anchors.top: parent.top; anchors.topMargin: 0; width: paintedWidth; @@ -473,13 +480,15 @@ Rectangle { } FiraSansSemiBold { id: itemPriceText; - text: (root.isUpdating && root.itemEdition > 0) ? "FREE\nUPDATE" : ((root.itemPrice === -1) ? "--" : ((root.itemPrice > 0) ? root.itemPrice : "FREE")); + text: isTradingIn ? "FREE\nUPDATE" : + (isStocking ? "Free for creator" : + ((root.itemPrice === -1) ? "--" : ((root.itemPrice > 0) ? root.itemPrice : "FREE"))); // Text size - size: (root.isUpdating && root.itemEdition > 0) ? 20 : 26; + size: isTradingIn ? 20 : 26; // Anchors anchors.top: parent.top; - anchors.right: parent.right; - anchors.rightMargin: 16; + anchors.left: itemPriceTextLabel.visible ? itemPriceTextLabel.right : parent.left; + anchors.leftMargin: 4; width: paintedWidth; height: paintedHeight; // Style @@ -571,7 +580,7 @@ Rectangle { // "View in Inventory" button HifiControlsUit.Button { id: viewInMyPurchasesButton; - visible: false; + visible: isCertified && dataReady && (isUpdating ? !hasSomethingToTradeIn : alreadyOwned); color: hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top; @@ -592,8 +601,8 @@ Rectangle { // "Buy" button HifiControlsUit.Button { id: buyButton; - visible: !((root.itemType === "avatar" || root.itemType === "app") && viewInMyPurchasesButton.visible) - enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived && availableUpdatesReceived) || (!root.isCertified) || root.isUpdating; + visible: isTradingIn || !alreadyOwned || isStocking || !(root.itemType === "avatar" || root.itemType === "app"); + enabled: (root.balanceAfterPurchase >= 0 && dataReady) || (!root.isCertified) || root.isUpdating; color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue; colorScheme: hifi.colorSchemes.light; anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom : @@ -602,10 +611,15 @@ Rectangle { height: 50; anchors.left: parent.left; anchors.right: parent.right; - text: (root.isUpdating && root.itemEdition > 0) ? "CONFIRM UPDATE" : (((root.isCertified) ? ((ownershipStatusReceived && balanceReceived && availableUpdatesReceived) ? - ((viewInMyPurchasesButton.visible && !root.isUpdating) ? "Get It Again" : "Confirm") : "--") : "Get Item")); + text: isTradingIn ? + "CONFIRM UPDATE" : + (((root.isCertified) ? + (dataReady ? + ((viewInMyPurchasesButton.visible && !root.isUpdating) ? "Get It Again" : "Confirm") : + "--") : + "Get Item")); onClicked: { - if (root.isUpdating && root.itemEdition > 0) { + if (isTradingIn) { // If we're updating an app, the existing app needs to be uninstalled. // This call will fail/return `false` if the app isn't installed, but that's OK. if (root.itemType === "app") { @@ -1063,7 +1077,11 @@ Rectangle { buyButton.color = hifi.buttons.red; root.shouldBuyWithControlledFailure = true; } else { - buyButton.text = (root.isCertified ? ((ownershipStatusReceived && balanceReceived && availableUpdatesReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item"); + buyButton.text = (root.isCertified ? + (dataReady ? + (root.alreadyOwned ? "Buy Another" : "Buy") : + "--") : + "Get Item"); buyButton.color = hifi.buttons.blue; root.shouldBuyWithControlledFailure = false; } @@ -1091,6 +1109,8 @@ Rectangle { root.itemPrice = result.data.cost; root.itemAuthor = result.data.creator; root.itemType = result.data.item_type || "unknown"; + root.availability = result.data.availability; + root.creator = result.data.creator; if (root.itemType === "unknown") { root.itemHref = result.data.review_url; } else { @@ -1139,7 +1159,7 @@ Rectangle { signal sendToScript(var message); function canBuyAgain() { - return (root.itemType === "entity" || root.itemType === "wearable" || root.itemType === "contentSet" || root.itemType === "unknown"); + return root.itemType === "entity" || root.itemType === "wearable" || root.itemType === "contentSet" || root.itemType === "unknown" || isStocking; } function handleContentSets() { @@ -1185,29 +1205,23 @@ Rectangle { function refreshBuyUI() { if (root.isCertified) { - if (root.ownershipStatusReceived && root.balanceReceived && root.availableUpdatesReceived) { + if (dataReady) { buyText.text = ""; // If the user IS on the checkout page for the updated version of an owned item... if (root.isUpdating) { // If the user HAS already selected a specific edition to update... - if (root.itemEdition > 0) { + if (hasSomethingToTradeIn) { buyText.text = "By pressing \"Confirm Update\", you agree to trade in your old item for the updated item that replaces it."; buyTextContainer.color = "#FFFFFF"; buyTextContainer.border.color = "#FFFFFF"; // Else if the user HAS NOT selected a specific edition to update... } else { - viewInMyPurchasesButton.visible = true; - handleBuyAgainLogic(); } // If the user IS NOT on the checkout page for the updated verison of an owned item... // (i.e. they are checking out an item "normally") } else { - if (root.alreadyOwned) { - viewInMyPurchasesButton.visible = true; - } - handleBuyAgainLogic(); } } else { diff --git a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml index cdb8368296..ca6838efea 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/Marketplace.qml @@ -121,7 +121,7 @@ Rectangle { marketplaceItem.description = result.data.description; marketplaceItem.attributions = result.data.attributions; marketplaceItem.license = result.data.license; - marketplaceItem.available = result.data.availability === "available"; + marketplaceItem.availability = result.data.availability; marketplaceItem.created_at = result.data.created_at; marketplaceItemScrollView.contentHeight = marketplaceItemContent.height; itemsList.visible = false; @@ -539,7 +539,7 @@ Rectangle { creator: model.creator category: model.primary_category price: model.cost - available: model.availability === "available" + availability: model.availability isLoggedIn: root.isLoggedIn; onShowItem: { @@ -711,7 +711,7 @@ Rectangle { topMargin: 10; leftMargin: 15; } - height: visible ? childrenRect.height : 0 + height: visible ? 36 : 0 RalewayRegular { id: sortText @@ -733,8 +733,9 @@ Rectangle { top: parent.top leftMargin: 20 } + width: root.isLoggedIn ? 342 : 262 - height: 36 + height: parent.height radius: 4 border.width: 1 diff --git a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml index 2c7a50033c..97e5c10a6b 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceItem.qml @@ -33,11 +33,11 @@ Rectangle { property string creator: "" property var categories: [] property int price: 0 + property string availability: "unknown" property var attributions: [] property string description: "" property string license: "" property string posted: "" - property bool available: false property string created_at: "" property bool isLoggedIn: false; property int edition: -1; @@ -264,9 +264,15 @@ Rectangle { } height: 50 - text: root.edition >= 0 ? "UPGRADE FOR FREE" : (root.available ? (root.price ? root.price : "FREE") : "UNAVAILABLE (not for sale)") - enabled: root.edition >= 0 || root.available - buttonGlyph: root.available ? (root.price ? hifi.glyphs.hfc : "") : "" + property bool isNFS: availability === "not for sale" // Note: server will say "sold out" or "invalidated" before it says NFS + property bool isMine: creator === Account.username + property bool isUpgrade: root.edition >= 0 + property int costToMe: ((isMine && isNFS) || isUpgrade) ? 0 : price + property bool isAvailable: costToMe >= 0 + + text: isUpgrade ? "UPGRADE FOR FREE" : (isAvailable ? (costToMe || "FREE") : availability) + enabled: isAvailable + buttonGlyph: isAvailable ? (costToMe ? hifi.glyphs.hfc : "") : "" color: hifi.buttons.blue onClicked: root.buy(); diff --git a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceListItem.qml b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceListItem.qml index 2f37637e40..587d71da28 100644 --- a/interface/resources/qml/hifi/commerce/marketplace/MarketplaceListItem.qml +++ b/interface/resources/qml/hifi/commerce/marketplace/MarketplaceListItem.qml @@ -34,7 +34,7 @@ Rectangle { property string creator: "" property string category: "" property int price: 0 - property bool available: false + property string availability: "unknown" property bool isLoggedIn: false; signal buy() @@ -299,8 +299,16 @@ Rectangle { bottomMargin: 10 } - text: root.price ? root.price : "FREE" - buttonGlyph: root.price ? hifi.glyphs.hfc : "" + property bool isNFS: availability === "not for sale" // Note: server will say "sold out" or "invalidated" before it says NFS + property bool isMine: creator === Account.username + property bool isUpgrade: root.edition >= 0 + property int costToMe: ((isMine && isNFS) || isUpgrade) ? 0 : price + property bool isAvailable: costToMe >= 0 + + text: isUpgrade ? "UPGRADE FOR FREE" : (isAvailable ? (costToMe || "FREE") : availability) + enabled: isAvailable + buttonGlyph: isAvailable ? (costToMe ? hifi.glyphs.hfc : "") : "" + color: hifi.buttons.blue; onClicked: root.buy(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 02b6732f1d..bcd07106ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1909,46 +1909,34 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } }, Qt::QueuedConnection); - EntityTree::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { + EntityTreeRenderer::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { if (_aboutToQuit) { return false; } - // try to find the renderable auto renderable = getEntities()->renderableForEntityId(entityID); if (renderable) { renderable->addMaterial(material, parentMaterialName); - } - - // even if we don't find it, try to find the entity - auto entity = getEntities()->getEntity(entityID); - if (entity) { - entity->addMaterial(material, parentMaterialName); return true; } + return false; }); - EntityTree::setRemoveMaterialFromEntityOperator([this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) { + EntityTreeRenderer::setRemoveMaterialFromEntityOperator([this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) { if (_aboutToQuit) { return false; } - // try to find the renderable auto renderable = getEntities()->renderableForEntityId(entityID); if (renderable) { renderable->removeMaterial(material, parentMaterialName); - } - - // even if we don't find it, try to find the entity - auto entity = getEntities()->getEntity(entityID); - if (entity) { - entity->removeMaterial(material, parentMaterialName); return true; } + return false; }); - EntityTree::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) { + EntityTreeRenderer::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) { auto avatarManager = DependencyManager::get(); auto avatar = avatarManager->getAvatarBySessionID(avatarID); if (avatar) { @@ -1957,7 +1945,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } return false; }); - EntityTree::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) { + EntityTreeRenderer::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) { auto avatarManager = DependencyManager::get(); auto avatar = avatarManager->getAvatarBySessionID(avatarID); if (avatar) { @@ -2280,7 +2268,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Setup the mouse ray pick and related operators { - auto mouseRayPick = std::make_shared(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES()), 0.0f, true); + auto mouseRayPick = std::make_shared(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_LOCAL_ENTITIES()), 0.0f, true); mouseRayPick->parentTransform = std::make_shared(); mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE); auto mouseRayPickID = DependencyManager::get()->addPick(PickQuery::Ray, mouseRayPick); diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp index ce01db3a56..09f4b68cb9 100644 --- a/interface/src/raypick/PickScriptingInterface.cpp +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -71,6 +71,18 @@ PickFilter getPickFilter(unsigned int filter) { unsigned int PickScriptingInterface::createRayPick(const QVariant& properties) { QVariantMap propMap = properties.toMap(); + +#if defined (Q_OS_ANDROID) + QString jointName { "" }; + if (propMap["joint"].isValid()) { + QString jointName = propMap["joint"].toString(); + const QString MOUSE_JOINT = "Mouse"; + if (jointName == MOUSE_JOINT) { + return PointerEvent::INVALID_POINTER_ID; + } + } +#endif + bool enabled = false; if (propMap["enabled"].isValid()) { enabled = propMap["enabled"].toBool(); diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp index 19c20f0c06..1c80caff88 100644 --- a/interface/src/raypick/PointerScriptingInterface.cpp +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -150,6 +150,17 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties) unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& properties) const { QVariantMap propertyMap = properties.toMap(); +#if defined (Q_OS_ANDROID) + QString jointName { "" }; + if (propertyMap["joint"].isValid()) { + QString jointName = propertyMap["joint"].toString(); + const QString MOUSE_JOINT = "Mouse"; + if (jointName == MOUSE_JOINT) { + return PointerEvent::INVALID_POINTER_ID; + } + } +#endif + bool faceAvatar = false; if (propertyMap["faceAvatar"].isValid()) { faceAvatar = propertyMap["faceAvatar"].toBool(); diff --git a/interface/src/raypick/StylusPick.cpp b/interface/src/raypick/StylusPick.cpp index 0e95959566..9c3ffb972f 100644 --- a/interface/src/raypick/StylusPick.cpp +++ b/interface/src/raypick/StylusPick.cpp @@ -137,7 +137,7 @@ PickResultPointer StylusPick::getDefaultResult(const QVariantMap& pickVariant) c } PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) { - std::vector results; + StylusPickResult nearestTarget(pick.toVariantMap()); for (const auto& target : getIncludeItems()) { if (target.isNull()) { continue; @@ -157,28 +157,21 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) { glm::vec3 normal = entityRotation * Vectors::UNIT_Z; float distance = glm::dot(pick.position - entityPosition, normal); - glm::vec3 intersection = pick.position - (normal * distance); - - glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(target, intersection, false); - if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) { - IntersectionType type = IntersectionType::ENTITY; - if (getFilter().doesPickLocalEntities()) { - EntityPropertyFlags desiredProperties; - desiredProperties += PROP_ENTITY_HOST_TYPE; - if (DependencyManager::get()->getEntityProperties(target, desiredProperties).getEntityHostType() == entity::HostType::LOCAL) { - type = IntersectionType::LOCAL_ENTITY; + if (distance < nearestTarget.distance) { + glm::vec3 intersection = pick.position - (normal * distance); + glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(target, intersection, false); + if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) { + IntersectionType type = IntersectionType::ENTITY; + if (getFilter().doesPickLocalEntities()) { + if (entity->getEntityHostType() == entity::HostType::LOCAL) { + type = IntersectionType::LOCAL_ENTITY; + } } + nearestTarget = StylusPickResult(type, target, distance, intersection, pick, normal); } - results.push_back(StylusPickResult(type, target, distance, intersection, pick, normal)); } } - StylusPickResult nearestTarget(pick.toVariantMap()); - for (const auto& result : results) { - if (result.distance < nearestTarget.distance) { - nearestTarget = result; - } - } return std::make_shared(nearestTarget); } diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index c382c3de43..24c0986d09 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -70,7 +70,6 @@ ContextOverlayInterface::ContextOverlayInterface() { } }); connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity); - connect(&qApp->getOverlays(), &Overlays::mousePressOnOverlay, this, &ContextOverlayInterface::contextOverlays_mousePressOnOverlay); connect(&qApp->getOverlays(), &Overlays::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay); connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay); @@ -103,10 +102,14 @@ void ContextOverlayInterface::setEnabled(bool enabled) { } } -void ContextOverlayInterface::clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event) { - if (_enabled && event.getButton() == PointerEvent::SecondaryButton && contextOverlayFilterPassed(entityItemID)) { - _mouseDownEntity = entityItemID; +void ContextOverlayInterface::clickDownOnEntity(const EntityItemID& id, const PointerEvent& event) { + if (_enabled && event.getButton() == PointerEvent::SecondaryButton && contextOverlayFilterPassed(id)) { + _mouseDownEntity = id; _mouseDownEntityTimestamp = usecTimestampNow(); + } else if (id == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) { + qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "ID:" << id; + emit contextOverlayClicked(_currentEntityWithContextOverlay); + _contextOverlayJustClicked = true; } else { if (!_currentEntityWithContextOverlay.isNull()) { disableEntityHighlight(_currentEntityWithContextOverlay); @@ -249,14 +252,6 @@ bool ContextOverlayInterface::destroyContextOverlay(const EntityItemID& entityIt return ContextOverlayInterface::destroyContextOverlay(entityItemID, PointerEvent()); } -void ContextOverlayInterface::contextOverlays_mousePressOnOverlay(const QUuid& id, const PointerEvent& event) { - if (id == _contextOverlayID && event.getButton() == PointerEvent::PrimaryButton) { - qCDebug(context_overlay) << "Clicked Context Overlay. Entity ID:" << _currentEntityWithContextOverlay << "ID:" << id; - emit contextOverlayClicked(_currentEntityWithContextOverlay); - _contextOverlayJustClicked = true; - } -} - void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const QUuid& id, const PointerEvent& event) { if (_contextOverlayID != UNKNOWN_ENTITY_ID) { qCDebug(context_overlay) << "Started hovering over Context Overlay. ID:" << id; diff --git a/interface/src/ui/overlays/ContextOverlayInterface.h b/interface/src/ui/overlays/ContextOverlayInterface.h index b87535acf2..57fc8ebe6e 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.h +++ b/interface/src/ui/overlays/ContextOverlayInterface.h @@ -65,7 +65,6 @@ public slots: bool createOrDestroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event); bool destroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event); bool destroyContextOverlay(const EntityItemID& entityItemID); - void contextOverlays_mousePressOnOverlay(const QUuid& id, const PointerEvent& event); void contextOverlays_hoverEnterOverlay(const QUuid& id, const PointerEvent& event); void contextOverlays_hoverLeaveOverlay(const QUuid& id, const PointerEvent& event); void contextOverlays_hoverEnterEntity(const EntityItemID& entityID, const PointerEvent& event); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index e1708c14fe..2dd8008281 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -63,13 +63,6 @@ Overlays::Overlays() { ADD_TYPE_MAP(PolyLine, line3d); ADD_TYPE_MAP(Grid, grid); ADD_TYPE_MAP(Gizmo, circle3d); - - auto mouseRayPick = std::make_shared(Vectors::ZERO, Vectors::UP, - PickFilter(PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES) | - PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE)), 0.0f, true); - mouseRayPick->parentTransform = std::make_shared(); - mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE); - _mouseRayPickID = DependencyManager::get()->addPick(PickQuery::Ray, mouseRayPick); } void Overlays::cleanupAllOverlays() { @@ -86,15 +79,7 @@ void Overlays::cleanupAllOverlays() { cleanupOverlaysToDelete(); } -void Overlays::init() { - auto entityScriptingInterface = DependencyManager::get(); - connect(this, &Overlays::hoverEnterOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity); - connect(this, &Overlays::hoverOverOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::hoverOverEntity); - connect(this, &Overlays::hoverLeaveOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity); - connect(this, &Overlays::mousePressOnOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity); - connect(this, &Overlays::mouseMoveOnOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::mouseMoveOnEntity); - connect(this, &Overlays::mouseReleaseOnOverlay, entityScriptingInterface.data(), &EntityScriptingInterface::mouseReleaseOnEntity); -} +void Overlays::init() {} void Overlays::update(float deltatime) { cleanupOverlaysToDelete(); @@ -375,6 +360,8 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove RENAME_PROP(animationSettings, animation); } else if (type == "Image") { RENAME_PROP(url, imageURL); + } else if (type == "Text") { + RENAME_PROP(color, textColor); } else if (type == "Web") { RENAME_PROP(url, sourceUrl); RENAME_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "Mouse" ? "mouse" : "touch"; }); @@ -675,6 +662,8 @@ QVariantMap Overlays::convertEntityToOverlayProperties(const EntityItemPropertie RENAME_PROP(animation, animationSettings); } else if (type == "Image") { RENAME_PROP(imageURL, url); + } else if (type == "Text") { + RENAME_PROP(textColor, color); } else if (type == "Web") { RENAME_PROP(sourceUrl, url); RENAME_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "mouse" ? "Mouse" : "Touch"; }); @@ -1228,12 +1217,12 @@ static PointerEvent::Button toPointerButton(const QMouseEvent& event) { } } -RayToOverlayIntersectionResult getPrevPickResult(unsigned int mouseRayPickID) { +RayToOverlayIntersectionResult getPrevPickResult() { RayToOverlayIntersectionResult overlayResult; overlayResult.intersects = false; - auto pickResult = DependencyManager::get()->getPrevPickResultTyped(mouseRayPickID); + auto pickResult = DependencyManager::get()->getPrevPickResultTyped(DependencyManager::get()->getMouseRayPickID()); if (pickResult) { - overlayResult.intersects = pickResult->type != IntersectionType::NONE; + overlayResult.intersects = pickResult->type == IntersectionType::LOCAL_ENTITY; if (overlayResult.intersects) { overlayResult.intersection = pickResult->intersection; overlayResult.distance = pickResult->distance; @@ -1281,7 +1270,7 @@ std::pair Overlays::mousePressEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mousePressEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); + RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(); if (rayPickResult.intersects) { _currentClickingOnOverlayID = rayPickResult.overlayID; @@ -1305,7 +1294,7 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); + RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(); if (rayPickResult.intersects) { _currentClickingOnOverlayID = rayPickResult.overlayID; @@ -1321,7 +1310,7 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseReleaseEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); + RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(); if (rayPickResult.intersects) { auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release); mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent); @@ -1343,7 +1332,7 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) { PerformanceTimer perfTimer("Overlays::mouseMoveEvent"); PickRay ray = qApp->computePickRay(event->x(), event->y()); - RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); + RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(); if (rayPickResult.intersects) { auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move); mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent); diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 7612779099..838a38eb54 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -719,7 +719,6 @@ private: PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult, QMouseEvent* event, PointerEvent::EventType eventType); - unsigned int _mouseRayPickID; QUuid _currentClickingOnOverlayID; QUuid _currentHoverOverOverlayID; diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 5f30d98ed6..c16d65506a 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -208,16 +208,16 @@ AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWe avatar->setSessionUUID(sessionUUID); avatar->setOwningAvatarMixer(mixerWeakPointer); - // addAvatar is only called from newOrExistingAvatar, which already locks _hashLock - _avatarHash.insert(sessionUUID, avatar); + { + QWriteLocker locker(&_hashLock); + _avatarHash.insert(sessionUUID, avatar); + } emit avatarAddedEvent(sessionUUID); return avatar; } -AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer, - bool& isNew) { - QWriteLocker locker(&_hashLock); - auto avatar = _avatarHash.value(sessionUUID); +AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer, bool& isNew) { + auto avatar = findAvatar(sessionUUID); if (!avatar) { avatar = addAvatar(sessionUUID, mixerWeakPointer); isNew = true; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 319acc750f..9d55d936a2 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -86,7 +86,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf auto handlePointerEvent = [&](const QUuid& entityID, const PointerEvent& event) { std::shared_ptr thisEntity; auto entity = getEntity(entityID); - if (entity && entity->getType() == EntityTypes::Web) { + if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) { thisEntity = std::static_pointer_cast(renderableForEntityId(entityID)); } if (thisEntity) { @@ -99,7 +99,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) { std::shared_ptr thisEntity; auto entity = getEntity(entityID); - if (entity && entity->getType() == EntityTypes::Web) { + if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) { thisEntity = std::static_pointer_cast(renderableForEntityId(entityID)); } if (thisEntity) { @@ -110,7 +110,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) { std::shared_ptr thisEntity; auto entity = getEntity(entityID); - if (entity && entity->getType() == EntityTypes::Web) { + if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) { thisEntity = std::static_pointer_cast(renderableForEntityId(entityID)); } if (thisEntity) { @@ -1360,3 +1360,36 @@ EntityEditPacketSender* EntityTreeRenderer::getPacketSender() { EntityEditPacketSender* packetSender = peSimulation ? peSimulation->getPacketSender() : nullptr; return packetSender; } + +std::function EntityTreeRenderer::_addMaterialToEntityOperator = nullptr; +std::function EntityTreeRenderer::_removeMaterialFromEntityOperator = nullptr; +std::function EntityTreeRenderer::_addMaterialToAvatarOperator = nullptr; +std::function EntityTreeRenderer::_removeMaterialFromAvatarOperator = nullptr; + +bool EntityTreeRenderer::addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { + if (_addMaterialToEntityOperator) { + return _addMaterialToEntityOperator(entityID, material, parentMaterialName); + } + return false; +} + +bool EntityTreeRenderer::removeMaterialFromEntity(const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) { + if (_removeMaterialFromEntityOperator) { + return _removeMaterialFromEntityOperator(entityID, material, parentMaterialName); + } + return false; +} + +bool EntityTreeRenderer::addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) { + if (_addMaterialToAvatarOperator) { + return _addMaterialToAvatarOperator(avatarID, material, parentMaterialName); + } + return false; +} + +bool EntityTreeRenderer::removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) { + if (_removeMaterialFromAvatarOperator) { + return _removeMaterialFromAvatarOperator(avatarID, material, parentMaterialName); + } + return false; +} \ No newline at end of file diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 204dc50c45..51568ab744 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -73,6 +73,7 @@ public: static void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { _calculateEntityLoadingPriorityFunc = fn; } void setMouseRayPickID(unsigned int rayPickID) { _mouseRayPickID = rayPickID; } + unsigned int getMouseRayPickID() { return _mouseRayPickID; } void setMouseRayPickResultOperator(std::function getPrevRayPickResultOperator) { _getPrevRayPickResultOperator = getPrevRayPickResultOperator; } void setSetPrecisionPickingOperator(std::function setPrecisionPickingOperator) { _setPrecisionPickingOperator = setPrecisionPickingOperator; } @@ -120,6 +121,16 @@ public: EntityEditPacketSender* getPacketSender(); + static void setAddMaterialToEntityOperator(std::function addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; } + static void setRemoveMaterialFromEntityOperator(std::function removeMaterialFromEntityOperator) { _removeMaterialFromEntityOperator = removeMaterialFromEntityOperator; } + static bool addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName); + static bool removeMaterialFromEntity(const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName); + + static void setAddMaterialToAvatarOperator(std::function addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; } + static void setRemoveMaterialFromAvatarOperator(std::function removeMaterialFromAvatarOperator) { _removeMaterialFromAvatarOperator = removeMaterialFromAvatarOperator; } + 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); + signals: void enterEntity(const EntityItemID& entityItemID); void leaveEntity(const EntityItemID& entityItemID); @@ -255,6 +266,11 @@ private: workload::SpacePointer _space{ new workload::Space() }; workload::Transaction::Updates _spaceUpdates; + static std::function _addMaterialToEntityOperator; + static std::function _removeMaterialFromEntityOperator; + static std::function _addMaterialToAvatarOperator; + static std::function _removeMaterialFromAvatarOperator; + }; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 80e352956b..e2e37515bf 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -146,7 +146,6 @@ EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entit _needsRenderUpdate = true; emit requestRenderUpdate(); }); - _materials = entity->getMaterials(); } EntityRenderer::~EntityRenderer() { } diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 483f9ffe1c..2eb877b0e1 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -14,42 +14,210 @@ using namespace render; using namespace render::entities; -bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { - if (entity->getMaterial() != _drawMaterial) { - return true; - } - if (entity->getParentID() != _parentID) { - return true; - } - if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) { +bool MaterialEntityRenderer::needsRenderUpdate() const { + if (_retryApply) { return true; } if (!_texturesLoaded) { return true; } + return Parent::needsRenderUpdate(); +} + +bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { + if (resultWithReadLock([&] { + if (entity->getMaterialMappingMode() != _materialMappingMode) { + return true; + } + if (entity->getMaterialRepeat() != _materialRepeat) { + return true; + } + if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) { + return true; + } + if (entity->getTransform() != _transform) { + return true; + } + if (entity->getUnscaledDimensions() != _dimensions) { + return true; + } + + if (entity->getMaterialURL() != _materialURL) { + return true; + } + if (entity->getMaterialData() != _materialData) { + return true; + } + if (entity->getParentMaterialName() != _parentMaterialName) { + return true; + } + if (entity->getParentID() != _parentID) { + return true; + } + if (entity->getPriority() != _priority) { + return true; + } + + return false; + })) { + return true; + } return false; } -void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { +void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { withWriteLock([&] { - if (_drawMaterial != entity->getMaterial()) { - _texturesLoaded = false; - _drawMaterial = entity->getMaterial(); + bool deleteNeeded = false; + bool addNeeded = _retryApply; + bool transformChanged = false; + { + MaterialMappingMode mode = entity->getMaterialMappingMode(); + if (mode != _materialMappingMode) { + _materialMappingMode = mode; + transformChanged = true; + } } - _parentID = entity->getParentID(); - _materialMappingPos = entity->getMaterialMappingPos(); - _materialMappingScale = entity->getMaterialMappingScale(); - _materialMappingRot = entity->getMaterialMappingRot(); + { + bool repeat = entity->getMaterialRepeat(); + if (repeat != _materialRepeat) { + _materialRepeat = repeat; + transformChanged = true; + } + } + { + glm::vec2 mappingPos = entity->getMaterialMappingPos(); + glm::vec2 mappingScale = entity->getMaterialMappingScale(); + float mappingRot = entity->getMaterialMappingRot(); + if (mappingPos != _materialMappingPos || mappingScale != _materialMappingScale || mappingRot != _materialMappingRot) { + _materialMappingPos = mappingPos; + _materialMappingScale = mappingScale; + _materialMappingRot = mappingRot; + transformChanged |= _materialMappingMode == MaterialMappingMode::UV; + } + } + { + Transform transform = entity->getTransform(); + glm::vec3 dimensions = entity->getUnscaledDimensions(); + if (transform != _transform || dimensions != _dimensions) { + _transform = transform; + _dimensions = dimensions; + transformChanged |= _materialMappingMode == MaterialMappingMode::PROJECTED; + } + } + + { + auto material = getMaterial(); + // Update the old material regardless of if it's going to change + if (transformChanged && material && !_parentID.isNull()) { + deleteNeeded = true; + addNeeded = true; + applyTextureTransform(material); + } + } + + bool urlChanged = false; + std::string newCurrentMaterialName = _currentMaterialName; + { + QString materialURL = entity->getMaterialURL(); + if (materialURL != _materialURL) { + _materialURL = materialURL; + if (_materialURL.contains("?")) { + auto split = _materialURL.split("?"); + newCurrentMaterialName = split.last().toStdString(); + } + urlChanged = true; + } + } + + bool usingMaterialData = _materialURL.startsWith("materialData"); + bool materialDataChanged = false; + QUuid oldParentID = _parentID; + QString oldParentMaterialName = _parentMaterialName; + { + QString materialData = entity->getMaterialData(); + if (materialData != _materialData) { + _materialData = materialData; + if (usingMaterialData) { + materialDataChanged = true; + } + } + } + { + QString parentMaterialName = entity->getParentMaterialName(); + if (parentMaterialName != _parentMaterialName) { + _parentMaterialName = parentMaterialName; + deleteNeeded = true; + addNeeded = true; + } + } + { + QUuid parentID = entity->getParentID(); + if (parentID != _parentID) { + _parentID = parentID; + deleteNeeded = true; + addNeeded = true; + } + } + { + quint16 priority = entity->getPriority(); + if (priority != _priority) { + _priority = priority; + deleteNeeded = true; + addNeeded = true; + } + } + + if (urlChanged && !usingMaterialData) { + _networkMaterial = MaterialCache::instance().getMaterial(_materialURL); + auto onMaterialRequestFinished = [&, oldParentID, oldParentMaterialName, newCurrentMaterialName](bool success) { + if (success) { + deleteMaterial(oldParentID, oldParentMaterialName); + _texturesLoaded = false; + _parsedMaterials = _networkMaterial->parsedMaterials; + setCurrentMaterialName(newCurrentMaterialName); + applyMaterial(); + } else { + deleteMaterial(oldParentID, oldParentMaterialName); + _retryApply = false; + _texturesLoaded = true; + } + }; + if (_networkMaterial) { + if (_networkMaterial->isLoaded()) { + onMaterialRequestFinished(!_networkMaterial->isFailed()); + } else { + connect(_networkMaterial.data(), &Resource::finished, this, onMaterialRequestFinished); + } + } + } else if (materialDataChanged && usingMaterialData) { + deleteMaterial(oldParentID, oldParentMaterialName); + _texturesLoaded = false; + _parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(_materialData.toUtf8()), _materialURL); + // Since our material changed, the current name might not be valid anymore, so we need to update + setCurrentMaterialName(newCurrentMaterialName); + applyMaterial(); + } else { + if (deleteNeeded) { + deleteMaterial(oldParentID, oldParentMaterialName); + } + if (addNeeded) { + applyMaterial(); + } + } + + { + auto material = getMaterial(); + bool newTexturesLoaded = material ? !material->isMissingTexture() : false; + if (!_texturesLoaded && newTexturesLoaded) { + material->checkResetOpacityMap(); + } + _texturesLoaded = newTexturesLoaded; + } + _renderTransform = getModelTransform(); const float MATERIAL_ENTITY_SCALE = 0.5f; _renderTransform.postScale(MATERIAL_ENTITY_SCALE); _renderTransform.postScale(ENTITY_ITEM_DEFAULT_DIMENSIONS); - - bool newTexturesLoaded = _drawMaterial ? !_drawMaterial->isMissingTexture() : false; - if (!_texturesLoaded && newTexturesLoaded) { - _drawMaterial->checkResetOpacityMap(); - } - _texturesLoaded = newTexturesLoaded; }); } @@ -61,8 +229,9 @@ ItemKey MaterialEntityRenderer::getKey() { builder.withInvisible(); } - if (_drawMaterial) { - auto matKey = _drawMaterial->getKey(); + const auto drawMaterial = getMaterial(); + if (drawMaterial) { + auto matKey = drawMaterial->getKey(); if (matKey.isTranslucent()) { builder.withTransparent(); } @@ -73,8 +242,9 @@ ItemKey MaterialEntityRenderer::getKey() { ShapeKey MaterialEntityRenderer::getShapeKey() { graphics::MaterialKey drawMaterialKey; - if (_drawMaterial) { - drawMaterialKey = _drawMaterial->getKey(); + const auto drawMaterial = getMaterial(); + if (drawMaterial) { + drawMaterialKey = drawMaterial->getKey(); } bool isTranslucent = drawMaterialKey.isTranslucent(); @@ -112,18 +282,24 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { // Don't render if our parent is set or our material is null QUuid parentID; + withReadLock([&] { + parentID = _parentID; + }); + if (!parentID.isNull()) { + return; + } + Transform renderTransform; graphics::MaterialPointer drawMaterial; Transform textureTransform; withReadLock([&] { - parentID = _parentID; renderTransform = _renderTransform; - drawMaterial = _drawMaterial; + drawMaterial = getMaterial(); textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0)); textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot))); textureTransform.setScale(glm::vec3(_materialMappingScale, 1)); }); - if (!parentID.isNull() || !drawMaterial) { + if (!drawMaterial) { return; } @@ -142,3 +318,86 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { args->_details._trianglesRendered += (int)DependencyManager::get()->getSphereTriangleCount(); } + +void MaterialEntityRenderer::setCurrentMaterialName(const std::string& currentMaterialName) { + if (_parsedMaterials.networkMaterials.find(currentMaterialName) != _parsedMaterials.networkMaterials.end()) { + _currentMaterialName = currentMaterialName; + } else if (_parsedMaterials.names.size() > 0) { + _currentMaterialName = _parsedMaterials.names[0]; + } +} + +std::shared_ptr MaterialEntityRenderer::getMaterial() const { + auto material = _parsedMaterials.networkMaterials.find(_currentMaterialName); + if (material != _parsedMaterials.networkMaterials.end()) { + return material->second; + } else { + return nullptr; + } +} + +void MaterialEntityRenderer::deleteMaterial(const QUuid& oldParentID, const QString& oldParentMaterialName) { + std::shared_ptr material = _appliedMaterial; + if (!material || oldParentID.isNull()) { + return; + } + + // Our parent could be an entity or an avatar + std::string oldParentMaterialNameStd = oldParentMaterialName.toStdString(); + if (EntityTreeRenderer::removeMaterialFromEntity(oldParentID, material, oldParentMaterialNameStd)) { + _appliedMaterial = nullptr; + return; + } + + if (EntityTreeRenderer::removeMaterialFromAvatar(oldParentID, material, oldParentMaterialNameStd)) { + _appliedMaterial = nullptr; + return; + } + + // if a remove fails, our parent is gone, so we don't need to retry +} + +void MaterialEntityRenderer::applyTextureTransform(std::shared_ptr& material) { + Transform textureTransform; + if (_materialMappingMode == MaterialMappingMode::UV) { + textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0.0f)); + textureTransform.setRotation(glm::vec3(0.0f, 0.0f, glm::radians(_materialMappingRot))); + textureTransform.setScale(glm::vec3(_materialMappingScale, 1.0f)); + } else if (_materialMappingMode == MaterialMappingMode::PROJECTED) { + textureTransform = _transform; + textureTransform.postScale(_dimensions); + // Pass the inverse transform here so we don't need to compute it in the shaders + textureTransform.evalFromRawMatrix(textureTransform.getInverseMatrix()); + } + material->setTextureTransforms(textureTransform, _materialMappingMode, _materialRepeat); +} + +void MaterialEntityRenderer::applyMaterial() { + _retryApply = false; + + std::shared_ptr material = getMaterial(); + QUuid parentID = _parentID; + if (!material || parentID.isNull()) { + _appliedMaterial = nullptr; + return; + } + + applyTextureTransform(material); + + graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, _priority); + + // Our parent could be an entity or an avatar + std::string parentMaterialName = _parentMaterialName.toStdString(); + if (EntityTreeRenderer::addMaterialToEntity(parentID, materialLayer, parentMaterialName)) { + _appliedMaterial = material; + return; + } + + if (EntityTreeRenderer::addMaterialToAvatar(parentID, materialLayer, parentMaterialName)) { + _appliedMaterial = material; + return; + } + + // if we've reached this point, we couldn't find our parent, so we need to try again later + _retryApply = true; +} \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index c90048ecf5..d714727c7a 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -13,6 +13,8 @@ #include +#include + class NetworkMaterial; namespace render { namespace entities { @@ -22,22 +24,46 @@ class MaterialEntityRenderer : public TypedEntityRenderer { using Pointer = std::shared_ptr; public: MaterialEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {} + ~MaterialEntityRenderer() { deleteMaterial(_parentID, _parentMaterialName); } private: + virtual bool needsRenderUpdate() const override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; - virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; + virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; ItemKey getKey() override; ShapeKey getShapeKey() override; + QString _materialURL; + QString _materialData; + QString _parentMaterialName; + quint16 _priority; QUuid _parentID; + + MaterialMappingMode _materialMappingMode; + bool _materialRepeat; glm::vec2 _materialMappingPos; glm::vec2 _materialMappingScale; float _materialMappingRot; - bool _texturesLoaded { false }; + Transform _transform; + glm::vec3 _dimensions; + + bool _texturesLoaded { false }; + bool _retryApply { false }; + + std::shared_ptr getMaterial() const; + void setCurrentMaterialName(const std::string& currentMaterialName); + + void applyTextureTransform(std::shared_ptr& material); + void applyMaterial(); + void deleteMaterial(const QUuid& oldParentID, const QString& oldParentMaterialName); + + NetworkMaterialResourcePointer _networkMaterial; + NetworkMaterialResource::ParsedMaterials _parsedMaterials; + std::shared_ptr _appliedMaterial; + std::string _currentMaterialName; - std::shared_ptr _drawMaterial; }; } } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 2c6d679b46..c0b12c4d1f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3250,25 +3250,6 @@ void EntityItem::setSpaceIndex(int32_t index) { void EntityItem::preDelete() { } -void EntityItem::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) { - std::lock_guard lock(_materialsLock); - _materials[parentMaterialName].push(material); -} - -void EntityItem::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) { - std::lock_guard lock(_materialsLock); - _materials[parentMaterialName].remove(material); -} - -std::unordered_map EntityItem::getMaterials() { - std::unordered_map toReturn; - { - std::lock_guard lock(_materialsLock); - toReturn = _materials; - } - return toReturn; -} - bool EntityItem::getCloneable() const { bool result; withReadLock([&] { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5d6627d461..824261c022 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -37,8 +37,6 @@ #include "EntityDynamicInterface.h" #include "GrabPropertyGroup.h" -#include "graphics/Material.h" - class EntitySimulation; class EntityTreeElement; class EntityTreeElementExtraEncodeData; @@ -542,10 +540,6 @@ public: virtual void preDelete(); virtual void postParentFixup() {} - void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); - void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); - std::unordered_map getMaterials(); - void setSimulationOwnershipExpiry(uint64_t expiry) { _simulationOwnershipExpiry = expiry; } uint64_t getSimulationOwnershipExpiry() const { return _simulationOwnershipExpiry; } @@ -754,11 +748,7 @@ protected: QHash _grabActions; private: - std::unordered_map _materials; - std::mutex _materialsLock; - static std::function _getBillboardRotationOperator; - }; #endif // hifi_EntityItem_h diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index cfae8e250b..53b4fb4fe4 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2953,41 +2953,9 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const { return entity->getJointNames(); } -std::function EntityTree::_addMaterialToEntityOperator = nullptr; -std::function EntityTree::_removeMaterialFromEntityOperator = nullptr; -std::function EntityTree::_addMaterialToAvatarOperator = nullptr; -std::function EntityTree::_removeMaterialFromAvatarOperator = nullptr; std::function EntityTree::_getEntityObjectOperator = nullptr; std::function EntityTree::_textSizeOperator = nullptr; -bool EntityTree::addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { - if (_addMaterialToEntityOperator) { - return _addMaterialToEntityOperator(entityID, material, parentMaterialName); - } - return false; -} - -bool EntityTree::removeMaterialFromEntity(const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) { - if (_removeMaterialFromEntityOperator) { - return _removeMaterialFromEntityOperator(entityID, material, parentMaterialName); - } - return false; -} - -bool EntityTree::addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) { - if (_addMaterialToAvatarOperator) { - return _addMaterialToAvatarOperator(avatarID, material, parentMaterialName); - } - return false; -} - -bool EntityTree::removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) { - if (_removeMaterialFromAvatarOperator) { - return _removeMaterialFromAvatarOperator(avatarID, material, parentMaterialName); - } - return false; -} - QObject* EntityTree::getEntityObject(const QUuid& id) { if (_getEntityObjectOperator) { return _getEntityObjectOperator(id); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 9df01267ea..dcce0e4b99 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -262,16 +262,6 @@ public: void setIsServerlessMode(bool value) { _serverlessDomain = value; } bool isServerlessMode() const { return _serverlessDomain; } - static void setAddMaterialToEntityOperator(std::function addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; } - static void setRemoveMaterialFromEntityOperator(std::function removeMaterialFromEntityOperator) { _removeMaterialFromEntityOperator = removeMaterialFromEntityOperator; } - static bool addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName); - static bool removeMaterialFromEntity(const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName); - - static void setAddMaterialToAvatarOperator(std::function addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; } - static void setRemoveMaterialFromAvatarOperator(std::function removeMaterialFromAvatarOperator) { _removeMaterialFromAvatarOperator = removeMaterialFromAvatarOperator; } - static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName); - static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName); - static void setGetEntityObjectOperator(std::function getEntityObjectOperator) { _getEntityObjectOperator = getEntityObjectOperator; } static QObject* getEntityObject(const QUuid& id); @@ -386,10 +376,6 @@ private: std::shared_ptr _myAvatar{ nullptr }; - static std::function _addMaterialToEntityOperator; - static std::function _removeMaterialFromEntityOperator; - static std::function _addMaterialToAvatarOperator; - static std::function _removeMaterialFromAvatarOperator; static std::function _getEntityObjectOperator; static std::function _textSizeOperator; diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 1baa0b213a..3a363f2e83 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -16,9 +16,6 @@ EntityItemPointer MaterialEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { Pointer entity(new MaterialEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); entity->setProperties(properties); - // When you reload content, setProperties doesn't have any of the propertiesChanged flags set, so it won't trigger a material add - entity->removeMaterial(); - entity->applyMaterial(); return entity; } @@ -27,10 +24,6 @@ MaterialEntityItem::MaterialEntityItem(const EntityItemID& entityItemID) : Entit _type = EntityTypes::Material; } -MaterialEntityItem::~MaterialEntityItem() { - removeMaterial(); -} - EntityItemProperties MaterialEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL); @@ -131,7 +124,6 @@ void MaterialEntityItem::debugDump() const { qCDebug(entities) << " MATERIAL EntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " name:" << _name; qCDebug(entities) << " material url:" << _materialURL; - qCDebug(entities) << " current material name:" << _currentMaterialName.c_str(); qCDebug(entities) << " material mapping mode:" << _materialMappingMode; qCDebug(entities) << " material repeat:" << _materialRepeat; qCDebug(entities) << " priority:" << _priority; @@ -154,208 +146,101 @@ void MaterialEntityItem::setUnscaledDimensions(const glm::vec3& value) { } } -std::shared_ptr MaterialEntityItem::getMaterial() const { - auto material = _parsedMaterials.networkMaterials.find(_currentMaterialName); - if (material != _parsedMaterials.networkMaterials.end()) { - return material->second; - } else { - return nullptr; - } +QString MaterialEntityItem::getMaterialURL() const { + return resultWithReadLock([&] { + return _materialURL; + }); } -void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool materialDataChanged) { - bool usingMaterialData = materialDataChanged || materialURLString.startsWith("materialData"); - if (_materialURL != materialURLString || (usingMaterialData && materialDataChanged)) { - removeMaterial(); - _materialURL = materialURLString; - - if (materialURLString.contains("?")) { - auto split = materialURLString.split("?"); - _currentMaterialName = split.last().toStdString(); - } - - if (usingMaterialData) { - _parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(getMaterialData().toUtf8()), materialURLString); - - // Since our material changed, the current name might not be valid anymore, so we need to update - setCurrentMaterialName(_currentMaterialName); - applyMaterial(); - } else { - _networkMaterial = MaterialCache::instance().getMaterial(materialURLString); - auto onMaterialRequestFinished = [&](bool success) { - if (success) { - _parsedMaterials = _networkMaterial->parsedMaterials; - - setCurrentMaterialName(_currentMaterialName); - applyMaterial(); - } - }; - if (_networkMaterial) { - if (_networkMaterial->isLoaded()) { - onMaterialRequestFinished(!_networkMaterial->isFailed()); - } else { - connect(_networkMaterial.data(), &Resource::finished, this, onMaterialRequestFinished); - } - } - } - } +void MaterialEntityItem::setMaterialURL(const QString& materialURL) { + withWriteLock([&] { + _materialURL = materialURL; + }); } -void MaterialEntityItem::setCurrentMaterialName(const std::string& currentMaterialName) { - if (_parsedMaterials.networkMaterials.find(currentMaterialName) != _parsedMaterials.networkMaterials.end()) { - _currentMaterialName = currentMaterialName; - } else if (_parsedMaterials.names.size() > 0) { - _currentMaterialName = _parsedMaterials.names[0]; - } +QString MaterialEntityItem::getMaterialData() const { + return resultWithReadLock([&] { + return _materialData; + }); } void MaterialEntityItem::setMaterialData(const QString& materialData) { - if (_materialData != materialData) { + withWriteLock([&] { _materialData = materialData; - if (_materialURL.startsWith("materialData")) { - // Trigger material update when material data changes - setMaterialURL(_materialURL, true); - } - } + }); +} + +MaterialMappingMode MaterialEntityItem::getMaterialMappingMode() const { + return resultWithReadLock([&] { + return _materialMappingMode; + }); } void MaterialEntityItem::setMaterialMappingMode(MaterialMappingMode mode) { - if (_materialMappingMode != mode) { - removeMaterial(); + withWriteLock([&] { _materialMappingMode = mode; - setUnscaledDimensions(_desiredDimensions); - applyMaterial(); - } + }); + setUnscaledDimensions(_desiredDimensions); } -void MaterialEntityItem::setMaterialRepeat(bool repeat) { - if (_materialRepeat != repeat) { - removeMaterial(); - _materialRepeat = repeat; - applyMaterial(); - } -} - -void MaterialEntityItem::setMaterialMappingPos(const glm::vec2& materialMappingPos) { - if (_materialMappingPos != materialMappingPos) { - removeMaterial(); - _materialMappingPos = materialMappingPos; - applyMaterial(); - } -} - -void MaterialEntityItem::setMaterialMappingScale(const glm::vec2& materialMappingScale) { - if (_materialMappingScale != materialMappingScale) { - removeMaterial(); - _materialMappingScale = materialMappingScale; - applyMaterial(); - } -} - -void MaterialEntityItem::setMaterialMappingRot(const float& materialMappingRot) { - if (_materialMappingRot != materialMappingRot) { - removeMaterial(); - _materialMappingRot = materialMappingRot; - applyMaterial(); - } +quint16 MaterialEntityItem::getPriority() const { + return resultWithReadLock([&] { + return _priority; + }); } void MaterialEntityItem::setPriority(quint16 priority) { - if (_priority != priority) { - removeMaterial(); + withWriteLock([&] { _priority = priority; - applyMaterial(); - } + }); +} + +QString MaterialEntityItem::getParentMaterialName() const { + return resultWithReadLock([&] { + return _parentMaterialName; + }); } void MaterialEntityItem::setParentMaterialName(const QString& parentMaterialName) { - if (_parentMaterialName != parentMaterialName) { - removeMaterial(); + withWriteLock([&] { _parentMaterialName = parentMaterialName; - applyMaterial(); - } + }); } -void MaterialEntityItem::setParentID(const QUuid& parentID) { - if (getParentID() != parentID) { - removeMaterial(); - EntityItem::setParentID(parentID); - applyMaterial(); - } +glm::vec2 MaterialEntityItem::getMaterialMappingPos() const { + return resultWithReadLock([&] { + return _materialMappingPos; + }); } -void MaterialEntityItem::locationChanged(bool tellPhysics) { - EntityItem::locationChanged(); - if (_materialMappingMode == MaterialMappingMode::PROJECTED) { - removeMaterial(); - applyMaterial(); - } +void MaterialEntityItem::setMaterialMappingPos(const glm::vec2& materialMappingPos) { + withWriteLock([&] { + _materialMappingPos = materialMappingPos; + }); } -void MaterialEntityItem::dimensionsChanged() { - EntityItem::dimensionsChanged(); - if (_materialMappingMode == MaterialMappingMode::PROJECTED) { - removeMaterial(); - applyMaterial(); - } +glm::vec2 MaterialEntityItem::getMaterialMappingScale() const { + return resultWithReadLock([&] { + return _materialMappingScale; + }); } -void MaterialEntityItem::removeMaterial() { - graphics::MaterialPointer material = getMaterial(); - if (!material) { - return; - } - QUuid parentID = getParentID(); - if (parentID.isNull()) { - return; - } - - // Our parent could be an entity or an avatar - if (EntityTree::removeMaterialFromEntity(parentID, material, getParentMaterialName().toStdString())) { - return; - } - - if (EntityTree::removeMaterialFromAvatar(parentID, material, getParentMaterialName().toStdString())) { - return; - } - - // if a remove fails, our parent is gone, so we don't need to retry +void MaterialEntityItem::setMaterialMappingScale(const glm::vec2& materialMappingScale) { + withWriteLock([&] { + _materialMappingScale = materialMappingScale; + }); } -void MaterialEntityItem::applyMaterial() { - _retryApply = false; - graphics::MaterialPointer material = getMaterial(); - QUuid parentID = getParentID(); - if (!material || parentID.isNull()) { - return; - } +float MaterialEntityItem::getMaterialMappingRot() const { + return resultWithReadLock([&] { + return _materialMappingRot; + }); +} - Transform textureTransform; - if (_materialMappingMode == MaterialMappingMode::UV) { - textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0.0f)); - textureTransform.setRotation(glm::vec3(0.0f, 0.0f, glm::radians(_materialMappingRot))); - textureTransform.setScale(glm::vec3(_materialMappingScale, 1.0f)); - } else if (_materialMappingMode == MaterialMappingMode::PROJECTED) { - textureTransform = getTransform(); - textureTransform.postScale(getUnscaledDimensions()); - // Pass the inverse transform here so we don't need to compute it in the shaders - textureTransform.evalFromRawMatrix(textureTransform.getInverseMatrix()); - } - material->setTextureTransforms(textureTransform, _materialMappingMode, _materialRepeat); - - graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, getPriority()); - - // Our parent could be an entity or an avatar - if (EntityTree::addMaterialToEntity(parentID, materialLayer, getParentMaterialName().toStdString())) { - return; - } - - if (EntityTree::addMaterialToAvatar(parentID, materialLayer, getParentMaterialName().toStdString())) { - return; - } - - // if we've reached this point, we couldn't find our parent, so we need to try again later - _retryApply = true; +void MaterialEntityItem::setMaterialMappingRot(float materialMappingRot) { + withWriteLock([&] { + _materialMappingRot = materialMappingRot; + }); } AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) { @@ -372,18 +257,3 @@ AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) { } return aaCube; } - -void MaterialEntityItem::postParentFixup() { - removeMaterial(); - _queryAACubeSet = false; // force an update so we contain our parent - updateQueryAACube(); - applyMaterial(); -} - -void MaterialEntityItem::update(const quint64& now) { - if (_retryApply) { - applyMaterial(); - } - - EntityItem::update(now); -} diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index 069c71c1d6..b9e83a7fe5 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -12,8 +12,6 @@ #include "EntityItem.h" #include "MaterialMappingMode.h" -#include -#include class MaterialEntityItem : public EntityItem { using Pointer = std::shared_ptr; @@ -21,13 +19,9 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); MaterialEntityItem(const EntityItemID& entityItemID); - ~MaterialEntityItem(); ALLOW_INSTANTIATION // This class can be instantiated - void update(const quint64& now) override; - bool needsToCallUpdate() const override { return true; } - // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; @@ -52,44 +46,30 @@ public: virtual void setUnscaledDimensions(const glm::vec3& value) override; - QString getMaterialURL() const { return _materialURL; } - void setMaterialURL(const QString& materialURLString, bool materialDataChanged = false); + QString getMaterialURL() const; + void setMaterialURL(const QString& materialURL); - void setCurrentMaterialName(const std::string& currentMaterialName); + QString getMaterialData() const; + void setMaterialData(const QString& materialData); - MaterialMappingMode getMaterialMappingMode() const { return _materialMappingMode; } + MaterialMappingMode getMaterialMappingMode() const; void setMaterialMappingMode(MaterialMappingMode mode); bool getMaterialRepeat() const { return _materialRepeat; } - void setMaterialRepeat(bool repeat); + void setMaterialRepeat(bool repeat) { _materialRepeat = repeat; } - quint16 getPriority() const { return _priority; } + quint16 getPriority() const; void setPriority(quint16 priority); - QString getParentMaterialName() const { return _parentMaterialName; } + QString getParentMaterialName() const; void setParentMaterialName(const QString& parentMaterialName); - glm::vec2 getMaterialMappingPos() const { return _materialMappingPos; } + glm::vec2 getMaterialMappingPos() const; void setMaterialMappingPos(const glm::vec2& materialMappingPos); - glm::vec2 getMaterialMappingScale() const { return _materialMappingScale; } + glm::vec2 getMaterialMappingScale() const; void setMaterialMappingScale(const glm::vec2& materialMappingScale); - float getMaterialMappingRot() const { return _materialMappingRot; } - void setMaterialMappingRot(const float& materialMappingRot); - - QString getMaterialData() const { return _materialData; } - void setMaterialData(const QString& materialData); - - std::shared_ptr getMaterial() const; - - void setParentID(const QUuid& parentID) override; - - void locationChanged(bool tellPhysics) override; - void dimensionsChanged() override; - - void applyMaterial(); - void removeMaterial(); - - void postParentFixup() override; + float getMaterialMappingRot() const; + void setMaterialMappingRot(float materialMappingRot); AACube calculateInitialQueryAACube(bool& success) override; @@ -128,12 +108,6 @@ private: float _materialMappingRot { 0 }; QString _materialData; - NetworkMaterialResourcePointer _networkMaterial; - NetworkMaterialResource::ParsedMaterials _parsedMaterials; - std::string _currentMaterialName; - - bool _retryApply { false }; - }; #endif // hifi_MaterialEntityItem_h diff --git a/libraries/pointers/src/PickManager.cpp b/libraries/pointers/src/PickManager.cpp index d3326ea8b4..0cf5f90e3d 100644 --- a/libraries/pointers/src/PickManager.cpp +++ b/libraries/pointers/src/PickManager.cpp @@ -6,6 +6,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "PickManager.h" +#include "PerfStat.h" +#include "Profile.h" PickManager::PickManager() { setShouldPickHUDOperator([]() { return false; }); @@ -119,10 +121,26 @@ void PickManager::update() { bool shouldPickHUD = _shouldPickHUDOperator(); // FIXME: give each type its own expiry // Each type will update at least one pick, regardless of the expiry - _updatedPickCounts[PickQuery::Stylus] = _stylusPickCacheOptimizer.update(cachedPicks[PickQuery::Stylus], _nextPickToUpdate[PickQuery::Stylus], expiry, false); - _updatedPickCounts[PickQuery::Ray] = _rayPickCacheOptimizer.update(cachedPicks[PickQuery::Ray], _nextPickToUpdate[PickQuery::Ray], expiry, shouldPickHUD); - _updatedPickCounts[PickQuery::Parabola] = _parabolaPickCacheOptimizer.update(cachedPicks[PickQuery::Parabola], _nextPickToUpdate[PickQuery::Parabola], expiry, shouldPickHUD); - _updatedPickCounts[PickQuery::Collision] = _collisionPickCacheOptimizer.update(cachedPicks[PickQuery::Collision], _nextPickToUpdate[PickQuery::Collision], expiry, false); + { + PROFILE_RANGE(picks, "StylusPicks"); + PerformanceTimer perfTimer("StylusPicks"); + _updatedPickCounts[PickQuery::Stylus] = _stylusPickCacheOptimizer.update(cachedPicks[PickQuery::Stylus], _nextPickToUpdate[PickQuery::Stylus], expiry, false); + } + { + PROFILE_RANGE(picks, "RayPicks"); + PerformanceTimer perfTimer("RayPicks"); + _updatedPickCounts[PickQuery::Ray] = _rayPickCacheOptimizer.update(cachedPicks[PickQuery::Ray], _nextPickToUpdate[PickQuery::Ray], expiry, shouldPickHUD); + } + { + PROFILE_RANGE(picks, "ParabolaPick"); + PerformanceTimer perfTimer("ParabolaPick"); + _updatedPickCounts[PickQuery::Parabola] = _parabolaPickCacheOptimizer.update(cachedPicks[PickQuery::Parabola], _nextPickToUpdate[PickQuery::Parabola], expiry, shouldPickHUD); + } + { + PROFILE_RANGE(picks, "CollisoinPicks"); + PerformanceTimer perfTimer("CollisionPicks"); + _updatedPickCounts[PickQuery::Collision] = _collisionPickCacheOptimizer.update(cachedPicks[PickQuery::Collision], _nextPickToUpdate[PickQuery::Collision], expiry, false); + } } bool PickManager::isLeftHand(unsigned int uid) { diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index b1ca24de1f..ee53347158 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -205,7 +205,7 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() { } AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() : - render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false), + render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion"), perspectiveScale{ 1.0f }, edgeSharpness{ 1.0f }, blurRadius{ 4 }, diff --git a/libraries/render-utils/src/LightingModel.h b/libraries/render-utils/src/LightingModel.h index 571eadb60b..f6bd6dcd46 100644 --- a/libraries/render-utils/src/LightingModel.h +++ b/libraries/render-utils/src/LightingModel.h @@ -118,7 +118,7 @@ protected: float enableSkinning{ 1.0f }; float enableBlendshape{ 1.0f }; - float enableAmbientOcclusion{ 0.0f }; + float enableAmbientOcclusion{ 0.0f }; // false by default float enableShadow{ 1.0f }; float spare1{ 1.0f }; float spare2{ 1.0f }; @@ -196,15 +196,13 @@ public: bool enableSkinning{ true }; bool enableBlendshape{ true }; - bool enableAmbientOcclusion{ true }; + bool enableAmbientOcclusion{ false }; // false by default bool enableShadow{ true }; void setAmbientOcclusion(bool enable) { enableAmbientOcclusion = enable; emit dirty();} bool isAmbientOcclusionEnabled() const { return enableAmbientOcclusion; } - void setShadow(bool enable) { - enableShadow = enable; emit dirty(); - } + void setShadow(bool enable) { enableShadow = enable; emit dirty(); } bool isShadowEnabled() const { return enableShadow; } signals: diff --git a/libraries/shared/src/Profile.cpp b/libraries/shared/src/Profile.cpp index 778b39aca5..272538e26d 100644 --- a/libraries/shared/src/Profile.cpp +++ b/libraries/shared/src/Profile.cpp @@ -12,6 +12,7 @@ Q_LOGGING_CATEGORY(trace_app, "trace.app") Q_LOGGING_CATEGORY(trace_app_detail, "trace.app.detail") Q_LOGGING_CATEGORY(trace_metadata, "trace.metadata") Q_LOGGING_CATEGORY(trace_network, "trace.network") +Q_LOGGING_CATEGORY(trace_picks, "trace.picks") Q_LOGGING_CATEGORY(trace_parse, "trace.parse") Q_LOGGING_CATEGORY(trace_render, "trace.render") Q_LOGGING_CATEGORY(trace_render_detail, "trace.render.detail") diff --git a/libraries/shared/src/Profile.h b/libraries/shared/src/Profile.h index 01d86f8f2e..dc2ed6e754 100644 --- a/libraries/shared/src/Profile.h +++ b/libraries/shared/src/Profile.h @@ -18,6 +18,7 @@ Q_DECLARE_LOGGING_CATEGORY(trace_app) Q_DECLARE_LOGGING_CATEGORY(trace_app_detail) Q_DECLARE_LOGGING_CATEGORY(trace_metadata) Q_DECLARE_LOGGING_CATEGORY(trace_network) +Q_DECLARE_LOGGING_CATEGORY(trace_picks) Q_DECLARE_LOGGING_CATEGORY(trace_render) Q_DECLARE_LOGGING_CATEGORY(trace_render_detail) Q_DECLARE_LOGGING_CATEGORY(trace_render_gpu) diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 6d98e96780..f5c0b8c5da 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -47,7 +47,7 @@ Rectangle { "Lightmap:LightingModel:enableLightmap", "Background:LightingModel:enableBackground", "Haze:LightingModel:enableHaze", - "ssao:LightingModel:enableAmbientOcclusion", + "AO:LightingModel:enableAmbientOcclusion", "Textures:LightingModel:enableMaterialTexturing" ] HifiControls.CheckBox { diff --git a/scripts/system/away.js b/scripts/system/away.js index a2e73ae63c..45b6f43b73 100644 --- a/scripts/system/away.js +++ b/scripts/system/away.js @@ -45,7 +45,8 @@ var OVERLAY_DATA_HMD = { emissive: true, drawInFront: true, parentID: MyAvatar.SELF_ID, - parentJointIndex: CAMERA_MATRIX + parentJointIndex: CAMERA_MATRIX, + ignorePickIntersection: true }; var AWAY_INTRO = { diff --git a/scripts/system/controllers/+android_questInterface/controllerScripts.js b/scripts/system/controllers/+android_questInterface/controllerScripts.js new file mode 100644 index 0000000000..d313efaca1 --- /dev/null +++ b/scripts/system/controllers/+android_questInterface/controllerScripts.js @@ -0,0 +1,58 @@ +"use strict"; + +// controllerScripts.js +// +// Created by David Rowe on 15 Mar 2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +/* global Script, Menu */ + +var CONTOLLER_SCRIPTS = [ + "squeezeHands.js", + "controllerDisplayManager.js", + "toggleAdvancedMovementForHandControllers.js", + "controllerDispatcher.js", + "controllerModules/nearParentGrabOverlay.js", + "controllerModules/stylusInput.js", + "controllerModules/equipEntity.js", + "controllerModules/nearTrigger.js", + "controllerModules/webSurfaceLaserInput.js", + "controllerModules/inVREditMode.js", + "controllerModules/disableOtherModule.js", + "controllerModules/farTrigger.js", + "controllerModules/teleport.js", + "controllerModules/hudOverlayPointer.js", + "controllerModules/scaleEntity.js", + "controllerModules/nearGrabHyperLinkEntity.js", + "controllerModules/nearTabletHighlight.js", + "controllerModules/nearGrabEntity.js", + "controllerModules/farGrabEntity.js" +]; + +var DEBUG_MENU_ITEM = "Debug defaultScripts.js"; + +function runDefaultsTogether() { + for (var j in CONTOLLER_SCRIPTS) { + if (CONTOLLER_SCRIPTS.hasOwnProperty(j)) { + Script.include(CONTOLLER_SCRIPTS[j]); + } + } +} + +function runDefaultsSeparately() { + for (var i in CONTOLLER_SCRIPTS) { + if (CONTOLLER_SCRIPTS.hasOwnProperty(i)) { + Script.load(CONTOLLER_SCRIPTS[i]); + } + } +} + +if (Menu.isOptionChecked(DEBUG_MENU_ITEM)) { + runDefaultsSeparately(); +} else { + runDefaultsTogether(); +} diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 2a5cf5a727..28c3e2a299 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -497,6 +497,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); distanceScaleEnd: true, hand: RIGHT_HAND }); + this.mouseRayPick = Pointers.createPointer(PickType.Ray, { joint: "Mouse", filter: Picks.PICK_OVERLAYS | Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index 8770ae8dde..23457cdd85 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -196,14 +196,14 @@ Script.include("/~/system/libraries/controllers.js"); var playAreaOverlayProperties = { dimensions: - Vec3.multiply(this.teleportScaleFactor * avatarScale, { - x: this.playArea.width, - y: this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y, - z: this.playArea.height + Vec3.multiply(_this.teleportScaleFactor * avatarScale, { + x: _this.playArea.width, + y: _this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y, + z: _this.playArea.height }) }; - if (this.teleportScaleFactor < 1) { + if (_this.teleportScaleFactor < 1) { // Adjust position of playAreOverlay so that its base is at correct height. // Always parenting to teleport target is good enough for this. var sensorToWorldMatrix = MyAvatar.sensorToWorldMatrix; @@ -212,37 +212,37 @@ Script.include("/~/system/libraries/controllers.js"); var avatarSensorPosition = Mat4.transformPoint(worldToSensorMatrix, MyAvatar.position); avatarSensorPosition.y = 0; - var targetRotation = Overlays.getProperty(this.targetOverlayID, "rotation"); + var targetRotation = Overlays.getProperty(_this.targetOverlayID, "rotation"); var relativePlayAreaCenterOffset = - Vec3.sum(this.playAreaCenterOffset, { x: 0, y: -TARGET_MODEL_DIMENSIONS.y / 2, z: 0 }); + Vec3.sum(_this.playAreaCenterOffset, { x: 0, y: -TARGET_MODEL_DIMENSIONS.y / 2, z: 0 }); var localPosition = Vec3.multiplyQbyV(Quat.inverse(targetRotation), Vec3.multiplyQbyV(sensorToWorldRotation, Vec3.multiply(avatarScale, Vec3.subtract(relativePlayAreaCenterOffset, avatarSensorPosition)))); - localPosition.y = this.teleportScaleFactor * localPosition.y; + localPosition.y = _this.teleportScaleFactor * localPosition.y; - playAreaOverlayProperties.parentID = this.targetOverlayID; + playAreaOverlayProperties.parentID = _this.targetOverlayID; playAreaOverlayProperties.localPosition = localPosition; } - Overlays.editOverlay(this.playAreaOverlay, playAreaOverlayProperties); + Overlays.editOverlay(_this.playAreaOverlay, playAreaOverlayProperties); - for (var i = 0; i < this.playAreaSensorPositionOverlays.length; i++) { - localPosition = this.playAreaSensorPositions[i]; + for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) { + localPosition = _this.playAreaSensorPositions[i]; localPosition = Vec3.multiply(avatarScale, localPosition); // Position relative to the play area. - localPosition.y = avatarScale * (this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS.y / 2 - - this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2); - Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], { - dimensions: Vec3.multiply(this.teleportScaleFactor * avatarScale, this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS), - parentID: this.playAreaOverlay, + localPosition.y = avatarScale * (_this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS.y / 2 + - _this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2); + Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { + dimensions: Vec3.multiply(_this.teleportScaleFactor * avatarScale, _this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS), + parentID: _this.playAreaOverlay, localPosition: localPosition }); } }; this.updatePlayAreaScale = function () { - if (this.isPlayAreaAvailable) { - this.setPlayAreaDimensions(); + if (_this.isPlayAreaAvailable) { + _this.setPlayAreaDimensions(); } }; @@ -265,7 +265,7 @@ Script.include("/~/system/libraries/controllers.js"); for (var i = 0, length = teleportRenderStates.length; i < length; i++) { var state = properties.renderStates[teleportRenderStates[i].name]; if (state && state.end) { - Selection.addToSelectedItemsList(this.teleporterSelectionName, "overlay", state.end); + Selection.addToSelectedItemsList(_this.teleporterSelectionName, "overlay", state.end); } } }; @@ -448,34 +448,34 @@ Script.include("/~/system/libraries/controllers.js"); this.translateZAction = Controller.findAction("TranslateZ"); this.setPlayAreaVisible = function (visible, targetOverlayID, fade) { - if (!this.isPlayAreaAvailable || this.isPlayAreaVisible === visible) { + if (!_this.isPlayAreaAvailable || _this.isPlayAreaVisible === visible) { return; } - this.wasPlayAreaVisible = this.isPlayAreaVisible; - this.isPlayAreaVisible = visible; - this.targetOverlayID = targetOverlayID; + _this.wasPlayAreaVisible = _this.isPlayAreaVisible; + _this.isPlayAreaVisible = visible; + _this.targetOverlayID = targetOverlayID; - if (this.teleportedFadeTimer !== null) { - Script.clearTimeout(this.teleportedFadeTimer); - this.teleportedFadeTimer = null; + if (_this.teleportedFadeTimer !== null) { + Script.clearTimeout(_this.teleportedFadeTimer); + _this.teleportedFadeTimer = null; } if (visible || !fade) { // Immediately make visible or invisible. - this.isPlayAreaVisible = visible; - Overlays.editOverlay(this.playAreaOverlay, { + _this.isPlayAreaVisible = visible; + Overlays.editOverlay(_this.playAreaOverlay, { dimensions: Vec3.ZERO, - alpha: this.PLAY_AREA_BOX_ALPHA, + alpha: _this.PLAY_AREA_BOX_ALPHA, visible: visible }); - for (var i = 0; i < this.playAreaSensorPositionOverlays.length; i++) { - Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], { + for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) { + Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { dimensions: Vec3.ZERO, - alpha: this.PLAY_AREA_SENSOR_ALPHA, + alpha: _this.PLAY_AREA_SENSOR_ALPHA, visible: visible }); } - Overlays.editOverlay(this.teleportedTargetOverlay, { visible: false }); + Overlays.editOverlay(_this.teleportedTargetOverlay, { visible: false }); } else { // Fading out of overlays is initiated in setTeleportVisible(). } @@ -494,22 +494,22 @@ Script.include("/~/system/libraries/controllers.js"); var MIN_PARENTING_DISTANCE = 0.2; // Parenting under this distance results in the play area's rotation jittering. if (Vec3.distance(targetXZPosition, avatarXZPosition) < MIN_PARENTING_DISTANCE) { // Set play area position and rotation in world coordinates with no parenting. - Overlays.editOverlay(this.playAreaOverlay, { + Overlays.editOverlay(_this.playAreaOverlay, { parentID: Uuid.NULL, position: Vec3.sum(position, Vec3.multiplyQbyV(sensorToWorldRotation, Vec3.multiply(MyAvatar.sensorToWorldScale, - Vec3.subtract(this.playAreaCenterOffset, avatarSensorPosition)))), + Vec3.subtract(_this.playAreaCenterOffset, avatarSensorPosition)))), rotation: sensorToWorldRotation }); } else { // Set play area position and rotation in local coordinates with parenting. - var targetRotation = Overlays.getProperty(this.targetOverlayID, "rotation"); + var targetRotation = Overlays.getProperty(_this.targetOverlayID, "rotation"); var sensorToTargetRotation = Quat.multiply(Quat.inverse(targetRotation), sensorToWorldRotation); var relativePlayAreaCenterOffset = - Vec3.sum(this.playAreaCenterOffset, { x: 0, y: -TARGET_MODEL_DIMENSIONS.y / 2, z: 0 }); - Overlays.editOverlay(this.playAreaOverlay, { - parentID: this.targetOverlayID, + Vec3.sum(_this.playAreaCenterOffset, { x: 0, y: -TARGET_MODEL_DIMENSIONS.y / 2, z: 0 }); + Overlays.editOverlay(_this.playAreaOverlay, { + parentID: _this.targetOverlayID, localPosition: Vec3.multiplyQbyV(Quat.inverse(targetRotation), Vec3.multiplyQbyV(sensorToWorldRotation, Vec3.multiply(MyAvatar.sensorToWorldScale, @@ -578,33 +578,33 @@ Script.include("/~/system/libraries/controllers.js"); } } _this.teleportedFadeTimer = null; - Selection.disableListHighlight(this.teleporterSelectionName); + Selection.disableListHighlight(_this.teleporterSelectionName); } }; this.cancelFade = function () { // Other hand may call this to immediately hide fading overlays. var i, length; - if (this.teleportedFadeTimer) { - Overlays.editOverlay(this.teleportedTargetOverlay, { visible: false }); - if (this.wasPlayAreaVisible) { - Overlays.editOverlay(this.playAreaOverlay, { visible: false }); - for (i = 0, length = this.playAreaSensorPositionOverlays.length; i < length; i++) { - Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], { visible: false }); + if (_this.teleportedFadeTimer) { + Overlays.editOverlay(_this.teleportedTargetOverlay, { visible: false }); + if (_this.wasPlayAreaVisible) { + Overlays.editOverlay(_this.playAreaOverlay, { visible: false }); + for (i = 0, length = _this.playAreaSensorPositionOverlays.length; i < length; i++) { + Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { visible: false }); } } - this.teleportedFadeTimer = null; + _this.teleportedFadeTimer = null; } }; this.setTeleportVisible = function (visible, mode, fade) { // Scales in teleport target and play area when start displaying them. - if (visible === this.isTeleportVisible) { + if (visible === _this.isTeleportVisible) { return; } if (visible) { - this.teleportScaleMode = mode; + _this.teleportScaleMode = mode; Pointers.editRenderState( mode === "head" ? _this.teleportParabolaHeadVisuals : _this.teleportParabolaHandVisuals, "teleport", @@ -613,42 +613,42 @@ Script.include("/~/system/libraries/controllers.js"); end: { dimensions: Vec3.ZERO } } ); - this.getOtherModule().cancelFade(); - this.teleportScaleStart = Date.now(); - this.teleportScaleFactor = 0; - this.scaleInTeleport(); - Selection.enableListHighlight(this.teleporterSelectionName, this.TELEPORTER_SELECTION_STYLE); + _this.getOtherModule().cancelFade(); + _this.teleportScaleStart = Date.now(); + _this.teleportScaleFactor = 0; + _this.scaleInTeleport(); + Selection.enableListHighlight(_this.teleporterSelectionName, _this.TELEPORTER_SELECTION_STYLE); } else { - if (this.teleportScaleTimer !== null) { - Script.clearTimeout(this.teleportScaleTimer); - this.teleportScaleTimer = null; + if (_this.teleportScaleTimer !== null) { + Script.clearTimeout(_this.teleportScaleTimer); + _this.teleportScaleTimer = null; } if (fade) { // Copy of target at teleported position for fading. var avatarScale = MyAvatar.sensorToWorldScale; - Overlays.editOverlay(this.teleportedTargetOverlay, { - position: Vec3.sum(this.teleportedPosition, { + Overlays.editOverlay(_this.teleportedTargetOverlay, { + position: Vec3.sum(_this.teleportedPosition, { x: 0, y: -getAvatarFootOffset() + avatarScale * TARGET_MODEL_DIMENSIONS.y / 2, z: 0 }), - rotation: Quat.multiply(this.TELEPORTED_TARGET_ROTATION, MyAvatar.orientation), + rotation: Quat.multiply(_this.TELEPORTED_TARGET_ROTATION, MyAvatar.orientation), dimensions: Vec3.multiply(avatarScale, TARGET_MODEL_DIMENSIONS), - alpha: this.TELEPORTED_TARGET_ALPHA, + alpha: _this.TELEPORTED_TARGET_ALPHA, visible: true }); // Fade out over time. - this.teleportedFadeDelayFactor = 1.0; - this.teleportedFadeFactor = 1.0; - this.teleportedFadeTimer = Script.setTimeout(this.fadeOutTeleport, this.TELEPORTED_FADE_DELAY); + _this.teleportedFadeDelayFactor = 1.0; + _this.teleportedFadeFactor = 1.0; + _this.teleportedFadeTimer = Script.setTimeout(_this.fadeOutTeleport, _this.TELEPORTED_FADE_DELAY); } else { - Selection.disableListHighlight(this.teleporterSelectionName); + Selection.disableListHighlight(_this.teleporterSelectionName); } } - this.isTeleportVisible = visible; + _this.isTeleportVisible = visible; }; @@ -697,7 +697,7 @@ Script.include("/~/system/libraries/controllers.js"); 100); this.enterTeleport = function() { - this.state = TELEPORTER_STATES.TARGETTING; + _this.state = TELEPORTER_STATES.TARGETTING; }; this.isReady = function(controllerData, deltaTime) { @@ -761,23 +761,23 @@ Script.include("/~/system/libraries/controllers.js"); if (teleportLocationType === TARGET.NONE) { // Use the cancel default state - this.setTeleportState(mode, "cancel", ""); + _this.setTeleportState(mode, "cancel", ""); } else if (teleportLocationType === TARGET.INVALID) { - this.setTeleportState(mode, "", "cancel"); + _this.setTeleportState(mode, "", "cancel"); } else if (teleportLocationType === TARGET.COLLIDES) { - this.setTeleportState(mode, "cancel", "collision"); + _this.setTeleportState(mode, "cancel", "collision"); } else if (teleportLocationType === TARGET.SURFACE || teleportLocationType === TARGET.DISCREPANCY) { - this.setTeleportState(mode, "teleport", "collision"); - this.updatePlayArea(result.intersection); + _this.setTeleportState(mode, "teleport", "collision"); + _this.updatePlayArea(result.intersection); } else if (teleportLocationType === TARGET.SEAT) { - this.setTeleportState(mode, "collision", "seat"); + _this.setTeleportState(mode, "collision", "seat"); } - return this.teleport(result, teleportLocationType); + return _this.teleport(result, teleportLocationType); }; this.teleport = function(newResult, target) { var result = newResult; - this.teleportedPosition = newResult.intersection; + _this.teleportedPosition = newResult.intersection; if (_this.buttonValue !== 0) { return makeRunningValues(true, [], []); } @@ -795,14 +795,14 @@ Script.include("/~/system/libraries/controllers.js"); MyAvatar.centerBody(); } - this.disableLasers(); - this.active = false; + _this.disableLasers(); + _this.active = false; return makeRunningValues(false, [], []); }; this.disableLasers = function() { - this.setPlayAreaVisible(false, null, true); - this.setTeleportVisible(false, null, true); + _this.setPlayAreaVisible(false, null, true); + _this.setTeleportVisible(false, null, true); Pointers.disablePointer(_this.teleportParabolaHandVisuals); Pointers.disablePointer(_this.teleportParabolaHandCollisions); Pointers.disablePointer(_this.teleportParabolaHeadVisuals); @@ -815,10 +815,10 @@ Script.include("/~/system/libraries/controllers.js"); this.setTeleportState = function (mode, visibleState, invisibleState) { var teleportState = mode + visibleState + invisibleState; - if (teleportState === this.teleportState) { + if (teleportState === _this.teleportState) { return; } - this.teleportState = teleportState; + _this.teleportState = teleportState; var pointerID; if (mode === 'head') { @@ -831,16 +831,16 @@ Script.include("/~/system/libraries/controllers.js"); pointerID = _this.teleportParabolaHandVisuals; } var visible = visibleState === "teleport"; - this.setPlayAreaVisible(visible && MyAvatar.showPlayArea, + _this.setPlayAreaVisible(visible && MyAvatar.showPlayArea, Pointers.getPointerProperties(pointerID).renderStates.teleport.end, false); - this.setTeleportVisible(visible, mode, false); + _this.setTeleportVisible(visible, mode, false); }; this.setIgnoreEntities = function(entitiesToIgnore) { - Pointers.setIgnoreItems(this.teleportParabolaHandVisuals, entitiesToIgnore); - Pointers.setIgnoreItems(this.teleportParabolaHandCollisions, entitiesToIgnore); - Pointers.setIgnoreItems(this.teleportParabolaHeadVisuals, entitiesToIgnore); - Pointers.setIgnoreItems(this.teleportParabolaHeadCollisions, entitiesToIgnore); + Pointers.setIgnoreItems(_this.teleportParabolaHandVisuals, entitiesToIgnore); + Pointers.setIgnoreItems(_this.teleportParabolaHandCollisions, entitiesToIgnore); + Pointers.setIgnoreItems(_this.teleportParabolaHeadVisuals, entitiesToIgnore); + Pointers.setIgnoreItems(_this.teleportParabolaHeadCollisions, entitiesToIgnore); Picks.setIgnoreItems(_this.teleportHeadCollisionPick, entitiesToIgnore); Picks.setIgnoreItems(_this.teleportHandCollisionPick, entitiesToIgnore); }; diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 141ea03330..0c4338b31d 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -161,7 +161,8 @@ ExtendedOverlay.unHover = function () { // calls hover(false) on lastHoveringId // hit(overlay) on the one overlay intersected by pickRay, if any. // noHit() if no ExtendedOverlay was intersected (helps with hover) ExtendedOverlay.applyPickRay = function (pickRay, hit, noHit) { - var pickedOverlay = Overlays.findRayIntersection(pickRay); // Depends on nearer coverOverlays to extend closer to us than farther ones. + // TODO: this could just include the necessary overlays for better performance + var pickedOverlay = Overlays.findRayIntersection(pickRay, true); // Depends on nearer coverOverlays to extend closer to us than farther ones. if (!pickedOverlay.intersects) { if (noHit) { return noHit(); diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index f9e9165f2e..60848224bb 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -137,11 +137,11 @@ UIWebTablet.calculateTabletAttachmentProperties(activeHand, true, tabletProperties); } tabletProperties.visible = true; + tabletProperties.ignorePickIntersection = false; Overlays.editOverlay(HMD.tabletID, tabletProperties); - Overlays.editOverlay(HMD.homeButtonID, { visible: true }); - Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: true }); - Overlays.editOverlay(HMD.tabletScreenID, { visible: true }); - Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 90 }); + Overlays.editOverlay(HMD.homeButtonID, { visible: true, ignorePickIntersection: false }); + Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: true, ignorePickIntersection: false }); + Overlays.editOverlay(HMD.tabletScreenID, { visible: true, ignorePickIntersection: false, maxFPS: 90 }); updateTabletWidthFromSettings(true); } gTablet.tabletShown = true; @@ -158,11 +158,10 @@ print("TABLET hide"); } - Overlays.editOverlay(HMD.tabletID, { visible: false }); - Overlays.editOverlay(HMD.homeButtonID, { visible: false }); - Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: false }); - Overlays.editOverlay(HMD.tabletScreenID, { visible: false }); - Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 1 }); + Overlays.editOverlay(HMD.tabletID, { visible: false, ignorePickIntersection: true }); + Overlays.editOverlay(HMD.homeButtonID, { visible: false, ignorePickIntersection: true }); + Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: false, ignorePickIntersection: true }); + Overlays.editOverlay(HMD.tabletScreenID, { visible: false, ignorePickIntersection: true, maxFPS: 1 }); } function closeTabletUI() {