diff --git a/cmake/macros/MemoryDebugger.cmake b/cmake/macros/MemoryDebugger.cmake index ed80e03c6b..09716715f0 100644 --- a/cmake/macros/MemoryDebugger.cmake +++ b/cmake/macros/MemoryDebugger.cmake @@ -16,9 +16,9 @@ if (HIFI_MEMORY_DEBUGGING) if (UNIX) if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") # for clang on Linux - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") - SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") - SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -shared-libasan -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -shared-libasan -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -shared-libasan -fsanitize=undefined -fsanitize=address -fsanitize-recover=address") else () # for gcc on Linux SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fsanitize=address -U_FORTIFY_SOURCE -fno-stack-protector -fno-omit-frame-pointer") diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index c2a4d47992..7e17d20375 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -19,6 +19,7 @@ import controlsUit 1.0 as HifiControlsUit import "../../../controls" as HifiControls import "../wallet" as HifiWallet import "../common" as HifiCommerceCommon +import "../.." as HifiCommon // references XXX from root context @@ -31,6 +32,7 @@ Rectangle { property bool ownershipStatusReceived: false; property bool balanceReceived: false; property bool availableUpdatesReceived: false; + property bool itemInfoReceived: false; property string baseItemName: ""; property string itemName; property string itemId; @@ -181,11 +183,14 @@ Rectangle { onItemIdChanged: { root.ownershipStatusReceived = false; + root.itemInfoReceived = false; Commerce.alreadyOwned(root.itemId); root.availableUpdatesReceived = false; root.currentUpdatesPage = 1; Commerce.getAvailableUpdates(root.itemId); - itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg"; + + var MARKETPLACE_API_URL = Account.metaverseServerURL + "/api/v1/marketplace/items/"; + http.request({uri: MARKETPLACE_API_URL + root.itemId}, updateCheckoutQMLFromHTTP); } onItemTypeChanged: { @@ -279,6 +284,7 @@ Rectangle { ownershipStatusReceived = false; balanceReceived = false; availableUpdatesReceived = false; + itemInfoReceived = false; Commerce.getWalletStatus(); } } @@ -355,7 +361,7 @@ Rectangle { Rectangle { id: loading; z: 997; - visible: !root.ownershipStatusReceived || !root.balanceReceived || !root.availableUpdatesReceived; + visible: !root.ownershipStatusReceived || !root.balanceReceived || !root.availableUpdatesReceived || !root.itemInfoReceived; anchors.fill: parent; color: hifi.colors.white; @@ -1063,10 +1069,33 @@ Rectangle { } } } + + + HifiCommon.RootHttpRequest { + id: http; + } // // FUNCTION DEFINITIONS START // + + function updateCheckoutQMLFromHTTP(error, result) { + if (error || (result.status !== 'success')) { + // The QML will display a loading spinner forever if the user is stuck here. + console.log("Error in Checkout.qml when getting marketplace item info!"); + return; + } + + root.itemInfoReceived = true; + root.itemName = result.data.title; + root.itemPrice = result.data.cost; + root.itemHref = Account.metaverseServerURL + result.data.path; + root.itemAuthor = result.data.creator; + root.itemType = result.data.item_type || "unknown"; + itemPreviewImage.source = result.data.thumbnail_url; + refreshBuyUI(); + } + // // Function Name: fromScript() // @@ -1080,18 +1109,24 @@ Rectangle { // Description: // Called when a message is received from a script. // + function fromScript(message) { switch (message.method) { - case 'updateCheckoutQML': - root.itemId = message.params.itemId; - root.itemName = message.params.itemName.trim(); - root.itemPrice = message.params.itemPrice; - root.itemHref = message.params.itemHref; - root.referrer = message.params.referrer; - root.itemAuthor = message.params.itemAuthor; + case 'updateCheckoutQMLItemID': + if (!message.params.itemId) { + console.log("A message with method 'updateCheckoutQMLItemID' was sent without an itemId!"); + return; + } + + // If we end up following the referrer (i.e. in case the wallet "isn't set up" or the user cancels), + // we want the user to be placed back on the individual item's page - thus we set the + // default of the referrer in this case to "itemPage". + root.referrer = message.params.referrer || "itemPage"; root.itemEdition = message.params.itemEdition || -1; - root.itemType = message.params.itemType || "unknown"; - refreshBuyUI(); + root.itemId = message.params.itemId; + break; + case 'http.response': + http.handleHttpResponse(message); break; default: console.log('Checkout.qml: Unrecognized message from marketplaces.js'); diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/RecipientDisplay.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/RecipientDisplay.qml index 9e1a967d50..10756957d3 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/RecipientDisplay.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/RecipientDisplay.qml @@ -25,14 +25,15 @@ Item { id: root; - property bool isDisplayingNearby; // as opposed to 'connections' + // true when sending to 'nearby' or when a script raises the send asset dialog + property bool multiLineDisplay; property string displayName; property string userName; property string profilePic; property string textColor: hifi.colors.white; Item { - visible: root.isDisplayingNearby; + visible: root.multiLineDisplay; anchors.fill: parent; RalewaySemiBold { @@ -71,7 +72,7 @@ Item { } Item { - visible: !root.isDisplayingNearby; + visible: !root.multiLineDisplay; anchors.fill: parent; Image { diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index d6378f82ac..2d0bb2d87b 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -39,7 +39,7 @@ Item { property string sendingPubliclyEffectImage; property var http; property var listModelName; - property var keyboardContainer: nil; + property var keyboardContainer; // This object is always used in a popup or full-screen Wallet section. // This MouseArea is used to prevent a user from being @@ -56,7 +56,7 @@ Item { // Background Rectangle { z: 1; - visible: root.assetName !== "" && sendAssetStep.visible; + visible: root.assetCertID !== "" && sendAssetStep.referrer !== "payIn" && sendAssetStep.visible; anchors.top: parent.top; anchors.topMargin: root.parentAppTitleBarHeight; anchors.left: parent.left; @@ -84,7 +84,6 @@ Item { if (sendPubliclyCheckbox.checked && sendAssetStep.referrer === "nearby") { sendSignalToParent({ method: 'sendAsset_sendPublicly', - assetName: root.assetName, recipient: sendAssetStep.selectedRecipientNodeID, amount: parseInt(amountTextField.text), effectImage: root.sendingPubliclyEffectImage @@ -108,6 +107,14 @@ Item { root.nextActiveView = 'paymentFailure'; } } + + onCertificateInfoResult: { + if (result.status !== 'success') { + console.log("Failed to get certificate info", result.data.message); + } else { + root.assetName = result.data.marketplace_item_name; + } + } } Connections { @@ -155,7 +162,7 @@ Item { Item { id: userInfoContainer; - visible: root.assetName === ""; + visible: root.assetCertID === ""; anchors.top: parent.top; anchors.left: parent.left; anchors.right: parent.right; @@ -251,7 +258,7 @@ Item { LinearGradient { anchors.fill: parent; - visible: root.assetName === ""; + visible: root.assetCertID === ""; start: Qt.point(0, 0); end: Qt.point(0, height); gradient: Gradient { @@ -262,7 +269,7 @@ Item { RalewaySemiBold { id: sendAssetText; - text: root.assetName === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"; + text: root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"; // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -405,7 +412,7 @@ Item { HifiModels.PSFListModel { id: connectionsModel; http: root.http; - listModelName: root.listModelName; + listModelName: root.listModelName || ""; endpoint: "/api/v1/users?filter=connections"; itemsPerPage: 9; listView: connectionsList; @@ -441,7 +448,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_connections; text: hifi.glyphs.close; - color: root.assetName === "" ? hifi.colors.lightGrayText : hifi.colors.baseGray; + color: root.assetCertID === "" ? hifi.colors.lightGrayText : hifi.colors.baseGray; size: 26; anchors.top: parent.top; anchors.topMargin: 10; @@ -684,7 +691,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_nearby; text: hifi.glyphs.close; - color: root.assetName === "" ? hifi.colors.lightGrayText : hifi.colors.baseGray; + color: root.assetCertID === "" ? hifi.colors.lightGrayText : hifi.colors.baseGray; size: 26; anchors.top: parent.top; anchors.topMargin: 10; @@ -760,7 +767,7 @@ Item { RalewaySemiBold { id: sendToText; - text: root.assetName === "" ? "Send to:" : "Gift to:"; + text: root.assetCertID === "" ? "Send to:" : "Gift to:"; // Anchors anchors.top: parent.top; anchors.topMargin: 36; @@ -853,7 +860,7 @@ Item { id: sendAssetStep; z: 996; - property string referrer; // either "connections" or "nearby" + property string referrer; // either "connections", "nearby", or "payIn" property string selectedRecipientNodeID; property string selectedRecipientDisplayName; property string selectedRecipientUserName; @@ -865,7 +872,8 @@ Item { RalewaySemiBold { id: sendAssetText_sendAssetStep; - text: root.assetName === "" ? "Send Money" : "Gift \"" + root.assetName + "\""; + text: sendAssetStep.referrer === "payIn" && root.assetCertID !== "" ? "Send \"" + root.assetName + "\":" : + (root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"); // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -878,7 +886,7 @@ Item { // Text size size: 22; // Style - color: root.assetName === "" ? hifi.colors.white : hifi.colors.black; + color: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.white : hifi.colors.black; } Item { @@ -893,7 +901,7 @@ Item { RalewaySemiBold { id: sendToText_sendAssetStep; - text: root.assetName === "" ? "Send to:" : "Gift to:"; + text: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? "Send to:" : "Gift to:"; // Anchors anchors.top: parent.top; anchors.left: parent.left; @@ -902,7 +910,7 @@ Item { // Text size size: 18; // Style - color: root.assetName === "" ? hifi.colors.white : hifi.colors.black; + color: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.white : hifi.colors.black; verticalAlignment: Text.AlignVCenter; } @@ -912,25 +920,26 @@ Item { anchors.right: changeButton.left; anchors.rightMargin: 12; height: parent.height; - textColor: root.assetName === "" ? hifi.colors.white : hifi.colors.black; + textColor: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.white : hifi.colors.black; displayName: sendAssetStep.selectedRecipientDisplayName; userName: sendAssetStep.selectedRecipientUserName; profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; - isDisplayingNearby: sendAssetStep.referrer === "nearby"; + multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; } // "CHANGE" button HifiControlsUit.Button { id: changeButton; - color: root.assetName === "" ? hifi.buttons.none : hifi.buttons.white; + color: root.assetCertID === "" ? hifi.buttons.none : hifi.buttons.white; colorScheme: hifi.colorSchemes.dark; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter; height: 35; width: 100; text: "CHANGE"; + visible: sendAssetStep.referrer !== "payIn"; onClicked: { if (sendAssetStep.referrer === "connections") { root.nextActiveView = "chooseRecipientConnection"; @@ -944,7 +953,7 @@ Item { Item { id: amountContainer; - visible: root.assetName === ""; + visible: root.assetCertID === ""; anchors.top: sendToContainer.bottom; anchors.topMargin: 2; anchors.left: parent.left; @@ -970,8 +979,9 @@ Item { HifiControlsUit.TextField { id: amountTextField; - text: root.assetName === "" ? "" : "1"; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + readOnly: sendAssetStep.referrer === "payIn"; + text: root.assetCertID === "" ? "" : "1"; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; inputMethodHints: Qt.ImhDigitsOnly; // Anchors anchors.verticalCenter: parent.verticalCenter; @@ -980,8 +990,8 @@ Item { height: 50; // Style leftPermanentGlyph: hifi.glyphs.hfc; - activeFocusOnPress: true; - activeFocusOnTab: true; + activeFocusOnPress: !amountTextField.readOnly; + activeFocusOnTab: !amountTextField.readOnly; validator: IntValidator { bottom: 0; } @@ -1071,6 +1081,7 @@ Item { TextArea { id: optionalMessage; + readOnly: sendAssetStep.referrer === "payIn"; property int maximumLength: 72; property string previousText: text; placeholderText: "<i>Optional Public Message (" + maximumLength + " character limit)</i>"; @@ -1081,12 +1092,13 @@ Item { // Style background: Rectangle { anchors.fill: parent; - color: root.assetName === "" ? (optionalMessage.activeFocus ? hifi.colors.black : hifi.colors.baseGrayShadow) : + color: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? + (optionalMessage.activeFocus && !optionalMessage.readOnly ? hifi.colors.black : hifi.colors.baseGrayShadow) : (optionalMessage.activeFocus ? "#EFEFEF" : "#EEEEEE"); - border.width: optionalMessage.activeFocus ? 1 : 0; - border.color: optionalMessage.activeFocus ? hifi.colors.primaryHighlight : hifi.colors.textFieldLightBackground; + border.width: optionalMessage.activeFocus && !optionalMessage.readOnly ? 1 : 0; + border.color: optionalMessage.activeFocus && !optionalMessage.readOnly ? hifi.colors.primaryHighlight : hifi.colors.textFieldLightBackground; } - color: root.assetName === "" ? hifi.colors.white : hifi.colors.black; + color: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.white : hifi.colors.black; textFormat: TextEdit.PlainText; wrapMode: TextEdit.Wrap; activeFocusOnPress: true; @@ -1122,7 +1134,8 @@ Item { // Text size size: 16; // Style - color: optionalMessage.text.length === optionalMessage.maximumLength ? "#ea89a5" : (root.assetName === "" ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight); + color: optionalMessage.text.length === optionalMessage.maximumLength ? "#ea89a5" : + (root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight); verticalAlignment: Text.AlignTop; horizontalAlignment: Text.AlignRight; } @@ -1167,7 +1180,7 @@ Item { parent.color = hifi.colors.blueAccent; } onClicked: { - lightboxPopup.titleText = (root.assetName === "" ? "Send Effect" : "Gift Effect"); + lightboxPopup.titleText = (root.assetCertID === "" ? "Send Effect" : "Gift Effect"); lightboxPopup.bodyImageSource = "sendAsset/images/send-money-effect-sm.jpg"; // Path relative to CommerceLightbox.qml lightboxPopup.bodyText = "Enabling this option will create a particle effect between you and " + "your recipient that is visible to everyone nearby."; @@ -1196,7 +1209,7 @@ Item { // "CANCEL" button HifiControlsUit.Button { id: cancelButton_sendAssetStep; - color: root.assetName === "" ? hifi.buttons.noneBorderlessWhite : hifi.buttons.noneBorderlessGray; + color: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.buttons.noneBorderlessWhite : hifi.buttons.noneBorderlessGray; colorScheme: hifi.colorSchemes.dark; anchors.right: sendButton.left; anchors.rightMargin: 24; @@ -1205,8 +1218,12 @@ Item { width: 100; text: "CANCEL"; onClicked: { - resetSendAssetData(); - root.nextActiveView = "sendAssetHome"; + if (sendAssetStep.referrer === "payIn") { + sendToScript({method: "closeSendAsset"}); + } else { + resetSendAssetData(); + root.nextActiveView = "sendAssetHome"; + } } } @@ -1214,7 +1231,7 @@ Item { HifiControlsUit.Button { id: sendButton; color: hifi.buttons.blue; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.right: parent.right; anchors.rightMargin: 0; anchors.verticalCenter: parent.verticalCenter; @@ -1222,11 +1239,11 @@ Item { width: 100; text: "SUBMIT"; onClicked: { - if (root.assetName === "" && parseInt(amountTextField.text) > parseInt(balanceText.text)) { + if (root.assetCertID === "" && parseInt(amountTextField.text) > parseInt(balanceText.text)) { amountTextField.focus = true; amountTextField.error = true; amountTextFieldError.text = "<i>amount exceeds available funds</i>"; - } else if (root.assetName === "" && (amountTextField.text === "" || parseInt(amountTextField.text) < 1)) { + } else if (root.assetCertID === "" && (amountTextField.text === "" || parseInt(amountTextField.text) < 1)) { amountTextField.focus = true; amountTextField.error = true; amountTextFieldError.text = "<i>invalid amount</i>"; @@ -1236,7 +1253,7 @@ Item { root.isCurrentlySendingAsset = true; amountTextField.focus = false; optionalMessage.focus = false; - if (sendAssetStep.referrer === "connections") { + if (sendAssetStep.referrer === "connections" || sendAssetStep.referrer === "payIn") { Commerce.transferAssetToUsername(sendAssetStep.selectedRecipientUserName, root.assetCertID, parseInt(amountTextField.text), @@ -1317,18 +1334,18 @@ Item { Rectangle { anchors.top: parent.top; - anchors.topMargin: root.assetName === "" ? 15 : 125; + anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 125; anchors.left: parent.left; - anchors.leftMargin: root.assetName === "" ? 15 : 50; + anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; anchors.right: parent.right; - anchors.rightMargin: root.assetName === "" ? 15 : 50; + anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 15 : 125; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 125; color: "#FFFFFF"; RalewaySemiBold { id: paymentSentText; - text: root.assetName === "" ? "Payment Sent" : "Gift Sent"; + text: root.assetCertID === "" ? "Payment Sent" : (sendAssetStep.referrer === "payIn" ? "Item Sent" : "Gift Sent"); // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -1346,7 +1363,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_paymentSuccess; - visible: root.assetName === ""; + visible: root.assetCertID === "" && sendAssetStep.referrer !== "payIn"; text: hifi.glyphs.close; color: hifi.colors.lightGrayText; size: 26; @@ -1364,10 +1381,14 @@ Item { parent.text = hifi.glyphs.close; } onClicked: { - root.nextActiveView = "sendAssetHome"; - resetSendAssetData(); - if (root.assetName !== "") { - sendSignalToParent({method: "closeSendAsset"}); + if (sendAssetStep.referrer === "payIn") { + sendToScript({method: "closeSendAsset"}); + } else { + root.nextActiveView = "sendAssetHome"; + resetSendAssetData(); + if (root.assetName !== "") { + sendSignalToParent({method: "closeSendAsset"}); + } } } } @@ -1409,14 +1430,14 @@ Item { userName: sendAssetStep.selectedRecipientUserName; profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; - isDisplayingNearby: sendAssetStep.referrer === "nearby"; + multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; } } Item { id: giftContainer_paymentSuccess; - visible: root.assetName !== ""; + visible: root.assetCertID !== ""; anchors.top: sendToContainer_paymentSuccess.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -1427,7 +1448,7 @@ Item { RalewaySemiBold { id: gift_paymentSuccess; - text: "Gift:"; + text: sendAssetStep.referrer === "payIn" ? "Item:" : "Gift:"; // Anchors anchors.top: parent.top; anchors.left: parent.left; @@ -1458,7 +1479,7 @@ Item { Item { id: amountContainer_paymentSuccess; - visible: root.assetName === ""; + visible: root.assetCertID === ""; anchors.top: sendToContainer_paymentSuccess.bottom; anchors.topMargin: 16; anchors.left: parent.left; @@ -1513,7 +1534,7 @@ Item { RalewaySemiBold { id: optionalMessage_paymentSuccess; - visible: root.assetName === ""; + visible: root.assetCertID === ""; text: optionalMessage.text; // Anchors anchors.top: amountContainer_paymentSuccess.visible ? amountContainer_paymentSuccess.bottom : sendToContainer_paymentSuccess.bottom; @@ -1535,18 +1556,22 @@ Item { HifiControlsUit.Button { id: closeButton; color: hifi.buttons.blue; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 80 : 30; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 80 : 30; height: 50; width: 120; text: "Close"; onClicked: { - root.nextActiveView = "sendAssetHome"; - resetSendAssetData(); - if (root.assetName !== "") { - sendSignalToParent({method: "closeSendAsset"}); + if (sendAssetStep.referrer === "payIn") { + sendToScript({method: "closeSendAsset"}); + } else { + root.nextActiveView = "sendAssetHome"; + resetSendAssetData(); + if (root.assetName !== "") { + sendSignalToParent({method: "closeSendAsset"}); + } } } } @@ -1574,18 +1599,18 @@ Item { Rectangle { anchors.top: parent.top; - anchors.topMargin: root.assetName === "" ? 15 : 150; + anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 150; anchors.left: parent.left; - anchors.leftMargin: root.assetName === "" ? 15 : 50; + anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; anchors.right: parent.right; - anchors.rightMargin: root.assetName === "" ? 15 : 50; + anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 15 : 300; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 300; color: "#FFFFFF"; RalewaySemiBold { id: paymentFailureText; - text: root.assetName === "" ? "Payment Failed" : "Failed"; + text: root.assetCertID === "" && sendAssetStep.referrer !== "payIn" ? "Payment Failed" : "Failed"; // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -1603,7 +1628,7 @@ Item { HiFiGlyphs { id: closeGlyphButton_paymentFailure; - visible: root.assetName === ""; + visible: root.assetCertID === "" && sendAssetStep.referrer !== "payIn"; text: hifi.glyphs.close; color: hifi.colors.lightGrayText; size: 26; @@ -1632,7 +1657,8 @@ Item { RalewaySemiBold { id: paymentFailureDetailText; - text: "The recipient you specified was unable to receive your " + (root.assetName === "" ? "payment." : "gift."); + text: "The recipient you specified was unable to receive your " + + (root.assetCertID === "" ? "payment." : (sendAssetStep.referrer === "payIn" ? "item." : "gift.")); anchors.top: paymentFailureText.bottom; anchors.topMargin: 20; anchors.left: parent.left; @@ -1650,7 +1676,7 @@ Item { Item { id: sendToContainer_paymentFailure; - visible: root.assetName === ""; + visible: root.assetCertID === "" || sendAssetStep.referrer === "payIn"; anchors.top: paymentFailureDetailText.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -1685,13 +1711,13 @@ Item { userName: sendAssetStep.selectedRecipientUserName; profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; - isDisplayingNearby: sendAssetStep.referrer === "nearby"; + multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; } } Item { id: amountContainer_paymentFailure; - visible: root.assetName === ""; + visible: root.assetCertID === ""; anchors.top: sendToContainer_paymentFailure.bottom; anchors.topMargin: 16; anchors.left: parent.left; @@ -1746,7 +1772,7 @@ Item { RalewaySemiBold { id: optionalMessage_paymentFailure; - visible: root.assetName === ""; + visible: root.assetCertID === "" || sendAssetStep.referrer === "payIn"; text: optionalMessage.text; // Anchors anchors.top: amountContainer_paymentFailure.visible ? amountContainer_paymentFailure.bottom : sendToContainer_paymentFailure.bottom; @@ -1768,19 +1794,23 @@ Item { HifiControlsUit.Button { id: closeButton_paymentFailure; color: hifi.buttons.noneBorderless; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.right: retryButton_paymentFailure.left; anchors.rightMargin: 12; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 80 : 30; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 80 : 30; height: 50; width: 120; text: "Cancel"; onClicked: { - root.nextActiveView = "sendAssetHome"; - resetSendAssetData(); - if (root.assetName !== "") { - sendSignalToParent({method: "closeSendAsset"}); + if (sendAssetStep.referrer === "payIn") { + sendToScript({method: "closeSendAsset"}); + } else { + root.nextActiveView = "sendAssetHome"; + resetSendAssetData(); + if (root.assetName !== "") { + sendSignalToParent({method: "closeSendAsset"}); + } } } } @@ -1789,17 +1819,17 @@ Item { HifiControlsUit.Button { id: retryButton_paymentFailure; color: hifi.buttons.blue; - colorScheme: root.assetName === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + colorScheme: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; anchors.right: parent.right; anchors.rightMargin: 12; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetName === "" ? 80 : 30; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 80 : 30; height: 50; width: 120; text: "Retry"; onClicked: { root.isCurrentlySendingAsset = true; - if (sendAssetStep.referrer === "connections") { + if (sendAssetStep.referrer === "connections" || sendAssetStep.referrer === "payIn") { Commerce.transferAssetToUsername(sendAssetStep.selectedRecipientUserName, root.assetCertID, parseInt(amountTextField.text), @@ -1866,11 +1896,32 @@ Item { case 'updateSelectedRecipientUsername': sendAssetStep.selectedRecipientUserName = message.userName; break; + case 'updateSendAssetQML': + root.assetName = ""; + root.assetCertID = message.assetCertID || ""; + if (root.assetCertID === "") { + amountTextField.text = message.amount || 1; + } else { + amountTextField.text = ""; + Commerce.certificateInfo(root.assetCertID); + } + sendAssetStep.referrer = "payIn"; + sendAssetStep.selectedRecipientNodeID = ""; + sendAssetStep.selectedRecipientDisplayName = "Determined by script:"; + sendAssetStep.selectedRecipientUserName = message.username; + optionalMessage.text = message.message || "No Message Provided"; + + root.nextActiveView = "sendAssetStep"; + break; + case 'inspectionCertificate_resetCert': + // NOP + break; default: console.log('SendAsset: Unrecognized message from wallet.js'); } } signal sendSignalToParent(var msg); + signal sendToScript(var message); // // FUNCTION DEFINITIONS END // diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fb6e8ec566..21af28ffcb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -927,7 +927,9 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { #endif DependencyManager::set<DiscoverabilityManager>(); DependencyManager::set<SceneScriptingInterface>(); +#if !defined(DISABLE_QML) DependencyManager::set<OffscreenUi>(); +#endif DependencyManager::set<Midi>(); DependencyManager::set<PathUtils>(); DependencyManager::set<InterfaceDynamicFactory>(); @@ -1000,6 +1002,14 @@ const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false; const QString DEFAULT_CURSOR_NAME = "DEFAULT"; const bool DEFAULT_MINI_TABLET_ENABLED = true; +QSharedPointer<OffscreenUi> getOffscreenUI() { +#if !defined(DISABLE_QML) + return DependencyManager::get<OffscreenUi>(); +#else + return nullptr; +#endif +} + Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runningMarkerExisted) : QApplication(argc, argv), _window(new MainWindow(desktop())), @@ -1604,7 +1614,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto userInputMapper = DependencyManager::get<UserInputMapper>(); connect(userInputMapper.data(), &UserInputMapper::actionEvent, [this](int action, float state) { using namespace controller; - auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); { auto actionEnum = static_cast<Action>(action); @@ -1743,7 +1752,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return qApp->getMyAvatar()->getCharacterController()->onGround() ? 1 : 0; }); _applicationStateDevice->setInputVariant(STATE_NAV_FOCUSED, []() -> float { - return DependencyManager::get<OffscreenUi>()->navigationFocused() ? 1 : 0; + auto offscreenUi = getOffscreenUI(); + return offscreenUi ? (offscreenUi->navigationFocused() ? 1 : 0) : 0; }); _applicationStateDevice->setInputVariant(STATE_PLATFORM_WINDOWS, []() -> float { #if defined(Q_OS_WIN) @@ -1809,9 +1819,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Now that we've loaded the menu and thus switched to the previous display plugin // we can unlock the desktop repositioning code, since all the positions will be // relative to the desktop size for this plugin - auto offscreenUi = DependencyManager::get<OffscreenUi>(); + auto offscreenUi = getOffscreenUI(); connect(offscreenUi.data(), &OffscreenUi::desktopReady, []() { - auto offscreenUi = DependencyManager::get<OffscreenUi>(); + auto offscreenUi = getOffscreenUI(); auto desktop = offscreenUi->getDesktop(); if (desktop) { desktop->setProperty("repositionLocked", false); @@ -2372,6 +2382,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground); AndroidHelper::instance().notifyLoadComplete(); #else +#if !defined(DISABLE_QML) // Do not show login dialog if requested not to on the command line const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "--no-login-suggestion"; int index = arguments().indexOf(HIFI_NO_LOGIN_COMMAND_LINE_KEY); @@ -2396,6 +2407,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo checkLoginTimer->start(); } #endif +#endif } void Application::updateVerboseLogging() { @@ -2546,7 +2558,9 @@ void Application::onAboutToQuit() { DependencyManager::get<CloseEventSender>()->startThread(); // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. - DependencyManager::get<OffscreenUi>()->hide("RunningScripts"); +#if !defined(DISABLE_QML) + getOffscreenUI()->hide("RunningScripts"); +#endif _aboutToQuit = true; @@ -2784,10 +2798,10 @@ void Application::initializeGL() { _glWidget->windowHandle()->setFormat(getDefaultOpenGLSurfaceFormat()); // When loading QtWebEngineWidgets, it creates a global share context on startup. - // We have to account for this possibility by checking here for an existing + // We have to account for this possibility by checking here for an existing // global share context auto globalShareContext = qt_gl_global_share_context(); - + #if !defined(DISABLE_QML) // Build a shared canvas / context for the Chromium processes if (!globalShareContext) { @@ -2974,7 +2988,9 @@ void Application::initializeRenderEngine() { } extern void setupPreferences(); +#if !defined(DISABLE_QML) static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, int index, bool active = false); +#endif void Application::initializeUi() { AddressBarDialog::registerType(); @@ -3024,12 +3040,13 @@ void Application::initializeUi() { tabletScriptingInterface->getTablet(SYSTEM_TABLET); } - auto offscreenUi = DependencyManager::get<OffscreenUi>(); + auto offscreenUi = getOffscreenUI(); connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootContextCreated, this, &Application::onDesktopRootContextCreated); connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootItemCreated, this, &Application::onDesktopRootItemCreated); +#if !defined(DISABLE_QML) offscreenUi->setProxyWindow(_window->windowHandle()); // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to // support the window management and scripting proxies for VR use @@ -3039,9 +3056,13 @@ void Application::initializeUi() { // FIXME either expose so that dialogs can set this themselves or // do better detection in the offscreen UI of what has focus offscreenUi->setNavigationFocused(false); +#else + _window->setMenuBar(new Menu()); +#endif setupPreferences(); +#if !defined(DISABLE_QML) _glWidget->installEventFilter(offscreenUi.data()); offscreenUi->setMouseTranslator([=](const QPointF& pt) { QPointF result = pt; @@ -3054,6 +3075,7 @@ void Application::initializeUi() { return result.toPoint(); }); offscreenUi->resume(); +#endif connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r){ resizeGL(); if (_touchscreenVirtualPadDevice) { @@ -3092,6 +3114,7 @@ void Application::initializeUi() { } }); +#if !defined(DISABLE_QML) // Pre-create a couple of Web3D overlays to speed up tablet UI auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>(); offscreenSurfaceCache->setOnRootContextCreated([&](const QString& rootObject, QQmlContext* surfaceContext) { @@ -3105,9 +3128,11 @@ void Application::initializeUi() { offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1); offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2); +#endif flushMenuUpdates(); +#if !defined(DISABLE_QML) // Now that the menu is instantiated, ensure the display plugin menu is properly updated { auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); @@ -3126,6 +3151,7 @@ void Application::initializeUi() { auto parent = getPrimaryMenu()->getMenu(MenuOption::OutputMenu); parent->addSeparator(); } +#endif // The display plugins are created before the menu now, so we need to do this here to hide the menu bar // now that it exists @@ -3230,12 +3256,12 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { Stats::show(); AnimStats::show(); - auto surfaceContext = DependencyManager::get<OffscreenUi>()->getSurfaceContext(); + auto surfaceContext = getOffscreenUI()->getSurfaceContext(); surfaceContext->setContextProperty("Stats", Stats::getInstance()); surfaceContext->setContextProperty("AnimStats", AnimStats::getInstance()); #if !defined(Q_OS_ANDROID) - auto offscreenUi = DependencyManager::get<OffscreenUi>(); + auto offscreenUi = getOffscreenUI(); auto qml = PathUtils::qmlUrl("AvatarInputsBar.qml"); offscreenUi->show(qml, "AvatarInputsBar"); #endif @@ -3418,7 +3444,7 @@ void Application::setPreferredCursor(const QString& cursorName) { void Application::setSettingConstrainToolbarPosition(bool setting) { _constrainToolbarPosition.set(setting); - DependencyManager::get<OffscreenUi>()->setConstrainToolbarToCenterX(setting); + getOffscreenUI()->setConstrainToolbarToCenterX(setting); } void Application::setMiniTabletEnabled(bool enabled) { @@ -3512,7 +3538,9 @@ void Application::resizeGL() { _myCamera.loadViewFrustum(_viewFrustum); } - DependencyManager::get<OffscreenUi>()->resize(fromGlm(displayPlugin->getRecommendedUiSize())); +#if !defined(DISABLE_QML) + getOffscreenUI()->resize(fromGlm(displayPlugin->getRecommendedUiSize())); +#endif } void Application::handleSandboxStatus(QNetworkReply* reply) { @@ -3912,10 +3940,12 @@ bool Application::eventFilter(QObject* object, QEvent* event) { } if (event->type() == QEvent::ShortcutOverride) { - if (DependencyManager::get<OffscreenUi>()->shouldSwallowShortcut(event)) { +#if !defined(DISABLE_QML) + if (getOffscreenUI()->shouldSwallowShortcut(event)) { event->accept(); return true; } +#endif // Filter out captured keys before they're used for shortcut actions. if (_controllerScriptingInterface->isKeyCaptured(static_cast<QKeyEvent*>(event))) { @@ -3998,7 +4028,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_X: if (isShifted && isMeta) { - auto offscreenUi = DependencyManager::get<OffscreenUi>(); + auto offscreenUi = getOffscreenUI(); offscreenUi->togglePinned(); //offscreenUi->getSurfaceContext()->engine()->clearComponentCache(); //OffscreenUi::information("Debugging", "Component cache cleared"); @@ -4014,7 +4044,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_B: if (isMeta) { - auto offscreenUi = DependencyManager::get<OffscreenUi>(); + auto offscreenUi = getOffscreenUI(); offscreenUi->load("Browser.qml"); } else if (isOption) { controller::InputRecorder* inputRecorder = controller::InputRecorder::getInstance(); @@ -4036,7 +4066,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_R: if (isMeta && !event->isAutoRepeat()) { DependencyManager::get<ScriptEngines>()->reloadAllScripts(); - DependencyManager::get<OffscreenUi>()->clearCache(); + getOffscreenUI()->clearCache(); } break; @@ -4233,9 +4263,13 @@ void Application::mouseMoveEvent(QMouseEvent* event) { return; // bail } - auto offscreenUi = DependencyManager::get<OffscreenUi>(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); auto eventPosition = compositor.getMouseEventPosition(event); - QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition); + QPointF transformedPos = offscreenUi ? offscreenUi->mapToVirtualScreen(eventPosition) : QPointF(); +#else + QPointF transformedPos; +#endif auto button = event->button(); auto buttons = event->buttons(); // Determine if the ReticleClick Action is 1 and if so, fake include the LeftMouseButton @@ -4273,7 +4307,8 @@ void Application::mousePressEvent(QMouseEvent* event) { // Inhibit the menu if the user is using alt-mouse dragging _altPressed = false; - auto offscreenUi = DependencyManager::get<OffscreenUi>(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); // If we get a mouse press event it means it wasn't consumed by the offscreen UI, // hence, we should defocus all of the offscreen UI windows, in order to allow // keyboard shortcuts not to be swallowed by them. In particular, WebEngineViews @@ -4282,6 +4317,9 @@ void Application::mousePressEvent(QMouseEvent* event) { auto eventPosition = getApplicationCompositor().getMouseEventPosition(event); QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition); +#else + QPointF transformedPos; +#endif QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), @@ -4318,9 +4356,13 @@ void Application::mousePressEvent(QMouseEvent* event) { } void Application::mouseDoublePressEvent(QMouseEvent* event) { - auto offscreenUi = DependencyManager::get<OffscreenUi>(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); auto eventPosition = getApplicationCompositor().getMouseEventPosition(event); QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition); +#else + QPointF transformedPos; +#endif QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), @@ -4341,9 +4383,13 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) { void Application::mouseReleaseEvent(QMouseEvent* event) { - auto offscreenUi = DependencyManager::get<OffscreenUi>(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); auto eventPosition = getApplicationCompositor().getMouseEventPosition(event); QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition); +#else + QPointF transformedPos; +#endif QMouseEvent mappedEvent(event->type(), transformedPos, event->screenPos(), event->button(), @@ -4739,7 +4785,8 @@ void Application::idle() { // Update the deadlock watchdog updateHeartbeat(); - auto offscreenUi = DependencyManager::get<OffscreenUi>(); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); // These tasks need to be done on our first idle, because we don't want the showing of // overlay subwindows to do a showDesktop() until after the first time through @@ -4748,6 +4795,7 @@ void Application::idle() { firstIdle = false; connect(offscreenUi.data(), &OffscreenUi::showDesktop, this, &Application::showDesktop); } +#endif #ifdef Q_OS_WIN // If tracing is enabled then monitor the CPU in a separate thread @@ -4764,6 +4812,7 @@ void Application::idle() { #endif auto displayPlugin = getActiveDisplayPlugin(); +#if !defined(DISABLE_QML) if (displayPlugin) { auto uiSize = displayPlugin->getRecommendedUiSize(); // Bit of a hack since there's no device pixel ratio change event I can find. @@ -4772,6 +4821,7 @@ void Application::idle() { offscreenUi->resize(fromGlm(uiSize)); } } +#endif if (displayPlugin) { PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate()); @@ -4806,6 +4856,7 @@ void Application::idle() { float secondsSinceLastUpdate = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_MSEC / MSECS_PER_SECOND; _lastTimeUpdated.start(); +#if !defined(DISABLE_QML) // If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus. if (offscreenUi && offscreenUi->getWindow()) { auto activeFocusItem = offscreenUi->getWindow()->activeFocusItem(); @@ -4817,9 +4868,11 @@ void Application::idle() { _keyboardDeviceHasFocus = true; } } +#endif checkChangeCursor(); +#if !defined(DISABLE_QML) auto stats = Stats::getInstance(); if (stats) { stats->updateStats(); @@ -4828,6 +4881,7 @@ void Application::idle() { if (animStats) { animStats->updateStats(); } +#endif // Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing // details if we're in ExtraDebugging mode. However, the ::update() and its subcomponents will show their timing @@ -5163,7 +5217,9 @@ QVector<EntityItemID> Application::pasteEntities(float x, float y, float z) { void Application::init() { // Make sure Login state is up to date +#if !defined(DISABLE_QML) DependencyManager::get<DialogsManager>()->toggleLoginDialog(); +#endif if (!DISABLE_DEFERRED) { DependencyManager::get<DeferredLightingEffect>()->init(); } @@ -6702,8 +6758,9 @@ void Application::nodeActivated(SharedNodePointer node) { if (node->getType() == NodeType::AssetServer) { // asset server just connected - check if we have the asset browser showing - auto offscreenUi = DependencyManager::get<OffscreenUi>(); - auto assetDialog = offscreenUi->getRootItem()->findChild<QQuickItem*>("AssetServer"); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); + auto assetDialog = offscreenUi ? offscreenUi->getRootItem()->findChild<QQuickItem*>("AssetServer") : nullptr; if (assetDialog) { auto nodeList = DependencyManager::get<NodeList>(); @@ -6716,6 +6773,7 @@ void Application::nodeActivated(SharedNodePointer node) { assetDialog->setVisible(false); } } +#endif } // If we get a new EntityServer activated, reset lastQueried time @@ -6773,13 +6831,15 @@ void Application::nodeKilled(SharedNodePointer node) { } else if (node->getType() == NodeType::AssetServer) { // asset server going away - check if we have the asset browser showing - auto offscreenUi = DependencyManager::get<OffscreenUi>(); - auto assetDialog = offscreenUi->getRootItem()->findChild<QQuickItem*>("AssetServer"); +#if !defined(DISABLE_QML) + auto offscreenUi = getOffscreenUI(); + auto assetDialog = offscreenUi ? offscreenUi->getRootItem()->findChild<QQuickItem*>("AssetServer") : nullptr; if (assetDialog) { // call reload on the shown asset browser dialog QMetaObject::invokeMethod(assetDialog, "clear"); } +#endif } } @@ -6886,8 +6946,10 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe qScriptRegisterMetaType(scriptEngine.data(), RayToOverlayIntersectionResultToScriptValue, RayToOverlayIntersectionResultFromScriptValue); - scriptEngine->registerGlobalObject("OffscreenFlags", DependencyManager::get<OffscreenUi>()->getFlags()); +#if !defined(DISABLE_QML) + scriptEngine->registerGlobalObject("OffscreenFlags", getOffscreenUI()->getFlags()); scriptEngine->registerGlobalObject("Desktop", DependencyManager::get<DesktopScriptingInterface>().data()); +#endif qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue<ToolbarProxy>, wrapperFromScriptValue<ToolbarProxy>); qScriptRegisterMetaType(scriptEngine.data(), @@ -6913,14 +6975,16 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe bool clientScript = scriptEngine->isClientScript(); scriptEngine->registerFunction("OverlayWindow", clientScript ? QmlWindowClass::constructor : QmlWindowClass::restricted_constructor); -#if !defined(Q_OS_ANDROID) +#if !defined(Q_OS_ANDROID) && !defined(DISABLE_QML) scriptEngine->registerFunction("OverlayWebWindow", clientScript ? QmlWebWindowClass::constructor : QmlWebWindowClass::restricted_constructor); #endif scriptEngine->registerFunction("QmlFragment", clientScript ? QmlFragmentClass::constructor : QmlFragmentClass::restricted_constructor); scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("DesktopPreviewProvider", DependencyManager::get<DesktopPreviewProvider>().data()); +#if !defined(DISABLE_QML) scriptEngine->registerGlobalObject("Stats", Stats::getInstance()); +#endif scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); scriptEngine->registerGlobalObject("Snapshot", DependencyManager::get<Snapshot>().data()); scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get<AudioClient>()->getStats().data()); @@ -7116,7 +7180,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { qCDebug(interfaceapp) << "Declined to agree to avatar license"; } - //auto offscreenUi = DependencyManager::get<OffscreenUi>(); + //auto offscreenUi = getOffscreenUI(); }); } else { setAvatar(url, modelName); @@ -7314,7 +7378,9 @@ void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const toggleTabletUI(true); } } else { - DependencyManager::get<OffscreenUi>()->show(widgetUrl, name); +#if !defined(DISABLE_QML) + getOffscreenUI()->show(widgetUrl, name); +#endif } } @@ -7339,10 +7405,10 @@ void Application::showAssetServerWidget(QString filePath) { auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet(SYSTEM_TABLET)); auto hmd = DependencyManager::get<HMDScriptingInterface>(); if (tablet->getToolbarMode()) { - DependencyManager::get<OffscreenUi>()->show(url, "AssetServer", startUpload); + getOffscreenUI()->show(url, "AssetServer", startUpload); } else { if (!hmd->getShouldShowTablet() && !isHMDMode()) { - DependencyManager::get<OffscreenUi>()->show(url, "AssetServer", startUpload); + getOffscreenUI()->show(url, "AssetServer", startUpload); } else { static const QUrl url("hifi/dialogs/TabletAssetServer.qml"); if (!tablet->isPathLoaded(url)) { @@ -7697,7 +7763,7 @@ void Application::addAssetToWorldInfo(QString modelName, QString infoText) { if (!_addAssetToWorldErrorTimer.isActive()) { if (!_addAssetToWorldMessageBox) { - _addAssetToWorldMessageBox = DependencyManager::get<OffscreenUi>()->createMessageBox(OffscreenUi::ICON_INFORMATION, + _addAssetToWorldMessageBox = getOffscreenUI()->createMessageBox(OffscreenUi::ICON_INFORMATION, "Downloading Model", "", QMessageBox::NoButton, QMessageBox::NoButton); connect(_addAssetToWorldMessageBox, SIGNAL(destroyed()), this, SLOT(onAssetToWorldMessageBoxClosed())); } @@ -7780,7 +7846,7 @@ void Application::addAssetToWorldError(QString modelName, QString errorText) { addAssetToWorldInfoClear(modelName); if (!_addAssetToWorldMessageBox) { - _addAssetToWorldMessageBox = DependencyManager::get<OffscreenUi>()->createMessageBox(OffscreenUi::ICON_INFORMATION, + _addAssetToWorldMessageBox = getOffscreenUI()->createMessageBox(OffscreenUi::ICON_INFORMATION, "Downloading Model", "", QMessageBox::NoButton, QMessageBox::NoButton); connect(_addAssetToWorldMessageBox, SIGNAL(destroyed()), this, SLOT(onAssetToWorldMessageBoxClosed())); } @@ -8274,6 +8340,8 @@ DisplayPluginPointer Application::getActiveDisplayPlugin() const { return _displayPlugin; } + +#if !defined(DISABLE_QML) static const char* EXCLUSION_GROUP_KEY = "exclusionGroup"; static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, int index, bool active) { @@ -8314,6 +8382,7 @@ static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, in action->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(displayPluginGroup)); Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name)); } +#endif void Application::updateDisplayMode() { // Unsafe to call this method from anything but the main thread @@ -8358,8 +8427,8 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) { // instead emit a signal that the display plugin is changing and let // the desktop lock itself. Reduces coupling between the UI and display // plugins - auto offscreenUi = DependencyManager::get<OffscreenUi>(); - auto desktop = offscreenUi->getDesktop(); + auto offscreenUi = getOffscreenUI(); + auto desktop = offscreenUi ? offscreenUi->getDesktop() : nullptr; auto menu = Menu::getInstance(); // Make the switch atomic from the perspective of other threads @@ -8405,7 +8474,9 @@ void Application::setDisplayPlugin(DisplayPluginPointer newDisplayPlugin) { } } - offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); + if (offscreenUi) { + offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); + } getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); _displayPlugin = newDisplayPlugin; connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection); diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index a87caeb9a8..646cc53cc0 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -156,12 +156,14 @@ void Application::paintGL() { renderArgs._blitFramebuffer.reset(); renderArgs._context->enableStereo(false); +#if !defined(DISABLE_QML) { auto stats = Stats::getInstance(); if (stats) { stats->setRenderDetails(renderArgs._details); } } +#endif uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; _frameTimingsScriptingInterface.addValue(lastPaintDuration); diff --git a/interface/src/ConnectionMonitor.cpp b/interface/src/ConnectionMonitor.cpp index e86061b090..33d9fddc1b 100644 --- a/interface/src/ConnectionMonitor.cpp +++ b/interface/src/ConnectionMonitor.cpp @@ -48,7 +48,9 @@ void ConnectionMonitor::init() { emit setRedirectErrorState(REDIRECT_HIFI_ADDRESS, "", 5); } else { qDebug() << "ConnectionMonitor: Showing connection failure window"; +#if !defined(DISABLE_QML) DependencyManager::get<DialogsManager>()->setDomainConnectionFailureVisibility(true); +#endif } }); } @@ -59,8 +61,10 @@ void ConnectionMonitor::startTimer() { void ConnectionMonitor::stopTimer() { _timer.stop(); +#if !defined(DISABLE_QML) bool enableInterstitial = DependencyManager::get<NodeList>()->getDomainHandler().getInterstitialModeEnabled(); if (!enableInterstitial) { DependencyManager::get<DialogsManager>()->setDomainConnectionFailureVisibility(false); } +#endif } diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index c4f8ef5ddd..84325da473 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -17,6 +17,7 @@ #include <QTemporaryDir> #include <FSTReader.h> +#include <FBXSerializer.h> #include <OffscreenUi.h> #include "ModelSelector.h" @@ -108,7 +109,7 @@ bool ModelPackager::loadModel() { qCDebug(interfaceapp) << "Reading FBX file : " << _fbxInfo.filePath(); QByteArray fbxContents = fbx.readAll(); - _hfmModel.reset(readFBX(fbxContents, QVariantHash(), _fbxInfo.filePath())); + _hfmModel = FBXSerializer().read(fbxContents, QVariantHash(), _fbxInfo.filePath()); // make sure we have some basic mappings populateBasicMapping(_mapping, _fbxInfo.filePath(), *_hfmModel); diff --git a/interface/src/ModelPackager.h b/interface/src/ModelPackager.h index 09dab5039f..58d3d6bfee 100644 --- a/interface/src/ModelPackager.h +++ b/interface/src/ModelPackager.h @@ -45,7 +45,7 @@ private: QString _scriptDir; QVariantHash _mapping; - std::unique_ptr<hfm::Model> _hfmModel; + std::shared_ptr<hfm::Model> _hfmModel; QStringList _textures; QStringList _scripts; }; diff --git a/interface/src/ModelPropertiesDialog.h b/interface/src/ModelPropertiesDialog.h index 1058dbfa4e..7019d239ff 100644 --- a/interface/src/ModelPropertiesDialog.h +++ b/interface/src/ModelPropertiesDialog.h @@ -14,7 +14,7 @@ #include <QDialog> -#include <FBXReader.h> +#include <hfm/HFM.h> #include <FSTReader.h> #include "ui/ModelsBrowser.h" diff --git a/interface/src/raypick/CollisionPick.cpp b/interface/src/raypick/CollisionPick.cpp index dfb0db1da1..d30f98051e 100644 --- a/interface/src/raypick/CollisionPick.cpp +++ b/interface/src/raypick/CollisionPick.cpp @@ -149,7 +149,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha uint32_t numIndices = (uint32_t)meshPart.triangleIndices.size(); // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up //assert(numIndices % TRIANGLE_STRIDE == 0); - numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader + numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer for (uint32_t j = 0; j < numIndices; j += TRIANGLE_STRIDE) { glm::vec3 p0 = mesh.vertices[meshPart.triangleIndices[j]]; @@ -170,7 +170,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha numIndices = (uint32_t)meshPart.quadIndices.size(); // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up //assert(numIndices % QUAD_STRIDE == 0); - numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXReader + numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer for (uint32_t j = 0; j < numIndices; j += QUAD_STRIDE) { glm::vec3 p0 = mesh.vertices[meshPart.quadIndices[j]]; @@ -305,7 +305,7 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha auto numIndices = meshPart.triangleIndices.count(); // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up //assert(numIndices% TRIANGLE_STRIDE == 0); - numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader + numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer auto indexItr = meshPart.triangleIndices.cbegin(); while (indexItr != meshPart.triangleIndices.cend()) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 2fb40c8c30..26781631db 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -83,7 +83,9 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { // Now render the overlay components together into a single texture renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope +#if !defined(DISABLE_QML) renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts +#endif }); renderArgs->_batch = nullptr; // so future users of renderArgs don't try to use our batch diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 6852691634..46a25a24a7 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -60,7 +60,7 @@ static const float MALLET_TOUCH_Y_OFFSET = 0.050f; static const float MALLET_Y_OFFSET = 0.160f; static const glm::quat MALLET_ROTATION_OFFSET{0.70710678f, 0.0f, -0.70710678f, 0.0f}; -static const glm::vec3 MALLET_MODEL_DIMENSIONS{0.03f, MALLET_LENGTH, 0.03f}; +static const glm::vec3 MALLET_MODEL_DIMENSIONS{0.01f, MALLET_LENGTH, 0.01f}; static const glm::vec3 MALLET_POSITION_OFFSET{0.0f, -MALLET_Y_OFFSET / 2.0f, 0.0f}; static const glm::vec3 MALLET_TIP_OFFSET{0.0f, MALLET_LENGTH - MALLET_TOUCH_Y_OFFSET, 0.0f}; diff --git a/interface/src/ui/OverlayConductor.cpp b/interface/src/ui/OverlayConductor.cpp index da4fdaba44..8edd8ee3a5 100644 --- a/interface/src/ui/OverlayConductor.cpp +++ b/interface/src/ui/OverlayConductor.cpp @@ -74,6 +74,7 @@ void OverlayConductor::centerUI() { } void OverlayConductor::update(float dt) { +#if !defined(DISABLE_QML) auto offscreenUi = DependencyManager::get<OffscreenUi>(); if (!offscreenUi) { return; @@ -115,4 +116,5 @@ void OverlayConductor::update(float dt) { if (shouldRecenter && !_suppressedByHead) { centerUI(); } +#endif } diff --git a/interface/src/ui/OverlayConductor.h b/interface/src/ui/OverlayConductor.h index b47e23d28a..6c3732cf3c 100644 --- a/interface/src/ui/OverlayConductor.h +++ b/interface/src/ui/OverlayConductor.h @@ -25,8 +25,10 @@ private: bool headOutsideOverlay() const; bool updateAvatarIsAtRest(); +#if !defined(DISABLE_QML) bool _suppressedByHead { false }; bool _hmdMode { false }; +#endif // used by updateAvatarIsAtRest uint64_t _desiredAtRestTimer { 0 }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 22b123c85d..17b0895f47 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -232,11 +232,15 @@ OverlayID Overlays::addOverlay(const QString& type, const QVariant& properties) */ if (type == ImageOverlay::TYPE) { +#if !defined(DISABLE_QML) thisOverlay = Overlay::Pointer(new ImageOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); +#endif } else if (type == Image3DOverlay::TYPE || type == "billboard") { // "billboard" for backwards compatibility thisOverlay = Overlay::Pointer(new Image3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); } else if (type == TextOverlay::TYPE) { +#if !defined(DISABLE_QML) thisOverlay = Overlay::Pointer(new TextOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); +#endif } else if (type == Text3DOverlay::TYPE) { thisOverlay = Overlay::Pointer(new Text3DOverlay(), [](Overlay* ptr) { ptr->deleteLater(); }); } else if (type == Shape3DOverlay::TYPE) { diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index ab89eb643d..14f39eedbc 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -15,7 +15,7 @@ #include <glm/glm.hpp> #include <glm/gtc/quaternion.hpp> -#include <FBXReader.h> +#include <FBXSerializer.h> #include "AnimPose.h" class AnimSkeleton { diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 501b9e964d..ec26782d0e 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -71,7 +71,7 @@ void AnimationReader::run() { // Parse the FBX directly from the QNetworkReply HFMModel::Pointer hfmModel; if (_url.path().toLower().endsWith(".fbx")) { - hfmModel.reset(readFBX(_data, QVariantHash(), _url.path())); + hfmModel = FBXSerializer().read(_data, QVariantHash(), _url.path()); } else { QString errorStr("usupported format"); emit onError(299, errorStr); diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 4423e8f18d..d4574d9d3b 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -17,7 +17,7 @@ #include <QtScript/QScriptValue> #include <DependencyManager.h> -#include <FBXReader.h> +#include <FBXSerializer.h> #include <ResourceCache.h> class Animation; diff --git a/libraries/animation/src/AnimationObject.h b/libraries/animation/src/AnimationObject.h index 83880ed2ab..fc3a351832 100644 --- a/libraries/animation/src/AnimationObject.h +++ b/libraries/animation/src/AnimationObject.h @@ -15,7 +15,7 @@ #include <QObject> #include <QScriptable> -#include <FBXReader.h> +#include <FBXSerializer.h> class QScriptEngine; diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h index 8dbc7a75cc..6bfd249bc9 100644 --- a/libraries/audio/src/AudioDynamics.h +++ b/libraries/audio/src/AudioDynamics.h @@ -51,7 +51,7 @@ #include <xmmintrin.h> // convert float to int using round-to-nearest FORCEINLINE static int32_t floatToInt(float x) { - return _mm_cvt_ss2si(_mm_load_ss(&x)); + return _mm_cvt_ss2si(_mm_set_ss(x)); } #else @@ -150,7 +150,7 @@ static const int IEEE754_EXPN_BIAS = 127; // // Peak detection and -log2(x) for float input (mono) // x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff -// x > 2^LOG2_HEADROOM undefined +// x > 2^LOG2_HEADROOM returns 0 // FORCEINLINE static int32_t peaklog2(float* input) { @@ -161,12 +161,12 @@ FORCEINLINE static int32_t peaklog2(float* input) { uint32_t peak = u & IEEE754_FABS_MASK; // split into e and x - 1.0 - int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; + int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; - // saturate - if (e > 31) { - return 0x7fffffff; + // saturate when e > 31 or e < 0 + if ((uint32_t)e > 31) { + return 0x7fffffff & ~(e >> 31); } int k = x >> (31 - LOG2_TABBITS); @@ -186,7 +186,7 @@ FORCEINLINE static int32_t peaklog2(float* input) { // // Peak detection and -log2(x) for float input (stereo) // x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff -// x > 2^LOG2_HEADROOM undefined +// x > 2^LOG2_HEADROOM returns 0 // FORCEINLINE static int32_t peaklog2(float* input0, float* input1) { @@ -200,12 +200,12 @@ FORCEINLINE static int32_t peaklog2(float* input0, float* input1) { uint32_t peak = MAX(u0, u1); // split into e and x - 1.0 - int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; + int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; - // saturate - if (e > 31) { - return 0x7fffffff; + // saturate when e > 31 or e < 0 + if ((uint32_t)e > 31) { + return 0x7fffffff & ~(e >> 31); } int k = x >> (31 - LOG2_TABBITS); @@ -225,7 +225,7 @@ FORCEINLINE static int32_t peaklog2(float* input0, float* input1) { // // Peak detection and -log2(x) for float input (quad) // x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff -// x > 2^LOG2_HEADROOM undefined +// x > 2^LOG2_HEADROOM returns 0 // FORCEINLINE static int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) { @@ -243,12 +243,12 @@ FORCEINLINE static int32_t peaklog2(float* input0, float* input1, float* input2, uint32_t peak = MAX(MAX(u0, u1), MAX(u2, u3)); // split into e and x - 1.0 - int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; + int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; - // saturate - if (e > 31) { - return 0x7fffffff; + // saturate when e > 31 or e < 0 + if ((uint32_t)e > 31) { + return 0x7fffffff & ~(e >> 31); } int k = x >> (31 - LOG2_TABBITS); diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 4af6e79caf..1581990e0c 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -447,9 +447,9 @@ AudioInjectorPointer AudioInjector::playSound(SharedSoundPointer sound, const A using AudioConstants::AudioSample; using AudioConstants::SAMPLE_RATE; const int standardRate = SAMPLE_RATE; - // limit to 4 octaves - const int pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f); - const int resampledRate = SAMPLE_RATE / pitch; + // limit pitch to 4 octaves + const float pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f); + const int resampledRate = glm::round(SAMPLE_RATE / pitch); auto audioData = sound->getAudioData(); auto numChannels = audioData->getNumChannels(); @@ -499,9 +499,9 @@ AudioInjectorPointer AudioInjector::playSound(AudioDataPointer audioData, const using AudioConstants::AudioSample; using AudioConstants::SAMPLE_RATE; const int standardRate = SAMPLE_RATE; - // limit to 4 octaves - const int pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f); - const int resampledRate = SAMPLE_RATE / pitch; + // limit pitch to 4 octaves + const float pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f); + const int resampledRate = glm::round(SAMPLE_RATE / pitch); auto numChannels = audioData->getNumChannels(); auto numFrames = audioData->getNumFrames(); diff --git a/libraries/baking/src/FBXBaker.cpp b/libraries/baking/src/FBXBaker.cpp index cef6c9b900..afaca1dd62 100644 --- a/libraries/baking/src/FBXBaker.cpp +++ b/libraries/baking/src/FBXBaker.cpp @@ -27,7 +27,7 @@ #include <PathUtils.h> -#include <FBXReader.h> +#include <FBXSerializer.h> #include <FBXWriter.h> #include "ModelBakingLoggingCategory.h" @@ -187,10 +187,10 @@ void FBXBaker::importScene() { return; } - FBXReader reader; + FBXSerializer fbxSerializer; qCDebug(model_baking) << "Parsing" << _modelURL; - _rootNode = reader._rootNode = reader.parseFBX(&fbxFile); + _rootNode = fbxSerializer._rootNode = fbxSerializer.parseFBX(&fbxFile); #ifdef HIFI_DUMP_FBX { @@ -206,8 +206,8 @@ void FBXBaker::importScene() { } #endif - _hfmModel = reader.extractHFMModel({}, _modelURL.toString()); - _textureContentMap = reader._textureContent; + _hfmModel = fbxSerializer.extractHFMModel({}, _modelURL.toString()); + _textureContentMap = fbxSerializer._textureContent; } void FBXBaker::rewriteAndBakeSceneModels() { @@ -232,7 +232,7 @@ void FBXBaker::rewriteAndBakeSceneModels() { if (objectChild.name == "Geometry") { // TODO Pull this out of _hfmModel instead so we don't have to reprocess it - auto extractedMesh = FBXReader::extractMesh(objectChild, meshIndex, false); + auto extractedMesh = FBXSerializer::extractMesh(objectChild, meshIndex, false); // Callback to get MaterialID GetMaterialIDCallback materialIDcallback = [&extractedMesh](int partIndex) { diff --git a/libraries/baking/src/ModelBaker.cpp b/libraries/baking/src/ModelBaker.cpp index ca352cebae..34f302b501 100644 --- a/libraries/baking/src/ModelBaker.cpp +++ b/libraries/baking/src/ModelBaker.cpp @@ -13,7 +13,6 @@ #include <PathUtils.h> -#include <FBXReader.h> #include <FBXWriter.h> #ifdef _WIN32 diff --git a/libraries/baking/src/OBJBaker.cpp b/libraries/baking/src/OBJBaker.cpp index d9f56b393e..5a1239f88f 100644 --- a/libraries/baking/src/OBJBaker.cpp +++ b/libraries/baking/src/OBJBaker.cpp @@ -14,7 +14,7 @@ #include <PathUtils.h> #include <NetworkAccessManager.h> -#include "OBJReader.h" +#include "OBJSerializer.h" #include "FBXWriter.h" const double UNIT_SCALE_FACTOR = 100.0; @@ -143,9 +143,10 @@ void OBJBaker::bakeOBJ() { QByteArray objData = objFile.readAll(); - bool combineParts = true; // set true so that OBJReader reads material info from material library - OBJReader reader; - auto geometry = reader.readOBJ(objData, QVariantHash(), combineParts, _modelURL); + OBJSerializer serializer; + QVariantHash mapping; + mapping["combineParts"] = true; // set true so that OBJSerializer reads material info from material library + auto geometry = serializer.read(objData, mapping, _modelURL); // Write OBJ Data as FBX tree nodes createFBXNodeTree(_rootNode, *geometry); @@ -219,7 +220,7 @@ void OBJBaker::createFBXNodeTree(FBXNode& rootNode, HFMModel& hfmModel) { FBXNode materialNode; materialNode.name = MATERIAL_NODE_NAME; if (hfmModel.materials.size() == 1) { - // case when no material information is provided, OBJReader considers it as a single default material + // case when no material information is provided, OBJSerializer considers it as a single default material for (auto& materialID : hfmModel.materials.keys()) { setMaterialNodeProperties(materialNode, materialID, hfmModel); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 9a68f81b66..2b1d70f4d0 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -421,7 +421,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { uint32_t numIndices = (uint32_t)meshPart.triangleIndices.size(); // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up //assert(numIndices % TRIANGLE_STRIDE == 0); - numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader + numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer for (uint32_t j = 0; j < numIndices; j += TRIANGLE_STRIDE) { glm::vec3 p0 = mesh.vertices[meshPart.triangleIndices[j]]; @@ -442,7 +442,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { numIndices = (uint32_t)meshPart.quadIndices.size(); // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up //assert(numIndices % QUAD_STRIDE == 0); - numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXReader + numIndices -= numIndices % QUAD_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer for (uint32_t j = 0; j < numIndices; j += QUAD_STRIDE) { glm::vec3 p0 = mesh.vertices[meshPart.quadIndices[j]]; @@ -595,7 +595,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { if (partItr->_topology == graphics::Mesh::TRIANGLES) { // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up //assert(numIndices % TRIANGLE_STRIDE == 0); - numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader + numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer auto indexItr = indices.cbegin<const gpu::BufferView::Index>() + partItr->_startIndex; auto indexEnd = indexItr + numIndices; @@ -652,7 +652,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { if (partItr->_topology == graphics::Mesh::TRIANGLES) { // TODO: assert rather than workaround after we start sanitizing HFMMesh higher up //assert(numIndices% TRIANGLE_STRIDE == 0); - numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXReader + numIndices -= numIndices % TRIANGLE_STRIDE; // WORKAROUND lack of sanity checking in FBXSerializer auto indexItr = indices.cbegin<const gpu::BufferView::Index>() + partItr->_startIndex; auto indexEnd = indexItr + numIndices; diff --git a/libraries/fbx/src/FBX.h b/libraries/fbx/src/FBX.h index 90de82e310..157ca5b282 100644 --- a/libraries/fbx/src/FBX.h +++ b/libraries/fbx/src/FBX.h @@ -33,7 +33,7 @@ using NormalType = glm::vec3; #define FBX_NORMAL_ELEMENT gpu::Element::VEC3F_XYZ #endif -// See comment in FBXReader::parseFBX(). +// See comment in FBXSerializer::parseFBX(). static const int FBX_HEADER_BYTES_BEFORE_VERSION = 23; static const QByteArray FBX_BINARY_PROLOG("Kaydara FBX Binary "); static const QByteArray FBX_BINARY_PROLOG2("\0\x1a\0", 3); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXSerializer.cpp similarity index 98% rename from libraries/fbx/src/FBXReader.cpp rename to libraries/fbx/src/FBXSerializer.cpp index dd10cd30b3..a9887cde15 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -1,6 +1,6 @@ // -// FBXReader.cpp -// interface/src/renderer +// FBXSerializer.cpp +// libraries/fbx/src // // Created by Andrzej Kapolka on 9/18/13. // Copyright 2013 High Fidelity, Inc. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "FBXReader.h" +#include "FBXSerializer.h" #include <iostream> #include <QBuffer> @@ -36,7 +36,7 @@ #include <hfm/ModelFormatLogging.h> // TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems... -//#define DEBUG_FBXREADER +//#define DEBUG_FBXSERIALIZER using namespace std; @@ -254,13 +254,13 @@ HFMBlendshape extractBlendshape(const FBXNode& object) { HFMBlendshape blendshape; foreach (const FBXNode& data, object.children) { if (data.name == "Indexes") { - blendshape.indices = FBXReader::getIntVector(data); + blendshape.indices = FBXSerializer::getIntVector(data); } else if (data.name == "Vertices") { - blendshape.vertices = FBXReader::createVec3Vector(FBXReader::getDoubleVector(data)); + blendshape.vertices = FBXSerializer::createVec3Vector(FBXSerializer::getDoubleVector(data)); } else if (data.name == "Normals") { - blendshape.normals = FBXReader::createVec3Vector(FBXReader::getDoubleVector(data)); + blendshape.normals = FBXSerializer::createVec3Vector(FBXSerializer::getDoubleVector(data)); } } return blendshape; @@ -384,7 +384,7 @@ HFMLight extractLight(const FBXNode& object) { if (propname == "Intensity") { light.intensity = 0.01f * property.properties.at(valIndex).value<float>(); } else if (propname == "Color") { - light.color = FBXReader::getVec3(property.properties, valIndex); + light.color = FBXSerializer::getVec3(property.properties, valIndex); } } } @@ -392,7 +392,7 @@ HFMLight extractLight(const FBXNode& object) { || subobject.name == "TypeFlags") { } } -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) QString type = object.properties.at(0).toString(); type = object.properties.at(1).toString(); @@ -441,7 +441,7 @@ QMap<QString, glm::quat> getJointRotationOffsets(const QVariantHash& mapping) { return jointRotationOffsets; } -HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& url) { +HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QString& url) { const FBXNode& node = _rootNode; QMap<QString, ExtractedMesh> meshes; QHash<QString, QString> modelIDsToNames; @@ -512,7 +512,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& } } QMultiHash<QString, WeightedIndex> blendshapeChannelIndices; -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) int unknown = 0; #endif HFMModel* hfmModelPtr = new HFMModel; @@ -760,7 +760,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& extractBlendshape(subobject) }; blendshapes.append(blendshape); } -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) else if (subobject.name == "TypeFlags") { QString attributetype = subobject.properties.at(0).toString(); if (!attributetype.empty()) { @@ -886,7 +886,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& tex.scaling.z = 1.0f; } } -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) else { QString propName = v; unknown++; @@ -895,7 +895,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& } } } -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) else { if (subobject.name == "Type") { } else if (subobject.name == "Version") { @@ -1068,7 +1068,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& } } } -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) else { QString propname = subobject.name.data(); int unknown = 0; @@ -1085,7 +1085,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& } else if (object.name == "NodeAttribute") { -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) std::vector<QString> properties; foreach(const QVariant& v, object.properties) { properties.push_back(v.toString()); @@ -1148,7 +1148,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& animationCurves.insert(getID(object.properties), curve); } -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) else { QString objectname = object.name.data(); if ( objectname == "Pose" @@ -1239,7 +1239,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& } } } -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) else { QString objectname = child.name.data(); if ( objectname == "Pose" @@ -1833,17 +1833,11 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& return hfmModelPtr; } -HFMModel* readFBX(const QByteArray& data, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { +HFMModel::Pointer FBXSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) { QBuffer buffer(const_cast<QByteArray*>(&data)); buffer.open(QIODevice::ReadOnly); - return readFBX(&buffer, mapping, url, loadLightmaps, lightmapLevel); -} -HFMModel* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url, bool loadLightmaps, float lightmapLevel) { - FBXReader reader; - reader._rootNode = FBXReader::parseFBX(device); - reader._loadLightmaps = loadLightmaps; - reader._lightmapLevel = lightmapLevel; + _rootNode = parseFBX(&buffer); - return reader.extractHFMModel(mapping, url); + return HFMModel::Pointer(extractHFMModel(mapping, url.toString())); } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXSerializer.h similarity index 85% rename from libraries/fbx/src/FBXReader.h rename to libraries/fbx/src/FBXSerializer.h index c74b4dc8ac..c69f75cc5c 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXSerializer.h @@ -1,6 +1,6 @@ // -// FBXReader.h -// interface/src/renderer +// FBXSerializer.h +// libraries/fbx/src // // Created by Andrzej Kapolka on 9/18/13. // Copyright 2013 High Fidelity, Inc. @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_FBXReader_h -#define hifi_FBXReader_h +#ifndef hifi_FBXSerializer_h +#define hifi_FBXSerializer_h #include <QtGlobal> #include <QMetaType> @@ -27,7 +27,7 @@ #include <Transform.h> #include "FBX.h" -#include <hfm/HFM.h> +#include <hfm/HFMSerializer.h> #include <graphics/Geometry.h> #include <graphics/Material.h> @@ -35,14 +35,6 @@ class QIODevice; class FBXNode; -/// Reads HFMModel from the supplied model and mapping data. -/// \exception QString if an error occurs in parsing -HFMModel* readFBX(const QByteArray& data, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); - -/// Reads HFMModel from the supplied model and mapping data. -/// \exception QString if an error occurs in parsing -HFMModel* readFBX(QIODevice* device, const QVariantHash& mapping, const QString& url = "", bool loadLightmaps = true, float lightmapLevel = 1.0f); - class TextureParam { public: glm::vec2 UVTranslation; @@ -102,9 +94,12 @@ public: class ExtractedMesh; -class FBXReader { +class FBXSerializer : public HFMSerializer { public: HFMModel* _hfmModel; + /// Reads HFMModel from the supplied model and mapping data. + /// \exception QString if an error occurs in parsing + HFMModel::Pointer read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url = QUrl()) override; FBXNode _rootNode; static FBXNode parseFBX(QIODevice* device); @@ -147,9 +142,9 @@ public: void consolidateHFMMaterials(const QVariantHash& mapping); - bool _loadLightmaps = true; - float _lightmapOffset = 0.0f; - float _lightmapLevel; + bool _loadLightmaps { true }; + float _lightmapOffset { 0.0f }; + float _lightmapLevel { 1.0f }; QMultiMap<QString, QString> _connectionParentMap; QMultiMap<QString, QString> _connectionChildMap; @@ -166,4 +161,4 @@ public: static QVector<double> getDoubleVector(const FBXNode& node); }; -#endif // hifi_FBXReader_h +#endif // hifi_FBXSerializer_h diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXSerializer_Material.cpp similarity index 98% rename from libraries/fbx/src/FBXReader_Material.cpp rename to libraries/fbx/src/FBXSerializer_Material.cpp index 2ec8cfde75..7713b36e57 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXSerializer_Material.cpp @@ -1,5 +1,5 @@ // -// FBXReader_Material.cpp +// FBXSerializer_Material.cpp // interface/src/fbx // // Created by Sam Gateau on 8/27/2015. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "FBXReader.h" +#include "FBXSerializer.h" #include <iostream> #include <memory> @@ -27,7 +27,7 @@ #include <hfm/ModelFormatLogging.h> -HFMTexture FBXReader::getTexture(const QString& textureID) { +HFMTexture FBXSerializer::getTexture(const QString& textureID) { HFMTexture texture; const QByteArray& filepath = _textureFilepaths.value(textureID); texture.content = _textureContent.value(filepath); @@ -69,7 +69,7 @@ HFMTexture FBXReader::getTexture(const QString& textureID) { return texture; } -void FBXReader::consolidateHFMMaterials(const QVariantHash& mapping) { +void FBXSerializer::consolidateHFMMaterials(const QVariantHash& mapping) { QString materialMapString = mapping.value("materialMap").toString(); QJsonDocument materialMapDocument = QJsonDocument::fromJson(materialMapString.toUtf8()); diff --git a/libraries/fbx/src/FBXReader_Mesh.cpp b/libraries/fbx/src/FBXSerializer_Mesh.cpp similarity index 98% rename from libraries/fbx/src/FBXReader_Mesh.cpp rename to libraries/fbx/src/FBXSerializer_Mesh.cpp index 527e3aef75..38533dbc42 100644 --- a/libraries/fbx/src/FBXReader_Mesh.cpp +++ b/libraries/fbx/src/FBXSerializer_Mesh.cpp @@ -1,5 +1,5 @@ // -// FBXReader_Mesh.cpp +// FBXSerializer_Mesh.cpp // interface/src/fbx // // Created by Sam Gateau on 8/27/2015. @@ -33,7 +33,7 @@ #include <LogHandler.h> #include <hfm/ModelFormatLogging.h> -#include "FBXReader.h" +#include "FBXSerializer.h" #include <memory> @@ -191,7 +191,7 @@ void appendIndex(MeshData& data, QVector<int>& indices, int index, bool deduplic } } -ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate) { +ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate) { MeshData data; data.extracted.mesh.meshIndex = meshIndex++; @@ -254,7 +254,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn data.colorsByVertex = true; } -#if defined(FBXREADER_KILL_BLACK_COLOR_ATTRIBUTE) +#if defined(FBXSERIALIZER_KILL_BLACK_COLOR_ATTRIBUTE) // Potential feature where we decide to kill the color attribute is to dark? // Tested with the model: // https://hifi-public.s3.amazonaws.com/ryan/gardenLight2.fbx @@ -281,7 +281,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn } else if (subdata.name == "Name") { attrib.name = subdata.properties.at(0).toString(); } -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) else { int unknown = 0; QString subname = subdata.name.data(); @@ -307,7 +307,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn } else if (subdata.name == "Name") { attrib.name = subdata.properties.at(0).toString(); } -#if defined(DEBUG_FBXREADER) +#if defined(DEBUG_FBXSERIALIZER) else { int unknown = 0; QString subname = subdata.name.data(); @@ -557,7 +557,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn return data.extracted; } -glm::vec3 FBXReader::normalizeDirForPacking(const glm::vec3& dir) { +glm::vec3 FBXSerializer::normalizeDirForPacking(const glm::vec3& dir) { auto maxCoord = glm::max(fabsf(dir.x), glm::max(fabsf(dir.y), fabsf(dir.z))); if (maxCoord > 1e-6f) { return dir / maxCoord; @@ -565,7 +565,7 @@ glm::vec3 FBXReader::normalizeDirForPacking(const glm::vec3& dir) { return dir; } -void FBXReader::buildModelMesh(HFMMesh& extractedMesh, const QString& url) { +void FBXSerializer::buildModelMesh(HFMMesh& extractedMesh, const QString& url) { unsigned int totalSourceIndices = 0; foreach(const HFMMeshPart& part, extractedMesh.parts) { totalSourceIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size()); diff --git a/libraries/fbx/src/FBXReader_Node.cpp b/libraries/fbx/src/FBXSerializer_Node.cpp similarity index 94% rename from libraries/fbx/src/FBXReader_Node.cpp rename to libraries/fbx/src/FBXSerializer_Node.cpp index cd717998dd..c982dfc7cb 100644 --- a/libraries/fbx/src/FBXReader_Node.cpp +++ b/libraries/fbx/src/FBXSerializer_Node.cpp @@ -1,5 +1,5 @@ // -// FBXReader_Node.cpp +// FBXSerializer_Node.cpp // interface/src/fbx // // Created by Sam Gateau on 8/27/2015. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "FBXReader.h" +#include "FBXSerializer.h" #include <iostream> #include <QtCore/QBuffer> @@ -345,7 +345,7 @@ FBXNode parseTextFBXNode(Tokenizer& tokenizer) { return node; } -FBXNode FBXReader::parseFBX(QIODevice* device) { +FBXNode FBXSerializer::parseFBX(QIODevice* device) { PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xff0000ff, device); // verify the prolog if (device->peek(FBX_BINARY_PROLOG.size()) != FBX_BINARY_PROLOG) { @@ -398,12 +398,12 @@ FBXNode FBXReader::parseFBX(QIODevice* device) { } -glm::vec3 FBXReader::getVec3(const QVariantList& properties, int index) { +glm::vec3 FBXSerializer::getVec3(const QVariantList& properties, int index) { return glm::vec3(properties.at(index).value<double>(), properties.at(index + 1).value<double>(), properties.at(index + 2).value<double>()); } -QVector<glm::vec4> FBXReader::createVec4Vector(const QVector<double>& doubleVector) { +QVector<glm::vec4> FBXSerializer::createVec4Vector(const QVector<double>& doubleVector) { QVector<glm::vec4> values; for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) { float x = *it++; @@ -416,7 +416,7 @@ QVector<glm::vec4> FBXReader::createVec4Vector(const QVector<double>& doubleVect } -QVector<glm::vec4> FBXReader::createVec4VectorRGBA(const QVector<double>& doubleVector, glm::vec4& average) { +QVector<glm::vec4> FBXSerializer::createVec4VectorRGBA(const QVector<double>& doubleVector, glm::vec4& average) { QVector<glm::vec4> values; for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 4) * 4); it != end; ) { float x = *it++; @@ -433,7 +433,7 @@ QVector<glm::vec4> FBXReader::createVec4VectorRGBA(const QVector<double>& double return values; } -QVector<glm::vec3> FBXReader::createVec3Vector(const QVector<double>& doubleVector) { +QVector<glm::vec3> FBXSerializer::createVec3Vector(const QVector<double>& doubleVector) { QVector<glm::vec3> values; for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 3) * 3); it != end; ) { float x = *it++; @@ -444,7 +444,7 @@ QVector<glm::vec3> FBXReader::createVec3Vector(const QVector<double>& doubleVect return values; } -QVector<glm::vec2> FBXReader::createVec2Vector(const QVector<double>& doubleVector) { +QVector<glm::vec2> FBXSerializer::createVec2Vector(const QVector<double>& doubleVector) { QVector<glm::vec2> values; for (const double* it = doubleVector.constData(), *end = it + ((doubleVector.size() / 2) * 2); it != end; ) { float s = *it++; @@ -454,14 +454,14 @@ QVector<glm::vec2> FBXReader::createVec2Vector(const QVector<double>& doubleVect return values; } -glm::mat4 FBXReader::createMat4(const QVector<double>& doubleVector) { +glm::mat4 FBXSerializer::createMat4(const QVector<double>& doubleVector) { return glm::mat4(doubleVector.at(0), doubleVector.at(1), doubleVector.at(2), doubleVector.at(3), doubleVector.at(4), doubleVector.at(5), doubleVector.at(6), doubleVector.at(7), doubleVector.at(8), doubleVector.at(9), doubleVector.at(10), doubleVector.at(11), doubleVector.at(12), doubleVector.at(13), doubleVector.at(14), doubleVector.at(15)); } -QVector<int> FBXReader::getIntVector(const FBXNode& node) { +QVector<int> FBXSerializer::getIntVector(const FBXNode& node) { foreach (const FBXNode& child, node.children) { if (child.name == "a") { return getIntVector(child); @@ -480,7 +480,7 @@ QVector<int> FBXReader::getIntVector(const FBXNode& node) { return vector; } -QVector<float> FBXReader::getFloatVector(const FBXNode& node) { +QVector<float> FBXSerializer::getFloatVector(const FBXNode& node) { foreach (const FBXNode& child, node.children) { if (child.name == "a") { return getFloatVector(child); @@ -499,7 +499,7 @@ QVector<float> FBXReader::getFloatVector(const FBXNode& node) { return vector; } -QVector<double> FBXReader::getDoubleVector(const FBXNode& node) { +QVector<double> FBXSerializer::getDoubleVector(const FBXNode& node) { foreach (const FBXNode& child, node.children) { if (child.name == "a") { return getDoubleVector(child); diff --git a/libraries/fbx/src/GLTFReader.cpp b/libraries/fbx/src/GLTFSerializer.cpp similarity index 93% rename from libraries/fbx/src/GLTFReader.cpp rename to libraries/fbx/src/GLTFSerializer.cpp index eb763cce90..28d377c605 100644 --- a/libraries/fbx/src/GLTFReader.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1,5 +1,5 @@ // -// GLTFReader.cpp +// GLTFSerializer.cpp // libraries/fbx/src // // Created by Luis Cuenca on 8/30/17. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "GLTFReader.h" +#include "GLTFSerializer.h" #include <QtCore/QBuffer> #include <QtCore/QIODevice> @@ -33,14 +33,14 @@ #include <ResourceManager.h> #include <PathUtils.h> -#include "FBXReader.h" +#include "FBXSerializer.h" -GLTFReader::GLTFReader() { +GLTFSerializer::GLTFSerializer() { } -bool GLTFReader::getStringVal(const QJsonObject& object, const QString& fieldname, +bool GLTFSerializer::getStringVal(const QJsonObject& object, const QString& fieldname, QString& value, QMap<QString, bool>& defined) { bool _defined = (object.contains(fieldname) && object[fieldname].isString()); if (_defined) { @@ -50,7 +50,7 @@ bool GLTFReader::getStringVal(const QJsonObject& object, const QString& fieldnam return _defined; } -bool GLTFReader::getBoolVal(const QJsonObject& object, const QString& fieldname, +bool GLTFSerializer::getBoolVal(const QJsonObject& object, const QString& fieldname, bool& value, QMap<QString, bool>& defined) { bool _defined = (object.contains(fieldname) && object[fieldname].isBool()); if (_defined) { @@ -60,7 +60,7 @@ bool GLTFReader::getBoolVal(const QJsonObject& object, const QString& fieldname, return _defined; } -bool GLTFReader::getIntVal(const QJsonObject& object, const QString& fieldname, +bool GLTFSerializer::getIntVal(const QJsonObject& object, const QString& fieldname, int& value, QMap<QString, bool>& defined) { bool _defined = (object.contains(fieldname) && !object[fieldname].isNull()); if (_defined) { @@ -70,7 +70,7 @@ bool GLTFReader::getIntVal(const QJsonObject& object, const QString& fieldname, return _defined; } -bool GLTFReader::getDoubleVal(const QJsonObject& object, const QString& fieldname, +bool GLTFSerializer::getDoubleVal(const QJsonObject& object, const QString& fieldname, double& value, QMap<QString, bool>& defined) { bool _defined = (object.contains(fieldname) && object[fieldname].isDouble()); if (_defined) { @@ -79,7 +79,7 @@ bool GLTFReader::getDoubleVal(const QJsonObject& object, const QString& fieldnam defined.insert(fieldname, _defined); return _defined; } -bool GLTFReader::getObjectVal(const QJsonObject& object, const QString& fieldname, +bool GLTFSerializer::getObjectVal(const QJsonObject& object, const QString& fieldname, QJsonObject& value, QMap<QString, bool>& defined) { bool _defined = (object.contains(fieldname) && object[fieldname].isObject()); if (_defined) { @@ -89,7 +89,7 @@ bool GLTFReader::getObjectVal(const QJsonObject& object, const QString& fieldnam return _defined; } -bool GLTFReader::getIntArrayVal(const QJsonObject& object, const QString& fieldname, +bool GLTFSerializer::getIntArrayVal(const QJsonObject& object, const QString& fieldname, QVector<int>& values, QMap<QString, bool>& defined) { bool _defined = (object.contains(fieldname) && object[fieldname].isArray()); if (_defined) { @@ -104,7 +104,7 @@ bool GLTFReader::getIntArrayVal(const QJsonObject& object, const QString& fieldn return _defined; } -bool GLTFReader::getDoubleArrayVal(const QJsonObject& object, const QString& fieldname, +bool GLTFSerializer::getDoubleArrayVal(const QJsonObject& object, const QString& fieldname, QVector<double>& values, QMap<QString, bool>& defined) { bool _defined = (object.contains(fieldname) && object[fieldname].isArray()); if (_defined) { @@ -119,7 +119,7 @@ bool GLTFReader::getDoubleArrayVal(const QJsonObject& object, const QString& fie return _defined; } -bool GLTFReader::getObjectArrayVal(const QJsonObject& object, const QString& fieldname, +bool GLTFSerializer::getObjectArrayVal(const QJsonObject& object, const QString& fieldname, QJsonArray& objects, QMap<QString, bool>& defined) { bool _defined = (object.contains(fieldname) && object[fieldname].isArray()); if (_defined) { @@ -129,7 +129,7 @@ bool GLTFReader::getObjectArrayVal(const QJsonObject& object, const QString& fie return _defined; } -int GLTFReader::getMeshPrimitiveRenderingMode(const QString& type) +int GLTFSerializer::getMeshPrimitiveRenderingMode(const QString& type) { if (type == "POINTS") { return GLTFMeshPrimitivesRenderingMode::POINTS; @@ -155,7 +155,7 @@ int GLTFReader::getMeshPrimitiveRenderingMode(const QString& type) return GLTFMeshPrimitivesRenderingMode::TRIANGLES; } -int GLTFReader::getAccessorType(const QString& type) +int GLTFSerializer::getAccessorType(const QString& type) { if (type == "SCALAR") { return GLTFAccessorType::SCALAR; @@ -181,7 +181,7 @@ int GLTFReader::getAccessorType(const QString& type) return GLTFAccessorType::SCALAR; } -int GLTFReader::getMaterialAlphaMode(const QString& type) +int GLTFSerializer::getMaterialAlphaMode(const QString& type) { if (type == "OPAQUE") { return GLTFMaterialAlphaMode::OPAQUE; @@ -195,7 +195,7 @@ int GLTFReader::getMaterialAlphaMode(const QString& type) return GLTFMaterialAlphaMode::OPAQUE; } -int GLTFReader::getCameraType(const QString& type) +int GLTFSerializer::getCameraType(const QString& type) { if (type == "orthographic") { return GLTFCameraTypes::ORTHOGRAPHIC; @@ -206,7 +206,7 @@ int GLTFReader::getCameraType(const QString& type) return GLTFCameraTypes::PERSPECTIVE; } -int GLTFReader::getImageMimeType(const QString& mime) +int GLTFSerializer::getImageMimeType(const QString& mime) { if (mime == "image/jpeg") { return GLTFImageMimetype::JPEG; @@ -217,7 +217,7 @@ int GLTFReader::getImageMimeType(const QString& mime) return GLTFImageMimetype::JPEG; } -int GLTFReader::getAnimationSamplerInterpolation(const QString& interpolation) +int GLTFSerializer::getAnimationSamplerInterpolation(const QString& interpolation) { if (interpolation == "LINEAR") { return GLTFAnimationSamplerInterpolation::LINEAR; @@ -225,7 +225,7 @@ int GLTFReader::getAnimationSamplerInterpolation(const QString& interpolation) return GLTFAnimationSamplerInterpolation::LINEAR; } -bool GLTFReader::setAsset(const QJsonObject& object) { +bool GLTFSerializer::setAsset(const QJsonObject& object) { QJsonObject jsAsset; bool isAssetDefined = getObjectVal(object, "asset", jsAsset, _file.defined); if (isAssetDefined) { @@ -239,7 +239,7 @@ bool GLTFReader::setAsset(const QJsonObject& object) { return isAssetDefined; } -bool GLTFReader::addAccessor(const QJsonObject& object) { +bool GLTFSerializer::addAccessor(const QJsonObject& object) { GLTFAccessor accessor; getIntVal(object, "bufferView", accessor.bufferView, accessor.defined); @@ -259,7 +259,7 @@ bool GLTFReader::addAccessor(const QJsonObject& object) { return true; } -bool GLTFReader::addAnimation(const QJsonObject& object) { +bool GLTFSerializer::addAnimation(const QJsonObject& object) { GLTFAnimation animation; QJsonArray channels; @@ -297,7 +297,7 @@ bool GLTFReader::addAnimation(const QJsonObject& object) { return true; } -bool GLTFReader::addBufferView(const QJsonObject& object) { +bool GLTFSerializer::addBufferView(const QJsonObject& object) { GLTFBufferView bufferview; getIntVal(object, "buffer", bufferview.buffer, bufferview.defined); @@ -310,7 +310,7 @@ bool GLTFReader::addBufferView(const QJsonObject& object) { return true; } -bool GLTFReader::addBuffer(const QJsonObject& object) { +bool GLTFSerializer::addBuffer(const QJsonObject& object) { GLTFBuffer buffer; getIntVal(object, "byteLength", buffer.byteLength, buffer.defined); @@ -324,7 +324,7 @@ bool GLTFReader::addBuffer(const QJsonObject& object) { return true; } -bool GLTFReader::addCamera(const QJsonObject& object) { +bool GLTFSerializer::addCamera(const QJsonObject& object) { GLTFCamera camera; QJsonObject jsPerspective; @@ -352,7 +352,7 @@ bool GLTFReader::addCamera(const QJsonObject& object) { return true; } -bool GLTFReader::addImage(const QJsonObject& object) { +bool GLTFSerializer::addImage(const QJsonObject& object) { GLTFImage image; QString mime; @@ -367,7 +367,7 @@ bool GLTFReader::addImage(const QJsonObject& object) { return true; } -bool GLTFReader::getIndexFromObject(const QJsonObject& object, const QString& field, +bool GLTFSerializer::getIndexFromObject(const QJsonObject& object, const QString& field, int& outidx, QMap<QString, bool>& defined) { QJsonObject subobject; if (getObjectVal(object, field, subobject, defined)) { @@ -377,7 +377,7 @@ bool GLTFReader::getIndexFromObject(const QJsonObject& object, const QString& fi return false; } -bool GLTFReader::addMaterial(const QJsonObject& object) { +bool GLTFSerializer::addMaterial(const QJsonObject& object) { GLTFMaterial material; getStringVal(object, "name", material.name, material.defined); @@ -413,7 +413,7 @@ bool GLTFReader::addMaterial(const QJsonObject& object) { return true; } -bool GLTFReader::addMesh(const QJsonObject& object) { +bool GLTFSerializer::addMesh(const QJsonObject& object) { GLTFMesh mesh; getStringVal(object, "name", mesh.name, mesh.defined); @@ -467,7 +467,7 @@ bool GLTFReader::addMesh(const QJsonObject& object) { return true; } -bool GLTFReader::addNode(const QJsonObject& object) { +bool GLTFSerializer::addNode(const QJsonObject& object) { GLTFNode node; getStringVal(object, "name", node.name, node.defined); @@ -487,7 +487,7 @@ bool GLTFReader::addNode(const QJsonObject& object) { return true; } -bool GLTFReader::addSampler(const QJsonObject& object) { +bool GLTFSerializer::addSampler(const QJsonObject& object) { GLTFSampler sampler; getIntVal(object, "magFilter", sampler.magFilter, sampler.defined); @@ -501,7 +501,7 @@ bool GLTFReader::addSampler(const QJsonObject& object) { } -bool GLTFReader::addScene(const QJsonObject& object) { +bool GLTFSerializer::addScene(const QJsonObject& object) { GLTFScene scene; getStringVal(object, "name", scene.name, scene.defined); @@ -511,7 +511,7 @@ bool GLTFReader::addScene(const QJsonObject& object) { return true; } -bool GLTFReader::addSkin(const QJsonObject& object) { +bool GLTFSerializer::addSkin(const QJsonObject& object) { GLTFSkin skin; getIntVal(object, "inverseBindMatrices", skin.inverseBindMatrices, skin.defined); @@ -523,7 +523,7 @@ bool GLTFReader::addSkin(const QJsonObject& object) { return true; } -bool GLTFReader::addTexture(const QJsonObject& object) { +bool GLTFSerializer::addTexture(const QJsonObject& object) { GLTFTexture texture; getIntVal(object, "sampler", texture.sampler, texture.defined); getIntVal(object, "source", texture.source, texture.defined); @@ -533,7 +533,7 @@ bool GLTFReader::addTexture(const QJsonObject& object) { return true; } -bool GLTFReader::parseGLTF(const QByteArray& data) { +bool GLTFSerializer::parseGLTF(const QByteArray& data) { PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr); QJsonDocument d = QJsonDocument::fromJson(data); @@ -664,7 +664,7 @@ bool GLTFReader::parseGLTF(const QByteArray& data) { return true; } -glm::mat4 GLTFReader::getModelTransform(const GLTFNode& node) { +glm::mat4 GLTFSerializer::getModelTransform(const GLTFNode& node) { glm::mat4 tmat = glm::mat4(1.0); if (node.defined["matrix"] && node.matrix.size() == 16) { @@ -697,7 +697,7 @@ glm::mat4 GLTFReader::getModelTransform(const GLTFNode& node) { return tmat; } -bool GLTFReader::buildGeometry(HFMModel& hfmModel, const QUrl& url) { +bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const QUrl& url) { //Build dependencies QVector<QVector<int>> nodeDependencies(_file.nodes.size()); @@ -899,7 +899,7 @@ bool GLTFReader::buildGeometry(HFMModel& hfmModel, const QUrl& url) { } mesh.meshIndex = hfmModel.meshes.size(); - FBXReader::buildModelMesh(mesh, url.toString()); + FBXSerializer::buildModelMesh(mesh, url.toString()); } } @@ -910,13 +910,12 @@ bool GLTFReader::buildGeometry(HFMModel& hfmModel, const QUrl& url) { return true; } -HFMModel* GLTFReader::readGLTF(QByteArray& data, const QVariantHash& mapping, - const QUrl& url, bool loadLightmaps, float lightmapLevel) { +HFMModel::Pointer GLTFSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) { _url = url; // Normalize url for local files - QUrl normalizeUrl = DependencyManager::get<ResourceManager>()->normalizeURL(url); + QUrl normalizeUrl = DependencyManager::get<ResourceManager>()->normalizeURL(_url); if (normalizeUrl.scheme().isEmpty() || (normalizeUrl.scheme() == "file")) { QString localFileName = PathUtils::expandToLocalDataAbsolutePath(normalizeUrl).toLocalFile(); _url = QUrl(QFileInfo(localFileName).absoluteFilePath()); @@ -924,17 +923,17 @@ HFMModel* GLTFReader::readGLTF(QByteArray& data, const QVariantHash& mapping, parseGLTF(data); //_file.dump(); - HFMModel* hfmModelPtr = new HFMModel(); + auto hfmModelPtr = std::make_shared<HFMModel>(); HFMModel& hfmModel = *hfmModelPtr; - buildGeometry(hfmModel, url); + buildGeometry(hfmModel, _url); //hfmDebugDump(data); return hfmModelPtr; } -bool GLTFReader::readBinary(const QString& url, QByteArray& outdata) { +bool GLTFSerializer::readBinary(const QString& url, QByteArray& outdata) { QUrl binaryUrl = _url.resolved(url); bool success; @@ -943,7 +942,7 @@ bool GLTFReader::readBinary(const QString& url, QByteArray& outdata) { return success; } -bool GLTFReader::doesResourceExist(const QString& url) { +bool GLTFSerializer::doesResourceExist(const QString& url) { if (_url.isEmpty()) { return false; } @@ -951,9 +950,9 @@ bool GLTFReader::doesResourceExist(const QString& url) { return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl); } -std::tuple<bool, QByteArray> GLTFReader::requestData(QUrl& url) { +std::tuple<bool, QByteArray> GLTFSerializer::requestData(QUrl& url) { auto request = DependencyManager::get<ResourceManager>()->createResourceRequest( - nullptr, url, true, -1, "GLTFReader::requestData"); + nullptr, url, true, -1, "GLTFSerializer::requestData"); if (!request) { return std::make_tuple(false, QByteArray()); @@ -972,7 +971,7 @@ std::tuple<bool, QByteArray> GLTFReader::requestData(QUrl& url) { } -QNetworkReply* GLTFReader::request(QUrl& url, bool isTest) { +QNetworkReply* GLTFSerializer::request(QUrl& url, bool isTest) { if (!qApp) { return nullptr; } @@ -996,7 +995,7 @@ QNetworkReply* GLTFReader::request(QUrl& url, bool isTest) { return netReply; // trying to sync later on. } -HFMTexture GLTFReader::getHFMTexture(const GLTFTexture& texture) { +HFMTexture GLTFSerializer::getHFMTexture(const GLTFTexture& texture) { HFMTexture fbxtex = HFMTexture(); fbxtex.texcoordSet = 0; @@ -1011,7 +1010,7 @@ HFMTexture GLTFReader::getHFMTexture(const GLTFTexture& texture) { return fbxtex; } -void GLTFReader::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material) { +void GLTFSerializer::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& material) { if (material.defined["name"]) { @@ -1074,7 +1073,7 @@ void GLTFReader::setHFMMaterial(HFMMaterial& fbxmat, const GLTFMaterial& materia } template<typename T, typename L> -bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int count, +bool GLTFSerializer::readArray(const QByteArray& bin, int byteOffset, int count, QVector<L>& outarray, int accessorType) { QDataStream blobstream(bin); @@ -1131,7 +1130,7 @@ bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int count, return true; } template<typename T> -bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int count, +bool GLTFSerializer::addArrayOfType(const QByteArray& bin, int byteOffset, int count, QVector<T>& outarray, int accessorType, int componentType) { switch (componentType) { @@ -1155,7 +1154,7 @@ bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int count return false; } -void GLTFReader::retriangulate(const QVector<int>& inIndices, const QVector<glm::vec3>& in_vertices, +void GLTFSerializer::retriangulate(const QVector<int>& inIndices, const QVector<glm::vec3>& in_vertices, const QVector<glm::vec3>& in_normals, QVector<int>& outIndices, QVector<glm::vec3>& out_vertices, QVector<glm::vec3>& out_normals) { for (int i = 0; i < inIndices.size(); i = i + 3) { @@ -1178,7 +1177,7 @@ void GLTFReader::retriangulate(const QVector<int>& inIndices, const QVector<glm: } } -void GLTFReader::hfmDebugDump(const HFMModel& hfmModel) { +void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) { qCDebug(modelformat) << "---------------- hfmModel ----------------"; qCDebug(modelformat) << " hasSkeletonJoints =" << hfmModel.hasSkeletonJoints; qCDebug(modelformat) << " offset =" << hfmModel.offset; diff --git a/libraries/fbx/src/GLTFReader.h b/libraries/fbx/src/GLTFSerializer.h similarity index 98% rename from libraries/fbx/src/GLTFReader.h rename to libraries/fbx/src/GLTFSerializer.h index 016735778d..1ec1183e36 100644 --- a/libraries/fbx/src/GLTFReader.h +++ b/libraries/fbx/src/GLTFSerializer.h @@ -1,5 +1,5 @@ // -// GLTFReader.h +// GLTFSerializer.h // libraries/fbx/src // // Created by Luis Cuenca on 8/30/17. @@ -9,13 +9,14 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_GLTFReader_h -#define hifi_GLTFReader_h +#ifndef hifi_GLTFSerializer_h +#define hifi_GLTFSerializer_h #include <memory.h> #include <QtNetwork/QNetworkReply> #include <hfm/ModelFormatLogging.h> -#include "FBXReader.h" +#include <hfm/HFMSerializer.h> +#include "FBXSerializer.h" struct GLTFAsset { @@ -699,12 +700,11 @@ struct GLTFFile { } }; -class GLTFReader : public QObject { +class GLTFSerializer : public QObject, public HFMSerializer { Q_OBJECT public: - GLTFReader(); - HFMModel* readGLTF(QByteArray& data, const QVariantHash& mapping, - const QUrl& url, bool loadLightmaps = true, float lightmapLevel = 1.0f); + GLTFSerializer(); + HFMModel::Pointer read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url = QUrl()) override; private: GLTFFile _file; QUrl _url; @@ -780,4 +780,4 @@ private: void hfmDebugDump(const HFMModel& hfmModel); }; -#endif // hifi_GLTFReader_h \ No newline at end of file +#endif // hifi_GLTFSerializer_h \ No newline at end of file diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJSerializer.cpp similarity index 92% rename from libraries/fbx/src/OBJReader.cpp rename to libraries/fbx/src/OBJSerializer.cpp index e140f1b0b3..af8dfb5562 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJSerializer.cpp @@ -1,5 +1,5 @@ // -// OBJReader.cpp +// OBJSerializer.cpp // libraries/fbx/src/ // // Created by Seth Alves on 3/7/15. @@ -12,7 +12,7 @@ // http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/obj-file-format/obj-file-format/ // http://paulbourke.net/dataformats/obj/ -#include "OBJReader.h" +#include "OBJSerializer.h" #include <ctype.h> // .obj files are not locale-specific. The C/ASCII charset applies. #include <sstream> @@ -27,7 +27,7 @@ #include <NetworkAccessManager.h> #include <ResourceManager.h> -#include "FBXReader.h" +#include "FBXSerializer.h" #include <hfm/ModelFormatLogging.h> #include <shared/PlatformHacks.h> @@ -238,7 +238,7 @@ void OBJFace::addFrom(const OBJFace* face, int index) { // add using data from f } } -bool OBJReader::isValidTexture(const QByteArray &filename) { +bool OBJSerializer::isValidTexture(const QByteArray &filename) { if (_url.isEmpty()) { return false; } @@ -247,7 +247,7 @@ bool OBJReader::isValidTexture(const QByteArray &filename) { return DependencyManager::get<ResourceManager>()->resourceExists(candidateUrl); } -void OBJReader::parseMaterialLibrary(QIODevice* device) { +void OBJSerializer::parseMaterialLibrary(QIODevice* device) { OBJTokenizer tokenizer(device); QString matName = SMART_DEFAULT_MATERIAL_NAME; OBJMaterial& currentMaterial = materials[matName]; @@ -255,7 +255,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { switch (tokenizer.nextToken()) { case OBJTokenizer::COMMENT_TOKEN: #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader MTLLIB comment:" << tokenizer.getComment(); + qCDebug(modelformat) << "OBJSerializer MTLLIB comment:" << tokenizer.getComment(); #endif break; case OBJTokenizer::DATUM_TOKEN: @@ -264,7 +264,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { materials[matName] = currentMaterial; #ifdef WANT_DEBUG qCDebug(modelformat) << - "OBJ Reader Last material illumination model:" << currentMaterial.illuminationModel << + "OBJSerializer Last material illumination model:" << currentMaterial.illuminationModel << " shininess:" << currentMaterial.shininess << " opacity:" << currentMaterial.opacity << " diffuse color:" << currentMaterial.diffuseColor << @@ -287,7 +287,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { matName = tokenizer.getDatum(); currentMaterial = materials[matName]; #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader Starting new material definition " << matName; + qCDebug(modelformat) << "OBJSerializer Starting new material definition " << matName; #endif currentMaterial.diffuseTextureFilename = ""; currentMaterial.emissiveTextureFilename = ""; @@ -299,7 +299,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { currentMaterial.shininess = tokenizer.getFloat(); } else if (token == "Ni") { #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader Ignoring material Ni " << tokenizer.getFloat(); + qCDebug(modelformat) << "OBJSerializer Ignoring material Ni " << tokenizer.getFloat(); #else tokenizer.getFloat(); #endif @@ -311,13 +311,13 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { currentMaterial.illuminationModel = tokenizer.getFloat(); } else if (token == "Tf") { #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader Ignoring material Tf " << tokenizer.getVec3(); + qCDebug(modelformat) << "OBJSerializer Ignoring material Tf " << tokenizer.getVec3(); #else tokenizer.getVec3(); #endif } else if (token == "Ka") { #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader Ignoring material Ka " << tokenizer.getVec3();; + qCDebug(modelformat) << "OBJSerializer Ignoring material Ka " << tokenizer.getVec3();; #else tokenizer.getVec3(); #endif @@ -334,7 +334,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { parseTextureLine(textureLine, filename, textureOptions); if (filename.endsWith(".tga")) { #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader WARNING: currently ignoring tga texture " << filename << " in " << _url; + qCDebug(modelformat) << "OBJSerializer WARNING: currently ignoring tga texture " << filename << " in " << _url; #endif break; } @@ -354,7 +354,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { } } -void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& filename, OBJMaterialTextureOptions& textureOptions) { +void OBJSerializer::parseTextureLine(const QByteArray& textureLine, QByteArray& filename, OBJMaterialTextureOptions& textureOptions) { // Texture options reference http://paulbourke.net/dataformats/mtl/ // and https://wikivisually.com/wiki/Material_Template_Library @@ -368,7 +368,7 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file if (option == "-blendu" || option == "-blendv") { #ifdef WANT_DEBUG const std::string& onoff = parser[i++]; - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << onoff.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << onoff.c_str(); #endif } else if (option == "-bm") { const std::string& bm = parser[i++]; @@ -377,22 +377,22 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file #ifdef WANT_DEBUG const std::string& boost = parser[i++]; float boostFloat = std::stof(boost); - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << boost.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << boost.c_str(); #endif } else if (option == "-cc") { #ifdef WANT_DEBUG const std::string& onoff = parser[i++]; - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << onoff.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << onoff.c_str(); #endif } else if (option == "-clamp") { #ifdef WANT_DEBUG const std::string& onoff = parser[i++]; - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << onoff.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << onoff.c_str(); #endif } else if (option == "-imfchan") { #ifdef WANT_DEBUG const std::string& imfchan = parser[i++]; - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << imfchan.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << imfchan.c_str(); #endif } else if (option == "-mm") { if (i + 1 < parser.size()) { @@ -401,7 +401,7 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file const std::string& mmGain = parser[i++]; float mmBaseFloat = std::stof(mmBase); float mmGainFloat = std::stof(mmGain); - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << mmBase.c_str() << mmGain.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << mmBase.c_str() << mmGain.c_str(); #endif } } else if (option == "-o" || option == "-s" || option == "-t") { @@ -413,23 +413,23 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file float uFloat = std::stof(u); float vFloat = std::stof(v); float wFloat = std::stof(w); - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << u.c_str() << v.c_str() << w.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << u.c_str() << v.c_str() << w.c_str(); #endif } } else if (option == "-texres") { #ifdef WANT_DEBUG const std::string& texres = parser[i++]; float texresFloat = std::stof(texres); - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << texres.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << texres.c_str(); #endif } else if (option == "-type") { #ifdef WANT_DEBUG const std::string& type = parser[i++]; - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring texture option" << option.c_str() << type.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring texture option" << option.c_str() << type.c_str(); #endif } else if (option[0] == '-') { #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring unsupported texture option" << option.c_str(); + qCDebug(modelformat) << "OBJSerializer WARNING: Ignoring unsupported texture option" << option.c_str(); #endif } } else { // assume filename at end when no more options @@ -444,7 +444,7 @@ void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& file std::tuple<bool, QByteArray> requestData(QUrl& url) { auto request = DependencyManager::get<ResourceManager>()->createResourceRequest( - nullptr, url, true, -1, "(OBJReader) requestData"); + nullptr, url, true, -1, "(OBJSerializer) requestData"); if (!request) { return std::make_tuple(false, QByteArray()); @@ -488,7 +488,7 @@ QNetworkReply* request(QUrl& url, bool isTest) { } -bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, HFMModel& hfmModel, +bool OBJSerializer::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, HFMModel& hfmModel, float& scaleGuess, bool combineParts) { FaceGroup faces; HFMMesh& mesh = hfmModel.meshes[0]; @@ -557,7 +557,7 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi currentMaterialName = nextName; } #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader new current material:" << currentMaterialName; + qCDebug(modelformat) << "OBJSerializer new current material:" << currentMaterialName; #endif } } else if (token == "v") { @@ -652,12 +652,12 @@ done: } -HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mapping, bool combineParts, const QUrl& url) { +HFMModel::Pointer OBJSerializer::read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url) { PROFILE_RANGE_EX(resource_parse, __FUNCTION__, 0xffff0000, nullptr); - QBuffer buffer { &data }; + QBuffer buffer { const_cast<QByteArray*>(&data) }; buffer.open(QIODevice::ReadOnly); - auto hfmModelPtr { std::make_shared<HFMModel>() }; + auto hfmModelPtr = std::make_shared<HFMModel>(); HFMModel& hfmModel { *hfmModelPtr }; OBJTokenizer tokenizer { &buffer }; float scaleGuess = 1.0f; @@ -665,6 +665,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi bool needsMaterialLibrary = false; _url = url; + bool combineParts = mapping.value("combineParts").toBool(); hfmModel.meshExtents.reset(); hfmModel.meshes.append(HFMMesh()); @@ -720,7 +721,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi QString groupMaterialName = face.materialName; if (groupMaterialName.isEmpty() && specifiesUV) { #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader WARNING: " << url + qCDebug(modelformat) << "OBJSerializer WARNING: " << url << " needs a texture that isn't specified. Using default mechanism."; #endif groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; @@ -822,11 +823,11 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi } // Build the single mesh. - FBXReader::buildModelMesh(mesh, url.toString()); + FBXSerializer::buildModelMesh(mesh, _url.toString()); // hfmDebugDump(hfmModel); } catch(const std::exception& e) { - qCDebug(modelformat) << "OBJ reader fail: " << e.what(); + qCDebug(modelformat) << "OBJSerializer fail: " << e.what(); } QString queryPart = _url.query(); @@ -838,14 +839,14 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi } // Some .obj files use the convention that a group with uv coordinates that doesn't define a material, should use // a texture with the same basename as the .obj file. - if (preDefinedMaterial.userSpecifiesUV && !url.isEmpty()) { - QString filename = url.fileName(); + if (preDefinedMaterial.userSpecifiesUV && !_url.isEmpty()) { + QString filename = _url.fileName(); int extIndex = filename.lastIndexOf('.'); // by construction, this does not fail QString basename = filename.remove(extIndex + 1, sizeof("obj")); preDefinedMaterial.diffuseColor = glm::vec3(1.0f); QVector<QByteArray> extensions = { "jpg", "jpeg", "png", "tga" }; QByteArray base = basename.toUtf8(), textName = ""; - qCDebug(modelformat) << "OBJ Reader looking for default texture"; + qCDebug(modelformat) << "OBJSerializer looking for default texture"; for (int i = 0; i < extensions.count(); i++) { QByteArray candidateString = base + extensions[i]; if (isValidTexture(candidateString)) { @@ -856,7 +857,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi if (!textName.isEmpty()) { #ifdef WANT_DEBUG - qCDebug(modelformat) << "OBJ Reader found a default texture: " << textName; + qCDebug(modelformat) << "OBJSerializer found a default texture: " << textName; #endif preDefinedMaterial.diffuseTextureFilename = textName; } @@ -866,7 +867,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi foreach (QString libraryName, librariesSeen.keys()) { // Throw away any path part of libraryName, and merge against original url. QUrl libraryUrl = _url.resolved(QUrl(libraryName).fileName()); - qCDebug(modelformat) << "OBJ Reader material library" << libraryName; + qCDebug(modelformat) << "OBJSerializer material library" << libraryName; bool success; QByteArray data; std::tie<bool, QByteArray>(success, data) = requestData(libraryUrl); @@ -875,7 +876,7 @@ HFMModel::Pointer OBJReader::readOBJ(QByteArray& data, const QVariantHash& mappi buffer.open(QIODevice::ReadOnly); parseMaterialLibrary(&buffer); } else { - qCDebug(modelformat) << "OBJ Reader WARNING:" << libraryName << "did not answer"; + qCDebug(modelformat) << "OBJSerializer WARNING:" << libraryName << "did not answer"; } } } diff --git a/libraries/fbx/src/OBJReader.h b/libraries/fbx/src/OBJSerializer.h similarity index 85% rename from libraries/fbx/src/OBJReader.h rename to libraries/fbx/src/OBJSerializer.h index 0088e8e9d7..a6fe3817ca 100644 --- a/libraries/fbx/src/OBJReader.h +++ b/libraries/fbx/src/OBJSerializer.h @@ -1,6 +1,20 @@ +// +// OBJSerializer.h +// libraries/fbx/src/ +// +// Created by Seth Alves on 3/6/15. +// Copyright 2015 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_OBJSerializer_h +#define hifi_OBJSerializer_h #include <QtNetwork/QNetworkReply> -#include "FBXReader.h" +#include <hfm/HFMSerializer.h> +#include "FBXSerializer.h" class OBJTokenizer { public: @@ -75,7 +89,7 @@ public: OBJMaterial() : shininess(0.0f), opacity(1.0f), diffuseColor(0.9f), specularColor(0.9f), emissiveColor(0.0f), illuminationModel(-1) {} }; -class OBJReader: public QObject { // QObject so we can make network requests. +class OBJSerializer: public QObject, public HFMSerializer { // QObject so we can make network requests. Q_OBJECT public: typedef QVector<OBJFace> FaceGroup; @@ -86,8 +100,8 @@ public: QVector<FaceGroup> faceGroups; QString currentMaterialName; QHash<QString, OBJMaterial> materials; - - HFMModel::Pointer readOBJ(QByteArray& data, const QVariantHash& mapping, bool combineParts, const QUrl& url = QUrl()); + + HFMModel::Pointer read(const QByteArray& data, const QVariantHash& mapping, const QUrl& url = QUrl()) override; private: QUrl _url; @@ -105,3 +119,5 @@ private: // What are these utilities doing here? One is used by fbx loading code in VHACD Utils, and the other a general debugging utility. void setMeshPartDefaults(HFMMeshPart& meshPart, QString materialID); void hfmDebugDump(const HFMModel& hfmModel); + +#endif // hifi_OBJSerializer_h diff --git a/libraries/graphics/src/graphics/Stage.cpp b/libraries/graphics/src/graphics/Stage.cpp index 312ece6889..21929a61dd 100644 --- a/libraries/graphics/src/graphics/Stage.cpp +++ b/libraries/graphics/src/graphics/Stage.cpp @@ -223,8 +223,8 @@ void SunSkyStage::setSunDirection(const Vec3& direction) { } } -// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun -double evalSunDeclinaison(double dayNumber) { +// The sun declination calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun +double evalSunDeclination(double dayNumber) { return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); } @@ -235,8 +235,8 @@ void SunSkyStage::updateGraphicsObject() const { float sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); _earthSunModel.setSunLongitude(sunLongitude); - // And update the sunLAtitude as the declinaison depending of the time of the year - _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); + // And update the sunLatitude as the declination depending of the time of the year + _earthSunModel.setSunLatitude(evalSunDeclination(_yearTime)); if (isSunModelEnabled()) { Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); diff --git a/libraries/hfm/src/hfm/HFMSerializer.h b/libraries/hfm/src/hfm/HFMSerializer.h new file mode 100644 index 0000000000..db18f21e06 --- /dev/null +++ b/libraries/hfm/src/hfm/HFMSerializer.h @@ -0,0 +1,29 @@ +// +// FBXSerializer.h +// libraries/hfm/src/hfm +// +// Created by Sabrina Shanman on 2018/11/07. +// Copyright 2018 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_HFMSerializer_h +#define hifi_HFMSerializer_h + +#include <shared/HifiTypes.h> + +#include "HFM.h" + +namespace hfm { + +class Serializer { + virtual Model::Pointer read(const hifi::ByteArray& data, const hifi::VariantHash& mapping, const hifi::URL& url = hifi::URL()) = 0; +}; + +}; + +using HFMSerializer = hfm::Serializer; + +#endif // hifi_HFMSerializer_h diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index d3f24073c4..254f61eba9 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -12,9 +12,9 @@ #include "ModelCache.h" #include <Finally.h> #include <FSTReader.h> -#include "FBXReader.h" -#include "OBJReader.h" -#include "GLTFReader.h" +#include "FBXSerializer.h" +#include "OBJSerializer.h" +#include "GLTFSerializer.h" #include <gpu/Batch.h> #include <gpu/Stream.h> @@ -193,24 +193,26 @@ void GeometryReader::run() { HFMModel::Pointer hfmModel; + QVariantHash serializerMapping = _mapping; + serializerMapping["combineParts"] = _combineParts; + if (_url.path().toLower().endsWith(".fbx")) { - hfmModel.reset(readFBX(_data, _mapping, _url.path())); + hfmModel = FBXSerializer().read(_data, serializerMapping, _url); if (hfmModel->meshes.size() == 0 && hfmModel->joints.size() == 0) { throw QString("empty geometry, possibly due to an unsupported FBX version"); } } else if (_url.path().toLower().endsWith(".obj")) { - hfmModel = OBJReader().readOBJ(_data, _mapping, _combineParts, _url); + hfmModel = OBJSerializer().read(_data, serializerMapping, _url); } else if (_url.path().toLower().endsWith(".obj.gz")) { QByteArray uncompressedData; if (gunzip(_data, uncompressedData)){ - hfmModel = OBJReader().readOBJ(uncompressedData, _mapping, _combineParts, _url); + hfmModel = OBJSerializer().read(uncompressedData, serializerMapping, _url); } else { throw QString("failed to decompress .obj.gz"); } } else if (_url.path().toLower().endsWith(".gltf")) { - std::shared_ptr<GLTFReader> glreader = std::make_shared<GLTFReader>(); - hfmModel.reset(glreader->readGLTF(_data, _mapping, _url)); + hfmModel = GLTFSerializer().read(_data, serializerMapping, _url); if (hfmModel->meshes.size() == 0 && hfmModel->joints.size() == 0) { throw QString("empty geometry, possibly due to an unsupported GLTF version"); } diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 1bb340b83c..9d458e7512 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -18,7 +18,7 @@ #include <graphics/Material.h> #include <graphics/Asset.h> -#include "FBXReader.h" +#include "FBXSerializer.h" #include "TextureCache.h" // Alias instead of derive to avoid copying diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index 9cba4970ac..3178217a36 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -134,6 +134,7 @@ void SendQueue::stop() { } int SendQueue::sendPacket(const Packet& packet) { + _lastPacketSentAt = std::chrono::high_resolution_clock::now(); return _socket->writeDatagram(packet.getData(), packet.getDataSize(), _destination); } @@ -501,12 +502,31 @@ bool SendQueue::isInactive(bool attemptedToSendPacket) { // We think the client is still waiting for data (based on the sequence number gap) // Let's wait either for a response from the client or until the estimated timeout // (plus the sync interval to allow the client to respond) has elapsed - auto waitDuration = std::chrono::microseconds(_estimatedTimeout + _syncInterval); - + + auto estimatedTimeout = std::chrono::microseconds(_estimatedTimeout); + + // cap our maximum estimated timeout to the already unreasonable 5 seconds + const auto MAXIMUM_ESTIMATED_TIMEOUT = std::chrono::seconds(5); + + if (estimatedTimeout > MAXIMUM_ESTIMATED_TIMEOUT) { + estimatedTimeout = MAXIMUM_ESTIMATED_TIMEOUT; + } + // use our condition_variable_any to wait - auto cvStatus = _emptyCondition.wait_for(locker, waitDuration); - - if (cvStatus == std::cv_status::timeout && (_packets.isEmpty() || isFlowWindowFull()) && _naks.isEmpty() + auto cvStatus = _emptyCondition.wait_for(locker, estimatedTimeout); + + // when we wake-up check if we're "stuck" either if we've slept for the estimated timeout + // or it has been that long since the last time we sent a packet + + // we are stuck if all of the following are true + // - there are no new packets to send or the flow window is full and we can't send any new packets + // - there are no packets to resend + // - the client has yet to ACK some sent packets + auto now = std::chrono::high_resolution_clock::now(); + + if ((cvStatus == std::cv_status::timeout || (now - _lastPacketSentAt > estimatedTimeout)) + && (_packets.isEmpty() || isFlowWindowFull()) + && _naks.isEmpty() && SequenceNumber(_lastACKSequenceNumber) < _currentSequenceNumber) { // after a timeout if we still have sent packets that the client hasn't ACKed we // add them to the loss list diff --git a/libraries/networking/src/udt/SendQueue.h b/libraries/networking/src/udt/SendQueue.h index 65b1b89c7e..c1faac3b22 100644 --- a/libraries/networking/src/udt/SendQueue.h +++ b/libraries/networking/src/udt/SendQueue.h @@ -68,7 +68,6 @@ public: void setPacketSendPeriod(int newPeriod) { _packetSendPeriod = newPeriod; } void setEstimatedTimeout(int estimatedTimeout) { _estimatedTimeout = estimatedTimeout; } - void setSyncInterval(int syncInterval) { _syncInterval = syncInterval; } public slots: void stop(); @@ -124,7 +123,6 @@ private: std::atomic<State> _state { State::NotStarted }; std::atomic<int> _estimatedTimeout { 0 }; // Estimated timeout, set from CC - std::atomic<int> _syncInterval { udt::DEFAULT_SYN_INTERVAL_USECS }; // Sync interval, set from CC std::atomic<int> _flowWindowSize { 0 }; // Flow control window size (number of packets that can be on wire) - set from CC @@ -140,6 +138,8 @@ private: std::condition_variable _handshakeACKCondition; std::condition_variable_any _emptyCondition; + + std::chrono::high_resolution_clock::time_point _lastPacketSentAt; }; } diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 2cdfc20647..399ccf1919 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -191,7 +191,6 @@ void ScriptEngines::shutdownScripting() { // Gracefully stop the engine's scripting thread scriptEngine->stop(); - removeScriptEngine(scriptEngine); // We need to wait for the engine to be done running before we proceed, because we don't // want any of the scripts final "scriptEnding()" or pending "update()" methods from accessing @@ -370,13 +369,10 @@ QStringList ScriptEngines::getRunningScripts() { } void ScriptEngines::stopAllScripts(bool restart) { - QVector<QString> toReload; QReadLocker lock(&_scriptEnginesHashLock); if (_isReloading) { return; - } else { - _isReloading = true; } for (QHash<QUrl, ScriptEnginePointer>::const_iterator it = _scriptEnginesHash.constBegin(); @@ -389,29 +385,27 @@ void ScriptEngines::stopAllScripts(bool restart) { // queue user scripts if restarting if (restart && scriptEngine->isUserLoaded()) { - toReload << it.key().toString(); + _isReloading = true; + bool lastScript = (it == _scriptEnginesHash.constEnd() - 1); + ScriptEngine::Type type = scriptEngine->getType(); + + connect(scriptEngine.data(), &ScriptEngine::finished, this, [this, type, lastScript] (QString scriptName) { + reloadScript(scriptName, true)->setType(type); + + if (lastScript) { + _isReloading = false; + } + }); } // stop all scripts scriptEngine->stop(); - removeScriptEngine(scriptEngine); } - // wait for engines to stop (ie: providing time for .scriptEnding cleanup handlers to run) before - // triggering reload of any Client scripts / Entity scripts - QTimer::singleShot(1000, this, [=]() { - for(const auto &scriptName : toReload) { - auto scriptEngine = getScriptEngine(scriptName); - if (scriptEngine && !scriptEngine->isFinished()) { - scriptEngine->waitTillDoneRunning(); - } - reloadScript(scriptName); - } - if (restart) { - qCDebug(scriptengine) << "stopAllScripts -- emitting scriptsReloading"; - emit scriptsReloading(); - } - _isReloading = false; - }); + + if (restart) { + qCDebug(scriptengine) << "stopAllScripts -- emitting scriptsReloading"; + emit scriptsReloading(); + } } bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) { @@ -439,7 +433,6 @@ bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) { } } scriptEngine->stop(); - removeScriptEngine(scriptEngine); stoppedScript = true; } } diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index da877f7b3b..978732fd50 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -27,16 +27,16 @@ class Dependency { public: typedef std::function<void(Dependency* pointer)> DeleterFunction; - + protected: virtual ~Dependency() {} virtual void customDeleter() { _customDeleter(this); } - + void setCustomDeleter(DeleterFunction customDeleter) { _customDeleter = customDeleter; } DeleterFunction _customDeleter = [](Dependency* pointer) { delete pointer; }; - + friend class DependencyManager; }; @@ -49,10 +49,10 @@ class DependencyManager { public: template<typename T> static QSharedPointer<T> get(); - + template<typename T> static bool isSet(); - + template<typename T, typename ...Args> static QSharedPointer<T> set(Args&&... args); @@ -61,10 +61,10 @@ public: template<typename T> static void destroy(); - + template<typename Base, typename Derived> static void registerInheritance(); - + template <typename T> static size_t typeHash() { #ifdef Q_OS_ANDROID @@ -79,9 +79,9 @@ private: template<typename T> size_t getHashCode(); - + QSharedPointer<Dependency>& safeGet(size_t hashCode); - + QHash<size_t, QSharedPointer<Dependency>> _instanceHash; QHash<size_t, size_t> _inheritanceHash; }; @@ -90,15 +90,17 @@ template <typename T> QSharedPointer<T> DependencyManager::get() { static size_t hashCode = manager().getHashCode<T>(); static QWeakPointer<T> instance; - + if (instance.isNull()) { instance = qSharedPointerCast<T>(manager().safeGet(hashCode)); - + +#ifndef QT_NO_DEBUG if (instance.isNull()) { qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name(); } +#endif } - + return instance.toStrongRef(); } @@ -159,12 +161,12 @@ template<typename T> size_t DependencyManager::getHashCode() { size_t hashCode = typeHash<T>(); auto derivedHashCode = _inheritanceHash.find(hashCode); - + while (derivedHashCode != _inheritanceHash.end()) { hashCode = derivedHashCode.value(); derivedHashCode = _inheritanceHash.find(hashCode); } - + return hashCode; } diff --git a/libraries/shared/src/shared/HifiTypes.h b/libraries/shared/src/shared/HifiTypes.h new file mode 100644 index 0000000000..500170c88b --- /dev/null +++ b/libraries/shared/src/shared/HifiTypes.h @@ -0,0 +1,25 @@ +// +// HifiTypes.h +// libraries/shared/src/shared +// +// Created by Sabrina Shanman on 2018/11/12. +// Copyright 2018 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_HifiTypes_h +#define hifi_HifiTypes_h + +#include <QVarLengthArray> +#include <QVariant> +#include <QUrl> + +namespace hifi { + using ByteArray = QByteArray; + using VariantHash = QVariantHash; + using URL = QUrl; +}; + +#endif // hifi_HifiTypes_h diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 0aad297587..a13bdf0657 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -616,7 +616,9 @@ bool OffscreenUi::navigationFocused() { } void OffscreenUi::setNavigationFocused(bool focused) { - offscreenFlags->setNavigationFocused(focused); + if (offscreenFlags) { + offscreenFlags->setNavigationFocused(focused); + } } // FIXME HACK.... diff --git a/libraries/ui/src/ui/Menu.cpp b/libraries/ui/src/ui/Menu.cpp index 848b2362ee..b3b76ab534 100644 --- a/libraries/ui/src/ui/Menu.cpp +++ b/libraries/ui/src/ui/Menu.cpp @@ -422,9 +422,11 @@ void Menu::removeMenu(const QString& menuName) { } else { QMenuBar::removeAction(action); auto offscreenUi = DependencyManager::get<OffscreenUi>(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->removeAction(action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->removeAction(action); + }); + } } QMenuBar::repaint(); @@ -532,9 +534,11 @@ void Menu::setGroupingIsVisible(const QString& grouping, bool isVisible) { MenuWrapper::MenuWrapper(ui::Menu& rootMenu, QMenu* menu) : _rootMenu(rootMenu), _realMenu(menu) { auto offscreenUi = DependencyManager::get<OffscreenUi>(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addMenu(menu); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addMenu(menu); + }); + } _rootMenu._backMap[menu] = this; } @@ -553,50 +557,62 @@ void MenuWrapper::setEnabled(bool enabled) { QAction* MenuWrapper::addSeparator() { QAction* action = _realMenu->addSeparator(); auto offscreenUi = DependencyManager::get<OffscreenUi>(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addSeparator(_realMenu); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addSeparator(_realMenu); + }); + } return action; } void MenuWrapper::addAction(QAction* action) { _realMenu->addAction(action); auto offscreenUi = DependencyManager::get<OffscreenUi>(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addAction(_realMenu, action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addAction(_realMenu, action); + }); + } } QAction* MenuWrapper::addAction(const QString& menuName) { QAction* action = _realMenu->addAction(menuName); auto offscreenUi = DependencyManager::get<OffscreenUi>(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addAction(_realMenu, action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addAction(_realMenu, action); + }); + } return action; } QAction* MenuWrapper::addAction(const QString& menuName, const QObject* receiver, const char* member, const QKeySequence& shortcut) { QAction* action = _realMenu->addAction(menuName, receiver, member, shortcut); auto offscreenUi = DependencyManager::get<OffscreenUi>(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->addAction(_realMenu, action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->addAction(_realMenu, action); + }); + } return action; } void MenuWrapper::removeAction(QAction* action) { _realMenu->removeAction(action); auto offscreenUi = DependencyManager::get<OffscreenUi>(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->removeAction(action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->removeAction(action); + }); + } } void MenuWrapper::insertAction(QAction* before, QAction* action) { _realMenu->insertAction(before, action); auto offscreenUi = DependencyManager::get<OffscreenUi>(); - offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { - vrMenu->insertAction(before, action); - }); + if (offscreenUi) { + offscreenUi->addMenuInitializer([=](VrMenu* vrMenu) { + vrMenu->insertAction(before, action); + }); + } } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 8fc2d069ec..13b0498e76 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -366,6 +366,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { auto offscreenUi = DependencyManager::get<OffscreenUi>(); if (toolbarMode) { +#if !defined(DISABLE_QML) // create new desktop window auto tabletRootWindow = new TabletRootWindow(); tabletRootWindow->initQml(QVariantMap()); @@ -379,6 +380,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { // forward qml surface events to interface js connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml); +#endif } else { if (_currentPathLoaded != TABLET_HOME_SOURCE_URL) { loadHomeScreen(true); diff --git a/prebuild.py b/prebuild.py index dacc49a86e..b8cb2c96ae 100644 --- a/prebuild.py +++ b/prebuild.py @@ -83,12 +83,17 @@ class VcpkgRepo: self.sourcePortsPath = os.path.join(scriptPath, 'cmake', 'ports') # FIXME Revert to ports hash before release self.id = hashFolder(self.sourcePortsPath)[:8] + # OS dependent information + system = platform.system() if args.vcpkg_root is not None: print("override vcpkg path with " + args.vcpkg_root) self.path = args.vcpkg_root else: - defaultBasePath = os.path.join(tempfile.gettempdir(), 'hifi', 'vcpkg') + if 'Darwin' == system: + defaultBasePath = os.path.expanduser('~/hifi/vcpkg') + else: + defaultBasePath = os.path.join(tempfile.gettempdir(), 'hifi', 'vcpkg') basePath = os.getenv('HIFI_VCPKG_BASE', defaultBasePath) if (not os.path.isdir(basePath)): os.makedirs(basePath) @@ -101,8 +106,6 @@ class VcpkgRepo: self.tagContents = "{}_{}".format(self.id, self.version) print("prebuild path: " + self.path) - # OS dependent information - system = platform.system() if 'Windows' == system: self.exe = os.path.join(self.path, 'vcpkg.exe') self.vcpkgUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/vcpkg-win32.tar.gz?versionId=YZYkDejDRk7L_hrK_WVFthWvisAhbDzZ' diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index 5e0cdbb94b..d5365133b6 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -539,6 +539,9 @@ function fromQml(message) { case 'http.request': // Handled elsewhere, don't log. break; + case 'closeSendAsset': + ui.close(); + break; default: print('wallet.js: Unrecognized message from QML'); } @@ -663,6 +666,7 @@ function uninstallMarketplaceItemTester() { var BUTTON_NAME = "INVENTORY"; var WALLET_QML_SOURCE = "hifi/commerce/wallet/Wallet.qml"; +var SENDASSET_QML_SOURCE = "hifi/commerce/common/sendAsset/SendAsset.qml"; var NOTIFICATION_POLL_TIMEOUT = 300000; var ui; function startup() { @@ -686,6 +690,7 @@ function startup() { buttonName: BUTTON_NAME, sortOrder: 10, home: WALLET_QML_SOURCE, + additionalAppScreens: SENDASSET_QML_SOURCE, onOpened: walletOpened, onClosed: walletClosed, onMessage: fromQml, diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index b657faefba..2658f11989 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -129,9 +129,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); return getControllerWorldLocation(Controller.Standard.RightHand, true); }; - Selection.enableListHighlight(DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE); - Selection.enableListToScene(DISPATCHER_HOVERING_LIST); - this.updateTimings = function () { _this.intervalCount++; var thisInterval = Date.now(); @@ -525,7 +522,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Controller.disableMapping(MAPPING_NAME); _this.pointerManager.removePointers(); Pointers.removePointer(this.mouseRayPick); - Selection.disableListHighlight(DISPATCHER_HOVERING_LIST); }; } diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 12a69d7b27..c61e46c8eb 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -459,13 +459,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.dropGestureReset(); this.clearEquipHaptics(); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - unhighlightTargetEntity(this.targetEntityID); - var message = { - hand: this.hand, - entityID: this.targetEntityID - }; - Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); var grabbedProperties = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); var grabData = getGrabbableData(grabbedProperties); diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 91119a4292..1eaed44ce2 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -84,7 +84,6 @@ Script.include("/~/system/libraries/controllers.js"); this.entityWithContextOverlay = false; this.contextOverlayTimer = false; this.locked = false; - this.highlightedEntity = null; this.reticleMinX = MARGIN; this.reticleMaxX = null; this.reticleMinY = MARGIN; @@ -410,9 +409,6 @@ Script.include("/~/system/libraries/controllers.js"); if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || (this.notPointingAtEntity(controllerData) && Window.isPhysicsEnabled()) || this.targetIsNull()) { this.endFarGrabAction(); - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", - this.highlightedEntity); - this.highlightedEntity = null; this.restoreIgnoredEntities(); return makeRunningValues(false, [], []); } @@ -466,9 +462,6 @@ Script.include("/~/system/libraries/controllers.js"); if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) { if (controllerData.triggerClicks[this.hand]) { var entityID = rayPickInfo.objectID; - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", - this.highlightedEntity); - this.highlightedEntity = null; var targetProps = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); if (targetProps.href !== "") { AddressManager.handleLookupString(targetProps.href); @@ -513,66 +506,43 @@ Script.include("/~/system/libraries/controllers.js"); this.startFarGrabAction(controllerData, targetProps); } } - } else { - var targetEntityID = rayPickInfo.objectID; - if (this.highlightedEntity !== targetEntityID) { - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", - this.highlightedEntity); - var selectionTargetProps = Entities.getEntityProperties(targetEntityID, DISPATCHER_PROPERTIES); + } else if (!this.entityWithContextOverlay) { + var _this = this; - var selectionTargetObject = new TargetObject(targetEntityID, selectionTargetProps); - selectionTargetObject.parentProps = getEntityParents(selectionTargetProps); - var selectionTargetEntity = selectionTargetObject.getTargetEntity(); - - if (entityIsGrabbable(selectionTargetEntity.props) || - entityIsGrabbable(selectionTargetObject.entityProps)) { - - Selection.addToSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", rayPickInfo.objectID); + if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) { + if (_this.contextOverlayTimer) { + Script.clearTimeout(_this.contextOverlayTimer); } - this.highlightedEntity = rayPickInfo.objectID; + _this.contextOverlayTimer = false; + _this.potentialEntityWithContextOverlay = rayPickInfo.objectID; } - if (!this.entityWithContextOverlay) { - var _this = this; - - if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) { - if (_this.contextOverlayTimer) { - Script.clearTimeout(_this.contextOverlayTimer); + if (!_this.contextOverlayTimer) { + _this.contextOverlayTimer = Script.setTimeout(function () { + if (!_this.entityWithContextOverlay && + _this.contextOverlayTimer && + _this.potentialEntityWithContextOverlay === rayPickInfo.objectID) { + var props = Entities.getEntityProperties(rayPickInfo.objectID, DISPATCHER_PROPERTIES); + var pointerEvent = { + type: "Move", + id: _this.hand + 1, // 0 is reserved for hardware mouse + pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, + rayPickInfo.intersection, props), + pos3D: rayPickInfo.intersection, + normal: rayPickInfo.surfaceNormal, + direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal), + button: "Secondary" + }; + if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) { + _this.entityWithContextOverlay = rayPickInfo.objectID; + } } _this.contextOverlayTimer = false; - _this.potentialEntityWithContextOverlay = rayPickInfo.objectID; - } - - if (!_this.contextOverlayTimer) { - _this.contextOverlayTimer = Script.setTimeout(function () { - if (!_this.entityWithContextOverlay && - _this.contextOverlayTimer && - _this.potentialEntityWithContextOverlay === rayPickInfo.objectID) { - var props = Entities.getEntityProperties(rayPickInfo.objectID, DISPATCHER_PROPERTIES); - var pointerEvent = { - type: "Move", - id: _this.hand + 1, // 0 is reserved for hardware mouse - pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, - rayPickInfo.intersection, props), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.surfaceNormal, - direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal), - button: "Secondary" - }; - if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) { - _this.entityWithContextOverlay = rayPickInfo.objectID; - } - } - _this.contextOverlayTimer = false; - }, 500); - } + }, 500); } } } else if (this.distanceRotating) { this.distanceRotate(otherFarGrabModule); - } else if (this.highlightedEntity) { - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity); - this.highlightedEntity = null; } } return this.exitIfDisabled(controllerData); diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js deleted file mode 100644 index 403b5d5149..0000000000 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ /dev/null @@ -1,155 +0,0 @@ -// -// highlightNearbyEntities.js -// -// Created by Dante Ruiz 2018-4-10 -// 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, MyAvatar, entityIsCloneable, Messages, print */ - -"use strict"; - -(function () { - Script.include("/~/system/libraries/controllerDispatcherUtils.js"); - Script.include("/~/system/libraries/controllers.js"); - Script.include("/~/system/libraries/cloneEntityUtils.js"); - var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); - - function differenceInArrays(firstArray, secondArray) { - var differenceArray = firstArray.filter(function(element) { - return secondArray.indexOf(element) < 0; - }); - - return differenceArray; - } - - function HighlightNearbyEntities(hand) { - this.hand = hand; - this.otherHand = hand === dispatcherUtils.RIGHT_HAND ? dispatcherUtils.LEFT_HAND : - dispatcherUtils.RIGHT_HAND; - this.highlightedEntities = []; - - this.parameters = dispatcherUtils.makeDispatcherModuleParameters( - 480, - this.hand === dispatcherUtils.RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100); - - - this.isGrabable = function(controllerData, props) { - var canGrabEntity = false; - if (dispatcherUtils.entityIsGrabbable(props) || entityIsCloneable(props)) { - // if we've attempted to grab a child, roll up to the root of the tree - var groupRootProps = dispatcherUtils.findGroupParent(controllerData, props); - canGrabEntity = true; - if (!dispatcherUtils.entityIsGrabbable(groupRootProps)) { - canGrabEntity = false; - } - } - return canGrabEntity; - }; - - this.clearAll = function() { - this.highlightedEntities.forEach(function(entity) { - dispatcherUtils.unhighlightTargetEntity(entity); - }); - }; - - this.hasHyperLink = function(props) { - return (props.href !== "" && props.href !== undefined); - }; - - this.removeEntityFromHighlightList = function(entityID) { - var index = this.highlightedEntities.indexOf(entityID); - if (index > -1) { - this.highlightedEntities.splice(index, 1); - } - }; - - this.getOtherModule = function() { - var otherModule = this.hand === dispatcherUtils.RIGHT_HAND ? leftHighlightNearbyEntities : - rightHighlightNearbyEntities; - return otherModule; - }; - - this.getOtherHandHighlightedEntities = function() { - return this.getOtherModule().highlightedEntities; - }; - - this.highlightEntities = function(controllerData) { - var nearbyEntitiesProperties = controllerData.nearbyEntityProperties[this.hand]; - var otherHandHighlightedEntities = this.getOtherHandHighlightedEntities(); - var newHighlightedEntities = []; - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - for (var i = 0; i < nearbyEntitiesProperties.length; i++) { - var props = nearbyEntitiesProperties[i]; - if (props.distance > dispatcherUtils.NEAR_GRAB_RADIUS * sensorScaleFactor) { - continue; - } - if (this.isGrabable(controllerData, props) || this.hasHyperLink(props)) { - dispatcherUtils.highlightTargetEntity(props.id); - if (newHighlightedEntities.indexOf(props.id) < 0) { - newHighlightedEntities.push(props.id); - } - } - } - - var unhighlightEntities = differenceInArrays(this.highlightedEntities, newHighlightedEntities); - - unhighlightEntities.forEach(function(entityID) { - if (otherHandHighlightedEntities.indexOf(entityID) < 0 ) { - dispatcherUtils.unhighlightTargetEntity(entityID); - } - }); - this.highlightedEntities = newHighlightedEntities; - }; - - this.isReady = function(controllerData) { - this.highlightEntities(controllerData); - return dispatcherUtils.makeRunningValues(false, [], []); - }; - - this.run = function(controllerData) { - return this.isReady(controllerData); - }; - } - - var handleMessage = function(channel, message, sender) { - var data; - if (sender === MyAvatar.sessionUUID) { - if (channel === 'Hifi-unhighlight-entity') { - try { - data = JSON.parse(message); - var hand = data.hand; - if (hand === dispatcherUtils.LEFT_HAND) { - leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID); - } else if (hand === dispatcherUtils.RIGHT_HAND) { - rightHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID); - } - } catch (e) { - print("highlightNearbyEntities -- Failed to parse message: " + JSON.stringify(message)); - } - } else if (channel === 'Hifi-unhighlight-all') { - leftHighlightNearbyEntities.clearAll(); - rightHighlightNearbyEntities.clearAll(); - } - } - }; - var leftHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.LEFT_HAND); - var rightHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.RIGHT_HAND); - - dispatcherUtils.enableDispatcherModule("LeftHighlightNearbyEntities", leftHighlightNearbyEntities); - dispatcherUtils.enableDispatcherModule("RightHighlightNearbyEntities", rightHighlightNearbyEntities); - - function cleanup() { - dispatcherUtils.disableDispatcherModule("LeftHighlightNearbyEntities"); - dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities"); - } - Messages.subscribe('Hifi-unhighlight-entity'); - Messages.subscribe('Hifi-unhighlight-all'); - Messages.messageReceived.connect(handleMessage); - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js deleted file mode 100644 index 59a68d98a4..0000000000 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ /dev/null @@ -1,104 +0,0 @@ -// -// mouseHighlightEntities.js -// -// scripts/system/controllers/controllerModules/ -// -// Created by Dante Ruiz 2018-4-11 -// 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 -// - -/* jslint bitwise: true */ - -/* global Script, print, Entities, Messages, Picks, HMD, MyAvatar, isInEditMode, DISPATCHER_PROPERTIES */ - - -(function() { - Script.include("/~/system/libraries/utils.js"); - var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); - - function MouseHighlightEntities() { - this.highlightedEntity = null; - this.grabbedEntity = null; - - this.parameters = dispatcherUtils.makeDispatcherModuleParameters( - 5, - ["mouse"], - [], - 100); - - this.setGrabbedEntity = function(entity) { - this.grabbedEntity = entity; - this.highlightedEntity = null; - }; - - this.isReady = function(controllerData) { - if (HMD.active) { - if (this.highlightedEntity) { - dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; - } - } else if (!this.grabbedEntity && !isInEditMode()) { - var pickResult = controllerData.mouseRayPick; - if (pickResult.type === Picks.INTERSECTED_ENTITY) { - var targetEntityID = pickResult.objectID; - - if (this.highlightedEntity !== targetEntityID) { - var targetProps = Entities.getEntityProperties(targetEntityID, DISPATCHER_PROPERTIES); - - if (this.highlightedEntity) { - dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; - } - - if (dispatcherUtils.entityIsGrabbable(targetProps)) { - // highlight entity - dispatcherUtils.highlightTargetEntity(targetEntityID); - this.highlightedEntity = targetEntityID; - } - } - } else if (this.highlightedEntity) { - dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; - } - } - - return dispatcherUtils.makeRunningValues(false, [], []); - }; - - this.run = function(controllerData) { - return this.isReady(controllerData); - }; - } - - var mouseHighlightEntities = new MouseHighlightEntities(); - dispatcherUtils.enableDispatcherModule("MouseHighlightEntities", mouseHighlightEntities); - - var handleMessage = function(channel, message, sender) { - var data; - if (sender === MyAvatar.sessionUUID) { - if (channel === 'Hifi-Object-Manipulation') { - try { - data = JSON.parse(message); - if (data.action === 'grab') { - var grabbedEntity = data.grabbedEntity; - mouseHighlightEntities.setGrabbedEntity(grabbedEntity); - } else if (data.action === 'release') { - mouseHighlightEntities.setGrabbedEntity(null); - } - } catch (e) { - print("Warning: mouseHighlightEntities -- error parsing Hifi-Object-Manipulation: " + message); - } - } - } - }; - - function cleanup() { - dispatcherUtils.disableDispatcherModule("MouseHighlightEntities"); - } - Messages.subscribe('Hifi-Object-Manipulation'); - Messages.messageReceived.connect(handleMessage); - Script.scriptEnding.connect(cleanup); -})(); diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index 1d1f89e2c7..bb563a269c 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -114,13 +114,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "startNearGrab", args); - unhighlightTargetEntity(this.targetEntityID); - var message = { - hand: this.hand, - entityID: this.targetEntityID - }; - - Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); }; // this is for when the action is going to time-out diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 433ad9ef53..13557bdb7e 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -11,9 +11,8 @@ TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME, - TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, highlightTargetEntity, unhighlightTargetEntity, - distanceBetweenEntityLocalPositionAndBoundingBox, getGrabbableData, getGrabPointSphereOffset, DISPATCHER_PROPERTIES, - NEAR_GRAB_DISTANCE + TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, NEAR_GRAB_DISTANCE, + distanceBetweenEntityLocalPositionAndBoundingBox, getGrabbableData, getGrabPointSphereOffset, DISPATCHER_PROPERTIES */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -36,7 +35,6 @@ Script.include("/~/system/libraries/controllers.js"); this.autoUnequipCounter = 0; this.lastUnexpectedChildrenCheckTime = 0; this.robbed = false; - this.highlightedEntity = null; this.cloneAllowed = true; this.parameters = makeDispatcherModuleParameters( @@ -86,14 +84,7 @@ Script.include("/~/system/libraries/controllers.js"); this.startNearParentingGrabEntity = function (controllerData, targetProps) { var grabData = getGrabbableData(targetProps); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - unhighlightTargetEntity(this.targetEntityID); - this.highlightedEntity = null; - var message = { - hand: this.hand, - entityID: this.targetEntityID - }; - Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); var handJointIndex; if (grabData.grabFollowsController) { handJointIndex = getControllerJointIndex(this.hand); @@ -154,8 +145,7 @@ Script.include("/~/system/libraries/controllers.js"); grabbedEntity: this.targetEntityID, joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" })); - unhighlightTargetEntity(this.targetEntityID); - this.highlightedEntity = null; + this.grabbing = false; this.targetEntityID = null; this.robbed = false; @@ -279,15 +269,9 @@ Script.include("/~/system/libraries/controllers.js"); return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it } else { this.targetEntityID = targetProps.id; - this.highlightedEntity = this.targetEntityID; - highlightTargetEntity(this.targetEntityID); return makeRunningValues(true, [this.targetEntityID], []); } } else { - if (this.highlightedEntity) { - unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; - } this.robbed = false; return makeRunningValues(false, [], []); } @@ -304,8 +288,6 @@ Script.include("/~/system/libraries/controllers.js"); var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; if (!props) { // entity was deleted - unhighlightTargetEntity(this.targetEntityID); - this.highlightedEntity = null; this.grabbing = false; this.targetEntityID = null; this.robbed = false; @@ -322,12 +304,10 @@ Script.include("/~/system/libraries/controllers.js"); var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "continueNearGrab", args); } else { - // still searching / highlighting + // still searching var readiness = this.isReady(controllerData); if (!readiness.active) { this.robbed = false; - unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; return readiness; } if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) { diff --git a/scripts/system/controllers/controllerModules/nearTrigger.js b/scripts/system/controllers/controllerModules/nearTrigger.js index f4e39cfbb9..4bff4ea3f0 100644 --- a/scripts/system/controllers/controllerModules/nearTrigger.js +++ b/scripts/system/controllers/controllerModules/nearTrigger.js @@ -7,7 +7,7 @@ /* global Script, Entities, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, getGrabbableData, - Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS, unhighlightTargetEntity + Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -55,7 +55,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.startNearTrigger = function (controllerData) { var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "startNearTrigger", args); - unhighlightTargetEntity(this.targetEntityID); }; this.continueNearTrigger = function (controllerData) { diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 999e448171..83fa455519 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -35,9 +35,7 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/hudOverlayPointer.js", "controllerModules/mouseHMD.js", "controllerModules/scaleEntity.js", - "controllerModules/highlightNearbyEntities.js", "controllerModules/nearGrabHyperLinkEntity.js", - "controllerModules/mouseHighlightEntities.js", "controllerModules/nearTabletHighlight.js" ]; diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 1bfa9d4b20..e3da1c2577 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -219,17 +219,12 @@ }); } - function buyButtonClicked(id, name, author, price, href, referrer, edition, type) { + function buyButtonClicked(id, referrer, edition) { EventBridge.emitWebEvent(JSON.stringify({ type: "CHECKOUT", itemId: id, - itemName: name, - itemPrice: price ? parseInt(price, 10) : 0, - itemHref: href, referrer: referrer, - itemAuthor: author, - itemEdition: edition, - itemType: type.trim() + itemEdition: edition })); } @@ -313,13 +308,8 @@ return false; } buyButtonClicked($(this).closest('.grid-item').attr('data-item-id'), - $(this).closest('.grid-item').find('.item-title').text(), - $(this).closest('.grid-item').find('.creator').find('.value').text(), - $(this).closest('.grid-item').find('.item-cost').text(), - $(this).attr('data-href'), "mainPage", - -1, - $(this).closest('.grid-item').find('.item-type').text()); + -1); }); } @@ -427,13 +417,8 @@ purchaseButton.on('click', function () { if ('available' === availability || isUpdating) { buyButtonClicked(window.location.pathname.split("/")[3], - $('#top-center').find('h1').text(), - $('#creator').find('.value').text(), - cost, - href, "itemPage", - urlParams.get('edition'), - type); + urlParams.get('edition')); } }); } diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index be25d1265f..e4891a9bae 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -471,7 +471,7 @@ function onWebEventReceived(message) { wireQmlEventBridge(true); ui.open(MARKETPLACE_CHECKOUT_QML_PATH); ui.tablet.sendToQml({ - method: 'updateCheckoutQML', + method: 'updateCheckoutQMLItemID', params: message }); } else if (message.type === "REQUEST_SETTING") { @@ -649,8 +649,8 @@ var onQmlMessageReceived = function onQmlMessageReceived(message) { case 'purchases_openGoTo': case 'purchases_itemInfoClicked': case 'purchases_itemCertificateClicked': - case 'clearShouldShowDotHistory': - case 'giftAsset': + case 'clearShouldShowDotHistory': + case 'giftAsset': break; default: print('marketplaces.js: Unrecognized message from Checkout.qml'); diff --git a/tests-manual/gpu/src/TestFbx.cpp b/tests-manual/gpu/src/TestFbx.cpp index 9253f8bc91..d3eab9e8e3 100644 --- a/tests-manual/gpu/src/TestFbx.cpp +++ b/tests-manual/gpu/src/TestFbx.cpp @@ -12,7 +12,7 @@ #include <QtCore/QFile> -#include <FBXReader.h> +#include <FBXSerializer.h> struct MyVertex { vec3 position; @@ -100,7 +100,7 @@ bool TestFbx::isReady() const { void TestFbx::parseFbx(const QByteArray& fbxData) { QVariantHash mapping; - HFMModel* hfmModel = readFBX(fbxData, mapping); + HFMModel::Pointer hfmModel = FBXSerializer().read(fbxData, mapping); size_t totalVertexCount = 0; size_t totalIndexCount = 0; size_t totalPartCount = 0; @@ -163,7 +163,6 @@ void TestFbx::parseFbx(const QByteArray& fbxData) { _vertexBuffer->append(vertices); _indexBuffer->append(indices); _indirectBuffer->append(parts); - delete hfmModel; } void TestFbx::renderTest(size_t testId, RenderArgs* args) { diff --git a/tools/dissectors/1-hfudt.lua b/tools/dissectors/1-hfudt.lua index 9ad89462f9..3993b2d7a0 100644 --- a/tools/dissectors/1-hfudt.lua +++ b/tools/dissectors/1-hfudt.lua @@ -39,9 +39,9 @@ p_hfudt.fields = { local control_types = { [0] = { "ACK", "Acknowledgement" }, - [5] = { "Handshake", "Handshake" }, - [6] = { "HandshakeACK", "Acknowledgement of Handshake" }, - [8] = { "HandshakeRequest", "Request a Handshake" } + [1] = { "Handshake", "Handshake" }, + [2] = { "HandshakeACK", "Acknowledgement of Handshake" }, + [3] = { "HandshakeRequest", "Request a Handshake" } } local message_positions = { diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.cpp b/tools/skeleton-dump/src/SkeletonDumpApp.cpp index 10b13aef36..42a1c78090 100644 --- a/tools/skeleton-dump/src/SkeletonDumpApp.cpp +++ b/tools/skeleton-dump/src/SkeletonDumpApp.cpp @@ -12,7 +12,7 @@ #include "SkeletonDumpApp.h" #include <QCommandLineParser> #include <QFile> -#include <FBXReader.h> +#include <FBXSerializer.h> #include <AnimSkeleton.h> SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { @@ -54,7 +54,7 @@ SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc return; } QByteArray blob = file.readAll(); - std::unique_ptr<HFMModel> geometry(readFBX(blob, QVariantHash())); + HFMModel::Pointer geometry = FBXSerializer().read(blob, QVariantHash()); std::unique_ptr<AnimSkeleton> skeleton(new AnimSkeleton(*geometry)); skeleton->dump(verbose); } diff --git a/tools/vhacd-util/src/VHACDUtil.cpp b/tools/vhacd-util/src/VHACDUtil.cpp index 8de9c39da9..9401da4314 100644 --- a/tools/vhacd-util/src/VHACDUtil.cpp +++ b/tools/vhacd-util/src/VHACDUtil.cpp @@ -15,9 +15,11 @@ #include <QVector> #include <NumericalConstants.h> +#include <FBXSerializer.h> +#include <OBJSerializer.h> -// FBXReader jumbles the order of the meshes by reading them back out of a hashtable. This will put +// FBXSerializer jumbles the order of the meshes by reading them back out of a hashtable. This will put // them back in the order in which they appeared in the file. bool HFMModelLessThan(const HFMMesh& e1, const HFMMesh& e2) { return e1.meshIndex < e2.meshIndex; @@ -43,10 +45,9 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, HFMModel& result) { QByteArray fbxContents = fbx.readAll(); HFMModel::Pointer hfmModel; if (filename.toLower().endsWith(".obj")) { - bool combineParts = false; - hfmModel = OBJReader().readOBJ(fbxContents, QVariantHash(), combineParts); + hfmModel = OBJSerializer().read(fbxContents, QVariantHash(), filename); } else if (filename.toLower().endsWith(".fbx")) { - hfmModel.reset(readFBX(fbxContents, QVariantHash(), filename)); + hfmModel = FBXSerializer().read(fbxContents, QVariantHash(), filename); } else { qWarning() << "file has unknown extension" << filename; return false; diff --git a/tools/vhacd-util/src/VHACDUtil.h b/tools/vhacd-util/src/VHACDUtil.h index dd8f606756..0fb70e8af7 100644 --- a/tools/vhacd-util/src/VHACDUtil.h +++ b/tools/vhacd-util/src/VHACDUtil.h @@ -18,10 +18,10 @@ #include <vector> #include <chrono> //c++11 feature #include <QFile> -#include <FBXReader.h> -#include <OBJReader.h> #include <VHACD.h> +#include <hfm/HFM.h> + namespace vhacd { class VHACDUtil { public: diff --git a/tools/vhacd-util/src/VHACDUtilApp.h b/tools/vhacd-util/src/VHACDUtilApp.h index 7dadad20b3..1cbb29bb88 100644 --- a/tools/vhacd-util/src/VHACDUtilApp.h +++ b/tools/vhacd-util/src/VHACDUtilApp.h @@ -15,7 +15,7 @@ #include <QCoreApplication> -#include <FBXReader.h> +#include <FBXSerializer.h> const int VHACD_RETURN_CODE_FAILURE_TO_READ = 1; const int VHACD_RETURN_CODE_FAILURE_TO_WRITE = 2;