fixing merge conflict

This commit is contained in:
Dante Ruiz 2018-02-12 10:57:55 -08:00
commit 3c84318918
34 changed files with 2266 additions and 3321 deletions

5
.gitignore vendored
View file

@ -85,4 +85,7 @@ npm-debug.log
android/app/src/main/assets
# Resource binary file
interface/compiledResources
interface/compiledResources
# GPUCache
interface/resources/GPUCache/*

View file

@ -19,21 +19,31 @@ import "../../../controls-uit" as HifiControlsUit
import "../../../controls" as HifiControls
import "../wallet" as HifiWallet
// references XXX from root context
Rectangle {
HifiConstants { id: hifi; }
id: root;
property string marketplaceUrl;
property string certificateId;
property string marketplaceUrl: "";
property string entityId: "";
property string certificateId: "";
property string itemName: "--";
property string itemOwner: "--";
property string itemEdition: "--";
property string dateOfPurchase: "--";
property string itemCost: "--";
property string certTitleTextColor: hifi.colors.darkGray;
property string certTextColor: hifi.colors.white;
property string infoTextColor: hifi.colors.blueAccent;
// 0 means replace none
// 4 means replace all but "Item Edition"
// 5 means replace all 5 replaceable fields
property int certInfoReplaceMode: 5;
property bool isLightbox: false;
property bool isMyCert: false;
property bool isCertificateInvalid: false;
property bool useGoldCert: true;
property bool certificateInfoPending: true;
property int certificateStatus: 0;
property bool certificateStatusPending: true;
// Style
color: hifi.colors.faintGray;
Connections {
@ -45,72 +55,135 @@ Rectangle {
} else {
root.marketplaceUrl = result.data.marketplace_item_url;
root.isMyCert = result.isMyCert ? result.isMyCert : false;
root.itemOwner = root.isCertificateInvalid ? "--" : (root.isMyCert ? Account.username :
"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022");
root.itemEdition = root.isCertificateInvalid ? "Uncertified Copy" :
(result.data.edition_number + "/" + (result.data.limited_run === -1 ? "\u221e" : result.data.limited_run));
root.dateOfPurchase = root.isCertificateInvalid ? "" : getFormattedDate(result.data.transfer_created_at * 1000);
root.itemName = result.data.marketplace_item_name;
if (root.certInfoReplaceMode > 3) {
root.itemName = result.data.marketplace_item_name;
// "\u2022" is the Unicode character 'BULLET' - it's what's used in password fields on the web, etc
root.itemOwner = root.isMyCert ? Account.username :
"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
root.dateOfPurchase = root.isMyCert ? getFormattedDate(result.data.transfer_created_at * 1000) : "Undisclosed";
root.itemCost = (root.isMyCert && result.data.cost !== undefined) ? result.data.cost : "Undisclosed";
}
if (root.certInfoReplaceMode > 4) {
root.itemEdition = result.data.edition_number + "/" + (result.data.limited_run === -1 ? "\u221e" : result.data.limited_run);
}
if (root.certificateStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED
if (root.isMyCert) {
errorText.text = "This item is an uncertified copy of an item you purchased.";
} else {
errorText.text = "The person who placed this item doesn't own it.";
}
}
if (result.data.invalid_reason || result.data.transfer_status[0] === "failed") {
titleBarText.text = "Invalid Certificate";
titleBarText.color = hifi.colors.redHighlight;
root.useGoldCert = false;
root.certTitleTextColor = hifi.colors.redHighlight;
root.certTextColor = hifi.colors.redHighlight;
root.infoTextColor = hifi.colors.redHighlight;
titleBarText.text = "Certificate\nNo Longer Valid";
popText.text = "";
showInMarketplaceButton.visible = false;
// "Edition" text previously set above in this function
// "Owner" text previously set above in this function
// "Purchase Date" text previously set above in this function
// "Purchase Price" text previously set above in this function
if (result.data.invalid_reason) {
errorText.text = result.data.invalid_reason;
}
} else if (result.data.transfer_status[0] === "pending") {
root.useGoldCert = false;
root.certTitleTextColor = hifi.colors.redHighlight;
root.certTextColor = hifi.colors.redHighlight;
root.infoTextColor = hifi.colors.redHighlight;
titleBarText.text = "Certificate Pending";
popText.text = "";
showInMarketplaceButton.visible = true;
// "Edition" text previously set above in this function
// "Owner" text previously set above in this function
// "Purchase Date" text previously set above in this function
// "Purchase Price" text previously set above in this function
errorText.text = "The status of this item is still pending confirmation. If the purchase is not confirmed, " +
"this entity will be cleaned up by the domain.";
errorText.color = hifi.colors.baseGray;
}
}
root.certificateInfoPending = false;
}
onUpdateCertificateStatus: {
if (certStatus === 1) { // CERTIFICATE_STATUS_VERIFICATION_SUCCESS
// NOP
} else if (certStatus === 2) { // CERTIFICATE_STATUS_VERIFICATION_TIMEOUT
root.isCertificateInvalid = true;
errorText.text = "Verification of this certificate timed out.";
errorText.color = hifi.colors.redHighlight;
} else if (certStatus === 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED
root.isCertificateInvalid = true;
titleBarText.text = "Invalid Certificate";
titleBarText.color = hifi.colors.redHighlight;
popText.text = "";
root.itemOwner = "";
dateOfPurchaseHeader.text = "";
root.dateOfPurchase = "";
root.itemEdition = "Uncertified Copy";
errorText.text = "The information associated with this item has been modified and it no longer matches the original certified item.";
errorText.color = hifi.colors.baseGray;
} else if (certStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED
root.isCertificateInvalid = true;
titleBarText.text = "Invalid Certificate";
titleBarText.color = hifi.colors.redHighlight;
popText.text = "";
root.itemOwner = "";
dateOfPurchaseHeader.text = "";
root.dateOfPurchase = "";
root.itemEdition = "Uncertified Copy";
errorText.text = "The avatar who rezzed this item doesn't own it.";
errorText.color = hifi.colors.baseGray;
} else {
console.log("Unknown certificate status received from ledger signal!");
}
updateCertificateStatus(certStatus);
}
}
onCertificateIdChanged: {
if (certificateId !== "") {
Commerce.certificateInfo(certificateId);
function updateCertificateStatus(status) {
root.certificateStatus = status;
if (root.certificateStatus === 1) { // CERTIFICATE_STATUS_VERIFICATION_SUCCESS
root.useGoldCert = true;
root.certTitleTextColor = hifi.colors.darkGray;
root.certTextColor = hifi.colors.white;
root.infoTextColor = hifi.colors.blueAccent;
titleBarText.text = "Certificate";
popText.text = "PROOF OF PROVENANCE";
showInMarketplaceButton.visible = true;
root.certInfoReplaceMode = 5;
// "Item Name" text will be set in "onCertificateInfoResult()"
// "Edition" text will be set in "onCertificateInfoResult()"
// "Owner" text will be set in "onCertificateInfoResult()"
// "Purchase Date" text will be set in "onCertificateInfoResult()"
// "Purchase Price" text will be set in "onCertificateInfoResult()"
errorText.text = "";
} else if (root.certificateStatus === 2) { // CERTIFICATE_STATUS_VERIFICATION_TIMEOUT
root.useGoldCert = false;
root.certTitleTextColor = hifi.colors.redHighlight;
root.certTextColor = hifi.colors.redHighlight;
root.infoTextColor = hifi.colors.redHighlight;
titleBarText.text = "Request Timed Out";
popText.text = "";
showInMarketplaceButton.visible = false;
root.certInfoReplaceMode = 0;
root.itemName = "";
root.itemEdition = "";
root.itemOwner = "";
root.dateOfPurchase = "";
root.itemCost = "";
errorText.text = "Your request to inspect this item timed out. Please try again later.";
} else if (root.certificateStatus === 3) { // CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED
root.useGoldCert = false;
root.certTitleTextColor = hifi.colors.redHighlight;
root.certTextColor = hifi.colors.redHighlight;
root.infoTextColor = hifi.colors.redHighlight;
titleBarText.text = "Certificate\nNo Longer Valid";
popText.text = "";
showInMarketplaceButton.visible = true;
root.certInfoReplaceMode = 5;
// "Item Name" text will be set in "onCertificateInfoResult()"
// "Edition" text will be set in "onCertificateInfoResult()"
// "Owner" text will be set in "onCertificateInfoResult()"
// "Purchase Date" text will be set in "onCertificateInfoResult()"
// "Purchase Price" text will be set in "onCertificateInfoResult()"
errorText.text = "The information associated with this item has been modified and it no longer matches the original certified item.";
} else if (root.certificateStatus === 4) { // CERTIFICATE_STATUS_OWNER_VERIFICATION_FAILED
root.useGoldCert = false;
root.certTitleTextColor = hifi.colors.redHighlight;
root.certTextColor = hifi.colors.redHighlight;
root.infoTextColor = hifi.colors.redHighlight;
titleBarText.text = "Invalid Certificate";
popText.text = "";
showInMarketplaceButton.visible = true;
root.certInfoReplaceMode = 4;
// "Item Name" text will be set in "onCertificateInfoResult()"
root.itemEdition = "Uncertified Copy"
// "Owner" text will be set in "onCertificateInfoResult()"
// "Purchase Date" text will be set in "onCertificateInfoResult()"
// "Purchase Price" text will be set in "onCertificateInfoResult()"
// "Error Text" text will be set in "onCertificateInfoResult()"
} else {
console.log("Unknown certificate status received from ledger signal!");
}
root.certificateStatusPending = false;
// We've gotten cert status - we are GO on getting the cert info
Commerce.certificateInfo(root.certificateId);
}
// This object is always used in a popup.
@ -122,9 +195,35 @@ Rectangle {
hoverEnabled: true;
}
Image {
Rectangle {
id: loadingOverlay;
z: 998;
visible: root.certificateInfoPending || root.certificateStatusPending;
anchors.fill: parent;
source: "images/cert-bg.jpg";
color: Qt.rgba(0.0, 0.0, 0.0, 0.7);
// This object is always used in a popup or full-screen Wallet section.
// This MouseArea is used to prevent a user from being
// able to click on a button/mouseArea underneath the popup/section.
MouseArea {
anchors.fill: parent;
propagateComposedEvents: false;
}
AnimatedImage {
source: "../common/images/loader.gif"
width: 96;
height: width;
anchors.verticalCenter: parent.verticalCenter;
anchors.horizontalCenter: parent.horizontalCenter;
}
}
Image {
id: backgroundImage;
anchors.fill: parent;
source: root.useGoldCert ? "images/cert-bg-gold-split.png" : "images/nocert-bg-split.png";
}
// Title text
@ -137,16 +236,17 @@ Rectangle {
anchors.top: parent.top;
anchors.topMargin: 40;
anchors.left: parent.left;
anchors.leftMargin: 45;
anchors.leftMargin: 36;
anchors.right: parent.right;
anchors.rightMargin: 8;
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
color: root.certTitleTextColor;
wrapMode: Text.WordWrap;
}
// Title text
RalewayRegular {
id: popText;
text: "Proof of Provenance";
// Text size
size: 16;
// Anchors
@ -154,9 +254,39 @@ Rectangle {
anchors.topMargin: 4;
anchors.left: titleBarText.left;
anchors.right: titleBarText.right;
height: paintedHeight;
height: text === "" ? 0 : paintedHeight;
// Style
color: hifi.colors.darkGray;
color: root.certTitleTextColor;
}
// "Close" button
HiFiGlyphs {
z: 999;
id: closeGlyphButton;
text: hifi.glyphs.close;
color: hifi.colors.white;
size: 26;
anchors.top: parent.top;
anchors.topMargin: 10;
anchors.right: parent.right;
anchors.rightMargin: 10;
MouseArea {
anchors.fill: parent;
hoverEnabled: true;
onEntered: {
parent.text = hifi.glyphs.closeInverted;
}
onExited: {
parent.text = hifi.glyphs.close;
}
onClicked: {
if (root.isLightbox) {
root.visible = false;
} else {
sendToScript({method: 'inspectionCertificate_closeClicked', closeGoesToPurchases: root.closeGoesToPurchases});
}
}
}
}
//
@ -164,11 +294,13 @@ Rectangle {
//
Item {
id: certificateContainer;
anchors.top: popText.bottom;
anchors.topMargin: 30;
anchors.bottom: buttonsContainer.top;
anchors.top: titleBarText.top;
anchors.topMargin: 110;
anchors.bottom: infoContainer.top;
anchors.left: parent.left;
anchors.leftMargin: titleBarText.anchors.leftMargin;
anchors.right: parent.right;
anchors.rightMargin: 24;
RalewayRegular {
id: itemNameHeader;
@ -178,9 +310,7 @@ Rectangle {
// Anchors
anchors.top: parent.top;
anchors.left: parent.left;
anchors.leftMargin: 45;
anchors.right: parent.right;
anchors.rightMargin: 16;
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
@ -197,79 +327,30 @@ Rectangle {
anchors.right: itemNameHeader.right;
height: paintedHeight;
// Style
color: hifi.colors.white;
color: root.certTextColor;
elide: Text.ElideRight;
MouseArea {
enabled: showInMarketplaceButton.visible;
anchors.fill: parent;
hoverEnabled: enabled;
onClicked: {
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
}
onEntered: itemName.color = hifi.colors.blueHighlight;
onExited: itemName.color = hifi.colors.white;
onExited: itemName.color = root.certTextColor;
}
}
RalewayRegular {
id: ownedByHeader;
text: "OWNER";
// Text size
size: 16;
// Anchors
anchors.top: itemName.bottom;
anchors.topMargin: 28;
anchors.left: parent.left;
anchors.leftMargin: 45;
anchors.right: parent.right;
anchors.rightMargin: 16;
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
}
RalewayRegular {
id: ownedBy;
text: root.itemOwner;
// Text size
size: 22;
// Anchors
anchors.top: ownedByHeader.bottom;
anchors.topMargin: 8;
anchors.left: ownedByHeader.left;
height: paintedHeight;
// Style
color: hifi.colors.white;
elide: Text.ElideRight;
}
AnonymousProRegular {
id: isMyCertText;
visible: root.isMyCert && !root.isCertificateInvalid;
text: "(Private)";
size: 18;
// Anchors
anchors.top: ownedBy.top;
anchors.topMargin: 4;
anchors.bottom: ownedBy.bottom;
anchors.left: ownedBy.right;
anchors.leftMargin: 6;
anchors.right: ownedByHeader.right;
// Style
color: hifi.colors.white;
elide: Text.ElideRight;
verticalAlignment: Text.AlignVCenter;
}
RalewayRegular {
id: editionHeader;
text: "EDITION";
// Text size
size: 16;
// Anchors
anchors.top: ownedBy.bottom;
anchors.top: itemName.bottom;
anchors.topMargin: 28;
anchors.left: parent.left;
anchors.leftMargin: 45;
anchors.right: parent.right;
anchors.rightMargin: 16;
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
@ -286,21 +367,117 @@ Rectangle {
anchors.right: editionHeader.right;
height: paintedHeight;
// Style
color: hifi.colors.white;
color: root.certTextColor;
}
// "Show In Marketplace" button
HifiControlsUit.Button {
id: showInMarketplaceButton;
enabled: root.marketplaceUrl;
color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.light;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 48;
anchors.right: parent.right;
width: 200;
height: 40;
text: "View In Market"
onClicked: {
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
}
}
}
//
// "CERTIFICATE" END
//
//
// "INFO CONTAINER" START
//
Item {
id: infoContainer;
anchors.bottom: parent.bottom;
anchors.left: parent.left;
anchors.leftMargin: titleBarText.anchors.leftMargin;
anchors.right: parent.right;
anchors.rightMargin: 24;
height: root.useGoldCert ? 220 : 372;
RalewayRegular {
id: errorText;
visible: !root.useGoldCert;
// Text size
size: 20;
// Anchors
anchors.top: parent.top;
anchors.topMargin: 36;
anchors.left: parent.left;
anchors.right: parent.right;
height: 116;
// Style
wrapMode: Text.WordWrap;
color: hifi.colors.baseGray;
verticalAlignment: Text.AlignTop;
}
RalewayRegular {
id: ownedByHeader;
text: "OWNER";
// Text size
size: 16;
// Anchors
anchors.top: errorText.visible ? errorText.bottom : parent.top;
anchors.topMargin: 28;
anchors.left: parent.left;
anchors.right: parent.right;
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
}
RalewayRegular {
id: ownedBy;
text: root.itemOwner;
// Text size
size: 22;
// Anchors
anchors.top: ownedByHeader.bottom;
anchors.topMargin: 8;
anchors.left: ownedByHeader.left;
height: paintedHeight;
// Style
color: root.infoTextColor;
elide: Text.ElideRight;
}
AnonymousProRegular {
id: isMyCertText;
visible: root.isMyCert && ownedBy.text !== "--" && ownedBy.text !== "";
text: "(Private)";
size: 18;
// Anchors
anchors.top: ownedBy.top;
anchors.topMargin: 4;
anchors.bottom: ownedBy.bottom;
anchors.left: ownedBy.right;
anchors.leftMargin: 6;
anchors.right: ownedByHeader.right;
// Style
color: root.infoTextColor;
elide: Text.ElideRight;
verticalAlignment: Text.AlignVCenter;
}
RalewayRegular {
id: dateOfPurchaseHeader;
text: "DATE OF PURCHASE";
text: "PURCHASE DATE";
// Text size
size: 16;
// Anchors
anchors.top: edition.bottom;
anchors.top: ownedBy.bottom;
anchors.topMargin: 28;
anchors.left: parent.left;
anchors.leftMargin: 45;
anchors.right: parent.right;
anchors.rightMargin: 16;
anchors.right: parent.horizontalCenter;
anchors.rightMargin: 8;
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
@ -317,73 +494,58 @@ Rectangle {
anchors.right: dateOfPurchaseHeader.right;
height: paintedHeight;
// Style
color: hifi.colors.white;
color: root.infoTextColor;
}
RalewayRegular {
id: errorText;
id: priceHeader;
text: "PURCHASE PRICE";
// Text size
size: 20;
size: 16;
// Anchors
anchors.top: dateOfPurchase.bottom;
anchors.topMargin: 36;
anchors.left: dateOfPurchase.left;
anchors.right: dateOfPurchase.right;
anchors.bottom: parent.bottom;
// Style
wrapMode: Text.WordWrap;
color: hifi.colors.redHighlight;
verticalAlignment: Text.AlignTop;
}
}
//
// "CERTIFICATE" END
//
Item {
id: buttonsContainer;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 30;
anchors.left: parent.left;
anchors.right: parent.right;
height: 50;
// "Cancel" button
HifiControlsUit.Button {
color: hifi.buttons.noneBorderlessWhite;
colorScheme: hifi.colorSchemes.light;
anchors.top: parent.top;
anchors.left: parent.left;
anchors.leftMargin: 30;
width: parent.width/2 - 50;
height: 50;
text: "close";
onClicked: {
if (root.isLightbox) {
root.visible = false;
} else {
sendToScript({method: 'inspectionCertificate_closeClicked', closeGoesToPurchases: root.closeGoesToPurchases});
}
}
}
// "Show In Marketplace" button
HifiControlsUit.Button {
id: showInMarketplaceButton;
enabled: root.marketplaceUrl;
color: hifi.buttons.blue;
colorScheme: hifi.colorSchemes.light;
anchors.top: parent.top;
anchors.top: ownedBy.bottom;
anchors.topMargin: 28;
anchors.left: parent.horizontalCenter;
anchors.right: parent.right;
anchors.rightMargin: 30;
width: parent.width/2 - 50;
height: 50;
text: "View In Market"
onClicked: {
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
}
height: paintedHeight;
// Style
color: hifi.colors.darkGray;
}
HiFiGlyphs {
id: hfcGlyph;
visible: priceText.text !== "Undisclosed" && priceText.text !== "";
text: hifi.glyphs.hfc;
// Size
size: 24;
// Anchors
anchors.top: priceHeader.bottom;
anchors.topMargin: 8;
anchors.left: priceHeader.left;
width: visible ? paintedWidth + 6 : 0;
height: 40;
// Style
color: root.infoTextColor;
verticalAlignment: Text.AlignTop;
horizontalAlignment: Text.AlignLeft;
}
AnonymousProRegular {
id: priceText;
text: root.itemCost;
// Text size
size: 18;
// Anchors
anchors.top: priceHeader.bottom;
anchors.topMargin: 8;
anchors.left: hfcGlyph.right;
anchors.right: priceHeader.right;
height: paintedHeight;
// Style
color: root.infoTextColor;
}
}
//
// "INFO CONTAINER" END
//
//
// FUNCTION DEFINITIONS START
@ -404,19 +566,17 @@ Rectangle {
function fromScript(message) {
switch (message.method) {
case 'inspectionCertificate_setCertificateId':
resetCert(false);
root.certificateId = message.certificateId;
if (message.entityId === "") {
updateCertificateStatus(1); // CERTIFICATE_STATUS_VERIFICATION_SUCCESS
} else {
root.entityId = message.entityId;
sendToScript({method: 'inspectionCertificate_requestOwnershipVerification', entity: root.entityId});
}
break;
case 'inspectionCertificate_resetCert':
titleBarText.text = "Certificate";
popText.text = "PROOF OF PURCHASE";
root.certificateId = "";
root.itemName = "--";
root.itemOwner = "--";
root.itemEdition = "--";
root.dateOfPurchase = "--";
root.marketplaceUrl = "";
root.isMyCert = false;
errorText.text = "";
resetCert(true);
break;
default:
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
@ -424,7 +584,34 @@ Rectangle {
}
signal sendToScript(var message);
function resetCert(alsoResetCertID) {
if (alsoResetCertID) {
root.entityId = "";
root.certificateId = "";
}
root.certInfoReplaceMode = 5;
root.certificateInfoPending = true;
root.certificateStatusPending = true;
root.useGoldCert = true;
root.certTitleTextColor = hifi.colors.darkGray;
root.certTextColor = hifi.colors.white;
root.infoTextColor = hifi.colors.blueAccent;
titleBarText.text = "Certificate";
popText.text = "";
root.itemName = "--";
root.itemOwner = "--";
root.itemEdition = "--";
root.dateOfPurchase = "--";
root.marketplaceUrl = "";
root.itemCost = "--";
root.isMyCert = false;
errorText.text = "";
}
function getFormattedDate(timestamp) {
if (timestamp === "--") {
return "--";
}
function addLeadingZero(n) {
return n < 10 ? '0' + n : '' + n;
}
@ -449,7 +636,7 @@ Rectangle {
var min = addLeadingZero(a.getMinutes());
var sec = addLeadingZero(a.getSeconds());
return year + '-' + month + '-' + day + '<br>' + drawnHour + ':' + min + amOrPm;
return year + '-' + month + '-' + day + ' ' + drawnHour + ':' + min + amOrPm;
}
//
// FUNCTION DEFINITIONS END

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -1115,7 +1115,7 @@ Item {
AnimatedImage {
id: sendingMoneyImage;
source: "./images/loader.gif"
source: "../../common/images/loader.gif"
width: 96;
height: width;
anchors.verticalCenter: parent.verticalCenter;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

View file

@ -67,7 +67,7 @@ QPushButton#revealLogButton {
font-size: 11px;
}
QPushButton#showAllButton {
QPushButton#allLogsButton {
font-family: Helvetica, Arial, sans-serif;
background-color: #333333;
color: #BBBBBB;
@ -112,4 +112,11 @@ QComboBox::drop-down {
QComboBox::down-arrow {
image: url(:/styles/filter.png);
border-width: 0px;
}
QLabel#messageCount {
font-family: Helvetica, Arial, sans-serif;
text-align: center;
color: #3d3d3d;
font-size: 11px;
}

View file

@ -959,6 +959,18 @@ void MyAvatar::restoreRoleAnimation(const QString& role) {
_skeletonModel->getRig().restoreRoleAnimation(role);
}
void MyAvatar::saveAvatarUrl() {
Settings settings;
settings.beginGroup("Avatar");
if (qApp->getSaveAvatarOverrideUrl() || !qApp->getAvatarOverrideUrl().isValid() ) {
settings.setValue("fullAvatarURL",
_fullAvatarURLFromPreferences == AvatarData::defaultFullAvatarModelUrl() ?
"" :
_fullAvatarURLFromPreferences.toString());
}
settings.endGroup();
}
void MyAvatar::saveData() {
Settings settings;
settings.beginGroup("Avatar");
@ -1455,8 +1467,8 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
_headBoneSet.clear();
_cauterizationNeedsUpdate = true;
std::shared_ptr<QMetaObject::Connection> skeletonConnection = std::make_shared<QMetaObject::Connection>();
*skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() {
std::shared_ptr<QMetaObject::Connection> skeletonConnection = std::make_shared<QMetaObject::Connection>();
*skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() {
if (skeletonModelChangeCount == _skeletonModelChangeCount) {
initHeadBones();
_skeletonModel->setCauterizeBoneSet(_headBoneSet);
@ -1465,6 +1477,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
}
QObject::disconnect(*skeletonConnection);
});
saveAvatarUrl();
emit skeletonChanged();
}

View file

@ -647,6 +647,7 @@ private:
void simulate(float deltaTime);
void updateFromTrackers(float deltaTime);
void saveAvatarUrl();
virtual void render(RenderArgs* renderArgs) override;
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override;
void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; setEnableMeshVisible(shouldRender); }

View file

@ -29,8 +29,8 @@ const int SEARCH_TOGGLE_BUTTON_WIDTH = 50;
const int SEARCH_TEXT_WIDTH = 240;
const int TIME_STAMP_LENGTH = 16;
const int FONT_WEIGHT = 75;
const QColor HIGHLIGHT_COLOR = QColor("#3366CC");
const QColor BOLD_COLOR = QColor("#445c8c");
const QColor HIGHLIGHT_COLOR = QColor("#00B4EF");
const QColor BOLD_COLOR = QColor("#1080B8");
const QString BOLD_PATTERN = "\\[\\d*\\/.*:\\d*:\\d*\\]";
BaseLogDialog::BaseLogDialog(QWidget* parent) : QDialog(parent, Qt::Window) {
@ -182,6 +182,7 @@ void BaseLogDialog::updateSelection() {
Highlighter::Highlighter(QTextDocument* parent) : QSyntaxHighlighter(parent) {
boldFormat.setFontWeight(FONT_WEIGHT);
boldFormat.setForeground(BOLD_COLOR);
keywordFormat.setFontWeight(FONT_WEIGHT);
keywordFormat.setForeground(HIGHLIGHT_COLOR);
}

View file

@ -15,11 +15,12 @@
#include <QPushButton>
#include <QComboBox>
#include <QPlainTextEdit>
#include <QLabel>
#include <shared/AbstractLoggerInterface.h>
const int REVEAL_BUTTON_WIDTH = 122;
const int CLEAR_FILTER_BUTTON_WIDTH = 80;
const int ALL_LOGS_BUTTON_WIDTH = 90;
const int MARGIN_LEFT = 25;
const int DEBUG_CHECKBOX_WIDTH = 70;
const int INFO_CHECKBOX_WIDTH = 65;
@ -142,6 +143,11 @@ LogDialog::LogDialog(QWidget* parent, AbstractLoggerInterface* logger) : BaseLog
_filterDropdown->addItem("qml");
connect(_filterDropdown, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &LogDialog::handleFilterDropdownChanged);
_leftPad += COMBOBOX_WIDTH + MARGIN_LEFT + MARGIN_LEFT;
_messageCount = new QLabel("", this);
_messageCount->setObjectName("messageCount");
_messageCount->show();
_extraDebuggingBox = new QCheckBox("Extra debugging", this);
if (_logger->extraDebugging()) {
_extraDebuggingBox->setCheckState(Qt::Checked);
@ -149,12 +155,13 @@ LogDialog::LogDialog(QWidget* parent, AbstractLoggerInterface* logger) : BaseLog
_extraDebuggingBox->show();
connect(_extraDebuggingBox, &QCheckBox::stateChanged, this, &LogDialog::handleExtraDebuggingCheckbox);
_clearFilterButton = new QPushButton("Clear Filters", this);
_allLogsButton = new QPushButton("All Messages", this);
// set object name for css styling
_clearFilterButton->setObjectName("showAllButton");
_clearFilterButton->show();
connect(_clearFilterButton, &QPushButton::clicked, this, &LogDialog::handleClearFilterButton);
handleClearFilterButton();
_allLogsButton->setObjectName("allLogsButton");
_allLogsButton->show();
connect(_allLogsButton, &QPushButton::clicked, this, &LogDialog::handleAllLogsButton);
handleAllLogsButton();
auto windowGeometry = _windowGeometry.get();
if (windowGeometry.isValid()) {
@ -168,11 +175,15 @@ void LogDialog::resizeEvent(QResizeEvent* event) {
ELEMENT_MARGIN,
REVEAL_BUTTON_WIDTH,
ELEMENT_HEIGHT);
_clearFilterButton->setGeometry(width() - ELEMENT_MARGIN - CLEAR_FILTER_BUTTON_WIDTH,
_allLogsButton->setGeometry(width() - ELEMENT_MARGIN - ALL_LOGS_BUTTON_WIDTH,
THIRD_ROW,
CLEAR_FILTER_BUTTON_WIDTH,
ALL_LOGS_BUTTON_WIDTH,
ELEMENT_HEIGHT);
_extraDebuggingBox->setGeometry(width() - ELEMENT_MARGIN - COMBOBOX_WIDTH - ELEMENT_MARGIN - CLEAR_FILTER_BUTTON_WIDTH,
_extraDebuggingBox->setGeometry(width() - ELEMENT_MARGIN - COMBOBOX_WIDTH - ELEMENT_MARGIN - ALL_LOGS_BUTTON_WIDTH,
THIRD_ROW,
COMBOBOX_WIDTH,
ELEMENT_HEIGHT);
_messageCount->setGeometry(_leftPad,
THIRD_ROW,
COMBOBOX_WIDTH,
ELEMENT_HEIGHT);
@ -187,13 +198,13 @@ void LogDialog::handleRevealButton() {
_logger->locateLog();
}
void LogDialog::handleClearFilterButton() {
void LogDialog::handleAllLogsButton() {
_logger->setExtraDebugging(false);
_extraDebuggingBox->setCheckState(Qt::Unchecked);
_logger->setDebugPrint(false);
_debugPrintBox->setCheckState(Qt::Unchecked);
_logger->setInfoPrint(false);
_infoPrintBox->setCheckState(Qt::Unchecked);
_logger->setDebugPrint(true);
_debugPrintBox->setCheckState(Qt::Checked);
_logger->setInfoPrint(true);
_infoPrintBox->setCheckState(Qt::Checked);
_logger->setCriticalPrint(true);
_criticalPrintBox->setCheckState(Qt::Checked);
_logger->setWarningPrint(true);
@ -270,40 +281,67 @@ void LogDialog::appendLogLine(QString logLine) {
if (logLine.contains(DEBUG_TEXT, Qt::CaseSensitive)) {
if (_logger->debugPrint()) {
_logTextBox->appendPlainText(logLine.trimmed());
_count++;
updateMessageCount();
}
} else if (logLine.contains(INFO_TEXT, Qt::CaseSensitive)) {
if (_logger->infoPrint()) {
_logTextBox->appendPlainText(logLine.trimmed());
_count++;
updateMessageCount();
}
} else if (logLine.contains(CRITICAL_TEXT, Qt::CaseSensitive)) {
if (_logger->criticalPrint()) {
_logTextBox->appendPlainText(logLine.trimmed());
_count++;
updateMessageCount();
}
} else if (logLine.contains(WARNING_TEXT, Qt::CaseSensitive)) {
if (_logger->warningPrint()) {
_logTextBox->appendPlainText(logLine.trimmed());
_count++;
updateMessageCount();
}
} else if (logLine.contains(SUPPRESS_TEXT, Qt::CaseSensitive)) {
if (_logger->suppressPrint()) {
_logTextBox->appendPlainText(logLine.trimmed());
_count++;
updateMessageCount();
}
} else if (logLine.contains(FATAL_TEXT, Qt::CaseSensitive)) {
if (_logger->fatalPrint()) {
_logTextBox->appendPlainText(logLine.trimmed());
_count++;
updateMessageCount();
}
} else {
if (_logger->unknownPrint()) {
if (_logger->unknownPrint() && logLine.trimmed() != "") {
_logTextBox->appendPlainText(logLine.trimmed());
_count++;
updateMessageCount();
}
}
}
}
void LogDialog::printLogFile() {
_count = 0;
_logTextBox->clear();
QString log = getCurrentLog();
QStringList logList = log.split('\n');
for (const auto& message : logList) {
appendLogLine(message);
}
updateMessageCount();
}
void LogDialog::updateMessageCount() {
_countLabel = QString::number(_count);
if (_count != 1) {
_countLabel.append(" log messages");
}
else {
_countLabel.append(" log message");
}
_messageCount->setText(_countLabel);
}

View file

@ -18,6 +18,7 @@
class QCheckBox;
class QPushButton;
class QComboBox;
class QLabel;
class QResizeEvent;
class AbstractLoggerInterface;
@ -41,19 +42,21 @@ private slots:
void handleFatalPrintBox(int);
void handleUnknownPrintBox(int);
void handleFilterDropdownChanged(int);
void handleClearFilterButton();
void handleAllLogsButton();
void printLogFile();
protected:
void resizeEvent(QResizeEvent* event) override;
void closeEvent(QCloseEvent* event) override;
QString getCurrentLog() override;
void printLogFile();
void updateMessageCount();
private:
QCheckBox* _extraDebuggingBox;
QPushButton* _revealLogButton;
QPushButton* _clearFilterButton;
QPushButton* _allLogsButton;
QCheckBox* _debugPrintBox;
QCheckBox* _infoPrintBox;
QCheckBox* _criticalPrintBox;
@ -62,10 +65,12 @@ private:
QCheckBox* _fatalPrintBox;
QCheckBox* _unknownPrintBox;
QComboBox* _filterDropdown;
QLabel* _messageCount;
QString _filterSelection;
QString _countLabel;
AbstractLoggerInterface* _logger;
Setting::Handle<QRect> _windowGeometry;
int _count = 0;
};
#endif // hifi_LogDialog_h

View file

@ -181,6 +181,8 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) {
if (properties["parentID"].isValid()) {
setParentID(QUuid(properties["parentID"].toString()));
bool success;
getParentPointer(success); // call this to hook-up the parent's back-pointers to its child overlays
needRenderItemUpdate = true;
}
if (properties["parentJointIndex"].isValid()) {

View file

@ -274,82 +274,88 @@ void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID
auto nodeList = DependencyManager::get<NodeList>();
if (entityProperties.getClientOnly()) {
if (entityProperties.verifyStaticCertificateProperties()) {
SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer);
if (entityProperties.verifyStaticCertificateProperties()) {
if (entityProperties.getClientOnly()) {
SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer);
if (entityServer) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest;
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL();
requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer");
QJsonObject request;
request["certificate_id"] = entityProperties.getCertificateID();
networkRequest.setUrl(requestURL);
if (entityServer) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest;
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL();
requestURL.setPath("/api/v1/commerce/proof_of_purchase_status/transfer");
QJsonObject request;
request["certificate_id"] = entityProperties.getCertificateID();
networkRequest.setUrl(requestURL);
QNetworkReply* networkReply = NULL;
networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
QNetworkReply* networkReply = NULL;
networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
connect(networkReply, &QNetworkReply::finished, [=]() {
QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
jsonObject = jsonObject["data"].toObject();
connect(networkReply, &QNetworkReply::finished, [=]() {
QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
jsonObject = jsonObject["data"].toObject();
if (networkReply->error() == QNetworkReply::NoError) {
if (!jsonObject["invalid_reason"].toString().isEmpty()) {
qCDebug(entities) << "invalid_reason not empty";
} else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") {
qCDebug(entities) << "'transfer_status' is 'failed'";
} else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") {
qCDebug(entities) << "'transfer_status' is 'pending'";
} else {
QString ownerKey = jsonObject["transfer_recipient_key"].toString();
QByteArray certID = entityProperties.getCertificateID().toUtf8();
QByteArray text = DependencyManager::get<EntityTreeRenderer>()->getTree()->computeNonce(certID, ownerKey);
QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122();
int certIDByteArraySize = certID.length();
int textByteArraySize = text.length();
int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length();
auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest,
certIDByteArraySize + textByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int),
true);
challengeOwnershipPacket->writePrimitive(certIDByteArraySize);
challengeOwnershipPacket->writePrimitive(textByteArraySize);
challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize);
challengeOwnershipPacket->write(certID);
challengeOwnershipPacket->write(text);
challengeOwnershipPacket->write(nodeToChallengeByteArray);
nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer);
// Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time
if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer");
return;
if (networkReply->error() == QNetworkReply::NoError) {
if (!jsonObject["invalid_reason"].toString().isEmpty()) {
qCDebug(entities) << "invalid_reason not empty";
} else if (jsonObject["transfer_status"].toArray().first().toString() == "failed") {
qCDebug(entities) << "'transfer_status' is 'failed'";
} else if (jsonObject["transfer_status"].toArray().first().toString() == "pending") {
qCDebug(entities) << "'transfer_status' is 'pending'";
} else {
startChallengeOwnershipTimer();
}
}
} else {
qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() <<
"More info:" << networkReply->readAll();
}
QString ownerKey = jsonObject["transfer_recipient_key"].toString();
networkReply->deleteLater();
});
} else {
qCWarning(context_overlay) << "Couldn't get Entity Server!";
}
QByteArray certID = entityProperties.getCertificateID().toUtf8();
QByteArray text = DependencyManager::get<EntityTreeRenderer>()->getTree()->computeNonce(certID, ownerKey);
QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122();
int certIDByteArraySize = certID.length();
int textByteArraySize = text.length();
int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length();
auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest,
certIDByteArraySize + textByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int),
true);
challengeOwnershipPacket->writePrimitive(certIDByteArraySize);
challengeOwnershipPacket->writePrimitive(textByteArraySize);
challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize);
challengeOwnershipPacket->write(certID);
challengeOwnershipPacket->write(text);
challengeOwnershipPacket->write(nodeToChallengeByteArray);
nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer);
// Kickoff a 10-second timeout timer that marks the cert if we don't get an ownership response in time
if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this, "startChallengeOwnershipTimer");
return;
} else {
startChallengeOwnershipTimer();
}
}
} else {
qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() <<
"More info:" << networkReply->readAll();
}
networkReply->deleteLater();
});
} else {
qCWarning(context_overlay) << "Couldn't get Entity Server!";
}
} else {
// We don't currently verify ownership of entities that aren't Avatar Entities,
// so they always pass Ownership Verification. It's necessary to emit this signal
// so that the Inspection Certificate can continue its information-grabbing process.
auto ledger = DependencyManager::get<Ledger>();
_challengeOwnershipTimeoutTimer.stop();
emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED));
emit DependencyManager::get<WalletScriptingInterface>()->ownershipVerificationFailed(_lastInspectedEntity);
qCDebug(context_overlay) << "Entity" << _lastInspectedEntity << "failed static certificate verification!";
emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_SUCCESS));
}
} else {
auto ledger = DependencyManager::get<Ledger>();
_challengeOwnershipTimeoutTimer.stop();
emit ledger->updateCertificateStatus(entityProperties.getCertificateID(), (uint)(ledger->CERTIFICATE_STATUS_STATIC_VERIFICATION_FAILED));
emit DependencyManager::get<WalletScriptingInterface>()->ownershipVerificationFailed(_lastInspectedEntity);
qCDebug(context_overlay) << "Entity" << _lastInspectedEntity << "failed static certificate verification!";
}
}
@ -357,12 +363,10 @@ static const QString INSPECTION_CERTIFICATE_QML_PATH = "hifi/commerce/inspection
void ContextOverlayInterface::openInspectionCertificate() {
// lets open the tablet to the inspection certificate QML
if (!_currentEntityWithContextOverlay.isNull() && _entityMarketplaceID.length() > 0) {
setLastInspectedEntity(_currentEntityWithContextOverlay);
auto tablet = dynamic_cast<TabletProxy*>(_tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
tablet->loadQMLSource(INSPECTION_CERTIFICATE_QML_PATH);
_hmdScriptingInterface->openTablet();
setLastInspectedEntity(_currentEntityWithContextOverlay);
requestOwnershipVerification(_lastInspectedEntity);
}
}

View file

@ -57,7 +57,7 @@ public:
bool getEnabled() { return _enabled; }
bool getIsInMarketplaceInspectionMode() { return _isInMarketplaceInspectionMode; }
void setIsInMarketplaceInspectionMode(bool mode) { _isInMarketplaceInspectionMode = mode; }
void requestOwnershipVerification(const QUuid& entityID);
Q_INVOKABLE void requestOwnershipVerification(const QUuid& entityID);
EntityPropertyFlags getEntityPropertyFlags() { return _entityPropertyFlags; }
signals:

View file

@ -63,7 +63,7 @@ glm::vec3 Line3DOverlay::getEnd() const {
localEnd = getLocalEnd();
worldEnd = localToWorld(localEnd, getParentID(), getParentJointIndex(), getScalesWithParent(), success);
if (!success) {
qDebug() << "Line3DOverlay::getEnd failed";
qDebug() << "Line3DOverlay::getEnd failed, parentID = " << getParentID();
}
return worldEnd;
}

View file

@ -707,7 +707,11 @@ public slots:
void setJointMappingsFromNetworkReply();
void setSessionUUID(const QUuid& sessionUUID) {
if (sessionUUID != getID()) {
setID(sessionUUID);
if (sessionUUID == QUuid()) {
setID(AVATAR_SELF_ID);
} else {
setID(sessionUUID);
}
emit sessionUUIDChanged();
}
}

View file

@ -180,6 +180,8 @@ public:
float emissiveIntensity{ 1.0f };
float ambientFactor{ 1.0f };
float bumpMultiplier { 1.0f }; // TODO: to be implemented
QString materialID;
QString name;
QString shadingModel;

View file

@ -15,6 +15,7 @@
#include "OBJReader.h"
#include <ctype.h> // .obj files are not locale-specific. The C/ASCII charset applies.
#include <sstream>
#include <QtCore/QBuffer>
#include <QtCore/QIODevice>
@ -35,6 +36,11 @@ QHash<QString, float> COMMENT_SCALE_HINTS = {{"This file uses centimeters as uni
const QString SMART_DEFAULT_MATERIAL_NAME = "High Fidelity smart default material name";
const float ILLUMINATION_MODEL_MIN_OPACITY = 0.1f;
const float ILLUMINATION_MODEL_APPLY_SHININESS = 0.5f;
const float ILLUMINATION_MODEL_APPLY_ROUGHNESS = 1.0f;
const float ILLUMINATION_MODEL_APPLY_NON_METALLIC = 0.0f;
namespace {
template<class T>
T& checked_at(QVector<T>& vector, int i) {
@ -70,6 +76,7 @@ int OBJTokenizer::nextToken(bool allowSpaceChar /*= false*/) {
}
switch (ch) {
case '#': {
_datum = "";
_comment = _device->readLine(); // stash comment for a future call to getComment
return COMMENT_TOKEN;
}
@ -256,7 +263,14 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
default:
materials[matName] = currentMaterial;
#ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader Last material shininess:" << currentMaterial.shininess << " opacity:" << currentMaterial.opacity << " diffuse color:" << currentMaterial.diffuseColor << " specular color:" << currentMaterial.specularColor << " diffuse texture:" << currentMaterial.diffuseTextureFilename << " specular texture:" << currentMaterial.specularTextureFilename;
qCDebug(modelformat) << "OBJ Reader Last material illumination model:" << currentMaterial.illuminationModel <<
" shininess:" << currentMaterial.shininess << " opacity:" << currentMaterial.opacity <<
" diffuse color:" << currentMaterial.diffuseColor << " specular color:" <<
currentMaterial.specularColor << " emissive color:" << currentMaterial.emissiveColor <<
" diffuse texture:" << currentMaterial.diffuseTextureFilename << " specular texture:" <<
currentMaterial.specularTextureFilename << " emissive texture:" <<
currentMaterial.emissiveTextureFilename << " bump texture:" <<
currentMaterial.bumpTextureFilename;
#endif
return;
}
@ -272,20 +286,46 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
qCDebug(modelformat) << "OBJ Reader Starting new material definition " << matName;
#endif
currentMaterial.diffuseTextureFilename = "";
currentMaterial.emissiveTextureFilename = "";
currentMaterial.specularTextureFilename = "";
currentMaterial.bumpTextureFilename = "";
} else if (token == "Ns") {
currentMaterial.shininess = tokenizer.getFloat();
} else if ((token == "d") || (token == "Tr")) {
} else if (token == "Ni") {
#ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader Ignoring material Ni " << tokenizer.getFloat();
#else
tokenizer.getFloat();
#endif
} else if (token == "d") {
currentMaterial.opacity = tokenizer.getFloat();
} else if (token == "Tr") {
currentMaterial.opacity = 1.0f - tokenizer.getFloat();
} else if (token == "illum") {
currentMaterial.illuminationModel = tokenizer.getFloat();
} else if (token == "Tf") {
#ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader 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) << "OBJ Reader Ignoring material Ka " << tokenizer.getVec3();;
#else
tokenizer.getVec3();
#endif
} else if (token == "Kd") {
currentMaterial.diffuseColor = tokenizer.getVec3();
} else if (token == "Ke") {
currentMaterial.emissiveColor = tokenizer.getVec3();
} else if (token == "Ks") {
currentMaterial.specularColor = tokenizer.getVec3();
} else if ((token == "map_Kd") || (token == "map_Ks")) {
QByteArray filename = QUrl(tokenizer.getLineAsDatum()).fileName().toUtf8();
} else if ((token == "map_Kd") || (token == "map_Ke") || (token == "map_Ks") || (token == "map_bump") || (token == "bump")) {
const QByteArray textureLine = tokenizer.getLineAsDatum();
QByteArray filename;
OBJMaterialTextureOptions textureOptions;
parseTextureLine(textureLine, filename, textureOptions);
if (filename.endsWith(".tga")) {
#ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader WARNING: currently ignoring tga texture " << filename << " in " << _url;
@ -294,11 +334,104 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) {
}
if (token == "map_Kd") {
currentMaterial.diffuseTextureFilename = filename;
} else if( token == "map_Ks" ) {
} else if (token == "map_Ke") {
currentMaterial.emissiveTextureFilename = filename;
} else if (token == "map_Ks" ) {
currentMaterial.specularTextureFilename = filename;
} else if ((token == "map_bump") || (token == "bump")) {
currentMaterial.bumpTextureFilename = filename;
currentMaterial.bumpTextureOptions = textureOptions;
}
}
}
}
void OBJReader::parseTextureLine(const QByteArray& textureLine, QByteArray& filename, OBJMaterialTextureOptions& textureOptions) {
// Texture options reference http://paulbourke.net/dataformats/mtl/
// and https://wikivisually.com/wiki/Material_Template_Library
std::istringstream iss(textureLine.toStdString());
const std::vector<std::string> parser(std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>());
uint i = 0;
while (i < parser.size()) {
if (i + 1 < parser.size() && parser[i][0] == '-') {
const std::string& option = parser[i++];
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();
#endif
} else if (option == "-bm") {
const std::string& bm = parser[i++];
textureOptions.bumpMultiplier = std::stof(bm);
} else if (option == "-boost") {
#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();
#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();
#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();
#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();
#endif
} else if (option == "-mm") {
if (i + 1 < parser.size()) {
#ifdef WANT_DEBUG
const std::string& mmBase = parser[i++];
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();
#endif
}
} else if (option == "-o" || option == "-s" || option == "-t") {
if (i + 2 < parser.size()) {
#ifdef WANT_DEBUG
const std::string& u = parser[i++];
const std::string& v = parser[i++];
const std::string& w = parser[i++];
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();
#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();
#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();
#endif
} else if (option[0] == '-') {
#ifdef WANT_DEBUG
qCDebug(modelformat) << "OBJ Reader WARNING: Ignoring unsupported texture option" << option.c_str();
#endif
}
} else { // assume filename at end when no more options
std::string filenameString = parser[i++];
while (i < parser.size()) { // filename has space in it
filenameString += " " + parser[i++];
}
filename = filenameString.c_str();
}
}
}
std::tuple<bool, QByteArray> requestData(QUrl& url) {
@ -745,7 +878,7 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping,
}
geometry.materials[materialID] = FBXMaterial(objMaterial.diffuseColor,
objMaterial.specularColor,
glm::vec3(0.0f),
objMaterial.emissiveColor,
objMaterial.shininess,
objMaterial.opacity);
FBXMaterial& fbxMaterial = geometry.materials[materialID];
@ -759,17 +892,88 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping,
if (!objMaterial.specularTextureFilename.isEmpty()) {
fbxMaterial.specularTexture.filename = objMaterial.specularTextureFilename;
}
if (!objMaterial.emissiveTextureFilename.isEmpty()) {
fbxMaterial.emissiveTexture.filename = objMaterial.emissiveTextureFilename;
}
if (!objMaterial.bumpTextureFilename.isEmpty()) {
fbxMaterial.normalTexture.filename = objMaterial.bumpTextureFilename;
fbxMaterial.normalTexture.isBumpmap = true;
fbxMaterial.bumpMultiplier = objMaterial.bumpTextureOptions.bumpMultiplier;
}
modelMaterial->setEmissive(fbxMaterial.emissiveColor);
modelMaterial->setAlbedo(fbxMaterial.diffuseColor);
modelMaterial->setMetallic(glm::length(fbxMaterial.specularColor));
modelMaterial->setRoughness(graphics::Material::shininessToRoughness(fbxMaterial.shininess));
if (fbxMaterial.opacity <= 0.0f) {
modelMaterial->setOpacity(1.0f);
} else {
modelMaterial->setOpacity(fbxMaterial.opacity);
bool applyTransparency = false;
bool applyShininess = false;
bool applyRoughness = false;
bool applyNonMetallic = false;
bool fresnelOn = false;
// Illumination model reference http://paulbourke.net/dataformats/mtl/
switch (objMaterial.illuminationModel) {
case 0: // Color on and Ambient off
// We don't support ambient = do nothing?
break;
case 1: // Color on and Ambient on
// We don't support ambient = do nothing?
break;
case 2: // Highlight on
// Change specular intensity = do nothing for now?
break;
case 3: // Reflection on and Ray trace on
applyShininess = true;
break;
case 4: // Transparency: Glass on and Reflection: Ray trace on
applyTransparency = true;
applyShininess = true;
break;
case 5: // Reflection: Fresnel on and Ray trace on
applyShininess = true;
fresnelOn = true;
break;
case 6: // Transparency: Refraction on and Reflection: Fresnel off and Ray trace on
applyTransparency = true;
applyNonMetallic = true;
applyShininess = true;
break;
case 7: // Transparency: Refraction on and Reflection: Fresnel on and Ray trace on
applyTransparency = true;
applyNonMetallic = true;
applyShininess = true;
fresnelOn = true;
break;
case 8: // Reflection on and Ray trace off
applyShininess = true;
break;
case 9: // Transparency: Glass on and Reflection: Ray trace off
applyTransparency = true;
applyNonMetallic = true;
applyRoughness = true;
break;
case 10: // Casts shadows onto invisible surfaces
// Do nothing?
break;
}
if (applyTransparency) {
fbxMaterial.opacity = std::max(fbxMaterial.opacity, ILLUMINATION_MODEL_MIN_OPACITY);
}
if (applyShininess) {
modelMaterial->setRoughness(ILLUMINATION_MODEL_APPLY_SHININESS);
} else if (applyRoughness) {
modelMaterial->setRoughness(ILLUMINATION_MODEL_APPLY_ROUGHNESS);
}
if (applyNonMetallic) {
modelMaterial->setMetallic(ILLUMINATION_MODEL_APPLY_NON_METALLIC);
}
if (fresnelOn) {
modelMaterial->setFresnel(glm::vec3(1.0f));
}
modelMaterial->setOpacity(fbxMaterial.opacity);
}
return geometryPtr;

