mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 04:03:35 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into pop_dynamicTests
This commit is contained in:
commit
f037eab26c
67 changed files with 625 additions and 498 deletions
|
@ -88,7 +88,7 @@ FocusScope {
|
|||
return;
|
||||
}
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect();
|
||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedHUDRect();
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
newRecommendedRectJS.width,
|
||||
newRecommendedRectJS.height);
|
||||
|
@ -271,7 +271,7 @@ FocusScope {
|
|||
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
|
||||
var newRecommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var newRecommendedRect = Controller.getRecommendedHUDRect();
|
||||
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
|
||||
var windows = d.getTopLevelWindows();
|
||||
for (var i = 0; i < windows.length; ++i) {
|
||||
|
@ -410,7 +410,7 @@ FocusScope {
|
|||
return;
|
||||
}
|
||||
|
||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect();
|
||||
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedHUDRect();
|
||||
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
|
||||
newRecommendedRectJS.width,
|
||||
newRecommendedRectJS.height);
|
||||
|
@ -442,7 +442,7 @@ FocusScope {
|
|||
|
||||
var oldRecommendedRect = recommendedRect;
|
||||
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
|
||||
var newRecommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var newRecommendedRect = Controller.getRecommendedHUDRect();
|
||||
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
|
||||
repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
|
||||
}
|
||||
|
@ -459,7 +459,7 @@ FocusScope {
|
|||
return;
|
||||
}
|
||||
|
||||
var recommended = Controller.getRecommendedOverlayRect();
|
||||
var recommended = Controller.getRecommendedHUDRect();
|
||||
var maxX = recommended.x + recommended.width;
|
||||
var maxY = recommended.y + recommended.height;
|
||||
var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y);
|
||||
|
|
|
@ -25,16 +25,67 @@ Rectangle {
|
|||
HifiConstants { id: hifi; }
|
||||
|
||||
id: root;
|
||||
property string marketplaceId: "";
|
||||
property string marketplaceUrl;
|
||||
property string certificateId;
|
||||
property string itemName: "--";
|
||||
property string itemOwner: "--";
|
||||
property string itemEdition: "--";
|
||||
property string dateOfPurchase: "";
|
||||
property string dateOfPurchase: "--";
|
||||
property bool isLightbox: false;
|
||||
property bool isMyCert: false;
|
||||
// Style
|
||||
color: hifi.colors.faintGray;
|
||||
Hifi.QmlCommerce {
|
||||
id: commerce;
|
||||
|
||||
onCertificateInfoResult: {
|
||||
if (result.status !== 'success') {
|
||||
console.log("Failed to get certificate info", result.message);
|
||||
} else {
|
||||
root.marketplaceUrl = result.data.marketplace_item_url;
|
||||
root.isMyCert = result.isMyCert ? result.isMyCert : false;
|
||||
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.itemEdition = result.data.edition_number + "/" + (result.data.limited_run === -1 ? "\u221e" : result.data.limited_run);
|
||||
root.dateOfPurchase = getFormattedDate(result.data.transfer_created_at * 1000);
|
||||
root.itemName = result.data.marketplace_item_name;
|
||||
|
||||
if (result.data.invalid_reason || result.data.transfer_status[0] === "failed") {
|
||||
titleBarText.text = "Invalid Certificate";
|
||||
titleBarText.color = hifi.colors.redHighlight;
|
||||
popText.text = "";
|
||||
if (result.data.invalid_reason) {
|
||||
errorText.text = result.data.invalid_reason;
|
||||
}
|
||||
} else if (result.data.transfer_status[0] === "pending") {
|
||||
titleBarText.text = "Certificate Pending";
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onCertificateIdChanged: {
|
||||
if (certificateId !== "") {
|
||||
commerce.certificateInfo(certificateId);
|
||||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
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 = "";
|
||||
}
|
||||
}
|
||||
|
||||
// This object is always used in a popup.
|
||||
|
@ -115,7 +166,7 @@ Rectangle {
|
|||
size: 28;
|
||||
// Anchors
|
||||
anchors.top: itemNameHeader.bottom;
|
||||
anchors.topMargin: 4;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: itemNameHeader.left;
|
||||
anchors.right: itemNameHeader.right;
|
||||
height: paintedHeight;
|
||||
|
@ -126,7 +177,7 @@ Rectangle {
|
|||
anchors.fill: parent;
|
||||
hoverEnabled: enabled;
|
||||
onClicked: {
|
||||
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', itemId: root.marketplaceId});
|
||||
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
|
||||
}
|
||||
onEntered: itemName.color = hifi.colors.blueHighlight;
|
||||
onExited: itemName.color = hifi.colors.blueAccent;
|
||||
|
@ -140,14 +191,20 @@ Rectangle {
|
|||
size: 16;
|
||||
// Anchors
|
||||
anchors.top: itemName.bottom;
|
||||
anchors.topMargin: 20;
|
||||
anchors.topMargin: 28;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 45;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 16;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
color: hifi.colors.lightGray;
|
||||
}
|
||||
FontLoader { id: ralewayRegular; source: "../../../../fonts/Raleway-Regular.ttf"; }
|
||||
TextMetrics {
|
||||
id: textMetrics;
|
||||
font.family: ralewayRegular.name
|
||||
text: root.itemOwner;
|
||||
}
|
||||
RalewayRegular {
|
||||
id: ownedBy;
|
||||
|
@ -156,14 +213,31 @@ Rectangle {
|
|||
size: 22;
|
||||
// Anchors
|
||||
anchors.top: ownedByHeader.bottom;
|
||||
anchors.topMargin: 4;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: ownedByHeader.left;
|
||||
anchors.right: ownedByHeader.right;
|
||||
height: paintedHeight;
|
||||
height: textMetrics.height;
|
||||
width: root.isMyCert ? textMetrics.width + 25 : ownedByHeader.width;
|
||||
// Style
|
||||
color: hifi.colors.darkGray;
|
||||
elide: Text.ElideRight;
|
||||
}
|
||||
AnonymousProRegular {
|
||||
id: isMyCertText;
|
||||
visible: root.isMyCert;
|
||||
text: "(Private)";
|
||||
size: 18;
|
||||
// Anchors
|
||||
anchors.top: ownedBy.top;
|
||||
anchors.topMargin: 4;
|
||||
anchors.bottom: ownedBy.bottom;
|
||||
anchors.left: ownedBy.right;
|
||||
anchors.leftMargin: 4;
|
||||
anchors.right: ownedByHeader.right;
|
||||
// Style
|
||||
color: hifi.colors.lightGray;
|
||||
elide: Text.ElideRight;
|
||||
verticalAlignment: Text.AlignVCenter;
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
id: editionHeader;
|
||||
|
@ -172,23 +246,23 @@ Rectangle {
|
|||
size: 16;
|
||||
// Anchors
|
||||
anchors.top: ownedBy.bottom;
|
||||
anchors.topMargin: 20;
|
||||
anchors.topMargin: 28;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 45;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 16;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
color: hifi.colors.lightGray;
|
||||
}
|
||||
AnonymousProRegular {
|
||||
id: edition;
|
||||
text: root.itemEdition;
|
||||
// Text size
|
||||
size: 22;
|
||||
size: 18;
|
||||
// Anchors
|
||||
anchors.top: editionHeader.bottom;
|
||||
anchors.topMargin: 4;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: editionHeader.left;
|
||||
anchors.right: editionHeader.right;
|
||||
height: paintedHeight;
|
||||
|
@ -199,31 +273,29 @@ Rectangle {
|
|||
RalewayRegular {
|
||||
id: dateOfPurchaseHeader;
|
||||
text: "DATE OF PURCHASE";
|
||||
visible: root.dateOfPurchase !== "";
|
||||
// Text size
|
||||
size: 16;
|
||||
// Anchors
|
||||
anchors.top: ownedBy.bottom;
|
||||
anchors.topMargin: 20;
|
||||
anchors.top: edition.bottom;
|
||||
anchors.topMargin: 28;
|
||||
anchors.left: parent.left;
|
||||
anchors.leftMargin: 45;
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: 16;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.baseGray;
|
||||
color: hifi.colors.lightGray;
|
||||
}
|
||||
AnonymousProRegular {
|
||||
id: dateOfPurchase;
|
||||
text: root.dateOfPurchase;
|
||||
visible: root.dateOfPurchase !== "";
|
||||
// Text size
|
||||
size: 22;
|
||||
size: 18;
|
||||
// Anchors
|
||||
anchors.top: editionHeader.bottom;
|
||||
anchors.topMargin: 4;
|
||||
anchors.left: editionHeader.left;
|
||||
anchors.right: editionHeader.right;
|
||||
anchors.top: dateOfPurchaseHeader.bottom;
|
||||
anchors.topMargin: 8;
|
||||
anchors.left: dateOfPurchaseHeader.left;
|
||||
anchors.right: dateOfPurchaseHeader.right;
|
||||
height: paintedHeight;
|
||||
// Style
|
||||
color: hifi.colors.darkGray;
|
||||
|
@ -231,15 +303,13 @@ Rectangle {
|
|||
|
||||
RalewayRegular {
|
||||
id: errorText;
|
||||
text: "Here we will display some text if there's an <b>error</b> with the certificate " +
|
||||
"(DMCA takedown, invalid cert, location of item updated)";
|
||||
// Text size
|
||||
size: 20;
|
||||
// Anchors
|
||||
anchors.top: root.dateOfPurchase !== "" ? dateOfPurchase.bottom : edition.bottom;
|
||||
anchors.topMargin: 40;
|
||||
anchors.left: root.dateOfPurchase !== "" ? dateOfPurchase.left : edition.left;
|
||||
anchors.right: root.dateOfPurchase !== "" ? dateOfPurchase.right : edition.right;
|
||||
anchors.top: dateOfPurchase.bottom;
|
||||
anchors.topMargin: 36;
|
||||
anchors.left: dateOfPurchase.left;
|
||||
anchors.right: dateOfPurchase.right;
|
||||
anchors.bottom: parent.bottom;
|
||||
// Style
|
||||
wrapMode: Text.WordWrap;
|
||||
|
@ -254,7 +324,7 @@ Rectangle {
|
|||
Item {
|
||||
id: buttonsContainer;
|
||||
anchors.bottom: parent.bottom;
|
||||
anchors.bottomMargin: 50;
|
||||
anchors.bottomMargin: 30;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
height: 50;
|
||||
|
@ -281,6 +351,7 @@ Rectangle {
|
|||
// "Show In Marketplace" button
|
||||
HifiControlsUit.Button {
|
||||
id: showInMarketplaceButton;
|
||||
enabled: root.marketplaceUrl;
|
||||
color: hifi.buttons.blue;
|
||||
colorScheme: hifi.colorSchemes.light;
|
||||
anchors.top: parent.top;
|
||||
|
@ -290,7 +361,7 @@ Rectangle {
|
|||
height: 50;
|
||||
text: "View In Market"
|
||||
onClicked: {
|
||||
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', itemId: root.marketplaceId});
|
||||
sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -313,19 +384,42 @@ Rectangle {
|
|||
//
|
||||
function fromScript(message) {
|
||||
switch (message.method) {
|
||||
case 'inspectionCertificate_setMarketplaceId':
|
||||
root.marketplaceId = message.marketplaceId;
|
||||
break;
|
||||
case 'inspectionCertificate_setItemInfo':
|
||||
root.itemName = message.itemName;
|
||||
root.itemOwner = message.itemOwner;
|
||||
root.itemEdition = message.itemEdition;
|
||||
case 'inspectionCertificate_setCertificateId':
|
||||
root.certificateId = message.certificateId;
|
||||
break;
|
||||
default:
|
||||
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
|
||||
}
|
||||
}
|
||||
signal sendToScript(var message);
|
||||
|
||||
function getFormattedDate(timestamp) {
|
||||
function addLeadingZero(n) {
|
||||
return n < 10 ? '0' + n : '' + n;
|
||||
}
|
||||
|
||||
var a = new Date(timestamp);
|
||||
var year = a.getFullYear();
|
||||
var month = addLeadingZero(a.getMonth());
|
||||
var day = addLeadingZero(a.getDate());
|
||||
var hour = a.getHours();
|
||||
var drawnHour = hour;
|
||||
if (hour === 0) {
|
||||
drawnHour = 12;
|
||||
} else if (hour > 12) {
|
||||
drawnHour -= 12;
|
||||
}
|
||||
drawnHour = addLeadingZero(drawnHour);
|
||||
|
||||
var amOrPm = "AM";
|
||||
if (hour >= 12) {
|
||||
amOrPm = "PM";
|
||||
}
|
||||
|
||||
var min = addLeadingZero(a.getMinutes());
|
||||
var sec = addLeadingZero(a.getSeconds());
|
||||
return year + '-' + month + '-' + day + '<br>' + drawnHour + ':' + min + amOrPm;
|
||||
}
|
||||
//
|
||||
// FUNCTION DEFINITIONS END
|
||||
//
|
||||
|
|
|
@ -34,6 +34,7 @@ Item {
|
|||
property string itemId;
|
||||
property string itemPreviewImageUrl;
|
||||
property string itemHref;
|
||||
property string certificateId;
|
||||
property int displayedItemCount;
|
||||
property int itemEdition;
|
||||
property int numberSold;
|
||||
|
@ -168,7 +169,7 @@ Item {
|
|||
anchors.fill: parent;
|
||||
hoverEnabled: enabled;
|
||||
onClicked: {
|
||||
sendToPurchases({method: 'purchases_itemCertificateClicked', itemMarketplaceId: root.itemId});
|
||||
sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId});
|
||||
}
|
||||
onEntered: {
|
||||
certificateIcon.color = hifi.colors.black;
|
||||
|
@ -225,7 +226,7 @@ Item {
|
|||
} else if (root.purchaseStatus === "invalidated") {
|
||||
"INVALIDATED"
|
||||
} else if (root.numberSold !== -1) {
|
||||
("Sales: " + root.numberSold + "/" + (root.limitedRun === -1 ? "INFTY" : root.limitedRun))
|
||||
("Sales: " + root.numberSold + "/" + (root.limitedRun === -1 ? "\u221e" : root.limitedRun))
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
|
|
@ -427,6 +427,7 @@ Rectangle {
|
|||
itemId: id;
|
||||
itemPreviewImageUrl: preview;
|
||||
itemHref: download_url;
|
||||
certificateId: certificate_id;
|
||||
purchaseStatus: status;
|
||||
purchaseStatusChanged: statusChanged;
|
||||
itemEdition: model.edition_number;
|
||||
|
@ -684,8 +685,7 @@ Rectangle {
|
|||
titleBarContainer.referrerURL = message.referrerURL;
|
||||
filterBar.text = message.filterText ? message.filterText : "";
|
||||
break;
|
||||
case 'inspectionCertificate_setMarketplaceId':
|
||||
case 'inspectionCertificate_setItemInfo':
|
||||
case 'inspectionCertificate_setCertificateId':
|
||||
inspectionCertificate.fromScript(message);
|
||||
break;
|
||||
case 'purchases_showMyItems':
|
||||
|
|
|
@ -299,10 +299,14 @@ Item {
|
|||
//
|
||||
|
||||
function getFormattedDate(timestamp) {
|
||||
function addLeadingZero(n) {
|
||||
return n < 10 ? '0' + n : '' + n;
|
||||
}
|
||||
|
||||
var a = new Date(timestamp);
|
||||
var year = a.getFullYear();
|
||||
var month = a.getMonth();
|
||||
var day = a.getDate();
|
||||
var month = addLeadingZero(a.getMonth());
|
||||
var day = addLeadingZero(a.getDate());
|
||||
var hour = a.getHours();
|
||||
var drawnHour = hour;
|
||||
if (hour === 0) {
|
||||
|
@ -310,14 +314,15 @@ Item {
|
|||
} else if (hour > 12) {
|
||||
drawnHour -= 12;
|
||||
}
|
||||
drawnHour = addLeadingZero(drawnHour);
|
||||
|
||||
var amOrPm = "AM";
|
||||
if (hour >= 12) {
|
||||
amOrPm = "PM";
|
||||
}
|
||||
|
||||
var min = a.getMinutes();
|
||||
var sec = a.getSeconds();
|
||||
var min = addLeadingZero(a.getMinutes());
|
||||
var sec = addLeadingZero(a.getSeconds());
|
||||
return year + '-' + month + '-' + day + '<br>' + drawnHour + ':' + min + amOrPm;
|
||||
}
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ Item {
|
|||
|
||||
PropertyChanges {
|
||||
target: text
|
||||
color: "#ffffff"
|
||||
color: captionColorOverride !== "" ? captionColorOverride: "#ffffff"
|
||||
text: tabletButton.hoverText
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ Item {
|
|||
|
||||
PropertyChanges {
|
||||
target: text
|
||||
color: "#333333"
|
||||
color: captionColorOverride !== "" ? captionColorOverride: "#333333"
|
||||
text: tabletButton.activeText
|
||||
}
|
||||
|
||||
|
@ -225,7 +225,7 @@ Item {
|
|||
|
||||
PropertyChanges {
|
||||
target: text
|
||||
color: "#333333"
|
||||
color: captionColorOverride !== "" ? captionColorOverride: "#333333"
|
||||
text: tabletButton.activeHoverText
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/07/11
|
||||
// Copyright 2013-2016 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
|
||||
//
|
||||
|
||||
uniform sampler2D sampler;
|
||||
|
||||
struct OverlayData {
|
||||
mat4 mvp;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
layout(std140) uniform overlayBuffer {
|
||||
OverlayData overlay;
|
||||
};
|
||||
|
||||
in vec2 vTexCoord;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
FragColor = texture(sampler, vTexCoord);
|
||||
FragColor.a *= overlay.alpha;
|
||||
if (FragColor.a <= 0.0) {
|
||||
discard;
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/07/11
|
||||
// Copyright 2013-2016 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
|
||||
//
|
||||
|
||||
struct OverlayData {
|
||||
mat4 mvp;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
layout(std140) uniform overlayBuffer {
|
||||
OverlayData overlay;
|
||||
};
|
||||
|
||||
mat4 mvp = overlay.mvp;
|
||||
|
||||
layout(location = 0) in vec3 Position;
|
||||
layout(location = 3) in vec2 TexCoord;
|
||||
|
||||
out vec2 vTexCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = mvp * vec4(Position, 1);
|
||||
vTexCoord = TexCoord;
|
||||
}
|
|
@ -5052,6 +5052,7 @@ void Application::update(float deltaTime) {
|
|||
|
||||
float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale();
|
||||
appRenderArgs._sensorToWorldScale = sensorToWorldScale;
|
||||
appRenderArgs._sensorToWorld = getMyAvatar()->getSensorToWorldMatrix();
|
||||
{
|
||||
PROFILE_RANGE(render, "/buildFrustrumAndArgs");
|
||||
{
|
||||
|
@ -5093,6 +5094,7 @@ void Application::update(float deltaTime) {
|
|||
ipdScale *= sensorToWorldScale;
|
||||
|
||||
auto baseProjection = appRenderArgs._renderArgs.getViewFrustum().getProjection();
|
||||
|
||||
if (getActiveDisplayPlugin()->isStereo()) {
|
||||
// Stereo modes will typically have a larger projection matrix overall,
|
||||
// so we ask for the 'mono' projection matrix, which for stereo and HMD
|
||||
|
@ -7028,11 +7030,11 @@ glm::uvec2 Application::getUiSize() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
QRect Application::getRecommendedOverlayRect() const {
|
||||
QRect Application::getRecommendedHUDRect() const {
|
||||
auto uiSize = getUiSize();
|
||||
QRect result(0, 0, uiSize.x, uiSize.y);
|
||||
if (_displayPlugin) {
|
||||
result = getActiveDisplayPlugin()->getRecommendedOverlayRect();
|
||||
result = getActiveDisplayPlugin()->getRecommendedHUDRect();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ public:
|
|||
QRect getRenderingGeometry() const;
|
||||
|
||||
glm::uvec2 getUiSize() const;
|
||||
QRect getRecommendedOverlayRect() const;
|
||||
QRect getRecommendedHUDRect() const;
|
||||
QSize getDeviceSize() const;
|
||||
bool hasFocus() const;
|
||||
|
||||
|
|
|
@ -126,28 +126,18 @@ void Application::paintGL() {
|
|||
renderArgs._context->setStereoViews(stereoEyeOffsets);
|
||||
}
|
||||
|
||||
renderArgs._hudOperator = displayPlugin->getHUDOperator();
|
||||
renderArgs._hudTexture = _applicationOverlay.getOverlayTexture();
|
||||
renderArgs._blitFramebuffer = finalFramebuffer;
|
||||
runRenderFrame(&renderArgs);
|
||||
}
|
||||
|
||||
gpu::Batch postCompositeBatch;
|
||||
{
|
||||
PROFILE_RANGE(render, "/postComposite");
|
||||
PerformanceTimer perfTimer("postComposite");
|
||||
renderArgs._batch = &postCompositeBatch;
|
||||
renderArgs._batch->setViewportTransform(ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height()));
|
||||
renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView());
|
||||
_overlays.render3DHUDOverlays(&renderArgs);
|
||||
}
|
||||
|
||||
auto frame = _gpuContext->endFrame();
|
||||
frame->frameIndex = _renderFrameCount;
|
||||
frame->framebuffer = finalFramebuffer;
|
||||
frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) {
|
||||
DependencyManager::get<FramebufferCache>()->releaseFramebuffer(framebuffer);
|
||||
};
|
||||
frame->overlay = _applicationOverlay.getOverlayTexture();
|
||||
frame->postCompositeBatch = postCompositeBatch;
|
||||
// deliver final scene rendering commands to the display plugin
|
||||
{
|
||||
PROFILE_RANGE(render, "/pluginOutput");
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <QJsonArray>
|
||||
#include <QTimeZone>
|
||||
#include <QJsonDocument>
|
||||
#include "AccountManager.h"
|
||||
#include "Wallet.h"
|
||||
#include "Ledger.h"
|
||||
#include "CommerceLogging.h"
|
||||
|
@ -48,13 +47,13 @@ Handler(receiveAt)
|
|||
Handler(balance)
|
||||
Handler(inventory)
|
||||
|
||||
void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, QJsonObject request) {
|
||||
void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
const QString URL = "/api/v1/commerce/";
|
||||
JSONCallbackParameters callbackParams(this, success, this, fail);
|
||||
qCInfo(commerce) << "Sending" << endpoint << QJsonDocument(request).toJson(QJsonDocument::Compact);
|
||||
accountManager->sendRequest(URL + endpoint,
|
||||
AccountManagerAuth::Required,
|
||||
authType,
|
||||
method,
|
||||
callbackParams,
|
||||
QJsonDocument(request).toJson());
|
||||
|
@ -70,14 +69,14 @@ void Ledger::signedSend(const QString& propertyName, const QByteArray& text, con
|
|||
} else {
|
||||
request["signature"] = QString("controlled failure!");
|
||||
}
|
||||
send(endpoint, success, fail, QNetworkAccessManager::PutOperation, request);
|
||||
send(endpoint, success, fail, QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, request);
|
||||
}
|
||||
|
||||
void Ledger::keysQuery(const QString& endpoint, const QString& success, const QString& fail) {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
QJsonObject request;
|
||||
request["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys());
|
||||
send(endpoint, success, fail, QNetworkAccessManager::PostOperation, request);
|
||||
send(endpoint, success, fail, QNetworkAccessManager::PostOperation, AccountManagerAuth::Required, request);
|
||||
}
|
||||
|
||||
void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure) {
|
||||
|
@ -192,7 +191,7 @@ void Ledger::history(const QStringList& keys) {
|
|||
void Ledger::resetSuccess(QNetworkReply& reply) { apiResponse("reset", reply); }
|
||||
void Ledger::resetFailure(QNetworkReply& reply) { failResponse("reset", reply); }
|
||||
void Ledger::reset() {
|
||||
send("reset_user_hfc_account", "resetSuccess", "resetFailure", QNetworkAccessManager::PutOperation, QJsonObject());
|
||||
send("reset_user_hfc_account", "resetSuccess", "resetFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, QJsonObject());
|
||||
}
|
||||
|
||||
void Ledger::accountSuccess(QNetworkReply& reply) {
|
||||
|
@ -217,7 +216,7 @@ void Ledger::accountFailure(QNetworkReply& reply) {
|
|||
failResponse("account", reply);
|
||||
}
|
||||
void Ledger::account() {
|
||||
send("hfc_account", "accountSuccess", "accountFailure", QNetworkAccessManager::PutOperation, QJsonObject());
|
||||
send("hfc_account", "accountSuccess", "accountFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, QJsonObject());
|
||||
}
|
||||
|
||||
// The api/failResponse is called just for the side effect of logging.
|
||||
|
@ -242,3 +241,28 @@ void Ledger::updateLocation(const QString& asset_id, const QString location, con
|
|||
signedSend("transaction", transactionString, key, "location", "updateLocationSuccess", "updateLocationFailure", controlledFailure);
|
||||
}
|
||||
}
|
||||
|
||||
void Ledger::certificateInfoSuccess(QNetworkReply& reply) {
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
|
||||
QByteArray response = reply.readAll();
|
||||
QJsonObject replyObject = QJsonDocument::fromJson(response).object();
|
||||
|
||||
QStringList keys = wallet->listPublicKeys();
|
||||
if (keys.count() != 0) {
|
||||
QJsonObject data = replyObject["data"].toObject();
|
||||
if (data["transfer_recipient_key"].toString() == keys[0]) {
|
||||
replyObject.insert("isMyCert", true);
|
||||
}
|
||||
}
|
||||
qInfo(commerce) << "certificateInfo" << "response" << QJsonDocument(replyObject).toJson(QJsonDocument::Compact);
|
||||
emit certificateInfoResult(replyObject);
|
||||
}
|
||||
void Ledger::certificateInfoFailure(QNetworkReply& reply) { failResponse("certificateInfo", reply); }
|
||||
void Ledger::certificateInfo(const QString& certificateId) {
|
||||
QString endpoint = "proof_of_purchase_status/transfer";
|
||||
QJsonObject request;
|
||||
request["certificate_id"] = certificateId;
|
||||
send(endpoint, "certificateInfoSuccess", "certificateInfoFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::None, request);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <QJsonObject>
|
||||
#include <DependencyManager.h>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include "AccountManager.h"
|
||||
|
||||
|
||||
class Ledger : public QObject, public Dependency {
|
||||
|
@ -32,6 +33,7 @@ public:
|
|||
void account();
|
||||
void reset();
|
||||
void updateLocation(const QString& asset_id, const QString location, const bool controlledFailure = false);
|
||||
void certificateInfo(const QString& certificateId);
|
||||
|
||||
signals:
|
||||
void buyResult(QJsonObject result);
|
||||
|
@ -41,6 +43,7 @@ signals:
|
|||
void historyResult(QJsonObject result);
|
||||
void accountResult(QJsonObject result);
|
||||
void locationUpdateResult(QJsonObject result);
|
||||
void certificateInfoResult(QJsonObject result);
|
||||
|
||||
public slots:
|
||||
void buySuccess(QNetworkReply& reply);
|
||||
|
@ -59,11 +62,13 @@ public slots:
|
|||
void accountFailure(QNetworkReply& reply);
|
||||
void updateLocationSuccess(QNetworkReply& reply);
|
||||
void updateLocationFailure(QNetworkReply& reply);
|
||||
void certificateInfoSuccess(QNetworkReply& reply);
|
||||
void certificateInfoFailure(QNetworkReply& reply);
|
||||
|
||||
private:
|
||||
QJsonObject apiResponse(const QString& label, QNetworkReply& reply);
|
||||
QJsonObject failResponse(const QString& label, QNetworkReply& reply);
|
||||
void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, QJsonObject request);
|
||||
void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request);
|
||||
void keysQuery(const QString& endpoint, const QString& success, const QString& fail);
|
||||
void signedSend(const QString& propertyName, const QByteArray& text, const QString& key, const QString& endpoint, const QString& success, const QString& fail, const bool controlled_failure = false);
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@ QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) {
|
|||
connect(wallet.data(), &Wallet::keyFilePathIfExistsResult, this, &QmlCommerce::keyFilePathIfExistsResult);
|
||||
connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult);
|
||||
connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult);
|
||||
connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult);
|
||||
}
|
||||
|
||||
void QmlCommerce::getWalletStatus() {
|
||||
|
@ -125,3 +126,8 @@ void QmlCommerce::account() {
|
|||
auto ledger = DependencyManager::get<Ledger>();
|
||||
ledger->account();
|
||||
}
|
||||
|
||||
void QmlCommerce::certificateInfo(const QString& certificateId) {
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
ledger->certificateInfo(certificateId);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ signals:
|
|||
void inventoryResult(QJsonObject result);
|
||||
void historyResult(QJsonObject result);
|
||||
void accountResult(QJsonObject result);
|
||||
void certificateInfoResult(QJsonObject result);
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE void getWalletStatus();
|
||||
|
@ -63,6 +64,8 @@ protected:
|
|||
Q_INVOKABLE void generateKeyPair();
|
||||
Q_INVOKABLE void reset();
|
||||
Q_INVOKABLE void account();
|
||||
|
||||
Q_INVOKABLE void certificateInfo(const QString& certificateId);
|
||||
};
|
||||
|
||||
#endif // hifi_QmlCommerce_h
|
||||
|
|
|
@ -91,8 +91,8 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
|
|||
return qApp->getUiSize();
|
||||
}
|
||||
|
||||
QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const {
|
||||
auto rect = qApp->getRecommendedOverlayRect();
|
||||
QVariant ControllerScriptingInterface::getRecommendedHUDRect() const {
|
||||
auto rect = qApp->getRecommendedHUDRect();
|
||||
return qRectToVariant(rect);
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public slots:
|
|||
virtual void releaseEntityClickEvents();
|
||||
|
||||
virtual glm::vec2 getViewportDimensions() const;
|
||||
virtual QVariant getRecommendedOverlayRect() const;
|
||||
virtual QVariant getRecommendedHUDRect() const;
|
||||
|
||||
signals:
|
||||
void keyPressEvent(const KeyEvent& event);
|
||||
|
|
|
@ -29,7 +29,7 @@ int DesktopScriptingInterface::getHeight() {
|
|||
return size.height();
|
||||
}
|
||||
|
||||
void DesktopScriptingInterface::setOverlayAlpha(float alpha) {
|
||||
void DesktopScriptingInterface::setHUDAlpha(float alpha) {
|
||||
qApp->getApplicationCompositor().setAlpha(alpha);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class DesktopScriptingInterface : public QObject, public Dependency {
|
|||
Q_PROPERTY(int height READ getHeight) // Physical height of screen(s) including task bars and system menus
|
||||
|
||||
public:
|
||||
Q_INVOKABLE void setOverlayAlpha(float alpha);
|
||||
Q_INVOKABLE void setHUDAlpha(float alpha);
|
||||
Q_INVOKABLE void show(const QString& path, const QString& title);
|
||||
|
||||
int getWidth();
|
||||
|
|
|
@ -26,7 +26,8 @@ Base3DOverlay::Base3DOverlay() :
|
|||
_isSolid(DEFAULT_IS_SOLID),
|
||||
_isDashedLine(DEFAULT_IS_DASHED_LINE),
|
||||
_ignoreRayIntersection(false),
|
||||
_drawInFront(false)
|
||||
_drawInFront(false),
|
||||
_drawHUDLayer(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -38,6 +39,7 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) :
|
|||
_isDashedLine(base3DOverlay->_isDashedLine),
|
||||
_ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection),
|
||||
_drawInFront(base3DOverlay->_drawInFront),
|
||||
_drawHUDLayer(base3DOverlay->_drawHUDLayer),
|
||||
_isGrabbable(base3DOverlay->_isGrabbable)
|
||||
{
|
||||
setTransform(base3DOverlay->getTransform());
|
||||
|
@ -125,13 +127,19 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) {
|
|||
bool needRenderItemUpdate = false;
|
||||
|
||||
auto drawInFront = properties["drawInFront"];
|
||||
|
||||
if (drawInFront.isValid()) {
|
||||
bool value = drawInFront.toBool();
|
||||
setDrawInFront(value);
|
||||
needRenderItemUpdate = true;
|
||||
}
|
||||
|
||||
auto drawHUDLayer = properties["drawHUDLayer"];
|
||||
if (drawHUDLayer.isValid()) {
|
||||
bool value = drawHUDLayer.toBool();
|
||||
setDrawHUDLayer(value);
|
||||
needRenderItemUpdate = true;
|
||||
}
|
||||
|
||||
auto isGrabbable = properties["grabbable"];
|
||||
if (isGrabbable.isValid()) {
|
||||
setIsGrabbable(isGrabbable.toBool());
|
||||
|
@ -269,10 +277,10 @@ void Base3DOverlay::update(float duration) {
|
|||
// then the correct transform used for rendering is computed in the update transaction and assigned.
|
||||
if (_renderTransformDirty) {
|
||||
auto itemID = getRenderItemID();
|
||||
// Capture the render transform value in game loop before
|
||||
auto latestTransform = evalRenderTransform();
|
||||
_renderTransformDirty = false;
|
||||
if (render::Item::isValidID(itemID)) {
|
||||
// Capture the render transform value in game loop before
|
||||
auto latestTransform = evalRenderTransform();
|
||||
_renderTransformDirty = false;
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
transaction.updateItem<Overlay>(itemID, [latestTransform](Overlay& data) {
|
||||
|
@ -282,8 +290,6 @@ void Base3DOverlay::update(float duration) {
|
|||
}
|
||||
});
|
||||
scene->enqueueTransaction(transaction);
|
||||
} else {
|
||||
setRenderTransform(latestTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
bool getIsSolidLine() const { return !_isDashedLine; }
|
||||
bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; }
|
||||
bool getDrawInFront() const { return _drawInFront; }
|
||||
bool getDrawHUDLayer() const { return _drawHUDLayer; }
|
||||
bool getIsGrabbable() const { return _isGrabbable; }
|
||||
|
||||
void setLineWidth(float lineWidth) { _lineWidth = lineWidth; }
|
||||
|
@ -48,6 +49,7 @@ public:
|
|||
void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; }
|
||||
void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; }
|
||||
virtual void setDrawInFront(bool value) { _drawInFront = value; }
|
||||
virtual void setDrawHUDLayer(bool value) { _drawHUDLayer = value; }
|
||||
void setIsGrabbable(bool value) { _isGrabbable = value; }
|
||||
|
||||
virtual AABox getBounds() const override = 0;
|
||||
|
@ -81,6 +83,7 @@ protected:
|
|||
bool _isDashedLine;
|
||||
bool _ignoreRayIntersection;
|
||||
bool _drawInFront;
|
||||
bool _drawHUDLayer;
|
||||
bool _isGrabbable { false };
|
||||
mutable bool _renderTransformDirty{ true };
|
||||
|
||||
|
|
|
@ -263,7 +263,7 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() {
|
|||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||
if (!getIsSolid()) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
}
|
||||
return builder.build();
|
||||
|
|
|
@ -113,7 +113,7 @@ const render::ShapeKey Cube3DOverlay::getShapeKey() {
|
|||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||
if (!getIsSolid()) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
}
|
||||
return builder.build();
|
||||
|
|
|
@ -132,7 +132,7 @@ void Image3DOverlay::render(RenderArgs* args) {
|
|||
|
||||
const render::ShapeKey Image3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
|
||||
if (_emissive || shouldDrawHUDLayer()) {
|
||||
if (_emissive) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
if (isTransparent()) {
|
||||
|
|
|
@ -87,6 +87,10 @@ void ModelOverlay::update(float deltatime) {
|
|||
_drawInFrontDirty = false;
|
||||
_model->setLayeredInFront(getDrawInFront(), scene);
|
||||
}
|
||||
if (_drawInHUDDirty) {
|
||||
_drawInHUDDirty = false;
|
||||
_model->setLayeredInHUD(getDrawHUDLayer(), scene);
|
||||
}
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
|
@ -111,6 +115,11 @@ void ModelOverlay::setDrawInFront(bool drawInFront) {
|
|||
_drawInFrontDirty = true;
|
||||
}
|
||||
|
||||
void ModelOverlay::setDrawHUDLayer(bool drawHUDLayer) {
|
||||
Base3DOverlay::setDrawHUDLayer(drawHUDLayer);
|
||||
_drawInHUDDirty = true;
|
||||
}
|
||||
|
||||
void ModelOverlay::setProperties(const QVariantMap& properties) {
|
||||
auto origPosition = getPosition();
|
||||
auto origRotation = getRotation();
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
|
||||
void setVisible(bool visible) override;
|
||||
void setDrawInFront(bool drawInFront) override;
|
||||
void setDrawHUDLayer(bool drawHUDLayer) override;
|
||||
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
@ -78,8 +79,6 @@ private:
|
|||
bool _scaleToFit = { false };
|
||||
float _loadPriority { 0.0f };
|
||||
|
||||
bool _visibleDirty { false };
|
||||
bool _drawInFrontDirty { false };
|
||||
AnimationPointer _animation;
|
||||
|
||||
QUrl _animationURL;
|
||||
|
@ -97,6 +96,11 @@ private:
|
|||
QUrl _jointMappingURL;
|
||||
bool _jointMappingCompleted { false };
|
||||
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
|
||||
|
||||
bool _visibleDirty { false };
|
||||
bool _drawInFrontDirty { false };
|
||||
bool _drawInHUDDirty { false };
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_ModelOverlay_h
|
||||
|
|
|
@ -32,7 +32,6 @@ Overlay::Overlay() :
|
|||
_colorPulse(0.0f),
|
||||
_color(DEFAULT_OVERLAY_COLOR),
|
||||
_visible(true),
|
||||
_drawHUDLayer(false),
|
||||
_anchor(NO_ANCHOR)
|
||||
{
|
||||
}
|
||||
|
@ -51,7 +50,6 @@ Overlay::Overlay(const Overlay* overlay) :
|
|||
_colorPulse(overlay->_colorPulse),
|
||||
_color(overlay->_color),
|
||||
_visible(overlay->_visible),
|
||||
_drawHUDLayer(overlay->_drawHUDLayer),
|
||||
_anchor(overlay->_anchor)
|
||||
{
|
||||
}
|
||||
|
@ -90,11 +88,6 @@ void Overlay::setProperties(const QVariantMap& properties) {
|
|||
setColorPulse(properties["colorPulse"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["drawHUDLayer"].isValid()) {
|
||||
bool drawHUDLayer = properties["drawHUDLayer"].toBool();
|
||||
setDrawHUDLayer(drawHUDLayer);
|
||||
}
|
||||
|
||||
if (properties["visible"].isValid()) {
|
||||
bool visible = properties["visible"].toBool();
|
||||
setVisible(visible);
|
||||
|
@ -170,13 +163,6 @@ float Overlay::getAlpha() {
|
|||
return (_alphaPulse >= 0.0f) ? _alpha * pulseLevel : _alpha * (1.0f - pulseLevel);
|
||||
}
|
||||
|
||||
void Overlay::setDrawHUDLayer(bool drawHUDLayer) {
|
||||
if (drawHUDLayer != _drawHUDLayer) {
|
||||
qApp->getOverlays().setOverlayDrawHUDLayer(getOverlayID(), drawHUDLayer);
|
||||
_drawHUDLayer = drawHUDLayer;
|
||||
}
|
||||
}
|
||||
|
||||
// pulse travels from min to max, then max to min in one period.
|
||||
float Overlay::updatePulse() {
|
||||
if (_pulsePeriod <= 0.0f) {
|
||||
|
|
|
@ -58,7 +58,6 @@ public:
|
|||
virtual bool is3D() const = 0;
|
||||
bool isLoaded() { return _isLoaded; }
|
||||
bool getVisible() const { return _visible; }
|
||||
bool shouldDrawHUDLayer() const { return _drawHUDLayer; }
|
||||
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
|
||||
xColor getColor();
|
||||
float getAlpha();
|
||||
|
@ -117,7 +116,6 @@ protected:
|
|||
|
||||
xColor _color;
|
||||
bool _visible; // should the overlay be drawn at all
|
||||
bool _drawHUDLayer; // should the overlay be drawn on the HUD layer
|
||||
Anchor _anchor;
|
||||
|
||||
unsigned int _stackOrder { 0 };
|
||||
|
|
|
@ -37,29 +37,22 @@
|
|||
#include "Web3DOverlay.h"
|
||||
#include <QtQuick/QQuickWindow>
|
||||
|
||||
#include "render/ShapePipeline.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
|
||||
|
||||
extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
|
||||
|
||||
void Overlays::cleanupAllOverlays() {
|
||||
QMap<OverlayID, Overlay::Pointer> overlaysHUD;
|
||||
QMap<OverlayID, Overlay::Pointer> overlays3DHUD;
|
||||
QMap<OverlayID, Overlay::Pointer> overlaysWorld;
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
overlaysHUD.swap(_overlaysHUD);
|
||||
overlays3DHUD.swap(_overlays3DHUD);
|
||||
overlaysWorld.swap(_overlaysWorld);
|
||||
}
|
||||
|
||||
foreach(Overlay::Pointer overlay, overlaysHUD) {
|
||||
_overlaysToDelete.push_back(overlay);
|
||||
}
|
||||
foreach(Overlay::Pointer overlay, overlays3DHUD) {
|
||||
_overlaysToDelete.push_back(overlay);
|
||||
}
|
||||
foreach(Overlay::Pointer overlay, overlaysWorld) {
|
||||
_overlaysToDelete.push_back(overlay);
|
||||
}
|
||||
|
@ -73,8 +66,6 @@ void Overlays::init() {
|
|||
#if OVERLAY_PANELS
|
||||
_scriptEngine = new QScriptEngine();
|
||||
#endif
|
||||
_shapePlumber = std::make_shared<render::ShapePlumber>();
|
||||
initOverlay3DPipelines(*_shapePlumber, true);
|
||||
}
|
||||
|
||||
void Overlays::update(float deltatime) {
|
||||
|
@ -83,9 +74,6 @@ void Overlays::update(float deltatime) {
|
|||
foreach(const auto& thisOverlay, _overlaysHUD) {
|
||||
thisOverlay->update(deltatime);
|
||||
}
|
||||
foreach(const auto& thisOverlay, _overlays3DHUD) {
|
||||
thisOverlay->update(deltatime);
|
||||
}
|
||||
foreach(const auto& thisOverlay, _overlaysWorld) {
|
||||
thisOverlay->update(deltatime);
|
||||
}
|
||||
|
@ -142,23 +130,6 @@ void Overlays::renderHUD(RenderArgs* renderArgs) {
|
|||
}
|
||||
}
|
||||
|
||||
void Overlays::render3DHUDOverlays(RenderArgs* renderArgs) {
|
||||
PROFILE_RANGE(render_overlays, __FUNCTION__);
|
||||
gpu::Batch& batch = *renderArgs->_batch;
|
||||
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
|
||||
QMutexLocker lock(&_mutex);
|
||||
foreach(Overlay::Pointer thisOverlay, _overlays3DHUD) {
|
||||
// Reset necessary batch pipeline settings between overlays
|
||||
batch.setResourceTexture(0, textureCache->getWhiteTexture()); // FIXME - do we really need to do this??
|
||||
batch.setModelTransform(Transform());
|
||||
|
||||
renderArgs->_shapePipeline = _shapePlumber->pickPipeline(renderArgs, thisOverlay->getShapeKey());
|
||||
thisOverlay->render(renderArgs);
|
||||
}
|
||||
}
|
||||
|
||||
void Overlays::disable() {
|
||||
_enabled = false;
|
||||
}
|
||||
|
@ -173,8 +144,6 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const {
|
|||
QMutexLocker locker(&_mutex);
|
||||
if (_overlaysHUD.contains(id)) {
|
||||
return _overlaysHUD[id];
|
||||
} else if (_overlays3DHUD.contains(id)) {
|
||||
return _overlays3DHUD[id];
|
||||
} else if (_overlaysWorld.contains(id)) {
|
||||
return _overlaysWorld[id];
|
||||
}
|
||||
|
@ -232,7 +201,7 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
|
|||
OverlayID thisID = OverlayID(QUuid::createUuid());
|
||||
overlay->setOverlayID(thisID);
|
||||
overlay->setStackOrder(_stackOrder++);
|
||||
if (overlay->is3D() && !overlay->shouldDrawHUDLayer()) {
|
||||
if (overlay->is3D()) {
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
_overlaysWorld[thisID] = overlay;
|
||||
|
@ -242,9 +211,6 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
|
|||
render::Transaction transaction;
|
||||
overlay->addToScene(overlay, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
} else if (overlay->is3D() && overlay->shouldDrawHUDLayer()) {
|
||||
QMutexLocker locker(&_mutex);
|
||||
_overlays3DHUD[thisID] = overlay;
|
||||
} else {
|
||||
QMutexLocker locker(&_mutex);
|
||||
_overlaysHUD[thisID] = overlay;
|
||||
|
@ -253,28 +219,6 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
|
|||
return thisID;
|
||||
}
|
||||
|
||||
void Overlays::setOverlayDrawHUDLayer(const OverlayID& id, const bool drawHUDLayer) {
|
||||
QMutexLocker locker(&_mutex);
|
||||
if (drawHUDLayer && _overlaysWorld.contains(id)) {
|
||||
std::shared_ptr<Overlay> overlay = _overlaysWorld.take(id);
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
auto itemID = overlay->getRenderItemID();
|
||||
if (render::Item::isValidID(itemID)) {
|
||||
overlay->removeFromScene(overlay, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
_overlays3DHUD[id] = overlay;
|
||||
} else if (!drawHUDLayer && _overlays3DHUD.contains(id)) {
|
||||
std::shared_ptr<Overlay> overlay = _overlays3DHUD.take(id);
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
overlay->addToScene(overlay, scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
_overlaysWorld[id] = overlay;
|
||||
}
|
||||
}
|
||||
|
||||
OverlayID Overlays::cloneOverlay(OverlayID id) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
OverlayID result;
|
||||
|
@ -361,8 +305,6 @@ void Overlays::deleteOverlay(OverlayID id) {
|
|||
QMutexLocker locker(&_mutex);
|
||||
if (_overlaysHUD.contains(id)) {
|
||||
overlayToDelete = _overlaysHUD.take(id);
|
||||
} else if (_overlays3DHUD.contains(id)) {
|
||||
overlayToDelete = _overlays3DHUD.take(id);
|
||||
} else if (_overlaysWorld.contains(id)) {
|
||||
overlayToDelete = _overlaysWorld.take(id);
|
||||
} else {
|
||||
|
@ -771,7 +713,7 @@ bool Overlays::isAddedOverlay(OverlayID id) {
|
|||
}
|
||||
|
||||
QMutexLocker locker(&_mutex);
|
||||
return _overlaysHUD.contains(id) || _overlays3DHUD.contains(id) || _overlaysWorld.contains(id);
|
||||
return _overlaysHUD.contains(id) || _overlaysWorld.contains(id);
|
||||
}
|
||||
|
||||
void Overlays::sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {
|
||||
|
|
|
@ -90,7 +90,6 @@ public:
|
|||
void init();
|
||||
void update(float deltatime);
|
||||
void renderHUD(RenderArgs* renderArgs);
|
||||
void render3DHUDOverlays(RenderArgs* renderArgs);
|
||||
void disable();
|
||||
void enable();
|
||||
|
||||
|
@ -103,8 +102,6 @@ public:
|
|||
OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
|
||||
OverlayID addOverlay(const Overlay::Pointer& overlay);
|
||||
|
||||
void setOverlayDrawHUDLayer(const OverlayID& id, const bool drawHUDLayer);
|
||||
|
||||
bool mousePressEvent(QMouseEvent* event);
|
||||
bool mouseDoublePressEvent(QMouseEvent* event);
|
||||
bool mouseReleaseEvent(QMouseEvent* event);
|
||||
|
@ -334,11 +331,8 @@ private:
|
|||
|
||||
mutable QMutex _mutex { QMutex::Recursive };
|
||||
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
||||
QMap<OverlayID, Overlay::Pointer> _overlays3DHUD;
|
||||
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
||||
|
||||
render::ShapePlumberPointer _shapePlumber;
|
||||
|
||||
#if OVERLAY_PANELS
|
||||
QMap<OverlayID, OverlayPanel::Pointer> _panels;
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,8 @@ namespace render {
|
|||
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
|
||||
auto builder = ItemKey::Builder().withTypeShape();
|
||||
if (overlay->is3D()) {
|
||||
if (std::static_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront()) {
|
||||
auto overlay3D = std::static_pointer_cast<Base3DOverlay>(overlay);
|
||||
if (overlay3D->getDrawInFront() || overlay3D->getDrawHUDLayer()) {
|
||||
builder.withLayered();
|
||||
}
|
||||
if (overlay->isTransparent()) {
|
||||
|
@ -49,20 +50,17 @@ namespace render {
|
|||
return overlay->getBounds();
|
||||
}
|
||||
template <> int payloadGetLayer(const Overlay::Pointer& overlay) {
|
||||
// Magic number while we are defining the layering mechanism:
|
||||
const int LAYER_2D = 2;
|
||||
const int LAYER_3D_FRONT = 1;
|
||||
const int LAYER_3D = 0;
|
||||
|
||||
if (overlay->is3D()) {
|
||||
auto overlay3D = std::dynamic_pointer_cast<Base3DOverlay>(overlay);
|
||||
if (overlay3D->getDrawInFront()) {
|
||||
return LAYER_3D_FRONT;
|
||||
return Item::LAYER_3D_FRONT;
|
||||
} else if (overlay3D->getDrawHUDLayer()) {
|
||||
return Item::LAYER_3D_HUD;
|
||||
} else {
|
||||
return LAYER_3D;
|
||||
return Item::LAYER_3D;
|
||||
}
|
||||
} else {
|
||||
return LAYER_2D;
|
||||
return Item::LAYER_2D;
|
||||
}
|
||||
}
|
||||
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) {
|
||||
|
|
|
@ -55,7 +55,7 @@ const render::ShapeKey Shape3DOverlay::getShapeKey() {
|
|||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||
if (!getIsSolid()) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
}
|
||||
return builder.build();
|
||||
|
|
|
@ -60,7 +60,7 @@ const render::ShapeKey Sphere3DOverlay::getShapeKey() {
|
|||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||
if (!getIsSolid()) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
}
|
||||
return builder.build();
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
|
||||
void setModelTransform(const Transform& transform) { _modelTransform = transform; }
|
||||
const Transform& getModelTransform() const { return _modelTransform; }
|
||||
glm::mat4 getUiTransform() const;
|
||||
|
||||
float getAlpha() const { return _alpha; }
|
||||
void setAlpha(float alpha) { if (alpha != _alpha) { emit alphaChanged(); _alpha = alpha; } }
|
||||
|
@ -122,7 +123,6 @@ protected slots:
|
|||
void sendFakeMouseEvent();
|
||||
|
||||
private:
|
||||
glm::mat4 getUiTransform() const;
|
||||
void updateTooltips();
|
||||
|
||||
DisplayPluginPointer _currentDisplayPlugin;
|
||||
|
|
|
@ -307,7 +307,7 @@ bool OpenGLDisplayPlugin::activate() {
|
|||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
connect(compositorHelper.data(), &CompositorHelper::alphaChanged, [this] {
|
||||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
auto animation = new QPropertyAnimation(this, "overlayAlpha");
|
||||
auto animation = new QPropertyAnimation(this, "hudAlpha");
|
||||
animation->setDuration(200);
|
||||
animation->setEndValue(compositorHelper->getAlpha());
|
||||
animation->start();
|
||||
|
@ -415,7 +415,7 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
_overlayPipeline = gpu::Pipeline::create(program, state);
|
||||
_hudPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -437,7 +437,7 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
void OpenGLDisplayPlugin::uncustomizeContext() {
|
||||
_presentPipeline.reset();
|
||||
_cursorPipeline.reset();
|
||||
_overlayPipeline.reset();
|
||||
_hudPipeline.reset();
|
||||
_compositeFramebuffer.reset();
|
||||
withPresentThreadLock([&] {
|
||||
_currentFrame.reset();
|
||||
|
@ -562,22 +562,23 @@ void OpenGLDisplayPlugin::updateFrameData() {
|
|||
});
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::compositeOverlay() {
|
||||
render([&](gpu::Batch& batch){
|
||||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(_compositeFramebuffer);
|
||||
batch.setPipeline(_overlayPipeline);
|
||||
batch.setResourceTexture(0, _currentFrame->overlay);
|
||||
if (isStereo()) {
|
||||
for_each_eye([&](Eye eye) {
|
||||
batch.setViewportTransform(eyeViewport(eye));
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> OpenGLDisplayPlugin::getHUDOperator() {
|
||||
return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) {
|
||||
if (_hudPipeline) {
|
||||
batch.enableStereo(false);
|
||||
batch.setPipeline(_hudPipeline);
|
||||
batch.setResourceTexture(0, hudTexture);
|
||||
if (isStereo()) {
|
||||
for_each_eye([&](Eye eye) {
|
||||
batch.setViewportTransform(eyeViewport(eye));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
} else {
|
||||
batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize()));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
});
|
||||
} else {
|
||||
batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize()));
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::compositePointer() {
|
||||
|
@ -626,29 +627,15 @@ void OpenGLDisplayPlugin::compositeLayers() {
|
|||
compositeScene();
|
||||
}
|
||||
|
||||
// Clear the depth framebuffer after drawing the scene so that the HUD elements can depth test against each other
|
||||
render([&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(_compositeFramebuffer);
|
||||
batch.clearDepthFramebuffer((float) UINT32_MAX);
|
||||
});
|
||||
|
||||
#ifdef HIFI_ENABLE_NSIGHT_DEBUG
|
||||
if (false) // do not compositeoverlay if running nsight debug
|
||||
if (false) // do not draw the HUD if running nsight debug
|
||||
#endif
|
||||
{
|
||||
PROFILE_RANGE_EX(render_detail, "compositeOverlay", 0xff0077ff, (uint64_t)presentCount())
|
||||
compositeOverlay();
|
||||
}
|
||||
|
||||
// Only render HUD layer 3D overlays in HMD mode
|
||||
if (isHmd()) {
|
||||
PROFILE_RANGE_EX(render_detail, "compositeHUDOverlays", 0xff0077ff, (uint64_t)presentCount())
|
||||
render([&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(_compositeFramebuffer);
|
||||
PROFILE_RANGE_EX(render_detail, "handleHUDBatch", 0xff0077ff, (uint64_t)presentCount())
|
||||
auto hudOperator = getHUDOperator();
|
||||
withPresentThreadLock([&] {
|
||||
_hudOperator = hudOperator;
|
||||
});
|
||||
_gpuContext->executeBatch(_currentFrame->postCompositeBatch);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -656,13 +643,7 @@ void OpenGLDisplayPlugin::compositeLayers() {
|
|||
compositeExtra();
|
||||
}
|
||||
|
||||
// Clear the depth buffer again and draw the pointer last so it's on top of everything
|
||||
render([&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(_compositeFramebuffer);
|
||||
batch.clearDepthFramebuffer((float) UINT32_MAX);
|
||||
});
|
||||
|
||||
// Draw the pointer last so it's on top of everything
|
||||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
if (compositorHelper->getReticleVisible()) {
|
||||
PROFILE_RANGE_EX(render_detail, "compositePointer", 0xff0077ff, (uint64_t)presentCount())
|
||||
|
@ -844,7 +825,7 @@ void OpenGLDisplayPlugin::assertIsPresentThread() const {
|
|||
|
||||
bool OpenGLDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
withNonPresentThreadLock([&] {
|
||||
_compositeOverlayAlpha = _overlayAlpha;
|
||||
_compositeHUDAlpha = _hudAlpha;
|
||||
});
|
||||
return Parent::beginFrameRender(frameIndex);
|
||||
}
|
||||
|
@ -887,8 +868,7 @@ OpenGLDisplayPlugin::~OpenGLDisplayPlugin() {
|
|||
void OpenGLDisplayPlugin::updateCompositeFramebuffer() {
|
||||
auto renderSize = getRecommendedRenderSize();
|
||||
if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) {
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL);
|
||||
_compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, depthFormat, renderSize.x, renderSize.y));
|
||||
_compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <SimpleMovingAverage.h>
|
||||
#include <shared/RateCounter.h>
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
|
||||
namespace gpu {
|
||||
namespace gl {
|
||||
class GLBackend;
|
||||
|
@ -30,7 +32,7 @@ namespace gpu {
|
|||
|
||||
class OpenGLDisplayPlugin : public DisplayPlugin {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float overlayAlpha MEMBER _overlayAlpha)
|
||||
Q_PROPERTY(float hudAlpha MEMBER _hudAlpha)
|
||||
using Parent = DisplayPlugin;
|
||||
protected:
|
||||
using Mutex = std::mutex;
|
||||
|
@ -93,7 +95,7 @@ protected:
|
|||
virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; }
|
||||
virtual void compositeLayers();
|
||||
virtual void compositeScene();
|
||||
virtual void compositeOverlay();
|
||||
virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator();
|
||||
virtual void compositePointer();
|
||||
virtual void compositeExtra() {};
|
||||
|
||||
|
@ -137,12 +139,12 @@ protected:
|
|||
gpu::FramePointer _currentFrame;
|
||||
gpu::Frame* _lastFrame { nullptr };
|
||||
gpu::FramebufferPointer _compositeFramebuffer;
|
||||
gpu::PipelinePointer _overlayPipeline;
|
||||
gpu::PipelinePointer _hudPipeline;
|
||||
gpu::PipelinePointer _simplePipeline;
|
||||
gpu::PipelinePointer _presentPipeline;
|
||||
gpu::PipelinePointer _cursorPipeline;
|
||||
gpu::TexturePointer _displayTexture{};
|
||||
float _compositeOverlayAlpha { 1.0f };
|
||||
float _compositeHUDAlpha { 1.0f };
|
||||
|
||||
struct CursorData {
|
||||
QImage image;
|
||||
|
@ -176,6 +178,6 @@ protected:
|
|||
// Any resource shared by the main thread and the presentation thread must
|
||||
// be serialized through this mutex
|
||||
mutable Mutex _presentMutex;
|
||||
float _overlayAlpha{ 1.0f };
|
||||
float _hudAlpha{ 1.0f };
|
||||
};
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
#include "../Logging.h"
|
||||
#include "../CompositorHelper.h"
|
||||
|
||||
#include "render-utils/hmd_ui_vert.h"
|
||||
#include "render-utils/hmd_ui_frag.h"
|
||||
|
||||
static const QString MONO_PREVIEW = "Mono Preview";
|
||||
static const QString DISABLE_PREVIEW = "Disable Preview";
|
||||
static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate";
|
||||
|
@ -46,19 +49,11 @@ static const glm::mat4 IDENTITY_MATRIX;
|
|||
//#define LIVE_SHADER_RELOAD 1
|
||||
extern glm::vec3 getPoint(float yaw, float pitch);
|
||||
|
||||
static QString readFile(const QString& filename) {
|
||||
QFile file(filename);
|
||||
file.open(QFile::Text | QFile::ReadOnly);
|
||||
QString result;
|
||||
result.append(QTextStream(&file).readAll());
|
||||
return result;
|
||||
}
|
||||
|
||||
glm::uvec2 HmdDisplayPlugin::getRecommendedUiSize() const {
|
||||
return CompositorHelper::VIRTUAL_SCREEN_SIZE;
|
||||
}
|
||||
|
||||
QRect HmdDisplayPlugin::getRecommendedOverlayRect() const {
|
||||
QRect HmdDisplayPlugin::getRecommendedHUDRect() const {
|
||||
return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT;
|
||||
}
|
||||
|
||||
|
@ -108,7 +103,7 @@ void HmdDisplayPlugin::internalDeactivate() {
|
|||
|
||||
void HmdDisplayPlugin::customizeContext() {
|
||||
Parent::customizeContext();
|
||||
_overlayRenderer.build();
|
||||
_hudRenderer.build();
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::uncustomizeContext() {
|
||||
|
@ -121,7 +116,7 @@ void HmdDisplayPlugin::uncustomizeContext() {
|
|||
batch.setFramebuffer(_compositeFramebuffer);
|
||||
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0));
|
||||
});
|
||||
_overlayRenderer = OverlayRenderer();
|
||||
_hudRenderer = HUDRenderer();
|
||||
_previewTexture.reset();
|
||||
Parent::uncustomizeContext();
|
||||
}
|
||||
|
@ -171,7 +166,7 @@ float HmdDisplayPlugin::getLeftCenterPixel() const {
|
|||
void HmdDisplayPlugin::internalPresent() {
|
||||
PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)presentCount())
|
||||
|
||||
// Composite together the scene, overlay and mouse cursor
|
||||
// Composite together the scene, hud and mouse cursor
|
||||
hmdPresent();
|
||||
|
||||
if (_displayTexture) {
|
||||
|
@ -344,17 +339,9 @@ void HmdDisplayPlugin::updateFrameData() {
|
|||
auto correction = glm::inverse(batchPose) * currentPose;
|
||||
getGLBackend()->setCameraCorrection(correction);
|
||||
}
|
||||
|
||||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
glm::mat4 modelMat = compositorHelper->getModelTransform().getMatrix();
|
||||
|
||||
for_each_eye([&](Eye eye) {
|
||||
auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye)) * modelMat;
|
||||
_overlayRenderer.mvps[eye] = _eyeProjections[eye] * modelView;
|
||||
});
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::OverlayRenderer::build() {
|
||||
void HmdDisplayPlugin::HUDRenderer::build() {
|
||||
vertices = std::make_shared<gpu::Buffer>();
|
||||
indices = std::make_shared<gpu::Buffer>();
|
||||
|
||||
|
@ -410,38 +397,20 @@ void HmdDisplayPlugin::OverlayRenderer::build() {
|
|||
format = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||
format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||
format->setAttribute(gpu::Stream::TEXCOORD, gpu::Stream::TEXCOORD, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV));
|
||||
uniformBuffers[0] = std::make_shared<gpu::Buffer>(sizeof(Uniforms), nullptr);
|
||||
uniformBuffers[1] = std::make_shared<gpu::Buffer>(sizeof(Uniforms), nullptr);
|
||||
uniformsBuffer = std::make_shared<gpu::Buffer>(sizeof(Uniforms), nullptr);
|
||||
updatePipeline();
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::OverlayRenderer::updatePipeline() {
|
||||
static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.vert";
|
||||
static const QString fsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.frag";
|
||||
|
||||
#if LIVE_SHADER_RELOAD
|
||||
static qint64 vsBuiltAge = 0;
|
||||
static qint64 fsBuiltAge = 0;
|
||||
QFileInfo vsInfo(vsFile);
|
||||
QFileInfo fsInfo(fsFile);
|
||||
auto vsAge = vsInfo.lastModified().toMSecsSinceEpoch();
|
||||
auto fsAge = fsInfo.lastModified().toMSecsSinceEpoch();
|
||||
if (!pipeline || vsAge > vsBuiltAge || fsAge > fsBuiltAge) {
|
||||
vsBuiltAge = vsAge;
|
||||
fsBuiltAge = fsAge;
|
||||
#else
|
||||
void HmdDisplayPlugin::HUDRenderer::updatePipeline() {
|
||||
if (!pipeline) {
|
||||
#endif
|
||||
QString vsSource = readFile(vsFile);
|
||||
QString fsSource = readFile(fsFile);
|
||||
auto vs = gpu::Shader::createVertex(vsSource.toLocal8Bit().toStdString());
|
||||
auto ps = gpu::Shader::createPixel(fsSource.toLocal8Bit().toStdString());
|
||||
auto vs = gpu::Shader::createVertex(std::string(hmd_ui_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(hmd_ui_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::gl::GLBackend::makeProgram(*program, gpu::Shader::BindingSet());
|
||||
this->uniformsLocation = program->getUniformBuffers().findLocation("overlayBuffer");
|
||||
uniformsLocation = program->getUniformBuffers().findLocation("hudBuffer");
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false, false, gpu::LESS_EQUAL));
|
||||
state->setDepthTest(gpu::State::DepthTest(true, true, gpu::LESS_EQUAL));
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
@ -450,30 +419,29 @@ void HmdDisplayPlugin::OverlayRenderer::updatePipeline() {
|
|||
}
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::OverlayRenderer::render(HmdDisplayPlugin& plugin) {
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) {
|
||||
updatePipeline();
|
||||
for_each_eye([&](Eye eye){
|
||||
uniforms.mvp = mvps[eye];
|
||||
uniformBuffers[eye]->setSubData(0, uniforms);
|
||||
});
|
||||
plugin.render([&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(plugin._compositeFramebuffer);
|
||||
batch.setPipeline(pipeline);
|
||||
batch.setInputFormat(format);
|
||||
gpu::BufferView posView(vertices, VERTEX_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::POSITION)._element);
|
||||
gpu::BufferView uvView(vertices, TEXTURE_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::TEXCOORD)._element);
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, posView);
|
||||
batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView);
|
||||
batch.setIndexBuffer(gpu::UINT16, indices, 0);
|
||||
batch.setResourceTexture(0, plugin._currentFrame->overlay);
|
||||
// FIXME use stereo information input to set both MVPs in the uniforms
|
||||
for_each_eye([&](Eye eye) {
|
||||
batch.setUniformBuffer(uniformsLocation, uniformBuffers[eye]);
|
||||
batch.setViewportTransform(plugin.eyeViewport(eye));
|
||||
return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) {
|
||||
if (pipeline) {
|
||||
batch.setPipeline(pipeline);
|
||||
|
||||
batch.setInputFormat(format);
|
||||
gpu::BufferView posView(vertices, VERTEX_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::POSITION)._element);
|
||||
gpu::BufferView uvView(vertices, TEXTURE_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::TEXCOORD)._element);
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, posView);
|
||||
batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView);
|
||||
batch.setIndexBuffer(gpu::UINT16, indices, 0);
|
||||
|
||||
uniformsBuffer->setSubData(0, uniforms);
|
||||
batch.setUniformBuffer(uniformsLocation, uniformsBuffer);
|
||||
|
||||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
batch.setModelTransform(compositorHelper->getUiTransform());
|
||||
batch.setResourceTexture(0, hudTexture);
|
||||
|
||||
batch.drawIndexed(gpu::TRIANGLES, indexCount);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::compositePointer() {
|
||||
|
@ -500,12 +468,8 @@ void HmdDisplayPlugin::compositePointer() {
|
|||
});
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::compositeOverlay() {
|
||||
if (!_currentFrame || !_currentFrame->overlay) {
|
||||
return;
|
||||
}
|
||||
|
||||
_overlayRenderer.render(*this);
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> HmdDisplayPlugin::getHUDOperator() {
|
||||
return _hudRenderer.render(*this);
|
||||
}
|
||||
|
||||
HmdDisplayPlugin::~HmdDisplayPlugin() {
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
glm::uvec2 getRecommendedRenderSize() const override final { return _renderTargetSize; }
|
||||
bool isDisplayVisible() const override { return isHmdMounted(); }
|
||||
|
||||
QRect getRecommendedOverlayRect() const override final;
|
||||
QRect getRecommendedHUDRect() const override final;
|
||||
|
||||
virtual glm::mat4 getHeadPose() const override;
|
||||
|
||||
|
@ -53,7 +53,7 @@ protected:
|
|||
|
||||
bool internalActivate() override;
|
||||
void internalDeactivate() override;
|
||||
void compositeOverlay() override;
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator() override;
|
||||
void compositePointer() override;
|
||||
void internalPresent() override;
|
||||
void customizeContext() override;
|
||||
|
@ -91,7 +91,7 @@ private:
|
|||
gpu::TexturePointer _previewTexture;
|
||||
glm::vec2 _lastWindowSize;
|
||||
|
||||
struct OverlayRenderer {
|
||||
struct HUDRenderer {
|
||||
gpu::Stream::FormatPointer format;
|
||||
gpu::BufferPointer vertices;
|
||||
gpu::BufferPointer indices;
|
||||
|
@ -99,12 +99,9 @@ private:
|
|||
gpu::PipelinePointer pipeline;
|
||||
int32_t uniformsLocation { -1 };
|
||||
|
||||
// FIXME this is stupid, use the built in transformation pipeline
|
||||
std::array<gpu::BufferPointer, 2> uniformBuffers;
|
||||
std::array<mat4, 2> mvps;
|
||||
gpu::BufferPointer uniformsBuffer;
|
||||
|
||||
struct Uniforms {
|
||||
mat4 mvp;
|
||||
float alpha { 1.0f };
|
||||
} uniforms;
|
||||
|
||||
|
@ -119,6 +116,6 @@ private:
|
|||
|
||||
void build();
|
||||
void updatePipeline();
|
||||
void render(HmdDisplayPlugin& plugin);
|
||||
} _overlayRenderer;
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> render(HmdDisplayPlugin& plugin);
|
||||
} _hudRenderer;
|
||||
};
|
||||
|
|
|
@ -78,6 +78,7 @@ protected:
|
|||
// Will be called by the lambda posted to the scene in updateInScene.
|
||||
// This function will execute on the rendering thread, so you cannot use network caches to fetch
|
||||
// data in this method if using multi-threaded rendering
|
||||
|
||||
virtual void doRenderUpdateAsynchronous(const EntityItemPointer& entity) { }
|
||||
|
||||
// Called by the `render` method after `needsRenderUpdate`
|
||||
|
|
|
@ -92,7 +92,7 @@ public:
|
|||
void captureNamedDrawCallInfo(std::string name);
|
||||
|
||||
Batch();
|
||||
explicit Batch(const Batch& batch);
|
||||
Batch(const Batch& batch);
|
||||
~Batch();
|
||||
|
||||
void clear();
|
||||
|
|
|
@ -32,14 +32,10 @@ namespace gpu {
|
|||
Mat4 pose;
|
||||
/// The collection of batches which make up the frame
|
||||
Batches batches;
|
||||
/// Single batch containing overlays to be drawn in the composite framebuffer
|
||||
Batch postCompositeBatch;
|
||||
/// The main thread updates to buffers that are applicable for this frame.
|
||||
BufferUpdates bufferUpdates;
|
||||
/// The destination framebuffer in which the results will be placed
|
||||
FramebufferPointer framebuffer;
|
||||
/// The destination texture containing the 2D overlay
|
||||
TexturePointer overlay;
|
||||
/// How to process the framebuffer when the frame dies. MUST BE THREAD SAFE
|
||||
FramebufferRecycler framebufferRecycler;
|
||||
|
||||
|
|
|
@ -74,9 +74,7 @@ glm::uvec2 rectifyToSparseSize(const glm::uvec2& size) {
|
|||
|
||||
namespace image {
|
||||
|
||||
enum {
|
||||
QIMAGE_HDR_FORMAT = QImage::Format_RGB30
|
||||
};
|
||||
QImage::Format QIMAGE_HDR_FORMAT = QImage::Format_RGB30;
|
||||
|
||||
TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, const QVariantMap& options) {
|
||||
switch (type) {
|
||||
|
@ -440,10 +438,8 @@ void generateHDRMips(gpu::Texture* texture, const QImage& image, const std::atom
|
|||
auto mipFormat = texture->getStoredMipFormat();
|
||||
std::function<glm::vec3(uint32)> unpackFunc;
|
||||
|
||||
nvtt::TextureType textureType = nvtt::TextureType_2D;
|
||||
nvtt::InputFormat inputFormat = nvtt::InputFormat_RGBA_32F;
|
||||
nvtt::WrapMode wrapMode = nvtt::WrapMode_Mirror;
|
||||
nvtt::RoundMode roundMode = nvtt::RoundMode_None;
|
||||
nvtt::AlphaMode alphaMode = nvtt::AlphaMode_None;
|
||||
|
||||
nvtt::CompressionOptions compressionOptions;
|
||||
|
|
|
@ -71,14 +71,14 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) {
|
|||
} else {
|
||||
QUrl url = _url.resolved(filename);
|
||||
|
||||
QString texdir = mapping.value("texdir").toString();
|
||||
QString texdir = mapping.value(TEXDIR_FIELD).toString();
|
||||
if (!texdir.isNull()) {
|
||||
if (!texdir.endsWith('/')) {
|
||||
texdir += '/';
|
||||
}
|
||||
_textureBaseUrl = resolveTextureBaseUrl(url, _url.resolved(texdir));
|
||||
} else {
|
||||
_textureBaseUrl = _effectiveBaseURL;
|
||||
_textureBaseUrl = url.resolved(QUrl("."));
|
||||
}
|
||||
|
||||
auto animGraphVariant = mapping.value("animGraphUrl");
|
||||
|
@ -241,8 +241,10 @@ private:
|
|||
};
|
||||
|
||||
void GeometryDefinitionResource::downloadFinished(const QByteArray& data) {
|
||||
_url = _effectiveBaseURL;
|
||||
_textureBaseUrl = _effectiveBaseURL;
|
||||
if (_url != _effectiveBaseURL) {
|
||||
_url = _effectiveBaseURL;
|
||||
_textureBaseUrl = _effectiveBaseURL;
|
||||
}
|
||||
QThreadPool::globalInstance()->start(new GeometryReader(_self, _effectiveBaseURL, _mapping, data, _combineParts));
|
||||
}
|
||||
|
||||
|
|
|
@ -33,4 +33,13 @@ void DisplayPlugin::waitForPresent() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> DisplayPlugin::getHUDOperator() {
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> hudOperator;
|
||||
{
|
||||
QMutexLocker locker(&_presentMutex);
|
||||
hudOperator = _hudOperator;
|
||||
}
|
||||
return hudOperator;
|
||||
}
|
|
@ -156,8 +156,8 @@ public:
|
|||
return aspect(getRecommendedRenderSize());
|
||||
}
|
||||
|
||||
// The recommended bounds for primary overlay placement
|
||||
virtual QRect getRecommendedOverlayRect() const {
|
||||
// The recommended bounds for primary HUD placement
|
||||
virtual QRect getRecommendedHUDRect() const {
|
||||
const int DESKTOP_SCREEN_PADDING = 50;
|
||||
auto recommendedSize = getRecommendedUiSize() - glm::uvec2(DESKTOP_SCREEN_PADDING);
|
||||
return QRect(0, 0, recommendedSize.x, recommendedSize.y);
|
||||
|
@ -204,8 +204,9 @@ public:
|
|||
|
||||
void waitForPresent();
|
||||
|
||||
static const QString& MENU_PATH();
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator();
|
||||
|
||||
static const QString& MENU_PATH();
|
||||
|
||||
signals:
|
||||
void recommendedFramebufferSizeChanged(const QSize& size);
|
||||
|
@ -217,6 +218,8 @@ protected:
|
|||
|
||||
gpu::ContextPointer _gpuContext;
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> _hudOperator { std::function<void(gpu::Batch&, const gpu::TexturePointer&)>() };
|
||||
|
||||
private:
|
||||
QMutex _presentMutex;
|
||||
QWaitCondition _presentCondition;
|
||||
|
|
|
@ -68,8 +68,6 @@ static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT;
|
|||
|
||||
static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normals
|
||||
static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);
|
||||
static const gpu::Type SHAPE_INDEX_TYPE = gpu::UINT32;
|
||||
static const uint SHAPE_INDEX_SIZE = sizeof(gpu::uint32);
|
||||
|
||||
template <size_t SIDES>
|
||||
std::vector<vec3> polygon() {
|
||||
|
@ -84,67 +82,83 @@ std::vector<vec3> polygon() {
|
|||
}
|
||||
|
||||
void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices) {
|
||||
gpu::Buffer::Size offset = vertexBuffer->getSize();
|
||||
vertexBuffer->append(vertices);
|
||||
|
||||
_positionView = gpu::BufferView(vertexBuffer, 0,
|
||||
vertexBuffer->getSize(), SHAPE_VERTEX_STRIDE, POSITION_ELEMENT);
|
||||
_normalView = gpu::BufferView(vertexBuffer, SHAPE_NORMALS_OFFSET,
|
||||
vertexBuffer->getSize(), SHAPE_VERTEX_STRIDE, NORMAL_ELEMENT);
|
||||
gpu::Buffer::Size viewSize = vertices.size() * 2 * sizeof(glm::vec3);
|
||||
|
||||
_positionView = gpu::BufferView(vertexBuffer, offset,
|
||||
viewSize, SHAPE_VERTEX_STRIDE, POSITION_ELEMENT);
|
||||
_normalView = gpu::BufferView(vertexBuffer, offset + SHAPE_NORMALS_OFFSET,
|
||||
viewSize, SHAPE_VERTEX_STRIDE, NORMAL_ELEMENT);
|
||||
}
|
||||
|
||||
void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices) {
|
||||
_indices = indexBuffer;
|
||||
gpu::Buffer::Size offset = indexBuffer->getSize();
|
||||
if (!indices.empty()) {
|
||||
_indexOffset = indexBuffer->getSize() / SHAPE_INDEX_SIZE;
|
||||
_indexCount = indices.size();
|
||||
indexBuffer->append(indices);
|
||||
for (uint32_t i = 0; i < indices.size(); ++i) {
|
||||
indexBuffer->append((uint16_t)indices[i]);
|
||||
}
|
||||
}
|
||||
gpu::Size viewSize = indices.size() * sizeof(uint16_t);
|
||||
_indicesView = gpu::BufferView(indexBuffer, offset, viewSize, gpu::Element::INDEX_UINT16);
|
||||
|
||||
offset = indexBuffer->getSize();
|
||||
if (!wireIndices.empty()) {
|
||||
_wireIndexOffset = indexBuffer->getSize() / SHAPE_INDEX_SIZE;
|
||||
_wireIndexCount = wireIndices.size();
|
||||
indexBuffer->append(wireIndices);
|
||||
for (uint32_t i = 0; i < wireIndices.size(); ++i) {
|
||||
indexBuffer->append((uint16_t)wireIndices[i]);
|
||||
}
|
||||
}
|
||||
viewSize = wireIndices.size() * sizeof(uint16_t);
|
||||
_wireIndicesView = gpu::BufferView(indexBuffer, offset, viewSize, gpu::Element::INDEX_UINT16);
|
||||
}
|
||||
|
||||
void GeometryCache::ShapeData::setupBatch(gpu::Batch& batch) const {
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, _positionView);
|
||||
batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);
|
||||
batch.setIndexBuffer(SHAPE_INDEX_TYPE, _indices, 0);
|
||||
batch.setIndexBuffer(_indicesView);
|
||||
}
|
||||
|
||||
void GeometryCache::ShapeData::draw(gpu::Batch& batch) const {
|
||||
if (_indexCount) {
|
||||
uint32_t numIndices = (uint32_t)_indicesView.getNumElements();
|
||||
if (numIndices > 0) {
|
||||
setupBatch(batch);
|
||||
batch.drawIndexed(gpu::TRIANGLES, (gpu::uint32)_indexCount, (gpu::uint32)_indexOffset);
|
||||
batch.drawIndexed(gpu::TRIANGLES, numIndices, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryCache::ShapeData::drawWire(gpu::Batch& batch) const {
|
||||
if (_wireIndexCount) {
|
||||
setupBatch(batch);
|
||||
batch.drawIndexed(gpu::LINES, (gpu::uint32)_wireIndexCount, (gpu::uint32)_wireIndexOffset);
|
||||
uint32_t numIndices = (uint32_t)_wireIndicesView.getNumElements();
|
||||
if (numIndices > 0) {
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, _positionView);
|
||||
batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);
|
||||
batch.setIndexBuffer(_wireIndicesView);
|
||||
batch.drawIndexed(gpu::LINES, numIndices, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryCache::ShapeData::drawInstances(gpu::Batch& batch, size_t count) const {
|
||||
if (_indexCount) {
|
||||
uint32_t numIndices = (uint32_t)_indicesView.getNumElements();
|
||||
if (numIndices > 0) {
|
||||
setupBatch(batch);
|
||||
batch.drawIndexedInstanced((gpu::uint32)count, gpu::TRIANGLES, (gpu::uint32)_indexCount, (gpu::uint32)_indexOffset);
|
||||
batch.drawIndexedInstanced((gpu::uint32)count, gpu::TRIANGLES, numIndices, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryCache::ShapeData::drawWireInstances(gpu::Batch& batch, size_t count) const {
|
||||
if (_wireIndexCount) {
|
||||
setupBatch(batch);
|
||||
batch.drawIndexedInstanced((gpu::uint32)count, gpu::LINES, (gpu::uint32)_wireIndexCount, (gpu::uint32)_wireIndexOffset);
|
||||
uint32_t numIndices = (uint32_t)_wireIndicesView.getNumElements();
|
||||
if (numIndices > 0) {
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, _positionView);
|
||||
batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);
|
||||
batch.setIndexBuffer(_wireIndicesView);
|
||||
batch.drawIndexedInstanced((gpu::uint32)count, gpu::LINES, numIndices, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static const size_t ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT = 3;
|
||||
|
||||
size_t GeometryCache::getShapeTriangleCount(Shape shape) {
|
||||
return _shapes[shape]._indexCount / VERTICES_PER_TRIANGLE;
|
||||
return _shapes[shape]._indicesView.getNumElements() / VERTICES_PER_TRIANGLE;
|
||||
}
|
||||
|
||||
size_t GeometryCache::getSphereTriangleCount() {
|
||||
|
@ -168,7 +182,6 @@ static IndexPair indexToken(geometry::Index a, geometry::Index b) {
|
|||
template <size_t N>
|
||||
void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
||||
using namespace geometry;
|
||||
Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE);
|
||||
VertexVector vertices;
|
||||
IndexVector solidIndices, wireIndices;
|
||||
IndexPairs wireSeenIndices;
|
||||
|
@ -179,6 +192,7 @@ void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N
|
|||
vertices.reserve(N * faceCount * 2);
|
||||
solidIndices.reserve(faceIndexCount * faceCount);
|
||||
|
||||
Index baseVertex = 0;
|
||||
for (size_t f = 0; f < faceCount; f++) {
|
||||
const Face<N>& face = shape.faces[f];
|
||||
// Compute the face normal
|
||||
|
@ -219,7 +233,6 @@ void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N
|
|||
template <size_t N>
|
||||
void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {
|
||||
using namespace geometry;
|
||||
Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE);
|
||||
|
||||
VertexVector vertices;
|
||||
vertices.reserve(shape.vertices.size() * 2);
|
||||
|
@ -236,6 +249,7 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid
|
|||
|
||||
solidIndices.reserve(faceIndexCount * faceCount);
|
||||
|
||||
Index baseVertex = 0;
|
||||
for (size_t f = 0; f < faceCount; f++) {
|
||||
const Face<N>& face = shape.faces[f];
|
||||
// Create the wire indices for unseen edges
|
||||
|
@ -265,7 +279,6 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid
|
|||
template <uint32_t N>
|
||||
void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer, bool isConical = false) {
|
||||
using namespace geometry;
|
||||
Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE);
|
||||
VertexVector vertices;
|
||||
IndexVector solidIndices, wireIndices;
|
||||
|
||||
|
@ -286,6 +299,7 @@ void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& ver
|
|||
vertices.push_back(vec3(v.x, -0.5f, v.z));
|
||||
vertices.push_back(vec3(0.0f, -1.0f, 0.0f));
|
||||
}
|
||||
Index baseVertex = 0;
|
||||
for (uint32_t i = 2; i < N; i++) {
|
||||
solidIndices.push_back(baseVertex + 0);
|
||||
solidIndices.push_back(baseVertex + i);
|
||||
|
@ -343,7 +357,6 @@ void drawCircle(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexB
|
|||
// Draw a circle with radius 1/4th the size of the bounding box
|
||||
using namespace geometry;
|
||||
|
||||
Index baseVertex = (Index)(vertexBuffer->getSize() / SHAPE_VERTEX_STRIDE);
|
||||
VertexVector vertices;
|
||||
IndexVector solidIndices, wireIndices;
|
||||
const int NUM_CIRCLE_VERTICES = 64;
|
||||
|
@ -354,6 +367,7 @@ void drawCircle(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexB
|
|||
vertices.push_back(vec3(0.0f, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
Index baseVertex = 0;
|
||||
for (uint32_t i = 2; i < NUM_CIRCLE_VERTICES; i++) {
|
||||
solidIndices.push_back(baseVertex + 0);
|
||||
solidIndices.push_back(baseVertex + i);
|
||||
|
@ -403,7 +417,6 @@ void GeometryCache::buildShapes() {
|
|||
|
||||
// Line
|
||||
{
|
||||
Index baseVertex = (Index)(_shapeVertices->getSize() / SHAPE_VERTEX_STRIDE);
|
||||
ShapeData& shapeData = _shapes[Line];
|
||||
shapeData.setupVertices(_shapeVertices, VertexVector {
|
||||
vec3(-0.5f, 0.0f, 0.0f), vec3(-0.5f, 0.0f, 0.0f),
|
||||
|
@ -411,8 +424,8 @@ void GeometryCache::buildShapes() {
|
|||
});
|
||||
IndexVector wireIndices;
|
||||
// Only two indices
|
||||
wireIndices.push_back(0 + baseVertex);
|
||||
wireIndices.push_back(1 + baseVertex);
|
||||
wireIndices.push_back(0);
|
||||
wireIndices.push_back(1);
|
||||
shapeData.setupIndices(_shapeIndices, IndexVector(), wireIndices);
|
||||
}
|
||||
|
||||
|
|
|
@ -339,14 +339,10 @@ public:
|
|||
void useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend = false);
|
||||
|
||||
struct ShapeData {
|
||||
size_t _indexOffset{ 0 };
|
||||
size_t _indexCount{ 0 };
|
||||
size_t _wireIndexOffset{ 0 };
|
||||
size_t _wireIndexCount{ 0 };
|
||||
|
||||
gpu::BufferView _positionView;
|
||||
gpu::BufferView _normalView;
|
||||
gpu::BufferPointer _indices;
|
||||
gpu::BufferView _indicesView;
|
||||
gpu::BufferView _wireIndicesView;
|
||||
|
||||
void setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices);
|
||||
void setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices);
|
||||
|
|
|
@ -385,7 +385,7 @@ ItemKey ModelMeshPartPayload::getKey() const {
|
|||
builder.withInvisible();
|
||||
}
|
||||
|
||||
if (model->isLayeredInFront()) {
|
||||
if (model->isLayeredInFront() || model->isLayeredInHUD()) {
|
||||
builder.withLayered();
|
||||
}
|
||||
|
||||
|
@ -404,15 +404,15 @@ ItemKey ModelMeshPartPayload::getKey() const {
|
|||
}
|
||||
|
||||
int ModelMeshPartPayload::getLayer() const {
|
||||
// MAgic number while we are defining the layering mechanism:
|
||||
const int LAYER_3D_FRONT = 1;
|
||||
const int LAYER_3D = 0;
|
||||
ModelPointer model = _model.lock();
|
||||
if (model && model->isLayeredInFront()) {
|
||||
return LAYER_3D_FRONT;
|
||||
} else {
|
||||
return LAYER_3D;
|
||||
if (model) {
|
||||
if (model->isLayeredInFront()) {
|
||||
return Item::LAYER_3D_FRONT;
|
||||
} else if (model->isLayeredInHUD()) {
|
||||
return Item::LAYER_3D_HUD;
|
||||
}
|
||||
}
|
||||
return Item::LAYER_3D;
|
||||
}
|
||||
|
||||
ShapeKey ModelMeshPartPayload::getShapeKey() const {
|
||||
|
|
|
@ -603,6 +603,21 @@ void Model::setLayeredInFront(bool layered, const render::ScenePointer& scene) {
|
|||
}
|
||||
}
|
||||
|
||||
void Model::setLayeredInHUD(bool layered, const render::ScenePointer& scene) {
|
||||
if (_isLayeredInHUD != layered) {
|
||||
_isLayeredInHUD = layered;
|
||||
|
||||
render::Transaction transaction;
|
||||
foreach(auto item, _modelMeshRenderItemsMap.keys()) {
|
||||
transaction.resetItem(item, _modelMeshRenderItemsMap[item]);
|
||||
}
|
||||
foreach(auto item, _collisionRenderItemsMap.keys()) {
|
||||
transaction.resetItem(item, _collisionRenderItemsMap[item]);
|
||||
}
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
bool Model::addToScene(const render::ScenePointer& scene,
|
||||
render::Transaction& transaction,
|
||||
render::Item::Status::Getters& statusGetters) {
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
// new Scene/Engine rendering support
|
||||
void setVisibleInScene(bool newValue, const render::ScenePointer& scene);
|
||||
void setLayeredInFront(bool layered, const render::ScenePointer& scene);
|
||||
void setLayeredInHUD(bool layered, const render::ScenePointer& scene);
|
||||
bool needsFixupInScene() const;
|
||||
|
||||
bool needsReload() const { return _needsReload; }
|
||||
|
@ -101,6 +102,7 @@ public:
|
|||
bool isVisible() const { return _isVisible; }
|
||||
|
||||
bool isLayeredInFront() const { return _isLayeredInFront; }
|
||||
bool isLayeredInHUD() const { return _isLayeredInHUD; }
|
||||
|
||||
virtual void updateRenderItems();
|
||||
void setRenderItemsNeedUpdate();
|
||||
|
@ -411,6 +413,7 @@ protected:
|
|||
int _renderInfoHasTransparent { false };
|
||||
|
||||
bool _isLayeredInFront { false };
|
||||
bool _isLayeredInHUD { false };
|
||||
|
||||
private:
|
||||
float _loadingPriority { 0.0f };
|
||||
|
|
|
@ -186,15 +186,20 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DrawBounds>("DrawZones", zones);
|
||||
}
|
||||
|
||||
// Overlays
|
||||
const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).asVarying();
|
||||
const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).asVarying();
|
||||
task.addJob<DrawOverlay3D>("DrawOverlay3DOpaque", overlayOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlay3DTransparent", overlayTransparentsInputs, false);
|
||||
// Layered Overlays
|
||||
const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT);
|
||||
const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT);
|
||||
const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
|
||||
const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0);
|
||||
|
||||
{ // Debug the bounds of the rendered Overlay items, still look at the zbuffer
|
||||
task.addJob<DrawBounds>("DrawOverlayOpaqueBounds", overlayOpaques);
|
||||
task.addJob<DrawBounds>("DrawOverlayTransparentBounds", overlayTransparents);
|
||||
const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel).asVarying();
|
||||
const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel).asVarying();
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false);
|
||||
|
||||
{ // Debug the bounds of the rendered Overlay items that are marked drawInFront, still look at the zbuffer
|
||||
task.addJob<DrawBounds>("DrawOverlayInFrontOpaqueBounds", overlaysInFrontOpaque);
|
||||
task.addJob<DrawBounds>("DrawOverlayInFrontTransparentBounds", overlaysInFrontTransparent);
|
||||
}
|
||||
|
||||
// Debugging stages
|
||||
|
@ -233,6 +238,22 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
// AA job to be revisited
|
||||
task.addJob<Antialiasing>("Antialiasing", primaryFramebuffer);
|
||||
|
||||
// Composite the HUD and HUD overlays
|
||||
task.addJob<CompositeHUD>("HUD");
|
||||
|
||||
const auto overlaysHUDOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(1);
|
||||
const auto overlaysHUDTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(1);
|
||||
|
||||
const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel).asVarying();
|
||||
const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel).asVarying();
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false);
|
||||
|
||||
{ // Debug the bounds of the rendered Overlay items that are marked drawHUDLayer, still look at the zbuffer
|
||||
task.addJob<DrawBounds>("DrawOverlayHUDOpaqueBounds", overlaysHUDOpaque);
|
||||
task.addJob<DrawBounds>("DrawOverlayHUDTransparentBounds", overlaysHUDTransparent);
|
||||
}
|
||||
|
||||
task.addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer);
|
||||
|
||||
// Blit!
|
||||
|
@ -407,6 +428,18 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs&
|
|||
}
|
||||
}
|
||||
|
||||
void CompositeHUD::run(const RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
|
||||
// Grab the HUD texture
|
||||
gpu::doInBatch(renderContext->args->_context, [&](gpu::Batch& batch) {
|
||||
if (renderContext->args->_hudOperator) {
|
||||
renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Blit::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
|
|
|
@ -155,6 +155,14 @@ protected:
|
|||
bool _opaquePass { true };
|
||||
};
|
||||
|
||||
class CompositeHUD {
|
||||
public:
|
||||
using JobModel = render::Job::Model<CompositeHUD>;
|
||||
|
||||
CompositeHUD() {}
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
};
|
||||
|
||||
class Blit {
|
||||
public:
|
||||
using JobModel = render::Job::ModelI<Blit, gpu::FramebufferPointer>;
|
||||
|
|
37
libraries/render-utils/src/hmd_ui.slf
Normal file
37
libraries/render-utils/src/hmd_ui.slf
Normal file
|
@ -0,0 +1,37 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// hmd_ui.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gondelman on 9/28/17.
|
||||
// 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
|
||||
//
|
||||
|
||||
uniform sampler2D hudTexture;
|
||||
|
||||
struct HUDData {
|
||||
float alpha;
|
||||
};
|
||||
|
||||
layout(std140) uniform hudBuffer {
|
||||
HUDData hud;
|
||||
};
|
||||
|
||||
in vec2 _texCoord0;
|
||||
|
||||
out vec4 fragColor0;
|
||||
|
||||
void main() {
|
||||
vec4 color = texture(hudTexture, _texCoord0);
|
||||
color.a *= hud.alpha;
|
||||
if (color.a <= 0.0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
fragColor0 = color;
|
||||
}
|
36
libraries/render-utils/src/hmd_ui.slv
Normal file
36
libraries/render-utils/src/hmd_ui.slv
Normal file
|
@ -0,0 +1,36 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// hmd_ui.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Sam Gondelman on 9/28/17.
|
||||
// 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
|
||||
//
|
||||
|
||||
<@include gpu/Inputs.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
struct HUDData {
|
||||
float alpha;
|
||||
};
|
||||
|
||||
layout(std140) uniform hudBuffer {
|
||||
HUDData hud;
|
||||
};
|
||||
|
||||
out vec2 _texCoord0;
|
||||
|
||||
void main() {
|
||||
_texCoord0 = inTexCoord0.st;
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
}
|
|
@ -121,6 +121,9 @@ namespace render {
|
|||
RenderDetails _details;
|
||||
render::ScenePointer _scene;
|
||||
int8_t _cameraMode { -1 };
|
||||
|
||||
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> _hudOperator;
|
||||
gpu::TexturePointer _hudTexture;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -21,19 +21,24 @@
|
|||
|
||||
using namespace render;
|
||||
|
||||
void FilterLayeredItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) {
|
||||
void FilterLayeredItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, Outputs& outputs) {
|
||||
auto& scene = renderContext->_scene;
|
||||
|
||||
// Clear previous values
|
||||
outItems.clear();
|
||||
ItemBounds matchedItems;
|
||||
ItemBounds nonMatchItems;
|
||||
|
||||
// For each item, filter it into one bucket
|
||||
for (auto& itemBound : inItems) {
|
||||
auto& item = scene->getItem(itemBound.id);
|
||||
if (item.getLayer() == _keepLayer) {
|
||||
outItems.emplace_back(itemBound);
|
||||
matchedItems.emplace_back(itemBound);
|
||||
} else {
|
||||
nonMatchItems.emplace_back(itemBound);
|
||||
}
|
||||
}
|
||||
|
||||
outputs.edit0() = matchedItems;
|
||||
outputs.edit1() = nonMatchItems;
|
||||
}
|
||||
|
||||
void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) {
|
||||
|
|
|
@ -65,15 +65,15 @@ namespace render {
|
|||
// Filter the items belonging to the job's keep layer
|
||||
class FilterLayeredItems {
|
||||
public:
|
||||
using JobModel = Job::ModelIO<FilterLayeredItems, ItemBounds, ItemBounds>;
|
||||
using Outputs = render::VaryingSet2<ItemBounds, ItemBounds>;
|
||||
using JobModel = Job::ModelIO<FilterLayeredItems, ItemBounds, Outputs>;
|
||||
|
||||
FilterLayeredItems() {}
|
||||
FilterLayeredItems(int keepLayer) :
|
||||
_keepLayer(keepLayer) {}
|
||||
|
||||
int _keepLayer { 0 };
|
||||
int _keepLayer;
|
||||
|
||||
void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems);
|
||||
void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, Outputs& outputs);
|
||||
};
|
||||
|
||||
// SliceItems job config defining the slice range
|
||||
|
|
|
@ -29,6 +29,11 @@ const float Item::Status::Value::CYAN = 180.0f;
|
|||
const float Item::Status::Value::BLUE = 240.0f;
|
||||
const float Item::Status::Value::MAGENTA = 300.0f;
|
||||
|
||||
const int Item::LAYER_2D = 0;
|
||||
const int Item::LAYER_3D = 1;
|
||||
const int Item::LAYER_3D_FRONT = 2;
|
||||
const int Item::LAYER_3D_HUD = 3;
|
||||
|
||||
void Item::Status::Value::setScale(float scale) {
|
||||
_scale = (std::numeric_limits<unsigned short>::max() -1) * 0.5f * (1.0f + std::max(std::min(scale, 1.0f), 0.0f));
|
||||
}
|
||||
|
|
|
@ -356,9 +356,14 @@ public:
|
|||
// Get the bound of the item expressed in world space (or eye space depending on the key.isWorldSpace())
|
||||
const Bound getBound() const { return _payload->getBound(); }
|
||||
|
||||
// Get the layer where the item belongs. 0 by default meaning NOT LAYERED
|
||||
// Get the layer where the item belongs.
|
||||
int getLayer() const { return _payload->getLayer(); }
|
||||
|
||||
static const int LAYER_2D;
|
||||
static const int LAYER_3D;
|
||||
static const int LAYER_3D_FRONT;
|
||||
static const int LAYER_3D_HUD;
|
||||
|
||||
// Render call for the item
|
||||
void render(RenderArgs* args) const { _payload->render(args); }
|
||||
|
||||
|
|
|
@ -178,15 +178,26 @@ Column {
|
|||
onCheckedChanged: { mainViewTask.getConfig("DrawTransparentBounds")["enabled"] = checked }
|
||||
}
|
||||
CheckBox {
|
||||
text: "Overlay Opaques"
|
||||
checked: mainViewTask.getConfig("DrawOverlayOpaqueBounds")["enabled"]
|
||||
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayOpaqueBounds")["enabled"] = checked }
|
||||
text: "Opaques in Front"
|
||||
checked: mainViewTask.getConfig("DrawOverlayInFrontOpaqueBounds")["enabled"]
|
||||
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayInFrontOpaqueBounds")["enabled"] = checked }
|
||||
}
|
||||
CheckBox {
|
||||
text: "Overlay Transparents"
|
||||
checked: mainViewTask.getConfig("DrawOverlayTransparentBounds")["enabled"]
|
||||
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayTransparentBounds")["enabled"] = checked }
|
||||
text: "Transparents in Front"
|
||||
checked: mainViewTask.getConfig("DrawOverlayInFrontTransparentBounds")["enabled"]
|
||||
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayInFrontTransparentBounds")["enabled"] = checked }
|
||||
}
|
||||
CheckBox {
|
||||
text: "Opaques in HUD"
|
||||
checked: mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"]
|
||||
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"] = checked }
|
||||
}
|
||||
CheckBox {
|
||||
text: "Transparents in HUD"
|
||||
checked: mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"]
|
||||
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"] = checked }
|
||||
}
|
||||
|
||||
}
|
||||
Column {
|
||||
CheckBox {
|
||||
|
|
|
@ -436,7 +436,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.distanceRotating = false;
|
||||
|
||||
if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
this.updateLaserPointer(controllerData);
|
||||
this.prepareDistanceRotatingData(controllerData);
|
||||
return makeRunningValues(true, [], []);
|
||||
} else {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
glow: 1.0,
|
||||
lineWidth: 5,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawHUDLayer: true, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: true,
|
||||
parentID: AVATAR_SELF_ID
|
||||
};
|
||||
var halfEnd = {
|
||||
|
@ -40,7 +40,7 @@
|
|||
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawHUDLayer: true, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: true,
|
||||
visible: true
|
||||
};
|
||||
var fullPath = {
|
||||
|
@ -52,7 +52,7 @@
|
|||
glow: 1.0,
|
||||
lineWidth: 5,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawHUDLayer: true, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: true,
|
||||
parentID: AVATAR_SELF_ID
|
||||
};
|
||||
var fullEnd = {
|
||||
|
@ -61,7 +61,7 @@
|
|||
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
|
||||
alpha: 0.9,
|
||||
ignoreRayIntersection: true,
|
||||
drawHUDLayer: true, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: true,
|
||||
visible: true
|
||||
};
|
||||
var holdPath = {
|
||||
|
@ -73,7 +73,7 @@
|
|||
glow: 1.0,
|
||||
lineWidth: 5,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
drawHUDLayer: true, // Even when burried inside of something, show it.
|
||||
drawHUDLayer: true,
|
||||
parentID: AVATAR_SELF_ID
|
||||
};
|
||||
|
||||
|
|
|
@ -248,17 +248,20 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
}
|
||||
};
|
||||
|
||||
this.nearGrabWantsToRun = function(controllerData) {
|
||||
var moduleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay";
|
||||
var module = getEnabledModuleByName(moduleName);
|
||||
var ready = module ? module.isReady(controllerData) : makeRunningValues(false, [], []);
|
||||
return ready.active;
|
||||
this.otherModuleNeedsToRun = function(controllerData) {
|
||||
var grabOverlayModuleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay";
|
||||
var grabOverlayModule = getEnabledModuleByName(grabOverlayModuleName);
|
||||
var grabOverlayModuleReady = grabOverlayModule ? grabOverlayModule.isReady(controllerData) : makeRunningValues(false, [], []);
|
||||
var farGrabModuleName = this.hand === RIGHT_HAND ? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity";
|
||||
var farGrabModule = getEnabledModuleByName(farGrabModuleName);
|
||||
var farGrabModuleReady = farGrabModule ? farGrabModule.isReady(controllerData) : makeRunningValues(false, [], []);
|
||||
return grabOverlayModuleReady.active || farGrabModuleReady.active;
|
||||
};
|
||||
|
||||
this.processStylus = function(controllerData) {
|
||||
this.updateStylusTip();
|
||||
|
||||
if (!this.stylusTip.valid || this.overlayLaserActive(controllerData) || this.nearGrabWantsToRun(controllerData)) {
|
||||
if (!this.stylusTip.valid || this.overlayLaserActive(controllerData) || this.otherModuleNeedsToRun(controllerData)) {
|
||||
this.pointFinger(false);
|
||||
this.hideStylus();
|
||||
return false;
|
||||
|
|
|
@ -3877,7 +3877,6 @@ SelectionDisplay = (function() {
|
|||
if (controllerPose.valid && lastControllerPoses[hand].valid) {
|
||||
if (!Vec3.equal(controllerPose.position, lastControllerPoses[hand].position) ||
|
||||
!Vec3.equal(controllerPose.rotation, lastControllerPoses[hand].rotation)) {
|
||||
print("setting controller pose");
|
||||
that.mouseMoveEvent({});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -370,7 +370,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
return Math.min(Math.max(value, min), max);
|
||||
}
|
||||
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var recommendedRect = Controller.getRecommendedHUDRect();
|
||||
var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
that.windowDimensions = recommendedDimmensions; // Controller.getViewportDimensions();
|
||||
that.origin = { x: recommendedRect.x, y: recommendedRect.y };
|
||||
|
@ -378,7 +378,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
// For example, maybe we want "keep the same percentage to whatever two edges are closest to the edge of screen".
|
||||
// If we change that, the places to do so are onResizeViewport, save (maybe), and the initial move based on Settings, below.
|
||||
that.onResizeViewport = function (newSize) { // Can be overridden or extended by clients.
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var recommendedRect = Controller.getRecommendedHUDRect();
|
||||
var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
var originRelativeX = (that.x - that.origin.x - that.offset.x);
|
||||
var originRelativeY = (that.y - that.origin.y - that.offset.y);
|
||||
|
@ -396,7 +396,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
// code once the new toolbar position is well established with users.
|
||||
this.isNewPositionKey = optionalPersistenceKey + '.isNewPosition';
|
||||
this.save = function () {
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var recommendedRect = Controller.getRecommendedHUDRect();
|
||||
var screenSize = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
if (screenSize.x > 0 && screenSize.y > 0) {
|
||||
// Guard against invalid screen size that can occur at shut-down.
|
||||
|
@ -443,7 +443,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
that.move(that.dragOffsetX + event.x, that.dragOffsetY + event.y);
|
||||
};
|
||||
that.checkResize = function () { // Can be overriden or extended, but usually not. See onResizeViewport.
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var recommendedRect = Controller.getRecommendedHUDRect();
|
||||
var currentWindowSize = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
|
||||
if ((currentWindowSize.x !== that.windowDimensions.x) || (currentWindowSize.y !== that.windowDimensions.y)) {
|
||||
|
@ -471,7 +471,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
|
|||
var savedFraction = isNewPosition ? JSON.parse(Settings.getValue(this.fractionKey) || "0") : 0;
|
||||
Settings.setValue(this.isNewPositionKey, true);
|
||||
|
||||
var recommendedRect = Controller.getRecommendedOverlayRect();
|
||||
var recommendedRect = Controller.getRecommendedHUDRect();
|
||||
var screenSize = { x: recommendedRect.width, y: recommendedRect.height };
|
||||
if (savedFraction) {
|
||||
// If we have saved data, keep the toolbar at the same proportion of the screen width/height.
|
||||
|
|
|
@ -134,22 +134,12 @@
|
|||
tablet.pushOntoStack(MARKETPLACE_WALLET_QML_PATH);
|
||||
}
|
||||
|
||||
function setCertificateInfo(currentEntityWithContextOverlay, itemMarketplaceId) {
|
||||
function setCertificateInfo(currentEntityWithContextOverlay, itemCertificateId) {
|
||||
wireEventBridge(true);
|
||||
tablet.sendToQml({
|
||||
method: 'inspectionCertificate_setMarketplaceId',
|
||||
marketplaceId: itemMarketplaceId || Entities.getEntityProperties(currentEntityWithContextOverlay, ['marketplaceID']).marketplaceID
|
||||
method: 'inspectionCertificate_setCertificateId',
|
||||
certificateId: itemCertificateId || Entities.getEntityProperties(currentEntityWithContextOverlay, ['certificateID']).certificateID
|
||||
});
|
||||
// ZRF FIXME! Make a call to the endpoint to get item info instead of this silliness
|
||||
Script.setTimeout(function () {
|
||||
var randomNumber = Math.floor((Math.random() * 150) + 1);
|
||||
tablet.sendToQml({
|
||||
method: 'inspectionCertificate_setItemInfo',
|
||||
itemName: "The Greatest Item",
|
||||
itemOwner: "ABCDEFG1234567",
|
||||
itemEdition: (Math.floor(Math.random() * randomNumber) + " / " + randomNumber)
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function onUsernameChanged() {
|
||||
|
@ -358,13 +348,13 @@
|
|||
tablet.loadQMLSource("TabletAddressDialog.qml");
|
||||
break;
|
||||
case 'purchases_itemCertificateClicked':
|
||||
setCertificateInfo("", message.itemMarketplaceId);
|
||||
setCertificateInfo("", message.itemCertificateId);
|
||||
break;
|
||||
case 'inspectionCertificate_closeClicked':
|
||||
tablet.gotoHomeScreen();
|
||||
break;
|
||||
case 'inspectionCertificate_showInMarketplaceClicked':
|
||||
tablet.gotoWebScreen(MARKETPLACE_URL + '/items/' + message.itemId, MARKETPLACES_INJECT_SCRIPT_URL);
|
||||
tablet.gotoWebScreen(message.marketplaceUrl, MARKETPLACES_INJECT_SCRIPT_URL);
|
||||
break;
|
||||
case 'header_myItemsClicked':
|
||||
referrerURL = MARKETPLACE_URL_INITIAL;
|
||||
|
|
|
@ -576,6 +576,10 @@
|
|||
createNotification("Processing GIF snapshot...", NotificationType.SNAPSHOT);
|
||||
}
|
||||
|
||||
function processingGif() {
|
||||
createNotification("Your wallet isn't set up. Open the WALLET app.", NotificationType.WALLET);
|
||||
}
|
||||
|
||||
function connectionAdded(connectionName) {
|
||||
createNotification(connectionName, NotificationType.CONNECTION);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue