Merge branch 'master' of https://github.com/highfidelity/hifi into pop_dynamicTests

This commit is contained in:
Zach Fox 2017-10-11 11:07:32 -07:00
commit f037eab26c
67 changed files with 625 additions and 498 deletions

View file

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

View file

@ -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
//

View file

@ -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 {
""
}

View file

@ -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':

View file

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

View file

@ -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
}

View file

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

View file

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

View file

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

View file

@ -160,7 +160,7 @@ public:
QRect getRenderingGeometry() const;
glm::uvec2 getUiSize() const;
QRect getRecommendedOverlayRect() const;
QRect getRecommendedHUDRect() const;
QSize getDeviceSize() const;
bool hasFocus() const;

View file

@ -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");

View file

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

View file

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

View file

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

View file

@ -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

View file

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

View file

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

View file

@ -29,7 +29,7 @@ int DesktopScriptingInterface::getHeight() {
return size.height();
}
void DesktopScriptingInterface::setOverlayAlpha(float alpha) {
void DesktopScriptingInterface::setHUDAlpha(float alpha) {
qApp->getApplicationCompositor().setAlpha(alpha);
}

View file

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

View file

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

View file

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

View file

@ -263,7 +263,7 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() {
if (isTransparent()) {
builder.withTranslucent();
}
if (!getIsSolid() || shouldDrawHUDLayer()) {
if (!getIsSolid()) {
builder.withUnlit().withDepthBias();
}
return builder.build();

View file

@ -113,7 +113,7 @@ const render::ShapeKey Cube3DOverlay::getShapeKey() {
if (isTransparent()) {
builder.withTranslucent();
}
if (!getIsSolid() || shouldDrawHUDLayer()) {
if (!getIsSolid()) {
builder.withUnlit().withDepthBias();
}
return builder.build();

View file

@ -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()) {

View file

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

View file

@ -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

View file

@ -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) {

View file

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

View file

@ -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) {

View file

@ -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

View file

@ -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) {

View file

@ -55,7 +55,7 @@ const render::ShapeKey Shape3DOverlay::getShapeKey() {
if (isTransparent()) {
builder.withTranslucent();
}
if (!getIsSolid() || shouldDrawHUDLayer()) {
if (!getIsSolid()) {
builder.withUnlit().withDepthBias();
}
return builder.build();

View file

@ -60,7 +60,7 @@ const render::ShapeKey Sphere3DOverlay::getShapeKey() {
if (isTransparent()) {
builder.withTranslucent();
}
if (!getIsSolid() || shouldDrawHUDLayer()) {
if (!getIsSolid()) {
builder.withUnlit().withDepthBias();
}
return builder.build();

View file

@ -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;

View file

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

View file

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

View file

@ -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() {

View file

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

View file

@ -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`

View file

@ -92,7 +92,7 @@ public:
void captureNamedDrawCallInfo(std::string name);
Batch();
explicit Batch(const Batch& batch);
Batch(const Batch& batch);
~Batch();
void clear();

View file

@ -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;

View file

@ -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;

View file

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

View file

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

View file

@ -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;

View file

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

View file

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

View file

@ -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 {

View file

@ -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) {

View file

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

View file

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

View file

@ -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>;

View 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;
}

View 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)$>
}

View file

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

View file

@ -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) {

View file

@ -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

View file

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

View file

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

View file

@ -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 {

View file

@ -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 {

View file

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

View file

@ -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;

View file

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

View file

@ -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.

View file

@ -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;

View file

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