Merge remote-tracking branch 'upstream/master' into wearables

This commit is contained in:
SamGondelman 2019-02-19 16:52:00 -08:00
commit 6765268998
36 changed files with 766 additions and 571 deletions

View file

@ -33,15 +33,19 @@ Rectangle {
property bool balanceReceived: false; property bool balanceReceived: false;
property bool availableUpdatesReceived: false; property bool availableUpdatesReceived: false;
property bool itemInfoReceived: false; property bool itemInfoReceived: false;
property bool dataReady: itemInfoReceived && ownershipStatusReceived && balanceReceived && availableUpdatesReceived;
property string baseItemName: ""; property string baseItemName: "";
property string itemName; property string itemName;
property string itemId; property string itemId;
property string itemHref; property string itemHref;
property string itemAuthor; property string itemAuthor;
property int itemEdition: -1; 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 string certificateId;
property double balanceAfterPurchase; property double balanceAfterPurchase;
property bool alreadyOwned: false; property bool alreadyOwned: false; // Including proofs
property int itemPrice: -1; property int itemPrice: -1;
property bool isCertified; property bool isCertified;
property string itemType: "unknown"; property string itemType: "unknown";
@ -56,6 +60,8 @@ Rectangle {
property string referrer; property string referrer;
property bool isInstalled; property bool isInstalled;
property bool isUpdating; property bool isUpdating;
property string availability: "available";
property string creator: "";
property string baseAppURL; property string baseAppURL;
property int currentUpdatesPage: 1; property int currentUpdatesPage: 1;
// Style // Style
@ -434,7 +440,7 @@ Rectangle {
anchors.top: parent.top; anchors.top: parent.top;
anchors.left: itemPreviewImage.right; anchors.left: itemPreviewImage.right;
anchors.leftMargin: 12; anchors.leftMargin: 12;
anchors.right: itemPriceContainer.left; anchors.right: parent.right;
anchors.rightMargin: 8; anchors.rightMargin: 8;
height: 30; height: 30;
// Style // Style
@ -449,21 +455,22 @@ Rectangle {
Item { Item {
id: itemPriceContainer; id: itemPriceContainer;
// Anchors // Anchors
anchors.top: parent.top; anchors.top: itemNameText.bottom;
anchors.right: parent.right; anchors.topMargin: 8;
anchors.left: itemNameText.left;
height: 30; height: 30;
width: itemPriceTextLabel.width + itemPriceText.width + 20; width: itemPriceText.width + 20;
// "HFC" balance label // "HFC" label
HiFiGlyphs { HiFiGlyphs {
id: itemPriceTextLabel; id: itemPriceTextLabel;
visible: !(root.isUpdating && root.itemEdition > 0) && (root.itemPrice > 0); visible: !isTradingIn && (root.itemPrice > 0);
text: hifi.glyphs.hfc; text: hifi.glyphs.hfc;
// Size // Size
size: 30; size: 30;
// Anchors // Anchors
anchors.right: itemPriceText.left; anchors.right: parent.right;
anchors.rightMargin: 4; //anchors.rightMargin: 4;
anchors.top: parent.top; anchors.top: parent.top;
anchors.topMargin: 0; anchors.topMargin: 0;
width: paintedWidth; width: paintedWidth;
@ -473,13 +480,15 @@ Rectangle {
} }
FiraSansSemiBold { FiraSansSemiBold {
id: itemPriceText; 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 // Text size
size: (root.isUpdating && root.itemEdition > 0) ? 20 : 26; size: isTradingIn ? 20 : 26;
// Anchors // Anchors
anchors.top: parent.top; anchors.top: parent.top;
anchors.right: parent.right; anchors.left: itemPriceTextLabel.visible ? itemPriceTextLabel.right : parent.left;
anchors.rightMargin: 16; anchors.leftMargin: 4;
width: paintedWidth; width: paintedWidth;
height: paintedHeight; height: paintedHeight;
// Style // Style
@ -571,7 +580,7 @@ Rectangle {
// "View in Inventory" button // "View in Inventory" button
HifiControlsUit.Button { HifiControlsUit.Button {
id: viewInMyPurchasesButton; id: viewInMyPurchasesButton;
visible: false; visible: isCertified && dataReady && (isUpdating ? !hasSomethingToTradeIn : alreadyOwned);
color: hifi.buttons.blue; color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.light; colorScheme: hifi.colorSchemes.light;
anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top; anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top;
@ -592,8 +601,8 @@ Rectangle {
// "Buy" button // "Buy" button
HifiControlsUit.Button { HifiControlsUit.Button {
id: buyButton; id: buyButton;
visible: !((root.itemType === "avatar" || root.itemType === "app") && viewInMyPurchasesButton.visible) visible: isTradingIn || !alreadyOwned || isStocking || !(root.itemType === "avatar" || root.itemType === "app");
enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived && availableUpdatesReceived) || (!root.isCertified) || root.isUpdating; enabled: (root.balanceAfterPurchase >= 0 && dataReady) || (!root.isCertified) || root.isUpdating;
color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue; color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue;
colorScheme: hifi.colorSchemes.light; colorScheme: hifi.colorSchemes.light;
anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom : anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom :
@ -602,10 +611,15 @@ Rectangle {
height: 50; height: 50;
anchors.left: parent.left; anchors.left: parent.left;
anchors.right: parent.right; anchors.right: parent.right;
text: (root.isUpdating && root.itemEdition > 0) ? "CONFIRM UPDATE" : (((root.isCertified) ? ((ownershipStatusReceived && balanceReceived && availableUpdatesReceived) ? text: isTradingIn ?
((viewInMyPurchasesButton.visible && !root.isUpdating) ? "Get It Again" : "Confirm") : "--") : "Get Item")); "CONFIRM UPDATE" :
(((root.isCertified) ?
(dataReady ?
((viewInMyPurchasesButton.visible && !root.isUpdating) ? "Get It Again" : "Confirm") :
"--") :
"Get Item"));
onClicked: { onClicked: {
if (root.isUpdating && root.itemEdition > 0) { if (isTradingIn) {
// If we're updating an app, the existing app needs to be uninstalled. // 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. // This call will fail/return `false` if the app isn't installed, but that's OK.
if (root.itemType === "app") { if (root.itemType === "app") {
@ -1063,7 +1077,11 @@ Rectangle {
buyButton.color = hifi.buttons.red; buyButton.color = hifi.buttons.red;
root.shouldBuyWithControlledFailure = true; root.shouldBuyWithControlledFailure = true;
} else { } 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; buyButton.color = hifi.buttons.blue;
root.shouldBuyWithControlledFailure = false; root.shouldBuyWithControlledFailure = false;
} }
@ -1091,6 +1109,8 @@ Rectangle {
root.itemPrice = result.data.cost; root.itemPrice = result.data.cost;
root.itemAuthor = result.data.creator; root.itemAuthor = result.data.creator;
root.itemType = result.data.item_type || "unknown"; root.itemType = result.data.item_type || "unknown";
root.availability = result.data.availability;
root.creator = result.data.creator;
if (root.itemType === "unknown") { if (root.itemType === "unknown") {
root.itemHref = result.data.review_url; root.itemHref = result.data.review_url;
} else { } else {
@ -1139,7 +1159,7 @@ Rectangle {
signal sendToScript(var message); signal sendToScript(var message);
function canBuyAgain() { 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() { function handleContentSets() {
@ -1185,29 +1205,23 @@ Rectangle {
function refreshBuyUI() { function refreshBuyUI() {
if (root.isCertified) { if (root.isCertified) {
if (root.ownershipStatusReceived && root.balanceReceived && root.availableUpdatesReceived) { if (dataReady) {
buyText.text = ""; buyText.text = "";
// If the user IS on the checkout page for the updated version of an owned item... // If the user IS on the checkout page for the updated version of an owned item...
if (root.isUpdating) { if (root.isUpdating) {
// If the user HAS already selected a specific edition to update... // 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."; 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.color = "#FFFFFF";
buyTextContainer.border.color = "#FFFFFF"; buyTextContainer.border.color = "#FFFFFF";
// Else if the user HAS NOT selected a specific edition to update... // Else if the user HAS NOT selected a specific edition to update...
} else { } else {
viewInMyPurchasesButton.visible = true;
handleBuyAgainLogic(); handleBuyAgainLogic();
} }
// If the user IS NOT on the checkout page for the updated verison of an owned item... // 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") // (i.e. they are checking out an item "normally")
} else { } else {
if (root.alreadyOwned) {
viewInMyPurchasesButton.visible = true;
}
handleBuyAgainLogic(); handleBuyAgainLogic();
} }
} else { } else {

View file

@ -121,7 +121,7 @@ Rectangle {
marketplaceItem.description = result.data.description; marketplaceItem.description = result.data.description;
marketplaceItem.attributions = result.data.attributions; marketplaceItem.attributions = result.data.attributions;
marketplaceItem.license = result.data.license; marketplaceItem.license = result.data.license;
marketplaceItem.available = result.data.availability === "available"; marketplaceItem.availability = result.data.availability;
marketplaceItem.created_at = result.data.created_at; marketplaceItem.created_at = result.data.created_at;
marketplaceItemScrollView.contentHeight = marketplaceItemContent.height; marketplaceItemScrollView.contentHeight = marketplaceItemContent.height;
itemsList.visible = false; itemsList.visible = false;
@ -539,7 +539,7 @@ Rectangle {
creator: model.creator creator: model.creator
category: model.primary_category category: model.primary_category
price: model.cost price: model.cost
available: model.availability === "available" availability: model.availability
isLoggedIn: root.isLoggedIn; isLoggedIn: root.isLoggedIn;
onShowItem: { onShowItem: {
@ -711,7 +711,7 @@ Rectangle {
topMargin: 10; topMargin: 10;
leftMargin: 15; leftMargin: 15;
} }
height: visible ? childrenRect.height : 0 height: visible ? 36 : 0
RalewayRegular { RalewayRegular {
id: sortText id: sortText
@ -733,8 +733,9 @@ Rectangle {
top: parent.top top: parent.top
leftMargin: 20 leftMargin: 20
} }
width: root.isLoggedIn ? 342 : 262 width: root.isLoggedIn ? 342 : 262
height: 36 height: parent.height
radius: 4 radius: 4
border.width: 1 border.width: 1

View file

@ -33,11 +33,11 @@ Rectangle {
property string creator: "" property string creator: ""
property var categories: [] property var categories: []
property int price: 0 property int price: 0
property string availability: "unknown"
property var attributions: [] property var attributions: []
property string description: "" property string description: ""
property string license: "" property string license: ""
property string posted: "" property string posted: ""
property bool available: false
property string created_at: "" property string created_at: ""
property bool isLoggedIn: false; property bool isLoggedIn: false;
property int edition: -1; property int edition: -1;
@ -264,9 +264,15 @@ Rectangle {
} }
height: 50 height: 50
text: root.edition >= 0 ? "UPGRADE FOR FREE" : (root.available ? (root.price ? root.price : "FREE") : "UNAVAILABLE (not for sale)") property bool isNFS: availability === "not for sale" // Note: server will say "sold out" or "invalidated" before it says NFS
enabled: root.edition >= 0 || root.available property bool isMine: creator === Account.username
buttonGlyph: root.available ? (root.price ? hifi.glyphs.hfc : "") : "" 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 color: hifi.buttons.blue
onClicked: root.buy(); onClicked: root.buy();

View file

@ -34,7 +34,7 @@ Rectangle {
property string creator: "" property string creator: ""
property string category: "" property string category: ""
property int price: 0 property int price: 0
property bool available: false property string availability: "unknown"
property bool isLoggedIn: false; property bool isLoggedIn: false;
signal buy() signal buy()
@ -299,8 +299,16 @@ Rectangle {
bottomMargin: 10 bottomMargin: 10
} }
text: root.price ? root.price : "FREE" property bool isNFS: availability === "not for sale" // Note: server will say "sold out" or "invalidated" before it says NFS
buttonGlyph: root.price ? hifi.glyphs.hfc : "" 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; color: hifi.buttons.blue;
onClicked: root.buy(); onClicked: root.buy();

View file

@ -1909,46 +1909,34 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
} }
}, Qt::QueuedConnection); }, 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) { if (_aboutToQuit) {
return false; return false;
} }
// try to find the renderable
auto renderable = getEntities()->renderableForEntityId(entityID); auto renderable = getEntities()->renderableForEntityId(entityID);
if (renderable) { if (renderable) {
renderable->addMaterial(material, parentMaterialName); 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 true;
} }
return false; 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) { if (_aboutToQuit) {
return false; return false;
} }
// try to find the renderable
auto renderable = getEntities()->renderableForEntityId(entityID); auto renderable = getEntities()->renderableForEntityId(entityID);
if (renderable) { if (renderable) {
renderable->removeMaterial(material, parentMaterialName); 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 true;
} }
return false; 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<AvatarManager>(); auto avatarManager = DependencyManager::get<AvatarManager>();
auto avatar = avatarManager->getAvatarBySessionID(avatarID); auto avatar = avatarManager->getAvatarBySessionID(avatarID);
if (avatar) { if (avatar) {
@ -1957,7 +1945,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
} }
return false; 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<AvatarManager>(); auto avatarManager = DependencyManager::get<AvatarManager>();
auto avatar = avatarManager->getAvatarBySessionID(avatarID); auto avatar = avatarManager->getAvatarBySessionID(avatarID);
if (avatar) { if (avatar) {
@ -2280,7 +2268,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// Setup the mouse ray pick and related operators // Setup the mouse ray pick and related operators
{ {
auto mouseRayPick = std::make_shared<RayPick>(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES()), 0.0f, true); auto mouseRayPick = std::make_shared<RayPick>(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_LOCAL_ENTITIES()), 0.0f, true);
mouseRayPick->parentTransform = std::make_shared<MouseTransformNode>(); mouseRayPick->parentTransform = std::make_shared<MouseTransformNode>();
mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE); mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE);
auto mouseRayPickID = DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, mouseRayPick); auto mouseRayPickID = DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, mouseRayPick);

View file

@ -71,6 +71,18 @@ PickFilter getPickFilter(unsigned int filter) {
unsigned int PickScriptingInterface::createRayPick(const QVariant& properties) { unsigned int PickScriptingInterface::createRayPick(const QVariant& properties) {
QVariantMap propMap = properties.toMap(); 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; bool enabled = false;
if (propMap["enabled"].isValid()) { if (propMap["enabled"].isValid()) {
enabled = propMap["enabled"].toBool(); enabled = propMap["enabled"].toBool();

View file

@ -150,6 +150,17 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties)
unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& properties) const { unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& properties) const {
QVariantMap propertyMap = properties.toMap(); 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; bool faceAvatar = false;
if (propertyMap["faceAvatar"].isValid()) { if (propertyMap["faceAvatar"].isValid()) {
faceAvatar = propertyMap["faceAvatar"].toBool(); faceAvatar = propertyMap["faceAvatar"].toBool();

View file

@ -137,7 +137,7 @@ PickResultPointer StylusPick::getDefaultResult(const QVariantMap& pickVariant) c
} }
PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) { PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) {
std::vector<StylusPickResult> results; StylusPickResult nearestTarget(pick.toVariantMap());
for (const auto& target : getIncludeItems()) { for (const auto& target : getIncludeItems()) {
if (target.isNull()) { if (target.isNull()) {
continue; continue;
@ -157,28 +157,21 @@ PickResultPointer StylusPick::getEntityIntersection(const StylusTip& pick) {
glm::vec3 normal = entityRotation * Vectors::UNIT_Z; glm::vec3 normal = entityRotation * Vectors::UNIT_Z;
float distance = glm::dot(pick.position - entityPosition, normal); float distance = glm::dot(pick.position - entityPosition, normal);
glm::vec3 intersection = pick.position - (normal * distance); if (distance < nearestTarget.distance) {
glm::vec3 intersection = pick.position - (normal * distance);
glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(target, intersection, false); glm::vec2 pos2D = RayPick::projectOntoEntityXYPlane(target, intersection, false);
if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) { if (pos2D == glm::clamp(pos2D, glm::vec2(0), glm::vec2(1))) {
IntersectionType type = IntersectionType::ENTITY; IntersectionType type = IntersectionType::ENTITY;
if (getFilter().doesPickLocalEntities()) { if (getFilter().doesPickLocalEntities()) {
EntityPropertyFlags desiredProperties; if (entity->getEntityHostType() == entity::HostType::LOCAL) {
desiredProperties += PROP_ENTITY_HOST_TYPE; type = IntersectionType::LOCAL_ENTITY;
if (DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(target, desiredProperties).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<StylusPickResult>(nearestTarget); return std::make_shared<StylusPickResult>(nearestTarget);
} }

View file

@ -70,7 +70,6 @@ ContextOverlayInterface::ContextOverlayInterface() {
} }
}); });
connect(entityScriptingInterface, &EntityScriptingInterface::deletingEntity, this, &ContextOverlayInterface::deletingEntity); 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::hoverEnterOverlay, this, &ContextOverlayInterface::contextOverlays_hoverEnterOverlay);
connect(&qApp->getOverlays(), &Overlays::hoverLeaveOverlay, this, &ContextOverlayInterface::contextOverlays_hoverLeaveOverlay); 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) { void ContextOverlayInterface::clickDownOnEntity(const EntityItemID& id, const PointerEvent& event) {
if (_enabled && event.getButton() == PointerEvent::SecondaryButton && contextOverlayFilterPassed(entityItemID)) { if (_enabled && event.getButton() == PointerEvent::SecondaryButton && contextOverlayFilterPassed(id)) {
_mouseDownEntity = entityItemID; _mouseDownEntity = id;
_mouseDownEntityTimestamp = usecTimestampNow(); _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 { } else {
if (!_currentEntityWithContextOverlay.isNull()) { if (!_currentEntityWithContextOverlay.isNull()) {
disableEntityHighlight(_currentEntityWithContextOverlay); disableEntityHighlight(_currentEntityWithContextOverlay);
@ -249,14 +252,6 @@ bool ContextOverlayInterface::destroyContextOverlay(const EntityItemID& entityIt
return ContextOverlayInterface::destroyContextOverlay(entityItemID, PointerEvent()); 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) { void ContextOverlayInterface::contextOverlays_hoverEnterOverlay(const QUuid& id, const PointerEvent& event) {
if (_contextOverlayID != UNKNOWN_ENTITY_ID) { if (_contextOverlayID != UNKNOWN_ENTITY_ID) {
qCDebug(context_overlay) << "Started hovering over Context Overlay. ID:" << id; qCDebug(context_overlay) << "Started hovering over Context Overlay. ID:" << id;

View file

@ -65,7 +65,6 @@ public slots:
bool createOrDestroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event); bool createOrDestroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event);
bool destroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event); bool destroyContextOverlay(const EntityItemID& entityItemID, const PointerEvent& event);
bool destroyContextOverlay(const EntityItemID& entityItemID); 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_hoverEnterOverlay(const QUuid& id, const PointerEvent& event);
void contextOverlays_hoverLeaveOverlay(const QUuid& id, const PointerEvent& event); void contextOverlays_hoverLeaveOverlay(const QUuid& id, const PointerEvent& event);
void contextOverlays_hoverEnterEntity(const EntityItemID& entityID, const PointerEvent& event); void contextOverlays_hoverEnterEntity(const EntityItemID& entityID, const PointerEvent& event);

View file

@ -63,13 +63,6 @@ Overlays::Overlays() {
ADD_TYPE_MAP(PolyLine, line3d); ADD_TYPE_MAP(PolyLine, line3d);
ADD_TYPE_MAP(Grid, grid); ADD_TYPE_MAP(Grid, grid);
ADD_TYPE_MAP(Gizmo, circle3d); ADD_TYPE_MAP(Gizmo, circle3d);
auto mouseRayPick = std::make_shared<RayPick>(Vectors::ZERO, Vectors::UP,
PickFilter(PickFilter::getBitMask(PickFilter::FlagBit::LOCAL_ENTITIES) |
PickFilter::getBitMask(PickFilter::FlagBit::VISIBLE)), 0.0f, true);
mouseRayPick->parentTransform = std::make_shared<MouseTransformNode>();
mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE);
_mouseRayPickID = DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, mouseRayPick);
} }
void Overlays::cleanupAllOverlays() { void Overlays::cleanupAllOverlays() {
@ -86,15 +79,7 @@ void Overlays::cleanupAllOverlays() {
cleanupOverlaysToDelete(); cleanupOverlaysToDelete();
} }
void Overlays::init() { void Overlays::init() {}
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
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::update(float deltatime) { void Overlays::update(float deltatime) {
cleanupOverlaysToDelete(); cleanupOverlaysToDelete();
@ -375,6 +360,8 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove
RENAME_PROP(animationSettings, animation); RENAME_PROP(animationSettings, animation);
} else if (type == "Image") { } else if (type == "Image") {
RENAME_PROP(url, imageURL); RENAME_PROP(url, imageURL);
} else if (type == "Text") {
RENAME_PROP(color, textColor);
} else if (type == "Web") { } else if (type == "Web") {
RENAME_PROP(url, sourceUrl); RENAME_PROP(url, sourceUrl);
RENAME_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "Mouse" ? "mouse" : "touch"; }); 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); RENAME_PROP(animation, animationSettings);
} else if (type == "Image") { } else if (type == "Image") {
RENAME_PROP(imageURL, url); RENAME_PROP(imageURL, url);
} else if (type == "Text") {
RENAME_PROP(textColor, color);
} else if (type == "Web") { } else if (type == "Web") {
RENAME_PROP(sourceUrl, url); RENAME_PROP(sourceUrl, url);
RENAME_PROP_CONVERT(inputMode, inputMode, [](const QVariant& v) { return v.toString() == "mouse" ? "Mouse" : "Touch"; }); 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; RayToOverlayIntersectionResult overlayResult;
overlayResult.intersects = false; overlayResult.intersects = false;
auto pickResult = DependencyManager::get<PickManager>()->getPrevPickResultTyped<RayPickResult>(mouseRayPickID); auto pickResult = DependencyManager::get<PickManager>()->getPrevPickResultTyped<RayPickResult>(DependencyManager::get<EntityTreeRenderer>()->getMouseRayPickID());
if (pickResult) { if (pickResult) {
overlayResult.intersects = pickResult->type != IntersectionType::NONE; overlayResult.intersects = pickResult->type == IntersectionType::LOCAL_ENTITY;
if (overlayResult.intersects) { if (overlayResult.intersects) {
overlayResult.intersection = pickResult->intersection; overlayResult.intersection = pickResult->intersection;
overlayResult.distance = pickResult->distance; overlayResult.distance = pickResult->distance;
@ -1281,7 +1270,7 @@ std::pair<float, QUuid> Overlays::mousePressEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mousePressEvent"); PerformanceTimer perfTimer("Overlays::mousePressEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y()); PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
_currentClickingOnOverlayID = rayPickResult.overlayID; _currentClickingOnOverlayID = rayPickResult.overlayID;
@ -1305,7 +1294,7 @@ bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent"); PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y()); PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
_currentClickingOnOverlayID = rayPickResult.overlayID; _currentClickingOnOverlayID = rayPickResult.overlayID;
@ -1321,7 +1310,7 @@ bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent"); PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y()); PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release); auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Release);
mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent); mouseReleasePointerEvent(rayPickResult.overlayID, pointerEvent);
@ -1343,7 +1332,7 @@ bool Overlays::mouseMoveEvent(QMouseEvent* event) {
PerformanceTimer perfTimer("Overlays::mouseMoveEvent"); PerformanceTimer perfTimer("Overlays::mouseMoveEvent");
PickRay ray = qApp->computePickRay(event->x(), event->y()); PickRay ray = qApp->computePickRay(event->x(), event->y());
RayToOverlayIntersectionResult rayPickResult = getPrevPickResult(_mouseRayPickID); RayToOverlayIntersectionResult rayPickResult = getPrevPickResult();
if (rayPickResult.intersects) { if (rayPickResult.intersects) {
auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move); auto pointerEvent = calculateOverlayPointerEvent(rayPickResult.overlayID, ray, rayPickResult, event, PointerEvent::Move);
mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent); mouseMovePointerEvent(rayPickResult.overlayID, pointerEvent);

View file

@ -719,7 +719,6 @@ private:
PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult, PointerEvent calculateOverlayPointerEvent(const QUuid& id, const PickRay& ray, const RayToOverlayIntersectionResult& rayPickResult,
QMouseEvent* event, PointerEvent::EventType eventType); QMouseEvent* event, PointerEvent::EventType eventType);
unsigned int _mouseRayPickID;
QUuid _currentClickingOnOverlayID; QUuid _currentClickingOnOverlayID;
QUuid _currentHoverOverOverlayID; QUuid _currentHoverOverOverlayID;

View file

@ -208,16 +208,16 @@ AvatarSharedPointer AvatarHashMap::addAvatar(const QUuid& sessionUUID, const QWe
avatar->setSessionUUID(sessionUUID); avatar->setSessionUUID(sessionUUID);
avatar->setOwningAvatarMixer(mixerWeakPointer); 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); emit avatarAddedEvent(sessionUUID);
return avatar; return avatar;
} }
AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer, AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer, bool& isNew) {
bool& isNew) { auto avatar = findAvatar(sessionUUID);
QWriteLocker locker(&_hashLock);
auto avatar = _avatarHash.value(sessionUUID);
if (!avatar) { if (!avatar) {
avatar = addAvatar(sessionUUID, mixerWeakPointer); avatar = addAvatar(sessionUUID, mixerWeakPointer);
isNew = true; isNew = true;

View file

@ -86,7 +86,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
auto handlePointerEvent = [&](const QUuid& entityID, const PointerEvent& event) { auto handlePointerEvent = [&](const QUuid& entityID, const PointerEvent& event) {
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity; std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
auto entity = getEntity(entityID); auto entity = getEntity(entityID);
if (entity && entity->getType() == EntityTypes::Web) { if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID)); thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID));
} }
if (thisEntity) { if (thisEntity) {
@ -99,7 +99,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) { connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverEnterEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity; std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
auto entity = getEntity(entityID); auto entity = getEntity(entityID);
if (entity && entity->getType() == EntityTypes::Web) { if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID)); thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID));
} }
if (thisEntity) { if (thisEntity) {
@ -110,7 +110,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) { connect(entityScriptingInterface.data(), &EntityScriptingInterface::hoverLeaveEntity, this, [&](const QUuid& entityID, const PointerEvent& event) {
std::shared_ptr<render::entities::WebEntityRenderer> thisEntity; std::shared_ptr<render::entities::WebEntityRenderer> thisEntity;
auto entity = getEntity(entityID); auto entity = getEntity(entityID);
if (entity && entity->getType() == EntityTypes::Web) { if (entity && entity->isVisible() && entity->getType() == EntityTypes::Web) {
thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID)); thisEntity = std::static_pointer_cast<render::entities::WebEntityRenderer>(renderableForEntityId(entityID));
} }
if (thisEntity) { if (thisEntity) {
@ -1360,3 +1360,36 @@ EntityEditPacketSender* EntityTreeRenderer::getPacketSender() {
EntityEditPacketSender* packetSender = peSimulation ? peSimulation->getPacketSender() : nullptr; EntityEditPacketSender* packetSender = peSimulation ? peSimulation->getPacketSender() : nullptr;
return packetSender; return packetSender;
} }
std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> EntityTreeRenderer::_addMaterialToEntityOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> EntityTreeRenderer::_removeMaterialFromEntityOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> EntityTreeRenderer::_addMaterialToAvatarOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> 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;
}

View file

@ -73,6 +73,7 @@ public:
static void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { _calculateEntityLoadingPriorityFunc = fn; } static void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { _calculateEntityLoadingPriorityFunc = fn; }
void setMouseRayPickID(unsigned int rayPickID) { _mouseRayPickID = rayPickID; } void setMouseRayPickID(unsigned int rayPickID) { _mouseRayPickID = rayPickID; }
unsigned int getMouseRayPickID() { return _mouseRayPickID; }
void setMouseRayPickResultOperator(std::function<RayToEntityIntersectionResult(unsigned int)> getPrevRayPickResultOperator) { _getPrevRayPickResultOperator = getPrevRayPickResultOperator; } void setMouseRayPickResultOperator(std::function<RayToEntityIntersectionResult(unsigned int)> getPrevRayPickResultOperator) { _getPrevRayPickResultOperator = getPrevRayPickResultOperator; }
void setSetPrecisionPickingOperator(std::function<void(unsigned int, bool)> setPrecisionPickingOperator) { _setPrecisionPickingOperator = setPrecisionPickingOperator; } void setSetPrecisionPickingOperator(std::function<void(unsigned int, bool)> setPrecisionPickingOperator) { _setPrecisionPickingOperator = setPrecisionPickingOperator; }
@ -120,6 +121,16 @@ public:
EntityEditPacketSender* getPacketSender(); EntityEditPacketSender* getPacketSender();
static void setAddMaterialToEntityOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; }
static void setRemoveMaterialFromEntityOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> 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<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; }
static void setRemoveMaterialFromAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> 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: signals:
void enterEntity(const EntityItemID& entityItemID); void enterEntity(const EntityItemID& entityItemID);
void leaveEntity(const EntityItemID& entityItemID); void leaveEntity(const EntityItemID& entityItemID);
@ -255,6 +266,11 @@ private:
workload::SpacePointer _space{ new workload::Space() }; workload::SpacePointer _space{ new workload::Space() };
workload::Transaction::Updates _spaceUpdates; workload::Transaction::Updates _spaceUpdates;
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToEntityOperator;
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromEntityOperator;
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToAvatarOperator;
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromAvatarOperator;
}; };

View file

@ -146,7 +146,6 @@ EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entit
_needsRenderUpdate = true; _needsRenderUpdate = true;
emit requestRenderUpdate(); emit requestRenderUpdate();
}); });
_materials = entity->getMaterials();
} }
EntityRenderer::~EntityRenderer() { } EntityRenderer::~EntityRenderer() { }

View file

@ -14,42 +14,210 @@
using namespace render; using namespace render;
using namespace render::entities; using namespace render::entities;
bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { bool MaterialEntityRenderer::needsRenderUpdate() const {
if (entity->getMaterial() != _drawMaterial) { if (_retryApply) {
return true;
}
if (entity->getParentID() != _parentID) {
return true;
}
if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) {
return true; return true;
} }
if (!_texturesLoaded) { if (!_texturesLoaded) {
return true; return true;
} }
return Parent::needsRenderUpdate();
}
bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
if (resultWithReadLock<bool>([&] {
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; return false;
} }
void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { void MaterialEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
withWriteLock([&] { withWriteLock([&] {
if (_drawMaterial != entity->getMaterial()) { bool deleteNeeded = false;
_texturesLoaded = false; bool addNeeded = _retryApply;
_drawMaterial = entity->getMaterial(); bool transformChanged = false;
{
MaterialMappingMode mode = entity->getMaterialMappingMode();
if (mode != _materialMappingMode) {
_materialMappingMode = mode;
transformChanged = true;
}
} }
_parentID = entity->getParentID(); {
_materialMappingPos = entity->getMaterialMappingPos(); bool repeat = entity->getMaterialRepeat();
_materialMappingScale = entity->getMaterialMappingScale(); if (repeat != _materialRepeat) {
_materialMappingRot = entity->getMaterialMappingRot(); _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(); _renderTransform = getModelTransform();
const float MATERIAL_ENTITY_SCALE = 0.5f; const float MATERIAL_ENTITY_SCALE = 0.5f;
_renderTransform.postScale(MATERIAL_ENTITY_SCALE); _renderTransform.postScale(MATERIAL_ENTITY_SCALE);
_renderTransform.postScale(ENTITY_ITEM_DEFAULT_DIMENSIONS); _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(); builder.withInvisible();
} }
if (_drawMaterial) { const auto drawMaterial = getMaterial();
auto matKey = _drawMaterial->getKey(); if (drawMaterial) {
auto matKey = drawMaterial->getKey();
if (matKey.isTranslucent()) { if (matKey.isTranslucent()) {
builder.withTransparent(); builder.withTransparent();
} }
@ -73,8 +242,9 @@ ItemKey MaterialEntityRenderer::getKey() {
ShapeKey MaterialEntityRenderer::getShapeKey() { ShapeKey MaterialEntityRenderer::getShapeKey() {
graphics::MaterialKey drawMaterialKey; graphics::MaterialKey drawMaterialKey;
if (_drawMaterial) { const auto drawMaterial = getMaterial();
drawMaterialKey = _drawMaterial->getKey(); if (drawMaterial) {
drawMaterialKey = drawMaterial->getKey();
} }
bool isTranslucent = drawMaterialKey.isTranslucent(); 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 // Don't render if our parent is set or our material is null
QUuid parentID; QUuid parentID;
withReadLock([&] {
parentID = _parentID;
});
if (!parentID.isNull()) {
return;
}
Transform renderTransform; Transform renderTransform;
graphics::MaterialPointer drawMaterial; graphics::MaterialPointer drawMaterial;
Transform textureTransform; Transform textureTransform;
withReadLock([&] { withReadLock([&] {
parentID = _parentID;
renderTransform = _renderTransform; renderTransform = _renderTransform;
drawMaterial = _drawMaterial; drawMaterial = getMaterial();
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0)); textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0));
textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot))); textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialMappingRot)));
textureTransform.setScale(glm::vec3(_materialMappingScale, 1)); textureTransform.setScale(glm::vec3(_materialMappingScale, 1));
}); });
if (!parentID.isNull() || !drawMaterial) { if (!drawMaterial) {
return; return;
} }
@ -142,3 +318,86 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
args->_details._trianglesRendered += (int)DependencyManager::get<GeometryCache>()->getSphereTriangleCount(); args->_details._trianglesRendered += (int)DependencyManager::get<GeometryCache>()->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<NetworkMaterial> 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<NetworkMaterial> 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<NetworkMaterial>& 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<NetworkMaterial> 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;
}

View file

@ -13,6 +13,8 @@
#include <MaterialEntityItem.h> #include <MaterialEntityItem.h>
#include <material-networking/MaterialCache.h>
class NetworkMaterial; class NetworkMaterial;
namespace render { namespace entities { namespace render { namespace entities {
@ -22,22 +24,46 @@ class MaterialEntityRenderer : public TypedEntityRenderer<MaterialEntityItem> {
using Pointer = std::shared_ptr<MaterialEntityRenderer>; using Pointer = std::shared_ptr<MaterialEntityRenderer>;
public: public:
MaterialEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {} MaterialEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {}
~MaterialEntityRenderer() { deleteMaterial(_parentID, _parentMaterialName); }
private: private:
virtual bool needsRenderUpdate() const override;
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) 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; virtual void doRender(RenderArgs* args) override;
ItemKey getKey() override; ItemKey getKey() override;
ShapeKey getShapeKey() override; ShapeKey getShapeKey() override;
QString _materialURL;
QString _materialData;
QString _parentMaterialName;
quint16 _priority;
QUuid _parentID; QUuid _parentID;
MaterialMappingMode _materialMappingMode;
bool _materialRepeat;
glm::vec2 _materialMappingPos; glm::vec2 _materialMappingPos;
glm::vec2 _materialMappingScale; glm::vec2 _materialMappingScale;
float _materialMappingRot; float _materialMappingRot;
bool _texturesLoaded { false }; Transform _transform;
glm::vec3 _dimensions;
bool _texturesLoaded { false };
bool _retryApply { false };
std::shared_ptr<NetworkMaterial> getMaterial() const;
void setCurrentMaterialName(const std::string& currentMaterialName);
void applyTextureTransform(std::shared_ptr<NetworkMaterial>& material);
void applyMaterial();
void deleteMaterial(const QUuid& oldParentID, const QString& oldParentMaterialName);
NetworkMaterialResourcePointer _networkMaterial;
NetworkMaterialResource::ParsedMaterials _parsedMaterials;
std::shared_ptr<NetworkMaterial> _appliedMaterial;
std::string _currentMaterialName;
std::shared_ptr<NetworkMaterial> _drawMaterial;
}; };
} } } }

View file

@ -3250,25 +3250,6 @@ void EntityItem::setSpaceIndex(int32_t index) {
void EntityItem::preDelete() { void EntityItem::preDelete() {
} }
void EntityItem::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {
std::lock_guard<std::mutex> lock(_materialsLock);
_materials[parentMaterialName].push(material);
}
void EntityItem::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
std::lock_guard<std::mutex> lock(_materialsLock);
_materials[parentMaterialName].remove(material);
}
std::unordered_map<std::string, graphics::MultiMaterial> EntityItem::getMaterials() {
std::unordered_map<std::string, graphics::MultiMaterial> toReturn;
{
std::lock_guard<std::mutex> lock(_materialsLock);
toReturn = _materials;
}
return toReturn;
}
bool EntityItem::getCloneable() const { bool EntityItem::getCloneable() const {
bool result; bool result;
withReadLock([&] { withReadLock([&] {

View file

@ -37,8 +37,6 @@
#include "EntityDynamicInterface.h" #include "EntityDynamicInterface.h"
#include "GrabPropertyGroup.h" #include "GrabPropertyGroup.h"
#include "graphics/Material.h"
class EntitySimulation; class EntitySimulation;
class EntityTreeElement; class EntityTreeElement;
class EntityTreeElementExtraEncodeData; class EntityTreeElementExtraEncodeData;
@ -542,10 +540,6 @@ public:
virtual void preDelete(); virtual void preDelete();
virtual void postParentFixup() {} virtual void postParentFixup() {}
void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName);
void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName);
std::unordered_map<std::string, graphics::MultiMaterial> getMaterials();
void setSimulationOwnershipExpiry(uint64_t expiry) { _simulationOwnershipExpiry = expiry; } void setSimulationOwnershipExpiry(uint64_t expiry) { _simulationOwnershipExpiry = expiry; }
uint64_t getSimulationOwnershipExpiry() const { return _simulationOwnershipExpiry; } uint64_t getSimulationOwnershipExpiry() const { return _simulationOwnershipExpiry; }
@ -754,11 +748,7 @@ protected:
QHash<QUuid, EntityDynamicPointer> _grabActions; QHash<QUuid, EntityDynamicPointer> _grabActions;
private: private:
std::unordered_map<std::string, graphics::MultiMaterial> _materials;
std::mutex _materialsLock;
static std::function<glm::quat(const glm::vec3&, const glm::quat&, BillboardMode)> _getBillboardRotationOperator; static std::function<glm::quat(const glm::vec3&, const glm::quat&, BillboardMode)> _getBillboardRotationOperator;
}; };
#endif // hifi_EntityItem_h #endif // hifi_EntityItem_h

View file

@ -2953,41 +2953,9 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const {
return entity->getJointNames(); return entity->getJointNames();
} }
std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> EntityTree::_addMaterialToEntityOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> EntityTree::_removeMaterialFromEntityOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> EntityTree::_addMaterialToAvatarOperator = nullptr;
std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> EntityTree::_removeMaterialFromAvatarOperator = nullptr;
std::function<QObject*(const QUuid&)> EntityTree::_getEntityObjectOperator = nullptr; std::function<QObject*(const QUuid&)> EntityTree::_getEntityObjectOperator = nullptr;
std::function<QSizeF(const QUuid&, const QString&)> EntityTree::_textSizeOperator = nullptr; std::function<QSizeF(const QUuid&, const QString&)> 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) { QObject* EntityTree::getEntityObject(const QUuid& id) {
if (_getEntityObjectOperator) { if (_getEntityObjectOperator) {
return _getEntityObjectOperator(id); return _getEntityObjectOperator(id);

View file

@ -262,16 +262,6 @@ public:
void setIsServerlessMode(bool value) { _serverlessDomain = value; } void setIsServerlessMode(bool value) { _serverlessDomain = value; }
bool isServerlessMode() const { return _serverlessDomain; } bool isServerlessMode() const { return _serverlessDomain; }
static void setAddMaterialToEntityOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; }
static void setRemoveMaterialFromEntityOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> 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<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; }
static void setRemoveMaterialFromAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> 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<QObject*(const QUuid&)> getEntityObjectOperator) { _getEntityObjectOperator = getEntityObjectOperator; } static void setGetEntityObjectOperator(std::function<QObject*(const QUuid&)> getEntityObjectOperator) { _getEntityObjectOperator = getEntityObjectOperator; }
static QObject* getEntityObject(const QUuid& id); static QObject* getEntityObject(const QUuid& id);
@ -386,10 +376,6 @@ private:
std::shared_ptr<AvatarData> _myAvatar{ nullptr }; std::shared_ptr<AvatarData> _myAvatar{ nullptr };
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToEntityOperator;
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromEntityOperator;
static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToAvatarOperator;
static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromAvatarOperator;
static std::function<QObject*(const QUuid&)> _getEntityObjectOperator; static std::function<QObject*(const QUuid&)> _getEntityObjectOperator;
static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator; static std::function<QSizeF(const QUuid&, const QString&)> _textSizeOperator;

View file

@ -16,9 +16,6 @@
EntityItemPointer MaterialEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer MaterialEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
Pointer entity(new MaterialEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); Pointer entity(new MaterialEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
entity->setProperties(properties); 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; return entity;
} }
@ -27,10 +24,6 @@ MaterialEntityItem::MaterialEntityItem(const EntityItemID& entityItemID) : Entit
_type = EntityTypes::Material; _type = EntityTypes::Material;
} }
MaterialEntityItem::~MaterialEntityItem() {
removeMaterial();
}
EntityItemProperties MaterialEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { EntityItemProperties MaterialEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL);
@ -131,7 +124,6 @@ void MaterialEntityItem::debugDump() const {
qCDebug(entities) << " MATERIAL EntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " MATERIAL EntityItem id:" << getEntityItemID() << "---------------------------------------------";
qCDebug(entities) << " name:" << _name; qCDebug(entities) << " name:" << _name;
qCDebug(entities) << " material url:" << _materialURL; qCDebug(entities) << " material url:" << _materialURL;
qCDebug(entities) << " current material name:" << _currentMaterialName.c_str();
qCDebug(entities) << " material mapping mode:" << _materialMappingMode; qCDebug(entities) << " material mapping mode:" << _materialMappingMode;
qCDebug(entities) << " material repeat:" << _materialRepeat; qCDebug(entities) << " material repeat:" << _materialRepeat;
qCDebug(entities) << " priority:" << _priority; qCDebug(entities) << " priority:" << _priority;
@ -154,208 +146,101 @@ void MaterialEntityItem::setUnscaledDimensions(const glm::vec3& value) {
} }
} }
std::shared_ptr<NetworkMaterial> MaterialEntityItem::getMaterial() const { QString MaterialEntityItem::getMaterialURL() const {
auto material = _parsedMaterials.networkMaterials.find(_currentMaterialName); return resultWithReadLock<QString>([&] {
if (material != _parsedMaterials.networkMaterials.end()) { return _materialURL;
return material->second; });
} else {
return nullptr;
}
} }
void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool materialDataChanged) { void MaterialEntityItem::setMaterialURL(const QString& materialURL) {
bool usingMaterialData = materialDataChanged || materialURLString.startsWith("materialData"); withWriteLock([&] {
if (_materialURL != materialURLString || (usingMaterialData && materialDataChanged)) { _materialURL = materialURL;
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::setCurrentMaterialName(const std::string& currentMaterialName) { QString MaterialEntityItem::getMaterialData() const {
if (_parsedMaterials.networkMaterials.find(currentMaterialName) != _parsedMaterials.networkMaterials.end()) { return resultWithReadLock<QString>([&] {
_currentMaterialName = currentMaterialName; return _materialData;
} else if (_parsedMaterials.names.size() > 0) { });
_currentMaterialName = _parsedMaterials.names[0];
}
} }
void MaterialEntityItem::setMaterialData(const QString& materialData) { void MaterialEntityItem::setMaterialData(const QString& materialData) {
if (_materialData != materialData) { withWriteLock([&] {
_materialData = materialData; _materialData = materialData;
if (_materialURL.startsWith("materialData")) { });
// Trigger material update when material data changes }
setMaterialURL(_materialURL, true);
} MaterialMappingMode MaterialEntityItem::getMaterialMappingMode() const {
} return resultWithReadLock<MaterialMappingMode>([&] {
return _materialMappingMode;
});
} }
void MaterialEntityItem::setMaterialMappingMode(MaterialMappingMode mode) { void MaterialEntityItem::setMaterialMappingMode(MaterialMappingMode mode) {
if (_materialMappingMode != mode) { withWriteLock([&] {
removeMaterial();
_materialMappingMode = mode; _materialMappingMode = mode;
setUnscaledDimensions(_desiredDimensions); });
applyMaterial(); setUnscaledDimensions(_desiredDimensions);
}
} }
void MaterialEntityItem::setMaterialRepeat(bool repeat) { quint16 MaterialEntityItem::getPriority() const {
if (_materialRepeat != repeat) { return resultWithReadLock<quint16>([&] {
removeMaterial(); return _priority;
_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();
}
} }
void MaterialEntityItem::setPriority(quint16 priority) { void MaterialEntityItem::setPriority(quint16 priority) {
if (_priority != priority) { withWriteLock([&] {
removeMaterial();
_priority = priority; _priority = priority;
applyMaterial(); });
} }
QString MaterialEntityItem::getParentMaterialName() const {
return resultWithReadLock<QString>([&] {
return _parentMaterialName;
});
} }
void MaterialEntityItem::setParentMaterialName(const QString& parentMaterialName) { void MaterialEntityItem::setParentMaterialName(const QString& parentMaterialName) {
if (_parentMaterialName != parentMaterialName) { withWriteLock([&] {
removeMaterial();
_parentMaterialName = parentMaterialName; _parentMaterialName = parentMaterialName;
applyMaterial(); });
}
} }
void MaterialEntityItem::setParentID(const QUuid& parentID) { glm::vec2 MaterialEntityItem::getMaterialMappingPos() const {
if (getParentID() != parentID) { return resultWithReadLock<glm::vec2>([&] {
removeMaterial(); return _materialMappingPos;
EntityItem::setParentID(parentID); });
applyMaterial();
}
} }
void MaterialEntityItem::locationChanged(bool tellPhysics) { void MaterialEntityItem::setMaterialMappingPos(const glm::vec2& materialMappingPos) {
EntityItem::locationChanged(); withWriteLock([&] {
if (_materialMappingMode == MaterialMappingMode::PROJECTED) { _materialMappingPos = materialMappingPos;
removeMaterial(); });
applyMaterial();
}
} }
void MaterialEntityItem::dimensionsChanged() { glm::vec2 MaterialEntityItem::getMaterialMappingScale() const {
EntityItem::dimensionsChanged(); return resultWithReadLock<glm::vec2>([&] {
if (_materialMappingMode == MaterialMappingMode::PROJECTED) { return _materialMappingScale;
removeMaterial(); });
applyMaterial();
}
} }
void MaterialEntityItem::removeMaterial() { void MaterialEntityItem::setMaterialMappingScale(const glm::vec2& materialMappingScale) {
graphics::MaterialPointer material = getMaterial(); withWriteLock([&] {
if (!material) { _materialMappingScale = materialMappingScale;
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::applyMaterial() { float MaterialEntityItem::getMaterialMappingRot() const {
_retryApply = false; return resultWithReadLock<float>([&] {
graphics::MaterialPointer material = getMaterial(); return _materialMappingRot;
QUuid parentID = getParentID(); });
if (!material || parentID.isNull()) { }
return;
}
Transform textureTransform; void MaterialEntityItem::setMaterialMappingRot(float materialMappingRot) {
if (_materialMappingMode == MaterialMappingMode::UV) { withWriteLock([&] {
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0.0f)); _materialMappingRot = materialMappingRot;
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;
} }
AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) { AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) {
@ -372,18 +257,3 @@ AACube MaterialEntityItem::calculateInitialQueryAACube(bool& success) {
} }
return aaCube; 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);
}

View file

@ -12,8 +12,6 @@
#include "EntityItem.h" #include "EntityItem.h"
#include "MaterialMappingMode.h" #include "MaterialMappingMode.h"
#include <model-networking/ModelCache.h>
#include <material-networking/MaterialCache.h>
class MaterialEntityItem : public EntityItem { class MaterialEntityItem : public EntityItem {
using Pointer = std::shared_ptr<MaterialEntityItem>; using Pointer = std::shared_ptr<MaterialEntityItem>;
@ -21,13 +19,9 @@ public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
MaterialEntityItem(const EntityItemID& entityItemID); MaterialEntityItem(const EntityItemID& entityItemID);
~MaterialEntityItem();
ALLOW_INSTANTIATION // This class can be instantiated 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 // methods for getting/setting all properties of an entity
virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
virtual bool setProperties(const EntityItemProperties& properties) override; virtual bool setProperties(const EntityItemProperties& properties) override;
@ -52,44 +46,30 @@ public:
virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual void setUnscaledDimensions(const glm::vec3& value) override;
QString getMaterialURL() const { return _materialURL; } QString getMaterialURL() const;
void setMaterialURL(const QString& materialURLString, bool materialDataChanged = false); 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); void setMaterialMappingMode(MaterialMappingMode mode);
bool getMaterialRepeat() const { return _materialRepeat; } 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); void setPriority(quint16 priority);
QString getParentMaterialName() const { return _parentMaterialName; } QString getParentMaterialName() const;
void setParentMaterialName(const QString& parentMaterialName); void setParentMaterialName(const QString& parentMaterialName);
glm::vec2 getMaterialMappingPos() const { return _materialMappingPos; } glm::vec2 getMaterialMappingPos() const;
void setMaterialMappingPos(const glm::vec2& materialMappingPos); void setMaterialMappingPos(const glm::vec2& materialMappingPos);
glm::vec2 getMaterialMappingScale() const { return _materialMappingScale; } glm::vec2 getMaterialMappingScale() const;
void setMaterialMappingScale(const glm::vec2& materialMappingScale); void setMaterialMappingScale(const glm::vec2& materialMappingScale);
float getMaterialMappingRot() const { return _materialMappingRot; } float getMaterialMappingRot() const;
void setMaterialMappingRot(const float& materialMappingRot); void setMaterialMappingRot(float materialMappingRot);
QString getMaterialData() const { return _materialData; }
void setMaterialData(const QString& materialData);
std::shared_ptr<NetworkMaterial> getMaterial() const;
void setParentID(const QUuid& parentID) override;
void locationChanged(bool tellPhysics) override;
void dimensionsChanged() override;
void applyMaterial();
void removeMaterial();
void postParentFixup() override;
AACube calculateInitialQueryAACube(bool& success) override; AACube calculateInitialQueryAACube(bool& success) override;
@ -128,12 +108,6 @@ private:
float _materialMappingRot { 0 }; float _materialMappingRot { 0 };
QString _materialData; QString _materialData;
NetworkMaterialResourcePointer _networkMaterial;
NetworkMaterialResource::ParsedMaterials _parsedMaterials;
std::string _currentMaterialName;
bool _retryApply { false };
}; };
#endif // hifi_MaterialEntityItem_h #endif // hifi_MaterialEntityItem_h

View file

@ -6,6 +6,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "PickManager.h" #include "PickManager.h"
#include "PerfStat.h"
#include "Profile.h"
PickManager::PickManager() { PickManager::PickManager() {
setShouldPickHUDOperator([]() { return false; }); setShouldPickHUDOperator([]() { return false; });
@ -119,10 +121,26 @@ void PickManager::update() {
bool shouldPickHUD = _shouldPickHUDOperator(); bool shouldPickHUD = _shouldPickHUDOperator();
// FIXME: give each type its own expiry // FIXME: give each type its own expiry
// Each type will update at least one pick, regardless of the 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); PROFILE_RANGE(picks, "StylusPicks");
_updatedPickCounts[PickQuery::Parabola] = _parabolaPickCacheOptimizer.update(cachedPicks[PickQuery::Parabola], _nextPickToUpdate[PickQuery::Parabola], expiry, shouldPickHUD); PerformanceTimer perfTimer("StylusPicks");
_updatedPickCounts[PickQuery::Collision] = _collisionPickCacheOptimizer.update(cachedPicks[PickQuery::Collision], _nextPickToUpdate[PickQuery::Collision], expiry, false); _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) { bool PickManager::isLeftHand(unsigned int uid) {

View file

@ -205,7 +205,7 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() {
} }
AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() : AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false), render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion"),
perspectiveScale{ 1.0f }, perspectiveScale{ 1.0f },
edgeSharpness{ 1.0f }, edgeSharpness{ 1.0f },
blurRadius{ 4 }, blurRadius{ 4 },

View file

@ -118,7 +118,7 @@ protected:
float enableSkinning{ 1.0f }; float enableSkinning{ 1.0f };
float enableBlendshape{ 1.0f }; float enableBlendshape{ 1.0f };
float enableAmbientOcclusion{ 0.0f }; float enableAmbientOcclusion{ 0.0f }; // false by default
float enableShadow{ 1.0f }; float enableShadow{ 1.0f };
float spare1{ 1.0f }; float spare1{ 1.0f };
float spare2{ 1.0f }; float spare2{ 1.0f };
@ -196,15 +196,13 @@ public:
bool enableSkinning{ true }; bool enableSkinning{ true };
bool enableBlendshape{ true }; bool enableBlendshape{ true };
bool enableAmbientOcclusion{ true }; bool enableAmbientOcclusion{ false }; // false by default
bool enableShadow{ true }; bool enableShadow{ true };
void setAmbientOcclusion(bool enable) { enableAmbientOcclusion = enable; emit dirty();} void setAmbientOcclusion(bool enable) { enableAmbientOcclusion = enable; emit dirty();}
bool isAmbientOcclusionEnabled() const { return enableAmbientOcclusion; } bool isAmbientOcclusionEnabled() const { return enableAmbientOcclusion; }
void setShadow(bool enable) { void setShadow(bool enable) { enableShadow = enable; emit dirty(); }
enableShadow = enable; emit dirty();
}
bool isShadowEnabled() const { return enableShadow; } bool isShadowEnabled() const { return enableShadow; }
signals: signals:

View file

@ -12,6 +12,7 @@ Q_LOGGING_CATEGORY(trace_app, "trace.app")
Q_LOGGING_CATEGORY(trace_app_detail, "trace.app.detail") Q_LOGGING_CATEGORY(trace_app_detail, "trace.app.detail")
Q_LOGGING_CATEGORY(trace_metadata, "trace.metadata") Q_LOGGING_CATEGORY(trace_metadata, "trace.metadata")
Q_LOGGING_CATEGORY(trace_network, "trace.network") 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_parse, "trace.parse")
Q_LOGGING_CATEGORY(trace_render, "trace.render") Q_LOGGING_CATEGORY(trace_render, "trace.render")
Q_LOGGING_CATEGORY(trace_render_detail, "trace.render.detail") Q_LOGGING_CATEGORY(trace_render_detail, "trace.render.detail")

View file

@ -18,6 +18,7 @@ Q_DECLARE_LOGGING_CATEGORY(trace_app)
Q_DECLARE_LOGGING_CATEGORY(trace_app_detail) Q_DECLARE_LOGGING_CATEGORY(trace_app_detail)
Q_DECLARE_LOGGING_CATEGORY(trace_metadata) Q_DECLARE_LOGGING_CATEGORY(trace_metadata)
Q_DECLARE_LOGGING_CATEGORY(trace_network) Q_DECLARE_LOGGING_CATEGORY(trace_network)
Q_DECLARE_LOGGING_CATEGORY(trace_picks)
Q_DECLARE_LOGGING_CATEGORY(trace_render) Q_DECLARE_LOGGING_CATEGORY(trace_render)
Q_DECLARE_LOGGING_CATEGORY(trace_render_detail) Q_DECLARE_LOGGING_CATEGORY(trace_render_detail)
Q_DECLARE_LOGGING_CATEGORY(trace_render_gpu) Q_DECLARE_LOGGING_CATEGORY(trace_render_gpu)

View file

@ -47,7 +47,7 @@ Rectangle {
"Lightmap:LightingModel:enableLightmap", "Lightmap:LightingModel:enableLightmap",
"Background:LightingModel:enableBackground", "Background:LightingModel:enableBackground",
"Haze:LightingModel:enableHaze", "Haze:LightingModel:enableHaze",
"ssao:LightingModel:enableAmbientOcclusion", "AO:LightingModel:enableAmbientOcclusion",
"Textures:LightingModel:enableMaterialTexturing" "Textures:LightingModel:enableMaterialTexturing"
] ]
HifiControls.CheckBox { HifiControls.CheckBox {

View file

@ -45,7 +45,8 @@ var OVERLAY_DATA_HMD = {
emissive: true, emissive: true,
drawInFront: true, drawInFront: true,
parentID: MyAvatar.SELF_ID, parentID: MyAvatar.SELF_ID,
parentJointIndex: CAMERA_MATRIX parentJointIndex: CAMERA_MATRIX,
ignorePickIntersection: true
}; };
var AWAY_INTRO = { var AWAY_INTRO = {

View file

@ -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();
}

View file

@ -497,6 +497,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
distanceScaleEnd: true, distanceScaleEnd: true,
hand: RIGHT_HAND hand: RIGHT_HAND
}); });
this.mouseRayPick = Pointers.createPointer(PickType.Ray, { this.mouseRayPick = Pointers.createPointer(PickType.Ray, {
joint: "Mouse", joint: "Mouse",
filter: Picks.PICK_OVERLAYS | Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, filter: Picks.PICK_OVERLAYS | Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE,

View file

@ -196,14 +196,14 @@ Script.include("/~/system/libraries/controllers.js");
var playAreaOverlayProperties = { var playAreaOverlayProperties = {
dimensions: dimensions:
Vec3.multiply(this.teleportScaleFactor * avatarScale, { Vec3.multiply(_this.teleportScaleFactor * avatarScale, {
x: this.playArea.width, x: _this.playArea.width,
y: this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y, y: _this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y,
z: this.playArea.height z: _this.playArea.height
}) })
}; };
if (this.teleportScaleFactor < 1) { if (_this.teleportScaleFactor < 1) {
// Adjust position of playAreOverlay so that its base is at correct height. // Adjust position of playAreOverlay so that its base is at correct height.
// Always parenting to teleport target is good enough for this. // Always parenting to teleport target is good enough for this.
var sensorToWorldMatrix = MyAvatar.sensorToWorldMatrix; var sensorToWorldMatrix = MyAvatar.sensorToWorldMatrix;
@ -212,37 +212,37 @@ Script.include("/~/system/libraries/controllers.js");
var avatarSensorPosition = Mat4.transformPoint(worldToSensorMatrix, MyAvatar.position); var avatarSensorPosition = Mat4.transformPoint(worldToSensorMatrix, MyAvatar.position);
avatarSensorPosition.y = 0; avatarSensorPosition.y = 0;
var targetRotation = Overlays.getProperty(this.targetOverlayID, "rotation"); var targetRotation = Overlays.getProperty(_this.targetOverlayID, "rotation");
var relativePlayAreaCenterOffset = 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), var localPosition = Vec3.multiplyQbyV(Quat.inverse(targetRotation),
Vec3.multiplyQbyV(sensorToWorldRotation, Vec3.multiplyQbyV(sensorToWorldRotation,
Vec3.multiply(avatarScale, Vec3.subtract(relativePlayAreaCenterOffset, avatarSensorPosition)))); 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; playAreaOverlayProperties.localPosition = localPosition;
} }
Overlays.editOverlay(this.playAreaOverlay, playAreaOverlayProperties); Overlays.editOverlay(_this.playAreaOverlay, playAreaOverlayProperties);
for (var i = 0; i < this.playAreaSensorPositionOverlays.length; i++) { for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) {
localPosition = this.playAreaSensorPositions[i]; localPosition = _this.playAreaSensorPositions[i];
localPosition = Vec3.multiply(avatarScale, localPosition); localPosition = Vec3.multiply(avatarScale, localPosition);
// Position relative to the play area. // Position relative to the play area.
localPosition.y = avatarScale * (this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS.y / 2 localPosition.y = avatarScale * (_this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS.y / 2
- this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2); - _this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2);
Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], { Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], {
dimensions: Vec3.multiply(this.teleportScaleFactor * avatarScale, this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS), dimensions: Vec3.multiply(_this.teleportScaleFactor * avatarScale, _this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS),
parentID: this.playAreaOverlay, parentID: _this.playAreaOverlay,
localPosition: localPosition localPosition: localPosition
}); });
} }
}; };
this.updatePlayAreaScale = function () { this.updatePlayAreaScale = function () {
if (this.isPlayAreaAvailable) { if (_this.isPlayAreaAvailable) {
this.setPlayAreaDimensions(); _this.setPlayAreaDimensions();
} }
}; };
@ -265,7 +265,7 @@ Script.include("/~/system/libraries/controllers.js");
for (var i = 0, length = teleportRenderStates.length; i < length; i++) { for (var i = 0, length = teleportRenderStates.length; i < length; i++) {
var state = properties.renderStates[teleportRenderStates[i].name]; var state = properties.renderStates[teleportRenderStates[i].name];
if (state && state.end) { 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.translateZAction = Controller.findAction("TranslateZ");
this.setPlayAreaVisible = function (visible, targetOverlayID, fade) { this.setPlayAreaVisible = function (visible, targetOverlayID, fade) {
if (!this.isPlayAreaAvailable || this.isPlayAreaVisible === visible) { if (!_this.isPlayAreaAvailable || _this.isPlayAreaVisible === visible) {
return; return;
} }
this.wasPlayAreaVisible = this.isPlayAreaVisible; _this.wasPlayAreaVisible = _this.isPlayAreaVisible;
this.isPlayAreaVisible = visible; _this.isPlayAreaVisible = visible;
this.targetOverlayID = targetOverlayID; _this.targetOverlayID = targetOverlayID;
if (this.teleportedFadeTimer !== null) { if (_this.teleportedFadeTimer !== null) {
Script.clearTimeout(this.teleportedFadeTimer); Script.clearTimeout(_this.teleportedFadeTimer);
this.teleportedFadeTimer = null; _this.teleportedFadeTimer = null;
} }
if (visible || !fade) { if (visible || !fade) {
// Immediately make visible or invisible. // Immediately make visible or invisible.
this.isPlayAreaVisible = visible; _this.isPlayAreaVisible = visible;
Overlays.editOverlay(this.playAreaOverlay, { Overlays.editOverlay(_this.playAreaOverlay, {
dimensions: Vec3.ZERO, dimensions: Vec3.ZERO,
alpha: this.PLAY_AREA_BOX_ALPHA, alpha: _this.PLAY_AREA_BOX_ALPHA,
visible: visible visible: visible
}); });
for (var i = 0; i < this.playAreaSensorPositionOverlays.length; i++) { for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) {
Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], { Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], {
dimensions: Vec3.ZERO, dimensions: Vec3.ZERO,
alpha: this.PLAY_AREA_SENSOR_ALPHA, alpha: _this.PLAY_AREA_SENSOR_ALPHA,
visible: visible visible: visible
}); });
} }
Overlays.editOverlay(this.teleportedTargetOverlay, { visible: false }); Overlays.editOverlay(_this.teleportedTargetOverlay, { visible: false });
} else { } else {
// Fading out of overlays is initiated in setTeleportVisible(). // 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. 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) { if (Vec3.distance(targetXZPosition, avatarXZPosition) < MIN_PARENTING_DISTANCE) {
// Set play area position and rotation in world coordinates with no parenting. // Set play area position and rotation in world coordinates with no parenting.
Overlays.editOverlay(this.playAreaOverlay, { Overlays.editOverlay(_this.playAreaOverlay, {
parentID: Uuid.NULL, parentID: Uuid.NULL,
position: Vec3.sum(position, position: Vec3.sum(position,
Vec3.multiplyQbyV(sensorToWorldRotation, Vec3.multiplyQbyV(sensorToWorldRotation,
Vec3.multiply(MyAvatar.sensorToWorldScale, Vec3.multiply(MyAvatar.sensorToWorldScale,
Vec3.subtract(this.playAreaCenterOffset, avatarSensorPosition)))), Vec3.subtract(_this.playAreaCenterOffset, avatarSensorPosition)))),
rotation: sensorToWorldRotation rotation: sensorToWorldRotation
}); });
} else { } else {
// Set play area position and rotation in local coordinates with parenting. // 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 sensorToTargetRotation = Quat.multiply(Quat.inverse(targetRotation), sensorToWorldRotation);
var relativePlayAreaCenterOffset = 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 });
Overlays.editOverlay(this.playAreaOverlay, { Overlays.editOverlay(_this.playAreaOverlay, {
parentID: this.targetOverlayID, parentID: _this.targetOverlayID,
localPosition: Vec3.multiplyQbyV(Quat.inverse(targetRotation), localPosition: Vec3.multiplyQbyV(Quat.inverse(targetRotation),
Vec3.multiplyQbyV(sensorToWorldRotation, Vec3.multiplyQbyV(sensorToWorldRotation,
Vec3.multiply(MyAvatar.sensorToWorldScale, Vec3.multiply(MyAvatar.sensorToWorldScale,
@ -578,33 +578,33 @@ Script.include("/~/system/libraries/controllers.js");
} }
} }
_this.teleportedFadeTimer = null; _this.teleportedFadeTimer = null;
Selection.disableListHighlight(this.teleporterSelectionName); Selection.disableListHighlight(_this.teleporterSelectionName);
} }
}; };
this.cancelFade = function () { this.cancelFade = function () {
// Other hand may call this to immediately hide fading overlays. // Other hand may call this to immediately hide fading overlays.
var i, length; var i, length;
if (this.teleportedFadeTimer) { if (_this.teleportedFadeTimer) {
Overlays.editOverlay(this.teleportedTargetOverlay, { visible: false }); Overlays.editOverlay(_this.teleportedTargetOverlay, { visible: false });
if (this.wasPlayAreaVisible) { if (_this.wasPlayAreaVisible) {
Overlays.editOverlay(this.playAreaOverlay, { visible: false }); Overlays.editOverlay(_this.playAreaOverlay, { visible: false });
for (i = 0, length = this.playAreaSensorPositionOverlays.length; i < length; i++) { for (i = 0, length = _this.playAreaSensorPositionOverlays.length; i < length; i++) {
Overlays.editOverlay(this.playAreaSensorPositionOverlays[i], { visible: false }); Overlays.editOverlay(_this.playAreaSensorPositionOverlays[i], { visible: false });
} }
} }
this.teleportedFadeTimer = null; _this.teleportedFadeTimer = null;
} }
}; };
this.setTeleportVisible = function (visible, mode, fade) { this.setTeleportVisible = function (visible, mode, fade) {
// Scales in teleport target and play area when start displaying them. // Scales in teleport target and play area when start displaying them.
if (visible === this.isTeleportVisible) { if (visible === _this.isTeleportVisible) {
return; return;
} }
if (visible) { if (visible) {
this.teleportScaleMode = mode; _this.teleportScaleMode = mode;
Pointers.editRenderState( Pointers.editRenderState(
mode === "head" ? _this.teleportParabolaHeadVisuals : _this.teleportParabolaHandVisuals, mode === "head" ? _this.teleportParabolaHeadVisuals : _this.teleportParabolaHandVisuals,
"teleport", "teleport",
@ -613,42 +613,42 @@ Script.include("/~/system/libraries/controllers.js");
end: { dimensions: Vec3.ZERO } end: { dimensions: Vec3.ZERO }
} }
); );
this.getOtherModule().cancelFade(); _this.getOtherModule().cancelFade();
this.teleportScaleStart = Date.now(); _this.teleportScaleStart = Date.now();
this.teleportScaleFactor = 0; _this.teleportScaleFactor = 0;
this.scaleInTeleport(); _this.scaleInTeleport();
Selection.enableListHighlight(this.teleporterSelectionName, this.TELEPORTER_SELECTION_STYLE); Selection.enableListHighlight(_this.teleporterSelectionName, _this.TELEPORTER_SELECTION_STYLE);
} else { } else {
if (this.teleportScaleTimer !== null) { if (_this.teleportScaleTimer !== null) {
Script.clearTimeout(this.teleportScaleTimer); Script.clearTimeout(_this.teleportScaleTimer);
this.teleportScaleTimer = null; _this.teleportScaleTimer = null;
} }
if (fade) { if (fade) {
// Copy of target at teleported position for fading. // Copy of target at teleported position for fading.
var avatarScale = MyAvatar.sensorToWorldScale; var avatarScale = MyAvatar.sensorToWorldScale;
Overlays.editOverlay(this.teleportedTargetOverlay, { Overlays.editOverlay(_this.teleportedTargetOverlay, {
position: Vec3.sum(this.teleportedPosition, { position: Vec3.sum(_this.teleportedPosition, {
x: 0, x: 0,
y: -getAvatarFootOffset() + avatarScale * TARGET_MODEL_DIMENSIONS.y / 2, y: -getAvatarFootOffset() + avatarScale * TARGET_MODEL_DIMENSIONS.y / 2,
z: 0 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), dimensions: Vec3.multiply(avatarScale, TARGET_MODEL_DIMENSIONS),
alpha: this.TELEPORTED_TARGET_ALPHA, alpha: _this.TELEPORTED_TARGET_ALPHA,
visible: true visible: true
}); });
// Fade out over time. // Fade out over time.
this.teleportedFadeDelayFactor = 1.0; _this.teleportedFadeDelayFactor = 1.0;
this.teleportedFadeFactor = 1.0; _this.teleportedFadeFactor = 1.0;
this.teleportedFadeTimer = Script.setTimeout(this.fadeOutTeleport, this.TELEPORTED_FADE_DELAY); _this.teleportedFadeTimer = Script.setTimeout(_this.fadeOutTeleport, _this.TELEPORTED_FADE_DELAY);
} else { } 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); 100);
this.enterTeleport = function() { this.enterTeleport = function() {
this.state = TELEPORTER_STATES.TARGETTING; _this.state = TELEPORTER_STATES.TARGETTING;
}; };
this.isReady = function(controllerData, deltaTime) { this.isReady = function(controllerData, deltaTime) {
@ -761,23 +761,23 @@ Script.include("/~/system/libraries/controllers.js");
if (teleportLocationType === TARGET.NONE) { if (teleportLocationType === TARGET.NONE) {
// Use the cancel default state // Use the cancel default state
this.setTeleportState(mode, "cancel", ""); _this.setTeleportState(mode, "cancel", "");
} else if (teleportLocationType === TARGET.INVALID) { } else if (teleportLocationType === TARGET.INVALID) {
this.setTeleportState(mode, "", "cancel"); _this.setTeleportState(mode, "", "cancel");
} else if (teleportLocationType === TARGET.COLLIDES) { } else if (teleportLocationType === TARGET.COLLIDES) {
this.setTeleportState(mode, "cancel", "collision"); _this.setTeleportState(mode, "cancel", "collision");
} else if (teleportLocationType === TARGET.SURFACE || teleportLocationType === TARGET.DISCREPANCY) { } else if (teleportLocationType === TARGET.SURFACE || teleportLocationType === TARGET.DISCREPANCY) {
this.setTeleportState(mode, "teleport", "collision"); _this.setTeleportState(mode, "teleport", "collision");
this.updatePlayArea(result.intersection); _this.updatePlayArea(result.intersection);
} else if (teleportLocationType === TARGET.SEAT) { } 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) { this.teleport = function(newResult, target) {
var result = newResult; var result = newResult;
this.teleportedPosition = newResult.intersection; _this.teleportedPosition = newResult.intersection;
if (_this.buttonValue !== 0) { if (_this.buttonValue !== 0) {
return makeRunningValues(true, [], []); return makeRunningValues(true, [], []);
} }
@ -795,14 +795,14 @@ Script.include("/~/system/libraries/controllers.js");
MyAvatar.centerBody(); MyAvatar.centerBody();
} }
this.disableLasers(); _this.disableLasers();
this.active = false; _this.active = false;
return makeRunningValues(false, [], []); return makeRunningValues(false, [], []);
}; };
this.disableLasers = function() { this.disableLasers = function() {
this.setPlayAreaVisible(false, null, true); _this.setPlayAreaVisible(false, null, true);
this.setTeleportVisible(false, null, true); _this.setTeleportVisible(false, null, true);
Pointers.disablePointer(_this.teleportParabolaHandVisuals); Pointers.disablePointer(_this.teleportParabolaHandVisuals);
Pointers.disablePointer(_this.teleportParabolaHandCollisions); Pointers.disablePointer(_this.teleportParabolaHandCollisions);
Pointers.disablePointer(_this.teleportParabolaHeadVisuals); Pointers.disablePointer(_this.teleportParabolaHeadVisuals);
@ -815,10 +815,10 @@ Script.include("/~/system/libraries/controllers.js");
this.setTeleportState = function (mode, visibleState, invisibleState) { this.setTeleportState = function (mode, visibleState, invisibleState) {
var teleportState = mode + visibleState + invisibleState; var teleportState = mode + visibleState + invisibleState;
if (teleportState === this.teleportState) { if (teleportState === _this.teleportState) {
return; return;
} }
this.teleportState = teleportState; _this.teleportState = teleportState;
var pointerID; var pointerID;
if (mode === 'head') { if (mode === 'head') {
@ -831,16 +831,16 @@ Script.include("/~/system/libraries/controllers.js");
pointerID = _this.teleportParabolaHandVisuals; pointerID = _this.teleportParabolaHandVisuals;
} }
var visible = visibleState === "teleport"; var visible = visibleState === "teleport";
this.setPlayAreaVisible(visible && MyAvatar.showPlayArea, _this.setPlayAreaVisible(visible && MyAvatar.showPlayArea,
Pointers.getPointerProperties(pointerID).renderStates.teleport.end, false); Pointers.getPointerProperties(pointerID).renderStates.teleport.end, false);
this.setTeleportVisible(visible, mode, false); _this.setTeleportVisible(visible, mode, false);
}; };
this.setIgnoreEntities = function(entitiesToIgnore) { this.setIgnoreEntities = function(entitiesToIgnore) {
Pointers.setIgnoreItems(this.teleportParabolaHandVisuals, entitiesToIgnore); Pointers.setIgnoreItems(_this.teleportParabolaHandVisuals, entitiesToIgnore);
Pointers.setIgnoreItems(this.teleportParabolaHandCollisions, entitiesToIgnore); Pointers.setIgnoreItems(_this.teleportParabolaHandCollisions, entitiesToIgnore);
Pointers.setIgnoreItems(this.teleportParabolaHeadVisuals, entitiesToIgnore); Pointers.setIgnoreItems(_this.teleportParabolaHeadVisuals, entitiesToIgnore);
Pointers.setIgnoreItems(this.teleportParabolaHeadCollisions, entitiesToIgnore); Pointers.setIgnoreItems(_this.teleportParabolaHeadCollisions, entitiesToIgnore);
Picks.setIgnoreItems(_this.teleportHeadCollisionPick, entitiesToIgnore); Picks.setIgnoreItems(_this.teleportHeadCollisionPick, entitiesToIgnore);
Picks.setIgnoreItems(_this.teleportHandCollisionPick, entitiesToIgnore); Picks.setIgnoreItems(_this.teleportHandCollisionPick, entitiesToIgnore);
}; };

View file

@ -161,7 +161,8 @@ ExtendedOverlay.unHover = function () { // calls hover(false) on lastHoveringId
// hit(overlay) on the one overlay intersected by pickRay, if any. // hit(overlay) on the one overlay intersected by pickRay, if any.
// noHit() if no ExtendedOverlay was intersected (helps with hover) // noHit() if no ExtendedOverlay was intersected (helps with hover)
ExtendedOverlay.applyPickRay = function (pickRay, hit, noHit) { 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 (!pickedOverlay.intersects) {
if (noHit) { if (noHit) {
return noHit(); return noHit();

View file

@ -137,11 +137,11 @@
UIWebTablet.calculateTabletAttachmentProperties(activeHand, true, tabletProperties); UIWebTablet.calculateTabletAttachmentProperties(activeHand, true, tabletProperties);
} }
tabletProperties.visible = true; tabletProperties.visible = true;
tabletProperties.ignorePickIntersection = false;
Overlays.editOverlay(HMD.tabletID, tabletProperties); Overlays.editOverlay(HMD.tabletID, tabletProperties);
Overlays.editOverlay(HMD.homeButtonID, { visible: true }); Overlays.editOverlay(HMD.homeButtonID, { visible: true, ignorePickIntersection: false });
Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: true }); Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: true, ignorePickIntersection: false });
Overlays.editOverlay(HMD.tabletScreenID, { visible: true }); Overlays.editOverlay(HMD.tabletScreenID, { visible: true, ignorePickIntersection: false, maxFPS: 90 });
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 90 });
updateTabletWidthFromSettings(true); updateTabletWidthFromSettings(true);
} }
gTablet.tabletShown = true; gTablet.tabletShown = true;
@ -158,11 +158,10 @@
print("TABLET hide"); print("TABLET hide");
} }
Overlays.editOverlay(HMD.tabletID, { visible: false }); Overlays.editOverlay(HMD.tabletID, { visible: false, ignorePickIntersection: true });
Overlays.editOverlay(HMD.homeButtonID, { visible: false }); Overlays.editOverlay(HMD.homeButtonID, { visible: false, ignorePickIntersection: true });
Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: false }); Overlays.editOverlay(HMD.homeButtonHighlightID, { visible: false, ignorePickIntersection: true });
Overlays.editOverlay(HMD.tabletScreenID, { visible: false }); Overlays.editOverlay(HMD.tabletScreenID, { visible: false, ignorePickIntersection: true, maxFPS: 1 });
Overlays.editOverlay(HMD.tabletScreenID, { maxFPS: 1 });
} }
function closeTabletUI() { function closeTabletUI() {