mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-11 21:52:43 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into 21616-addPerTileThreshold
This commit is contained in:
commit
6cc510a5a9
26 changed files with 211 additions and 109 deletions
Binary file not shown.
|
@ -1016,8 +1016,8 @@
|
|||
"type": "clip",
|
||||
"data": {
|
||||
"url": "qrc:///avatar/animations/run_fwd.fbx",
|
||||
"startFrame": 0.0,
|
||||
"endFrame": 21.0,
|
||||
"startFrame": 1.0,
|
||||
"endFrame": 22.0,
|
||||
"timeScale": 1.0,
|
||||
"loopFlag": true
|
||||
},
|
||||
|
|
|
@ -40,9 +40,9 @@ Rectangle {
|
|||
property string itemHref;
|
||||
property string itemAuthor;
|
||||
property int itemEdition: -1;
|
||||
property bool hasSomethingToTradeIn: alreadyOwned && (itemEdition > 0); // i.e., don't trade in your artist's proof
|
||||
property bool isTradingIn: isUpdating && hasSomethingToTradeIn;
|
||||
property bool isStocking: availability === 'not for sale' && creator === Account.username;
|
||||
property bool hasSomethingToTradeIn: itemEdition > 0; // i.e., don't trade in your artist's proof
|
||||
property bool isTradingIn: canUpdate && hasSomethingToTradeIn;
|
||||
property bool isStocking: (availability === 'not for sale') && (creator === Account.username) && !updated_item_id;
|
||||
property string certificateId;
|
||||
property double balanceAfterPurchase;
|
||||
property bool alreadyOwned: false; // Including proofs
|
||||
|
@ -59,8 +59,9 @@ Rectangle {
|
|||
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
||||
property string referrer;
|
||||
property bool isInstalled;
|
||||
property bool isUpdating;
|
||||
property bool canUpdate;
|
||||
property string availability: "available";
|
||||
property string updated_item_id: "";
|
||||
property string creator: "";
|
||||
property string baseAppURL;
|
||||
property int currentUpdatesPage: 1;
|
||||
|
@ -144,6 +145,7 @@ Rectangle {
|
|||
}
|
||||
|
||||
onAvailableUpdatesResult: {
|
||||
// Answers the updatable original item cert data still owned by this user that are EITHER instances of this marketplace id, or update to this marketplace id.
|
||||
if (result.status !== 'success') {
|
||||
console.log("Failed to get Available Updates", result.data.message);
|
||||
} else {
|
||||
|
@ -155,7 +157,7 @@ Rectangle {
|
|||
if (root.itemEdition !== -1 && root.itemEdition !== parseInt(result.data.updates[i].edition_number)) {
|
||||
continue;
|
||||
}
|
||||
root.isUpdating = true;
|
||||
root.canUpdate = true;
|
||||
root.baseItemName = result.data.updates[i].base_item_title;
|
||||
// This CertID is the one corresponding to the base item CertID that the user already owns
|
||||
root.certificateId = result.data.updates[i].certificate_id;
|
||||
|
@ -166,7 +168,7 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
if (result.data.updates.length === 0 || root.isUpdating) {
|
||||
if (result.data.updates.length === 0 || root.canUpdate) {
|
||||
root.availableUpdatesReceived = true;
|
||||
refreshBuyUI();
|
||||
} else {
|
||||
|
@ -178,7 +180,7 @@ Rectangle {
|
|||
|
||||
onUpdateItemResult: {
|
||||
if (result.status !== 'success') {
|
||||
failureErrorText.text = result.message;
|
||||
failureErrorText.text = result.data ? (result.data.message || "Unknown Error") : JSON.stringify(result);
|
||||
root.activeView = "checkoutFailure";
|
||||
} else {
|
||||
root.itemHref = result.data.download_url;
|
||||
|
@ -266,13 +268,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
enabled: titleBarContainer.usernameDropdownVisible;
|
||||
anchors.fill: parent;
|
||||
onClicked: {
|
||||
titleBarContainer.usernameDropdownVisible = false;
|
||||
}
|
||||
}
|
||||
//
|
||||
// TITLE BAR END
|
||||
//
|
||||
|
@ -481,7 +476,7 @@ Rectangle {
|
|||
FiraSansSemiBold {
|
||||
id: itemPriceText;
|
||||
text: isTradingIn ? "FREE\nUPDATE" :
|
||||
(isStocking ? "Free for creator" :
|
||||
(isStocking ? "Free for creator" :
|
||||
((root.itemPrice === -1) ? "--" : ((root.itemPrice > 0) ? root.itemPrice : "FREE")));
|
||||
// Text size
|
||||
size: isTradingIn ? 20 : 26;
|
||||
|
@ -580,7 +575,7 @@ Rectangle {
|
|||
// "View in Inventory" button
|
||||
HifiControlsUit.Button {
|
||||
id: viewInMyPurchasesButton;
|
||||
visible: isCertified && dataReady && (isUpdating ? !hasSomethingToTradeIn : alreadyOwned);
|
||||
visible: isCertified && dataReady && (isTradingIn ? hasSomethingToTradeIn : alreadyOwned);
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.light;
|
||||
anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top;
|
||||
|
@ -588,9 +583,9 @@ Rectangle {
|
|||
height: 50;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
text: root.isUpdating ? "UPDATE TO THIS ITEM FOR FREE" : "VIEW THIS ITEM IN YOUR INVENTORY";
|
||||
text: (canUpdate && !isTradingIn) ? "UPDATE TO THIS ITEM FOR FREE" : "VIEW THIS ITEM IN YOUR INVENTORY";
|
||||
onClicked: {
|
||||
if (root.isUpdating) {
|
||||
if (root.canUpdate) {
|
||||
sendToScript({method: 'checkout_goToPurchases', filterText: root.baseItemName});
|
||||
} else {
|
||||
sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName});
|
||||
|
@ -602,7 +597,11 @@ Rectangle {
|
|||
HifiControlsUit.Button {
|
||||
id: buyButton;
|
||||
visible: isTradingIn || !alreadyOwned || isStocking || !(root.itemType === "avatar" || root.itemType === "app");
|
||||
enabled: (root.balanceAfterPurchase >= 0 && dataReady) || (!root.isCertified) || root.isUpdating;
|
||||
property bool checkBalance: dataReady && (root.availability === "available")
|
||||
enabled: (checkBalance && (balanceAfterPurchase >= 0)) || !isCertified || isTradingIn || isStocking;
|
||||
text: isTradingIn ? "Confirm Update" :
|
||||
(enabled ? (viewInMyPurchasesButton.visible ? "Get It Again" : (dataReady ? "Get Item" : "--")) :
|
||||
(checkBalance ? "Insufficient Funds" : availability))
|
||||
color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.light;
|
||||
anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom :
|
||||
|
@ -611,13 +610,6 @@ Rectangle {
|
|||
height: 50;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
text: isTradingIn ?
|
||||
"CONFIRM UPDATE" :
|
||||
(((root.isCertified) ?
|
||||
(dataReady ?
|
||||
((viewInMyPurchasesButton.visible && !root.isUpdating) ? "Get It Again" : "Confirm") :
|
||||
"--") :
|
||||
"Get Item"));
|
||||
onClicked: {
|
||||
if (isTradingIn) {
|
||||
// If we're updating an app, the existing app needs to be uninstalled.
|
||||
|
@ -1110,6 +1102,7 @@ Rectangle {
|
|||
root.itemAuthor = result.data.creator;
|
||||
root.itemType = result.data.item_type || "unknown";
|
||||
root.availability = result.data.availability;
|
||||
root.updated_item_id = result.data.updated_item_id || ""
|
||||
root.creator = result.data.creator;
|
||||
if (root.itemType === "unknown") {
|
||||
root.itemHref = result.data.review_url;
|
||||
|
@ -1209,7 +1202,7 @@ Rectangle {
|
|||
buyText.text = "";
|
||||
|
||||
// If the user IS on the checkout page for the updated version of an owned item...
|
||||
if (root.isUpdating) {
|
||||
if (root.canUpdate) {
|
||||
// If the user HAS already selected a specific edition to update...
|
||||
if (hasSomethingToTradeIn) {
|
||||
buyText.text = "By pressing \"Confirm Update\", you agree to trade in your old item for the updated item that replaces it.";
|
||||
|
|
|
@ -112,7 +112,7 @@ Rectangle {
|
|||
marketplaceItem.image_url = result.data.thumbnail_url;
|
||||
marketplaceItem.name = result.data.title;
|
||||
marketplaceItem.likes = result.data.likes;
|
||||
if(result.data.has_liked !== undefined) {
|
||||
if (result.data.has_liked !== undefined) {
|
||||
marketplaceItem.liked = result.data.has_liked;
|
||||
}
|
||||
marketplaceItem.creator = result.data.creator;
|
||||
|
@ -122,6 +122,7 @@ Rectangle {
|
|||
marketplaceItem.attributions = result.data.attributions;
|
||||
marketplaceItem.license = result.data.license;
|
||||
marketplaceItem.availability = result.data.availability;
|
||||
marketplaceItem.updated_item_id = result.data.updated_item_id || "";
|
||||
marketplaceItem.created_at = result.data.created_at;
|
||||
marketplaceItemScrollView.contentHeight = marketplaceItemContent.height;
|
||||
itemsList.visible = false;
|
||||
|
@ -979,7 +980,6 @@ Rectangle {
|
|||
xhr.open("GET", url);
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == XMLHttpRequest.DONE) {
|
||||
console.log(xhr.responseText);
|
||||
licenseText.text = xhr.responseText;
|
||||
licenseInfo.visible = true;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// MarketplaceListItem.qml
|
||||
// qml/hifi/commerce/marketplace
|
||||
//
|
||||
// MarketplaceListItem
|
||||
// MarketplaceItem
|
||||
//
|
||||
// Created by Roxanne Skelly on 2019-01-22
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
|
@ -34,6 +34,7 @@ Rectangle {
|
|||
property var categories: []
|
||||
property int price: 0
|
||||
property string availability: "unknown"
|
||||
property string updated_item_id: ""
|
||||
property var attributions: []
|
||||
property string description: ""
|
||||
property string license: ""
|
||||
|
@ -42,7 +43,6 @@ Rectangle {
|
|||
property bool isLoggedIn: false;
|
||||
property int edition: -1;
|
||||
property bool supports3DHTML: false;
|
||||
|
||||
|
||||
onCategoriesChanged: {
|
||||
categoriesListModel.clear();
|
||||
|
@ -52,7 +52,7 @@ Rectangle {
|
|||
}
|
||||
|
||||
onDescriptionChanged: {
|
||||
|
||||
|
||||
if(root.supports3DHTML) {
|
||||
descriptionTextModel.clear();
|
||||
descriptionTextModel.append({text: description});
|
||||
|
@ -264,17 +264,14 @@ Rectangle {
|
|||
}
|
||||
height: 50
|
||||
|
||||
property bool isNFS: availability === "not for sale" // Note: server will say "sold out" or "invalidated" before it says NFS
|
||||
property bool isMine: creator === Account.username
|
||||
property bool isUpgrade: root.edition >= 0
|
||||
property int costToMe: ((isMine && isNFS) || isUpgrade) ? 0 : price
|
||||
property bool isAvailable: costToMe >= 0
|
||||
|
||||
text: isUpgrade ? "UPGRADE FOR FREE" : (isAvailable ? (costToMe || "FREE") : availability)
|
||||
enabled: isAvailable
|
||||
buttonGlyph: isAvailable ? (costToMe ? hifi.glyphs.hfc : "") : ""
|
||||
property bool isUpdate: root.edition >= 0 // Special case of updating from a specific older item
|
||||
property bool isStocking: (creator === Account.username) && (availability === "not for sale") && !updated_item_id // Note: server will say "sold out" or "invalidated" before it says NFS
|
||||
property bool isFreeSpecial: isStocking || isUpdate
|
||||
enabled: isFreeSpecial || (availability === 'available')
|
||||
buttonGlyph: (enabled && !isUpdate && (price > 0)) ? hifi.glyphs.hfc : ""
|
||||
text: isUpdate ? "UPDATE FOR FREE" : (isStocking ? "FREE STOCK" : (enabled ? (price || "FREE") : availability))
|
||||
color: hifi.buttons.blue
|
||||
|
||||
|
||||
onClicked: root.buy();
|
||||
}
|
||||
|
||||
|
|
|
@ -380,7 +380,7 @@ Item {
|
|||
if (updateButton.visible && uninstallButton.visible) {
|
||||
item.itemButtonText = "";
|
||||
item.glyphSize = 20;
|
||||
} else {
|
||||
} else if (item) {
|
||||
item.itemButtonText = "Send to Trash";
|
||||
item.glyphSize = 30;
|
||||
}
|
||||
|
|
|
@ -40,10 +40,6 @@ Rectangle {
|
|||
source: "images/wallet-bg.jpg";
|
||||
}
|
||||
|
||||
Component.onDestruction: {
|
||||
KeyboardScriptingInterface.raised = false;
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Commerce;
|
||||
|
||||
|
|
|
@ -910,7 +910,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
|
|||
recorder->recordFrame(FRAME_TYPE, toFrame(*this));
|
||||
}
|
||||
|
||||
locationChanged();
|
||||
locationChanged(true, false);
|
||||
// if a entity-child of this avatar has moved outside of its queryAACube, update the cube and tell the entity server.
|
||||
auto entityTreeRenderer = qApp->getEntities();
|
||||
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
||||
|
@ -920,6 +920,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
|
|||
zoneInteractionProperties = entityTreeRenderer->getZoneInteractionProperties();
|
||||
EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
|
||||
forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||
locationChanged(true, false);
|
||||
// we need to update attached queryAACubes in our own local tree so point-select always works
|
||||
// however we don't want to flood the update pipeline with AvatarEntity updates, so we assume
|
||||
// others have all info required to properly update queryAACube of AvatarEntities on their end
|
||||
|
@ -2324,23 +2325,25 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
|
||||
std::shared_ptr<QMetaObject::Connection> skeletonConnection = std::make_shared<QMetaObject::Connection>();
|
||||
*skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() {
|
||||
if (skeletonModelChangeCount == _skeletonModelChangeCount) {
|
||||
if (skeletonModelChangeCount == _skeletonModelChangeCount) {
|
||||
|
||||
if (_fullAvatarModelName.isEmpty()) {
|
||||
// Store the FST file name into preferences
|
||||
const auto& mapping = _skeletonModel->getGeometry()->getMapping();
|
||||
if (mapping.value("name").isValid()) {
|
||||
_fullAvatarModelName = mapping.value("name").toString();
|
||||
}
|
||||
}
|
||||
if (_fullAvatarModelName.isEmpty()) {
|
||||
// Store the FST file name into preferences
|
||||
const auto& mapping = _skeletonModel->getGeometry()->getMapping();
|
||||
if (mapping.value("name").isValid()) {
|
||||
_fullAvatarModelName = mapping.value("name").toString();
|
||||
}
|
||||
}
|
||||
|
||||
initHeadBones();
|
||||
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
|
||||
_fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
|
||||
initAnimGraph();
|
||||
_skeletonModelLoaded = true;
|
||||
}
|
||||
QObject::disconnect(*skeletonConnection);
|
||||
initHeadBones();
|
||||
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
|
||||
_fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl();
|
||||
initAnimGraph();
|
||||
initFlowFromFST();
|
||||
|
||||
_skeletonModelLoaded = true;
|
||||
}
|
||||
QObject::disconnect(*skeletonConnection);
|
||||
});
|
||||
|
||||
saveAvatarUrl();
|
||||
|
@ -5384,6 +5387,15 @@ void MyAvatar::useFlow(bool isActive, bool isCollidable, const QVariantMap& phys
|
|||
}
|
||||
}
|
||||
|
||||
void MyAvatar::initFlowFromFST() {
|
||||
if (_skeletonModel->isLoaded()) {
|
||||
auto &flowData = _skeletonModel->getHFMModel().flowData;
|
||||
if (flowData.shouldInitFlow()) {
|
||||
useFlow(true, flowData.shouldInitCollisions(), flowData._physicsConfig, flowData._collisionsConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::sendPacket(const QUuid& entityID, const EntityItemProperties& properties) const {
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||
|
|
|
@ -1751,6 +1751,7 @@ private:
|
|||
void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
|
||||
void initHeadBones();
|
||||
void initAnimGraph();
|
||||
void initFlowFromFST();
|
||||
|
||||
// Avatar Preferences
|
||||
QUrl _fullAvatarURLFromPreferences;
|
||||
|
|
|
@ -204,7 +204,8 @@ QString Overlays::overlayToEntityType(const QString& type) {
|
|||
#define RENAME_PROP(o, e) \
|
||||
{ \
|
||||
auto iter = overlayProps.find(#o); \
|
||||
if (iter != overlayProps.end()) { \
|
||||
if (iter != overlayProps.end() && \
|
||||
!overlayProps.contains(#e)) { \
|
||||
overlayProps[#e] = iter.value(); \
|
||||
} \
|
||||
}
|
||||
|
@ -493,15 +494,34 @@ EntityItemProperties Overlays::convertOverlayToEntityProperties(QVariantMap& ove
|
|||
RENAME_PROP_CONVERT(p1, p1, [](const QVariant& v) { return vec3toVariant(glm::vec3(0.0f)); });
|
||||
RENAME_PROP_CONVERT(p2, p2, [=](const QVariant& v) {
|
||||
glm::vec3 position;
|
||||
bool hasPosition = false;
|
||||
glm::quat rotation;
|
||||
bool hasRotation = false;
|
||||
|
||||
auto iter2 = overlayProps.find("position");
|
||||
if (iter2 != overlayProps.end()) {
|
||||
position = vec3FromVariant(iter2.value());
|
||||
} else if (!add) {
|
||||
EntityPropertyFlags desiredProperties;
|
||||
desiredProperties += PROP_POSITION;
|
||||
position = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(id, desiredProperties).getPosition();
|
||||
hasPosition = true;
|
||||
}
|
||||
return vec3toVariant(vec3FromVariant(v) - position);
|
||||
iter2 = overlayProps.find("rotation");
|
||||
if (iter2 != overlayProps.end()) {
|
||||
rotation = quatFromVariant(iter2.value());
|
||||
hasRotation = true;
|
||||
}
|
||||
|
||||
if (!add && !(hasPosition && hasRotation)) {
|
||||
auto entity = DependencyManager::get<EntityTreeRenderer>()->getEntity(id);
|
||||
if (entity) {
|
||||
if (!hasPosition) {
|
||||
position = entity->getWorldPosition();
|
||||
}
|
||||
if (!hasRotation) {
|
||||
rotation = entity->getWorldOrientation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vec3toVariant(glm::inverse(rotation) * (vec3FromVariant(v) - position));
|
||||
});
|
||||
|
||||
RENAME_PROP(localStart, p1);
|
||||
|
|
|
@ -928,9 +928,9 @@ void RenderableModelEntityItem::setJointTranslationsSet(const QVector<bool>& tra
|
|||
_needsJointSimulation = true;
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::locationChanged(bool tellPhysics) {
|
||||
void RenderableModelEntityItem::locationChanged(bool tellPhysics, bool tellChildren) {
|
||||
DETAILED_PERFORMANCE_TIMER("locationChanged");
|
||||
EntityItem::locationChanged(tellPhysics);
|
||||
EntityItem::locationChanged(tellPhysics, tellChildren);
|
||||
auto model = getModel();
|
||||
if (model && model->isLoaded()) {
|
||||
model->updateRenderItems();
|
||||
|
@ -1032,9 +1032,7 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() {
|
|||
});
|
||||
|
||||
if (changed) {
|
||||
forEachChild([&](SpatiallyNestablePointer object) {
|
||||
object->locationChanged(false);
|
||||
});
|
||||
locationChanged(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ public:
|
|||
virtual void setJointTranslations(const QVector<glm::vec3>& translations) override;
|
||||
virtual void setJointTranslationsSet(const QVector<bool>& translationsSet) override;
|
||||
|
||||
virtual void locationChanged(bool tellPhysics = true) override;
|
||||
virtual void locationChanged(bool tellPhysics = true, bool tellChildren = true) override;
|
||||
|
||||
virtual int getJointIndex(const QString& name) const override;
|
||||
virtual QStringList getJointNames() const override;
|
||||
|
|
|
@ -150,7 +150,7 @@ public:
|
|||
virtual bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override;
|
||||
virtual void removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) override;
|
||||
private:
|
||||
virtual void locationChanged(bool tellPhysics = true) override { EntityItem::locationChanged(tellPhysics); notifyBoundChanged(); }
|
||||
virtual void locationChanged(bool tellPhysics = true, bool tellChildren = true) override { EntityItem::locationChanged(tellPhysics, tellChildren); notifyBoundChanged(); }
|
||||
virtual void dimensionsChanged() override { EntityItem::dimensionsChanged(); notifyBoundChanged(); }
|
||||
void notifyBoundChanged();
|
||||
void notifyChangedRenderItem();
|
||||
|
|
|
@ -1873,7 +1873,7 @@ void EntityItem::setParentID(const QUuid& value) {
|
|||
|
||||
glm::vec3 EntityItem::getScaledDimensions() const {
|
||||
glm::vec3 scale = getSNScale();
|
||||
return _unscaledDimensions * scale;
|
||||
return getUnscaledDimensions() * scale;
|
||||
}
|
||||
|
||||
void EntityItem::setScaledDimensions(const glm::vec3& value) {
|
||||
|
@ -2593,7 +2593,7 @@ QList<EntityDynamicPointer> EntityItem::getActionsOfType(EntityDynamicType typeT
|
|||
return result;
|
||||
}
|
||||
|
||||
void EntityItem::locationChanged(bool tellPhysics) {
|
||||
void EntityItem::locationChanged(bool tellPhysics, bool tellChildren) {
|
||||
requiresRecalcBoxes();
|
||||
if (tellPhysics) {
|
||||
_flags |= Simulation::DIRTY_TRANSFORM;
|
||||
|
@ -2602,7 +2602,7 @@ void EntityItem::locationChanged(bool tellPhysics) {
|
|||
tree->entityChanged(getThisPointer());
|
||||
}
|
||||
}
|
||||
SpatiallyNestable::locationChanged(tellPhysics); // tell all the children, also
|
||||
SpatiallyNestable::locationChanged(tellPhysics, tellChildren);
|
||||
std::pair<int32_t, glm::vec4> data(_spaceIndex, glm::vec4(getWorldPosition(), _boundingRadius));
|
||||
emit spaceUpdate(data);
|
||||
somethingChangedNotification();
|
||||
|
|
|
@ -518,7 +518,7 @@ public:
|
|||
|
||||
virtual bool getMeshes(MeshProxyList& result) { return true; }
|
||||
|
||||
virtual void locationChanged(bool tellPhysics = true) override;
|
||||
virtual void locationChanged(bool tellPhysics = true, bool tellChildren = true) override;
|
||||
|
||||
virtual bool getScalesWithParent() const override;
|
||||
|
||||
|
|
|
@ -4209,7 +4209,7 @@ void EntityItemProperties::copySimulationRestrictedProperties(const EntityItemPo
|
|||
setAcceleration(entity->getAcceleration());
|
||||
}
|
||||
if (!_localDimensionsChanged && !_dimensionsChanged) {
|
||||
setDimensions(entity->getScaledDimensions());
|
||||
setLocalDimensions(entity->getScaledDimensions());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2039,6 +2039,8 @@ void EntityTree::fixupNeedsParentFixups() {
|
|||
Simulation::DIRTY_COLLISION_GROUP |
|
||||
Simulation::DIRTY_TRANSFORM);
|
||||
entityChanged(entity);
|
||||
entity->locationChanged(true, false);
|
||||
|
||||
entity->forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||
if (object->getNestableType() == NestableType::Entity) {
|
||||
EntityItemPointer descendantEntity = std::static_pointer_cast<EntityItem>(object);
|
||||
|
@ -2047,8 +2049,8 @@ void EntityTree::fixupNeedsParentFixups() {
|
|||
Simulation::DIRTY_TRANSFORM);
|
||||
entityChanged(descendantEntity);
|
||||
}
|
||||
object->locationChanged(true, false);
|
||||
});
|
||||
entity->locationChanged(true);
|
||||
|
||||
// Update our parent's bounding box
|
||||
bool success = false;
|
||||
|
@ -3002,8 +3004,19 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object,
|
|||
// if the queryBox has changed, tell the entity-server
|
||||
EntityItemPointer entity = std::dynamic_pointer_cast<EntityItem>(object);
|
||||
if (entity) {
|
||||
// NOTE: we rely on side-effects of the entity->updateQueryAACube() call in the following if() conditional:
|
||||
if (entity->updateQueryAACube() || force) {
|
||||
bool queryAACubeChanged = false;
|
||||
if (!entity->hasChildren()) {
|
||||
// updateQueryAACube will also update all ancestors' AACubes, so we only need to call this for leaf nodes
|
||||
queryAACubeChanged = entity->updateQueryAACube();
|
||||
} else {
|
||||
AACube oldCube = entity->getQueryAACube();
|
||||
object->forEachChild([&](SpatiallyNestablePointer descendant) {
|
||||
updateEntityQueryAACubeWorker(descendant, packetSender, moveOperator, force, tellServer);
|
||||
});
|
||||
queryAACubeChanged = oldCube != entity->getQueryAACube();
|
||||
}
|
||||
|
||||
if (queryAACubeChanged || force) {
|
||||
bool success;
|
||||
AACube newCube = entity->getQueryAACube(success);
|
||||
if (success) {
|
||||
|
@ -3027,10 +3040,6 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object,
|
|||
entityChanged(entity);
|
||||
}
|
||||
}
|
||||
|
||||
object->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||
updateEntityQueryAACubeWorker(descendant, packetSender, moveOperator, force, tellServer);
|
||||
});
|
||||
}
|
||||
|
||||
void EntityTree::updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||
|
|
|
@ -55,8 +55,8 @@ void LightEntityItem::setUnscaledDimensions(const glm::vec3& value) {
|
|||
}
|
||||
}
|
||||
|
||||
void LightEntityItem::locationChanged(bool tellPhysics) {
|
||||
EntityItem::locationChanged(tellPhysics);
|
||||
void LightEntityItem::locationChanged(bool tellPhysics, bool tellChildren) {
|
||||
EntityItem::locationChanged(tellPhysics, tellChildren);
|
||||
withWriteLock([&] {
|
||||
_lightPropertiesChanged = true;
|
||||
});
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
static bool getLightsArePickable() { return _lightsArePickable; }
|
||||
static void setLightsArePickable(bool value) { _lightsArePickable = value; }
|
||||
|
||||
virtual void locationChanged(bool tellPhysics) override;
|
||||
virtual void locationChanged(bool tellPhysics, bool tellChildren) override;
|
||||
virtual void dimensionsChanged() override;
|
||||
|
||||
bool lightPropertiesChanged() const { return _lightPropertiesChanged; }
|
||||
|
|
|
@ -273,6 +273,15 @@ public:
|
|||
{}
|
||||
};
|
||||
|
||||
class FlowData {
|
||||
public:
|
||||
FlowData() {};
|
||||
QVariantMap _physicsConfig;
|
||||
QVariantMap _collisionsConfig;
|
||||
bool shouldInitFlow() const { return _physicsConfig.size() > 0; }
|
||||
bool shouldInitCollisions() const { return _collisionsConfig.size() > 0; }
|
||||
};
|
||||
|
||||
/// The runtime model format.
|
||||
class Model {
|
||||
public:
|
||||
|
@ -319,6 +328,7 @@ public:
|
|||
QList<QString> blendshapeChannelNames;
|
||||
|
||||
QMap<int, glm::quat> jointRotationOffsets;
|
||||
FlowData flowData;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -343,6 +353,7 @@ typedef hfm::Mesh HFMMesh;
|
|||
typedef hfm::AnimationFrame HFMAnimationFrame;
|
||||
typedef hfm::Light HFMLight;
|
||||
typedef hfm::Model HFMModel;
|
||||
typedef hfm::FlowData FlowData;
|
||||
|
||||
Q_DECLARE_METATYPE(HFMAnimationFrame)
|
||||
Q_DECLARE_METATYPE(QVector<HFMAnimationFrame>)
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "CalculateBlendshapeNormalsTask.h"
|
||||
#include "CalculateBlendshapeTangentsTask.h"
|
||||
#include "PrepareJointsTask.h"
|
||||
#include "ParseFlowDataTask.h"
|
||||
|
||||
namespace baker {
|
||||
|
||||
|
@ -101,7 +102,7 @@ namespace baker {
|
|||
|
||||
class BuildModelTask {
|
||||
public:
|
||||
using Input = VaryingSet5<hfm::Model::Pointer, std::vector<hfm::Mesh>, std::vector<hfm::Joint>, QMap<int, glm::quat>, QHash<QString, int>>;
|
||||
using Input = VaryingSet6<hfm::Model::Pointer, std::vector<hfm::Mesh>, std::vector<hfm::Joint>, QMap<int, glm::quat>, QHash<QString, int>, FlowData>;
|
||||
using Output = hfm::Model::Pointer;
|
||||
using JobModel = Job::ModelIO<BuildModelTask, Input, Output>;
|
||||
|
||||
|
@ -111,6 +112,7 @@ namespace baker {
|
|||
hfmModelOut->joints = QVector<hfm::Joint>::fromStdVector(input.get2());
|
||||
hfmModelOut->jointRotationOffsets = input.get3();
|
||||
hfmModelOut->jointIndices = input.get4();
|
||||
hfmModelOut->flowData = input.get5();
|
||||
output = hfmModelOut;
|
||||
}
|
||||
};
|
||||
|
@ -157,12 +159,15 @@ namespace baker {
|
|||
// Parse material mapping
|
||||
const auto materialMapping = model.addJob<ParseMaterialMappingTask>("ParseMaterialMapping", mapping);
|
||||
|
||||
// Parse flow data
|
||||
const auto flowData = model.addJob<ParseFlowDataTask>("ParseFlowData", mapping);
|
||||
|
||||
// Combine the outputs into a new hfm::Model
|
||||
const auto buildBlendshapesInputs = BuildBlendshapesTask::Input(blendshapesPerMeshIn, normalsPerBlendshapePerMesh, tangentsPerBlendshapePerMesh).asVarying();
|
||||
const auto blendshapesPerMeshOut = model.addJob<BuildBlendshapesTask>("BuildBlendshapes", buildBlendshapesInputs);
|
||||
const auto buildMeshesInputs = BuildMeshesTask::Input(meshesIn, graphicsMeshes, normalsPerMesh, tangentsPerMesh, blendshapesPerMeshOut).asVarying();
|
||||
const auto meshesOut = model.addJob<BuildMeshesTask>("BuildMeshes", buildMeshesInputs);
|
||||
const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices).asVarying();
|
||||
const auto buildModelInputs = BuildModelTask::Input(hfmModelIn, meshesOut, jointsOut, jointRotationOffsets, jointIndices, flowData).asVarying();
|
||||
const auto hfmModelOut = model.addJob<BuildModelTask>("BuildModel", buildModelInputs);
|
||||
|
||||
output = Output(hfmModelOut, materialMapping);
|
||||
|
|
33
libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp
Normal file
33
libraries/model-baker/src/model-baker/ParseFlowDataTask.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Created by Luis Cuenca on 5/3/2019
|
||||
// Copyright 2019 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
|
||||
//
|
||||
|
||||
#include "ParseFlowDataTask.h"
|
||||
|
||||
void ParseFlowDataTask::run(const baker::BakeContextPointer& context, const Input& mapping, Output& output) {
|
||||
FlowData flowData;
|
||||
static const QString FLOW_PHYSICS_FIELD = "flowPhysicsData";
|
||||
static const QString FLOW_COLLISIONS_FIELD = "flowCollisionsData";
|
||||
for (auto mappingIter = mapping.begin(); mappingIter != mapping.end(); mappingIter++) {
|
||||
if (mappingIter.key() == FLOW_PHYSICS_FIELD || mappingIter.key() == FLOW_COLLISIONS_FIELD) {
|
||||
QByteArray data = mappingIter.value().toByteArray();
|
||||
QJsonObject dataObject = QJsonDocument::fromJson(data).object();
|
||||
if (!dataObject.isEmpty() && dataObject.keys().size() == 1) {
|
||||
QString key = dataObject.keys()[0];
|
||||
if (dataObject[key].isObject()) {
|
||||
QVariantMap dataMap = dataObject[key].toObject().toVariantMap();
|
||||
if (mappingIter.key() == FLOW_PHYSICS_FIELD) {
|
||||
flowData._physicsConfig.insert(key, dataMap);
|
||||
} else {
|
||||
flowData._collisionsConfig.insert(key, dataMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
output = flowData;
|
||||
}
|
24
libraries/model-baker/src/model-baker/ParseFlowDataTask.h
Normal file
24
libraries/model-baker/src/model-baker/ParseFlowDataTask.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// Created by Luis Cuenca on 5/3/2019
|
||||
// Copyright 2019 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
|
||||
//
|
||||
|
||||
#ifndef hifi_ParseFlowDataTask_h
|
||||
#define hifi_ParseFlowDataTask_h
|
||||
|
||||
#include <hfm/HFM.h>
|
||||
#include "Engine.h"
|
||||
|
||||
class ParseFlowDataTask {
|
||||
public:
|
||||
using Input = QVariantHash;
|
||||
using Output = FlowData;
|
||||
using JobModel = baker::Job::ModelIO<ParseFlowDataTask, Input, Output>;
|
||||
|
||||
void run(const baker::BakeContextPointer& context, const Input& input, Output& output);
|
||||
};
|
||||
|
||||
#endif // hifi_ParseFlowDataTask_h
|
|
@ -1100,10 +1100,12 @@ void SpatiallyNestable::forEachDescendantTest(const ChildLambdaTest& actor) cons
|
|||
}
|
||||
}
|
||||
|
||||
void SpatiallyNestable::locationChanged(bool tellPhysics) {
|
||||
forEachChild([&](SpatiallyNestablePointer object) {
|
||||
object->locationChanged(tellPhysics);
|
||||
});
|
||||
void SpatiallyNestable::locationChanged(bool tellPhysics, bool tellChildren) {
|
||||
if (tellChildren) {
|
||||
forEachChild([&](SpatiallyNestablePointer object) {
|
||||
object->locationChanged(tellPhysics, tellChildren);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
AACube SpatiallyNestable::getMaximumAACube(bool& success) const {
|
||||
|
|
|
@ -211,7 +211,7 @@ public:
|
|||
|
||||
void dump(const QString& prefix = "") const;
|
||||
|
||||
virtual void locationChanged(bool tellPhysics = true); // called when a this object's location has changed
|
||||
virtual void locationChanged(bool tellPhysics = true, bool tellChildren = true); // called when a this object's location has changed
|
||||
virtual void dimensionsChanged() { _queryAACubeSet = false; } // called when a this object's dimensions have changed
|
||||
virtual void parentDeleted() { } // called on children of a deleted parent
|
||||
|
||||
|
|
|
@ -19,6 +19,11 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
|
||||
var isShowingOverlays = true;
|
||||
var debugOverlays = {};
|
||||
var textSizeOverlay = Overlays.addOverlay("text3d", {
|
||||
position: MyAvatar.position,
|
||||
lineHeight: 0.1,
|
||||
visible: false
|
||||
});
|
||||
|
||||
function removeOverlays() {
|
||||
// enumerate the overlays and remove them
|
||||
|
@ -31,6 +36,8 @@ function removeOverlays() {
|
|||
}
|
||||
}
|
||||
|
||||
Overlays.deleteOverlay(textSizeOverlay);
|
||||
|
||||
debugOverlays = {};
|
||||
}
|
||||
|
||||
|
@ -60,8 +67,6 @@ function updateOverlays() {
|
|||
var overlayPosition = avatar.getJointPosition("Head");
|
||||
overlayPosition.y += 1.15;
|
||||
|
||||
var rows = 8;
|
||||
|
||||
var text = avatarID + "\n"
|
||||
+"--- Data from Mixer ---\n"
|
||||
+"All: " + AvatarManager.getAvatarDataRate(avatarID).toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID).toFixed(2) + "hz)" + "\n"
|
||||
|
@ -85,9 +90,11 @@ function updateOverlays() {
|
|||
//+" SM: " + AvatarManager.getAvatarSimulationRate(avatarID,"skeletonModel").toFixed(2) + "hz \n"
|
||||
+" JD: " + AvatarManager.getAvatarSimulationRate(avatarID,"jointData").toFixed(2) + "hz \n"
|
||||
|
||||
var dimensions = Overlays.textSize(textSizeOverlay, text);
|
||||
if (avatarID in debugOverlays) {
|
||||
// keep the overlay above the current position of this avatar
|
||||
Overlays.editOverlay(debugOverlays[avatarID][0], {
|
||||
dimensions: { x: 1.1 * dimensions.width, y: 0.6 * dimensions.height },
|
||||
position: overlayPosition,
|
||||
text: text
|
||||
});
|
||||
|
@ -95,15 +102,9 @@ function updateOverlays() {
|
|||
// add the overlay above this avatar
|
||||
var newOverlay = Overlays.addOverlay("text3d", {
|
||||
position: overlayPosition,
|
||||
dimensions: {
|
||||
x: 1.25,
|
||||
y: rows * 0.13
|
||||
},
|
||||
dimensions: { x: 1.1 * dimensions.width, y: 0.6 * dimensions.height },
|
||||
lineHeight: 0.1,
|
||||
font:{size:0.1},
|
||||
text: text,
|
||||
size: 1,
|
||||
scale: 0.4,
|
||||
color: { red: 255, green: 255, blue: 255},
|
||||
alpha: 1,
|
||||
solid: true,
|
||||
|
|
Loading…
Reference in a new issue