View file

@ -48,6 +48,11 @@ private:
void addFrom(const OBJFace* face, int index);
};
class OBJMaterialTextureOptions {
public:
float bumpMultiplier { 1.0f };
}
;
// Materials and references to material names can come in any order, and different mesh parts can refer to the same material.
// Therefore it would get pretty hacky to try to use FBXMeshPart to store these as we traverse the files.
class OBJMaterial {
@ -56,11 +61,16 @@ public:
float opacity;
glm::vec3 diffuseColor;
glm::vec3 specularColor;
glm::vec3 emissiveColor;
QByteArray diffuseTextureFilename;
QByteArray specularTextureFilename;
QByteArray emissiveTextureFilename;
QByteArray bumpTextureFilename;
OBJMaterialTextureOptions bumpTextureOptions;
int illuminationModel;
bool used { false };
bool userSpecifiesUV { false };
OBJMaterial() : shininess(0.0f), opacity(1.0f), diffuseColor(0.9f), specularColor(0.9f) {}
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.
@ -84,6 +94,7 @@ private:
bool parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mapping, FBXGeometry& geometry,
float& scaleGuess, bool combineParts);
void parseMaterialLibrary(QIODevice* device);
void parseTextureLine(const QByteArray& textureLine, QByteArray& filename, OBJMaterialTextureOptions& textureOptions);
bool isValidTexture(const QByteArray &filename); // true if the file exists. TODO?: check content-type header and that it is a supported format.
int _partCounter { 0 };

View file

@ -75,10 +75,10 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie
) {
// Rotate surface normal and eye direction
vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;
vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;
vec3 ambientSpaceSurfaceNormal = (ambient.transform * vec4(surface.normal, 0.0)).xyz;
vec3 ambientSpaceSurfaceEyeDir = (ambient.transform * vec4(surface.eyeDir, 0.0)).xyz;
<@if supportScattering@>
vec3 ambientSpaceLowNormalCurvature = (ambient.transform * lowNormalCurvature).xyz;
vec3 ambientSpaceLowNormal = (ambient.transform * vec4(lowNormalCurvature.xyz, 0.0)).xyz;
<@endif@>
vec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness);
@ -99,7 +99,7 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie
obscurance = min(obscurance, ambientOcclusion);
// Diffuse from ambient
diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormalCurvature).xyz;
diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), ambientSpaceLowNormal).xyz;
// Scattering ambient specular is the same as non scattering for now
// TODO: we should use the same specular answer as for direct lighting

View file

@ -12,6 +12,8 @@
#ifndef hifi_BitVectorHelpers_h
#define hifi_BitVectorHelpers_h
#include "NumericalConstants.h"
int calcBitVectorSize(int numBits) {
return ((numBits - 1) >> 3) + 1;
}

View file

@ -50,8 +50,8 @@ signals:
private:
bool _extraDebugging{ false };
bool _debugPrint{ false };
bool _infoPrint{ false };
bool _debugPrint{ true };
bool _infoPrint{ true };
bool _criticalPrint{ true };
bool _warningPrint{ true };
bool _suppressPrint{ true };

View file

@ -208,7 +208,7 @@ Script.include("/~/system/libraries/Xform.js");
var worldToSensorMat = Mat4.inverse(MyAvatar.getSensorToWorldMatrix());
var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition);
var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, ["position"]);
var grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, GRABBABLE_PROPERTIES);
var now = Date.now();
var deltaObjectTime = (now - this.currentObjectTime) / MSECS_PER_SEC; // convert to seconds
this.currentObjectTime = now;
@ -369,6 +369,14 @@ Script.include("/~/system/libraries/Xform.js");
}
};
this.targetIsNull = function() {
var properties = Entities.getEntityProperties(this.grabbedThingID);
if (Object.keys(properties).length === 0 && this.distanceHolding) {
return true;
}
return false;
}
this.isReady = function (controllerData) {
if (HMD.active) {
if (this.notPointingAtEntity(controllerData)) {
@ -391,7 +399,7 @@ Script.include("/~/system/libraries/Xform.js");
this.run = function (controllerData) {
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE ||
this.notPointingAtEntity(controllerData)) {
this.notPointingAtEntity(controllerData) || this.targetIsNull()) {
this.endNearGrabAction();
return makeRunningValues(false, [], []);
}

View file

@ -1250,7 +1250,6 @@ var lastPosition = null;
// Do some stuff regularly, like check for placement of various overlays
Script.update.connect(function (deltaTime) {
progressDialog.move();
selectionDisplay.checkMove();
selectionDisplay.checkControllerMove();
var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1);
var dPosition = Vec3.distance(Camera.position, lastPosition);

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,6 @@ Pointer = function(hudLayer, pickType, pointerData) {
ignoreRayIntersection: true, // always ignore this
drawInFront: !hudLayer, // Even when burried inside of something, show it.
drawHUDLayer: hudLayer,
parentID: MyAvatar.SELF_ID
};
this.halfEnd = {
type: "sphere",
@ -53,7 +52,6 @@ Pointer = function(hudLayer, pickType, pointerData) {
ignoreRayIntersection: true, // always ignore this
drawInFront: !hudLayer, // Even when burried inside of something, show it.
drawHUDLayer: hudLayer,
parentID: MyAvatar.SELF_ID
};
this.fullEnd = {
type: "sphere",
@ -76,7 +74,6 @@ Pointer = function(hudLayer, pickType, pointerData) {
ignoreRayIntersection: true, // always ignore this
drawInFront: !hudLayer, // Even when burried inside of something, show it.
drawHUDLayer: hudLayer,
parentID: MyAvatar.SELF_ID
};
this.renderStates = [

View file

@ -163,6 +163,7 @@ var selectionDisplay = null; // for gridTool.js to ignore
var certificateId = itemCertificateId || (Entities.getEntityProperties(currentEntityWithContextOverlay, ['certificateID']).certificateID);
tablet.sendToQml({
method: 'inspectionCertificate_setCertificateId',
entityId: currentEntityWithContextOverlay,
certificateId: certificateId
});
}
@ -583,6 +584,9 @@ var selectionDisplay = null; // for gridTool.js to ignore
case 'inspectionCertificate_closeClicked':
tablet.gotoHomeScreen();
break;
case 'inspectionCertificate_requestOwnershipVerification':
ContextOverlay.requestOwnershipVerification(message.entity);
break;
case 'inspectionCertificate_showInMarketplaceClicked':
tablet.gotoWebScreen(message.marketplaceUrl, MARKETPLACES_INJECT_SCRIPT_URL);
break;

View file

@ -20,8 +20,6 @@
QTEST_MAIN(BitVectorHelperTests)
const int BITS_IN_BYTE = 8;
void BitVectorHelperTests::sizeTest() {
std::vector<int> sizes = {0, 6, 7, 8, 30, 31, 32, 33, 87, 88, 89, 90, 90, 91, 92, 93};
for (auto& size : sizes) {

View file

@ -33,7 +33,7 @@ size_t FileCacheTests::getCacheDirectorySize() const {
return result;
}
FileCachePointer makeFileCache(QString& location) {
FileCachePointer makeFileCache(QString location) {
auto result = std::make_shared<FileCache>(location.toStdString(), "tmp");
result->initialize();
result->setMaxSize(MAX_UNUSED_SIZE);
@ -53,7 +53,7 @@ void FileCacheTests::testUnusedFiles() {
auto file = cache->writeFile(TEST_DATA.data(), FileCache::Metadata(key, TEST_DATA.size()));
QVERIFY(file->_locked);
inUseFiles.push_back(file);
QThread::msleep(10);
}
QCOMPARE(cache->getNumCachedFiles(), (size_t)0);
@ -100,13 +100,13 @@ void FileCacheTests::testUnusedFiles() {
inUseFiles.push_back(file);
if (i == 94) {
// Each access touches the file, so we need to sleep here to ensure that the the last 5 files
// Each access touches the file, so we need to sleep here to ensure that the the last 5 files
// have later times for cache ejection priority, otherwise the test runs too fast to reliably
// differentiate
// differentiate
QThread::msleep(1000);
}
}
QCOMPARE(cache->getNumCachedFiles(), (size_t)0);
QCOMPARE(cache->getNumTotalFiles(), (size_t)10);
inUseFiles.clear();
@ -119,7 +119,7 @@ size_t FileCacheTests::getFreeSpace() const {
return QStorageInfo(_testDir.path()).bytesFree();
}
// FIXME if something else is changing the amount of free space on the target drive concurrently with this test
// FIXME if something else is changing the amount of free space on the target drive concurrently with this test
// running, then it may fail
void FileCacheTests::testFreeSpacePreservation() {
QCOMPARE(getCacheDirectorySize(), MAX_UNUSED_SIZE);

View file

@ -31,20 +31,20 @@ static void testSphereVsCone(const glm::vec3 coneNormal, const glm::vec3 coneBiN
glm::vec3 coneCenter = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 sphereCenter = coneCenter + coneEdge * sphereDistance;
float result = coneSphereAngle(coneCenter, u, sphereCenter, sphereRadius);
QCOMPARE(isnan(result), false);
QCOMPARE(glm::isnan(result), false);
QCOMPARE(result < coneAngle, true);
// push sphere outward from edge so it is tangent to the cone.
glm::vec3 sphereOffset = glm::angleAxis(PI / 2.0f, w) * coneEdge;
sphereCenter += sphereOffset * sphereRadius;
result = coneSphereAngle(coneCenter, u, sphereCenter, sphereRadius);
QCOMPARE(isnan(result), false);
QCOMPARE(glm::isnan(result), false);
QCOMPARE_WITH_ABS_ERROR(result, coneAngle, 0.001f);
// push sphere outward from edge a bit further, so it is outside of the cone.
sphereCenter += 0.1f * sphereOffset;
result = coneSphereAngle(coneCenter, u, sphereCenter, sphereRadius);
QCOMPARE(isnan(result), false);
QCOMPARE(glm::isnan(result), false);
QCOMPARE(result > coneAngle, true);
}

View file

@ -16,12 +16,8 @@
QTEST_MAIN(PathUtilsTests)
void PathUtilsTests::testPathUtils() {
QString result = PathUtils::qmlBasePath();
#if DEV_BUILD
QVERIFY(result.startsWith("file:///"));
#else
QString result = PathUtils::qmlBaseUrl();
QVERIFY(result.startsWith("qrc:///"));
#endif
QVERIFY(result.endsWith("/"));
}