mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 02:53:10 +02:00
Merge branch 'master' into bug-fix/entity-mat-avatar-dual-quaternions
This commit is contained in:
commit
f5fcaae283
93 changed files with 1367 additions and 703 deletions
|
@ -9,6 +9,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "AudioMixer.h"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <QtCore/QJsonArray>
|
#include <QtCore/QJsonArray>
|
||||||
|
@ -36,8 +38,6 @@
|
||||||
#include "AvatarAudioStream.h"
|
#include "AvatarAudioStream.h"
|
||||||
#include "InjectedAudioStream.h"
|
#include "InjectedAudioStream.h"
|
||||||
|
|
||||||
#include "AudioMixer.h"
|
|
||||||
|
|
||||||
static const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance)
|
static const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.5f; // attenuation = -6dB * log2(distance)
|
||||||
static const int DISABLE_STATIC_JITTER_FRAMES = -1;
|
static const int DISABLE_STATIC_JITTER_FRAMES = -1;
|
||||||
static const float DEFAULT_NOISE_MUTING_THRESHOLD = 1.0f;
|
static const float DEFAULT_NOISE_MUTING_THRESHOLD = 1.0f;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include <ThreadedAssignment.h>
|
#include <ThreadedAssignment.h>
|
||||||
#include <UUIDHasher.h>
|
#include <UUIDHasher.h>
|
||||||
|
|
||||||
|
#include <plugins/Forward.h>
|
||||||
|
|
||||||
#include "AudioMixerStats.h"
|
#include "AudioMixerStats.h"
|
||||||
#include "AudioMixerSlavePool.h"
|
#include "AudioMixerSlavePool.h"
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "AudioMixerClientData.h"
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
@ -22,8 +24,6 @@
|
||||||
#include "AudioLogging.h"
|
#include "AudioLogging.h"
|
||||||
#include "AudioHelpers.h"
|
#include "AudioHelpers.h"
|
||||||
#include "AudioMixer.h"
|
#include "AudioMixer.h"
|
||||||
#include "AudioMixerClientData.h"
|
|
||||||
|
|
||||||
|
|
||||||
AudioMixerClientData::AudioMixerClientData(const QUuid& nodeID) :
|
AudioMixerClientData::AudioMixerClientData(const QUuid& nodeID) :
|
||||||
NodeData(nodeID),
|
NodeData(nodeID),
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <AudioLimiter.h>
|
#include <AudioLimiter.h>
|
||||||
#include <UUIDHasher.h>
|
#include <UUIDHasher.h>
|
||||||
|
|
||||||
|
#include <plugins/Forward.h>
|
||||||
#include <plugins/CodecPlugin.h>
|
#include <plugins/CodecPlugin.h>
|
||||||
|
|
||||||
#include "PositionalAudioStream.h"
|
#include "PositionalAudioStream.h"
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "AudioMixerSlave.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
@ -34,8 +36,6 @@
|
||||||
#include "InjectedAudioStream.h"
|
#include "InjectedAudioStream.h"
|
||||||
#include "AudioHelpers.h"
|
#include "AudioHelpers.h"
|
||||||
|
|
||||||
#include "AudioMixerSlave.h"
|
|
||||||
|
|
||||||
using AudioStreamMap = AudioMixerClientData::AudioStreamMap;
|
using AudioStreamMap = AudioMixerClientData::AudioStreamMap;
|
||||||
|
|
||||||
// packet helpers
|
// packet helpers
|
||||||
|
|
Binary file not shown.
|
@ -14,8 +14,8 @@ import "../styles-uit"
|
||||||
Item {
|
Item {
|
||||||
property int colorScheme: 0;
|
property int colorScheme: 0;
|
||||||
|
|
||||||
readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray ];
|
readonly property var topColor: [ hifi.colors.baseGrayShadow, hifi.colors.faintGray, "#89858C" ];
|
||||||
readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray ];
|
readonly property var bottomColor: [ hifi.colors.baseGrayHighlight, hifi.colors.faintGray, "#89858C" ];
|
||||||
|
|
||||||
// Size
|
// Size
|
||||||
height: colorScheme === 0 ? 2 : 1;
|
height: colorScheme === 0 ? 2 : 1;
|
||||||
|
|
|
@ -22,6 +22,10 @@ TableView {
|
||||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||||
property bool expandSelectedRow: false
|
property bool expandSelectedRow: false
|
||||||
property bool centerHeaderText: false
|
property bool centerHeaderText: false
|
||||||
|
readonly property real headerSpacing: 3 //spacing between sort indicator and table header title
|
||||||
|
property var titlePaintedPos: [] // storing extra data position behind painted
|
||||||
|
// title text and sort indicatorin table's header
|
||||||
|
signal titlePaintedPosSignal(int column) //signal that extradata position gets changed
|
||||||
|
|
||||||
model: ListModel { }
|
model: ListModel { }
|
||||||
|
|
||||||
|
@ -69,36 +73,39 @@ TableView {
|
||||||
height: hifi.dimensions.tableHeaderHeight
|
height: hifi.dimensions.tableHeaderHeight
|
||||||
color: isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
|
color: isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
|
||||||
|
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: titleText
|
id: titleText
|
||||||
|
x: centerHeaderText ? (parent.width - paintedWidth -
|
||||||
|
((sortIndicatorVisible &&
|
||||||
|
sortIndicatorColumn === styleData.column) ?
|
||||||
|
(titleSort.paintedWidth / 5 + tableView.headerSpacing) : 0)) / 2 :
|
||||||
|
hifi.dimensions.tablePadding
|
||||||
text: styleData.value
|
text: styleData.value
|
||||||
size: hifi.fontSizes.tableHeading
|
size: hifi.fontSizes.tableHeading
|
||||||
font.capitalization: Font.AllUppercase
|
font.capitalization: Font.AllUppercase
|
||||||
color: hifi.colors.baseGrayHighlight
|
color: hifi.colors.baseGrayHighlight
|
||||||
horizontalAlignment: (centerHeaderText ? Text.AlignHCenter : Text.AlignLeft)
|
horizontalAlignment: (centerHeaderText ? Text.AlignHCenter : Text.AlignLeft)
|
||||||
anchors {
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
left: parent.left
|
|
||||||
leftMargin: hifi.dimensions.tablePadding
|
|
||||||
right: parent.right
|
|
||||||
rightMargin: hifi.dimensions.tablePadding
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//actual image of sort indicator in glyph font only 20% of real font size
|
||||||
|
//i.e. if the charachter size set to 60 pixels, actual image is 12 pixels
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
id: titleSort
|
id: titleSort
|
||||||
text: sortIndicatorOrder == Qt.AscendingOrder ? hifi.glyphs.caratUp : hifi.glyphs.caratDn
|
text: sortIndicatorOrder == Qt.AscendingOrder ? hifi.glyphs.caratUp : hifi.glyphs.caratDn
|
||||||
color: hifi.colors.darkGray
|
color: hifi.colors.darkGray
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
size: hifi.fontSizes.tableHeadingIcon
|
size: hifi.fontSizes.tableHeadingIcon
|
||||||
anchors {
|
anchors.verticalCenter: titleText.verticalCenter
|
||||||
left: titleText.right
|
anchors.left: titleText.right
|
||||||
leftMargin: -hifi.fontSizes.tableHeadingIcon / 3 - (centerHeaderText ? 15 : 10)
|
anchors.leftMargin: -(hifi.fontSizes.tableHeadingIcon / 2.5) + tableView.headerSpacing
|
||||||
right: parent.right
|
|
||||||
rightMargin: hifi.dimensions.tablePadding
|
|
||||||
verticalCenter: titleText.verticalCenter
|
|
||||||
}
|
|
||||||
visible: sortIndicatorVisible && sortIndicatorColumn === styleData.column
|
visible: sortIndicatorVisible && sortIndicatorColumn === styleData.column
|
||||||
|
onXChanged: {
|
||||||
|
titlePaintedPos[styleData.column] = titleText.x + titleText.paintedWidth +
|
||||||
|
paintedWidth / 5 + tableView.headerSpacing*2
|
||||||
|
titlePaintedPosSignal(styleData.column)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -152,7 +159,7 @@ TableView {
|
||||||
color: styleData.selected
|
color: styleData.selected
|
||||||
? hifi.colors.primaryHighlight
|
? hifi.colors.primaryHighlight
|
||||||
: tableView.isLightColorScheme
|
: tableView.isLightColorScheme
|
||||||
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
|
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
|
||||||
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
|
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,10 @@ TextField {
|
||||||
|
|
||||||
placeholderText: textField.placeholderText
|
placeholderText: textField.placeholderText
|
||||||
|
|
||||||
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
FontLoader { id: firaSansRegular; source: "../../fonts/FiraSans-Regular.ttf"; }
|
||||||
FontLoader { id: hifiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; }
|
FontLoader { id: hifiGlyphs; source: "../../fonts/hifi-glyphs.ttf"; }
|
||||||
font.family: firaSansSemiBold.name
|
font.family: firaSansRegular.name
|
||||||
font.pixelSize: hifi.fontSizes.textFieldInput
|
font.pixelSize: hifi.fontSizes.textFieldInput
|
||||||
font.italic: textField.text == ""
|
|
||||||
height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered.
|
height: implicitHeight + 3 // Make surrounding box higher so that highlight is vertically centered.
|
||||||
property alias textFieldLabel: textFieldLabel
|
property alias textFieldLabel: textFieldLabel
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ Rectangle {
|
||||||
property int myCardWidth: width - upperRightInfoContainer.width;
|
property int myCardWidth: width - upperRightInfoContainer.width;
|
||||||
property int myCardHeight: 100;
|
property int myCardHeight: 100;
|
||||||
property int rowHeight: 60;
|
property int rowHeight: 60;
|
||||||
property int actionButtonWidth: 55;
|
property int actionButtonWidth: 65;
|
||||||
property int locationColumnWidth: 170;
|
property int locationColumnWidth: 170;
|
||||||
property int nearbyNameCardWidth: nearbyTable.width - (iAmAdmin ? (actionButtonWidth * 4) : (actionButtonWidth * 2)) - 4 - hifi.dimensions.scrollbarBackgroundWidth;
|
property int nearbyNameCardWidth: nearbyTable.width - (iAmAdmin ? (actionButtonWidth * 4) : (actionButtonWidth * 2)) - 4 - hifi.dimensions.scrollbarBackgroundWidth;
|
||||||
property int connectionsNameCardWidth: connectionsTable.width - locationColumnWidth - actionButtonWidth - 4 - hifi.dimensions.scrollbarBackgroundWidth;
|
property int connectionsNameCardWidth: connectionsTable.width - locationColumnWidth - actionButtonWidth - 4 - hifi.dimensions.scrollbarBackgroundWidth;
|
||||||
|
@ -415,6 +415,7 @@ Rectangle {
|
||||||
movable: false;
|
movable: false;
|
||||||
resizable: false;
|
resizable: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TableViewColumn {
|
TableViewColumn {
|
||||||
role: "ignore";
|
role: "ignore";
|
||||||
title: "IGNORE";
|
title: "IGNORE";
|
||||||
|
@ -599,13 +600,23 @@ Rectangle {
|
||||||
}
|
}
|
||||||
// This Rectangle refers to the [?] popup button next to "NAMES"
|
// This Rectangle refers to the [?] popup button next to "NAMES"
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
id: questionRect
|
||||||
color: hifi.colors.tableBackgroundLight;
|
color: hifi.colors.tableBackgroundLight;
|
||||||
width: 20;
|
width: 20;
|
||||||
height: hifi.dimensions.tableHeaderHeight - 2;
|
height: hifi.dimensions.tableHeaderHeight - 2;
|
||||||
anchors.left: nearbyTable.left;
|
anchors.left: nearbyTable.left;
|
||||||
anchors.top: nearbyTable.top;
|
anchors.top: nearbyTable.top;
|
||||||
anchors.topMargin: 1;
|
anchors.topMargin: 1;
|
||||||
anchors.leftMargin: actionButtonWidth + nearbyNameCardWidth/2 + displayNameHeaderMetrics.width/2 + 6;
|
|
||||||
|
Connections {
|
||||||
|
target: nearbyTable
|
||||||
|
onTitlePaintedPosSignal: {
|
||||||
|
if (column === 1) { // name column
|
||||||
|
questionRect.anchors.leftMargin = actionButtonWidth + nearbyTable.titlePaintedPos[column]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: helpText;
|
id: helpText;
|
||||||
text: "[?]";
|
text: "[?]";
|
||||||
|
|
|
@ -28,7 +28,7 @@ Rectangle {
|
||||||
id: root;
|
id: root;
|
||||||
objectName: "checkout"
|
objectName: "checkout"
|
||||||
property string activeView: "initialize";
|
property string activeView: "initialize";
|
||||||
property bool purchasesReceived: false;
|
property bool ownershipStatusReceived: false;
|
||||||
property bool balanceReceived: false;
|
property bool balanceReceived: false;
|
||||||
property string itemName;
|
property string itemName;
|
||||||
property string itemId;
|
property string itemId;
|
||||||
|
@ -37,12 +37,18 @@ Rectangle {
|
||||||
property double balanceAfterPurchase;
|
property double balanceAfterPurchase;
|
||||||
property bool alreadyOwned: false;
|
property bool alreadyOwned: false;
|
||||||
property int itemPrice: -1;
|
property int itemPrice: -1;
|
||||||
property bool itemIsJson: true;
|
property bool isCertified;
|
||||||
|
property string itemType;
|
||||||
|
property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"];
|
||||||
|
property var itemTypesText: ["entity", "wearable", "content set", "app", "avatar"];
|
||||||
|
property var buttonTextNormal: ["REZ", "WEAR", "REPLACE CONTENT SET", "INSTALL", "WEAR"];
|
||||||
|
property var buttonTextClicked: ["REZZED!", "WORN!", "CONTENT SET REPLACED!", "INSTALLED!", "AVATAR CHANGED!"]
|
||||||
|
property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar];
|
||||||
property bool shouldBuyWithControlledFailure: false;
|
property bool shouldBuyWithControlledFailure: false;
|
||||||
property bool debugCheckoutSuccess: false;
|
property bool debugCheckoutSuccess: false;
|
||||||
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
||||||
property bool isWearable;
|
|
||||||
property string referrer;
|
property string referrer;
|
||||||
|
property bool isInstalled;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
Connections {
|
Connections {
|
||||||
|
@ -85,7 +91,9 @@ Rectangle {
|
||||||
UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message);
|
UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message);
|
||||||
} else {
|
} else {
|
||||||
root.itemHref = result.data.download_url;
|
root.itemHref = result.data.download_url;
|
||||||
root.isWearable = result.data.categories.indexOf("Wearables") > -1;
|
if (result.data.categories.indexOf("Wearables") > -1) {
|
||||||
|
root.itemType = "wearable";
|
||||||
|
}
|
||||||
root.activeView = "checkoutSuccess";
|
root.activeView = "checkoutSuccess";
|
||||||
UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned);
|
UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned);
|
||||||
}
|
}
|
||||||
|
@ -97,32 +105,60 @@ Rectangle {
|
||||||
} else {
|
} else {
|
||||||
root.balanceReceived = true;
|
root.balanceReceived = true;
|
||||||
root.balanceAfterPurchase = result.data.balance - root.itemPrice;
|
root.balanceAfterPurchase = result.data.balance - root.itemPrice;
|
||||||
root.setBuyText();
|
root.refreshBuyUI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onInventoryResult: {
|
onAlreadyOwnedResult: {
|
||||||
if (result.status !== 'success') {
|
if (result.status !== 'success') {
|
||||||
console.log("Failed to get purchases", result.data.message);
|
console.log("Failed to get Already Owned status", result.data.message);
|
||||||
} else {
|
} else {
|
||||||
root.purchasesReceived = true;
|
root.ownershipStatusReceived = true;
|
||||||
if (purchasesContains(result.data.assets, itemId)) {
|
if (result.data.marketplace_item_id === root.itemId) {
|
||||||
root.alreadyOwned = true;
|
root.alreadyOwned = result.data.already_owned;
|
||||||
} else {
|
} else {
|
||||||
|
console.log("WARNING - Received 'Already Owned' status about different Marketplace ID!");
|
||||||
root.alreadyOwned = false;
|
root.alreadyOwned = false;
|
||||||
}
|
}
|
||||||
root.setBuyText();
|
root.refreshBuyUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onAppInstalled: {
|
||||||
|
if (appHref === root.itemHref) {
|
||||||
|
root.isInstalled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemIdChanged: {
|
onItemIdChanged: {
|
||||||
Commerce.inventory();
|
root.ownershipStatusReceived = false;
|
||||||
|
Commerce.alreadyOwned(root.itemId);
|
||||||
itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
|
itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemHrefChanged: {
|
onItemHrefChanged: {
|
||||||
itemIsJson = root.itemHref.endsWith('.json');
|
if (root.itemHref.indexOf(".fst") > -1) {
|
||||||
|
root.itemType = "avatar";
|
||||||
|
} else if (root.itemHref.indexOf('.json.gz') > -1) {
|
||||||
|
root.itemType = "contentSet";
|
||||||
|
} else if (root.itemHref.indexOf('.app.json') > -1) {
|
||||||
|
root.itemType = "app";
|
||||||
|
} else if (root.itemHref.indexOf('.json') > -1) {
|
||||||
|
root.itemType = "entity"; // "wearable" type handled later
|
||||||
|
} else {
|
||||||
|
console.log("WARNING - Item type is UNKNOWN!");
|
||||||
|
root.itemType = "entity";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onItemTypeChanged: {
|
||||||
|
if (root.itemType === "entity" || root.itemType === "wearable" ||
|
||||||
|
root.itemType === "contentSet" || root.itemType === "avatar" || root.itemType === "app") {
|
||||||
|
root.isCertified = true;
|
||||||
|
} else {
|
||||||
|
root.isCertified = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemPriceChanged: {
|
onItemPriceChanged: {
|
||||||
|
@ -203,7 +239,7 @@ Rectangle {
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
purchasesReceived = false;
|
ownershipStatusReceived = false;
|
||||||
balanceReceived = false;
|
balanceReceived = false;
|
||||||
Commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
|
@ -278,6 +314,32 @@ Rectangle {
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: loading;
|
||||||
|
z: 997;
|
||||||
|
visible: !root.ownershipStatusReceived || !root.balanceReceived;
|
||||||
|
anchors.fill: parent;
|
||||||
|
color: hifi.colors.white;
|
||||||
|
|
||||||
|
// This object is always used in a popup.
|
||||||
|
// This MouseArea is used to prevent a user from being
|
||||||
|
// able to click on a button/mouseArea underneath the popup/section.
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent;
|
||||||
|
hoverEnabled: true;
|
||||||
|
propagateComposedEvents: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedImage {
|
||||||
|
id: loadingImage;
|
||||||
|
source: "../common/images/loader-blue.gif"
|
||||||
|
width: 74;
|
||||||
|
height: width;
|
||||||
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: confirmPurchaseText;
|
id: confirmPurchaseText;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
|
@ -286,8 +348,8 @@ Rectangle {
|
||||||
anchors.leftMargin: 16;
|
anchors.leftMargin: 16;
|
||||||
width: paintedWidth;
|
width: paintedWidth;
|
||||||
height: paintedHeight;
|
height: paintedHeight;
|
||||||
text: "Confirm Purchase:";
|
text: "Review Purchase:";
|
||||||
color: hifi.colors.baseGray;
|
color: hifi.colors.black;
|
||||||
size: 28;
|
size: 28;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +462,7 @@ Rectangle {
|
||||||
width: root.width;
|
width: root.width;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: separator2.bottom;
|
anchors.top: separator2.bottom;
|
||||||
anchors.topMargin: 16;
|
anchors.topMargin: 0;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 16;
|
anchors.leftMargin: 16;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
@ -411,8 +473,8 @@ Rectangle {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: buyTextContainer;
|
id: buyTextContainer;
|
||||||
visible: buyText.text !== "";
|
visible: buyText.text !== "";
|
||||||
anchors.top: cancelPurchaseButton.bottom;
|
anchors.top: parent.top;
|
||||||
anchors.topMargin: 16;
|
anchors.topMargin: 10;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
height: buyText.height + 30;
|
height: buyText.height + 30;
|
||||||
|
@ -454,32 +516,63 @@ Rectangle {
|
||||||
// Alignment
|
// Alignment
|
||||||
horizontalAlignment: Text.AlignLeft;
|
horizontalAlignment: Text.AlignLeft;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onLinkActivated: {
|
// "View in My Purchases" button
|
||||||
sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName});
|
HifiControlsUit.Button {
|
||||||
}
|
id: viewInMyPurchasesButton;
|
||||||
|
visible: false;
|
||||||
|
color: hifi.buttons.blue;
|
||||||
|
colorScheme: hifi.colorSchemes.light;
|
||||||
|
anchors.top: buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top;
|
||||||
|
anchors.topMargin: 10;
|
||||||
|
height: 50;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
text: "VIEW THIS ITEM IN MY PURCHASES";
|
||||||
|
onClicked: {
|
||||||
|
sendToScript({method: 'checkout_goToPurchases', filterText: root.itemName});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Buy" button
|
// "Buy" button
|
||||||
HifiControlsUit.Button {
|
HifiControlsUit.Button {
|
||||||
id: buyButton;
|
id: buyButton;
|
||||||
enabled: (root.balanceAfterPurchase >= 0 && purchasesReceived && balanceReceived) || !itemIsJson;
|
visible: !((root.itemType === "avatar" || root.itemType === "app") && viewInMyPurchasesButton.visible)
|
||||||
color: hifi.buttons.blue;
|
enabled: (root.balanceAfterPurchase >= 0 && ownershipStatusReceived && balanceReceived) || (!root.isCertified);
|
||||||
|
color: viewInMyPurchasesButton.visible ? hifi.buttons.white : hifi.buttons.blue;
|
||||||
colorScheme: hifi.colorSchemes.light;
|
colorScheme: hifi.colorSchemes.light;
|
||||||
anchors.top: checkoutActionButtonsContainer.top;
|
anchors.top: viewInMyPurchasesButton.visible ? viewInMyPurchasesButton.bottom :
|
||||||
anchors.topMargin: 16;
|
(buyTextContainer.visible ? buyTextContainer.bottom : checkoutActionButtonsContainer.top);
|
||||||
height: 40;
|
anchors.topMargin: 10;
|
||||||
|
height: 50;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
text: (itemIsJson ? ((purchasesReceived && balanceReceived) ? "Confirm Purchase" : "--") : "Get Item");
|
text: ((root.isCertified) ? ((ownershipStatusReceived && balanceReceived) ?
|
||||||
|
(viewInMyPurchasesButton.visible ? "Buy It Again" : "Confirm Purchase") : "--") : "Get Item");
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (itemIsJson) {
|
if (root.isCertified) {
|
||||||
buyButton.enabled = false;
|
|
||||||
if (!root.shouldBuyWithControlledFailure) {
|
if (!root.shouldBuyWithControlledFailure) {
|
||||||
Commerce.buy(itemId, itemPrice);
|
if (root.itemType === "contentSet" && !Entities.canReplaceContent()) {
|
||||||
|
lightboxPopup.titleText = "Purchase Content Set";
|
||||||
|
lightboxPopup.bodyText = "You will not be able to replace this domain's content with <b>" + root.itemName +
|
||||||
|
" </b>until the server owner gives you 'Replace Content' permissions.<br><br>Are you sure you want to purchase this content set?";
|
||||||
|
lightboxPopup.button1text = "CANCEL";
|
||||||
|
lightboxPopup.button1method = "root.visible = false;"
|
||||||
|
lightboxPopup.button2text = "CONFIRM";
|
||||||
|
lightboxPopup.button2method = "Commerce.buy('" + root.itemId + "', " + root.itemPrice + ");" +
|
||||||
|
"root.visible = false; buyButton.enabled = false; loading.visible = true;";
|
||||||
|
lightboxPopup.visible = true;
|
||||||
|
} else {
|
||||||
|
buyButton.enabled = false;
|
||||||
|
loading.visible = true;
|
||||||
|
Commerce.buy(root.itemId, root.itemPrice);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Commerce.buy(itemId, itemPrice, true);
|
buyButton.enabled = false;
|
||||||
|
loading.visible = true;
|
||||||
|
Commerce.buy(root.itemId, root.itemPrice, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (urlHandler.canHandleUrl(itemHref)) {
|
if (urlHandler.canHandleUrl(itemHref)) {
|
||||||
|
@ -494,9 +587,9 @@ Rectangle {
|
||||||
id: cancelPurchaseButton;
|
id: cancelPurchaseButton;
|
||||||
color: hifi.buttons.noneBorderlessGray;
|
color: hifi.buttons.noneBorderlessGray;
|
||||||
colorScheme: hifi.colorSchemes.light;
|
colorScheme: hifi.colorSchemes.light;
|
||||||
anchors.top: buyButton.bottom;
|
anchors.top: buyButton.visible ? buyButton.bottom : viewInMyPurchasesButton.bottom;
|
||||||
anchors.topMargin: 16;
|
anchors.topMargin: 10;
|
||||||
height: 40;
|
height: 50;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
text: "Cancel"
|
text: "Cancel"
|
||||||
|
@ -522,31 +615,32 @@ Rectangle {
|
||||||
anchors.top: titleBarContainer.bottom;
|
anchors.top: titleBarContainer.bottom;
|
||||||
anchors.bottom: root.bottom;
|
anchors.bottom: root.bottom;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 16;
|
anchors.leftMargin: 20;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 16;
|
anchors.rightMargin: 20;
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: completeText;
|
id: completeText;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
anchors.topMargin: 30;
|
anchors.topMargin: 18;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
width: paintedWidth;
|
width: paintedWidth;
|
||||||
height: paintedHeight;
|
height: paintedHeight;
|
||||||
text: "Thank you for your order!";
|
text: "Thank you for your order!";
|
||||||
color: hifi.colors.baseGray;
|
color: hifi.colors.baseGray;
|
||||||
size: 28;
|
size: 36;
|
||||||
}
|
}
|
||||||
|
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: completeText2;
|
id: completeText2;
|
||||||
text: "The item " + '<font color="' + hifi.colors.blueAccent + '"><a href="#">' + root.itemName + '</a></font>' +
|
text: "The " + (root.itemTypesText)[itemTypesArray.indexOf(root.itemType)] +
|
||||||
" has been added to your Purchases and a receipt will appear in your Wallet's transaction history.";
|
' <font color="' + hifi.colors.blueAccent + '"><a href="#">' + root.itemName + '</a></font>' +
|
||||||
|
" has been added to your Purchases and a receipt will appear in your Wallet's transaction history.";
|
||||||
// Text size
|
// Text size
|
||||||
size: 20;
|
size: 18;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: completeText.bottom;
|
anchors.top: completeText.bottom;
|
||||||
anchors.topMargin: 10;
|
anchors.topMargin: 15;
|
||||||
height: paintedHeight;
|
height: paintedHeight;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
@ -576,7 +670,7 @@ Rectangle {
|
||||||
|
|
||||||
RalewayBold {
|
RalewayBold {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
text: "REZZED";
|
text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)];
|
||||||
size: 18;
|
size: 18;
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
@ -592,26 +686,58 @@ Rectangle {
|
||||||
// "Rez" button
|
// "Rez" button
|
||||||
HifiControlsUit.Button {
|
HifiControlsUit.Button {
|
||||||
id: rezNowButton;
|
id: rezNowButton;
|
||||||
enabled: root.canRezCertifiedItems || root.isWearable;
|
enabled: (root.itemType === "entity" && root.canRezCertifiedItems) ||
|
||||||
buttonGlyph: hifi.glyphs.lightning;
|
(root.itemType === "contentSet" && Entities.canReplaceContent()) ||
|
||||||
|
root.itemType === "wearable" || root.itemType === "avatar" || root.itemType === "app";
|
||||||
|
buttonGlyph: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)];
|
||||||
color: hifi.buttons.red;
|
color: hifi.buttons.red;
|
||||||
colorScheme: hifi.colorSchemes.light;
|
colorScheme: hifi.colorSchemes.light;
|
||||||
anchors.top: completeText2.bottom;
|
anchors.top: completeText2.bottom;
|
||||||
anchors.topMargin: 30;
|
anchors.topMargin: 27;
|
||||||
height: 50;
|
height: 50;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
text: root.isWearable ? "Wear It" : "Rez It"
|
text: root.itemType === "app" && root.isInstalled ? "OPEN APP" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)];
|
||||||
onClicked: {
|
onClicked: {
|
||||||
sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable});
|
if (root.itemType === "contentSet") {
|
||||||
rezzedNotifContainer.visible = true;
|
lightboxPopup.titleText = "Replace Content";
|
||||||
rezzedNotifContainerTimer.start();
|
lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " +
|
||||||
UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.isWearable ? "rez" : "wear");
|
"If you want to save the state of the content in this domain, create a backup before proceeding.<br><br>" +
|
||||||
|
"For more information about backing up and restoring content, " +
|
||||||
|
"<a href='https://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content'>" +
|
||||||
|
"click here to open info on your desktop browser.";
|
||||||
|
lightboxPopup.button1text = "CANCEL";
|
||||||
|
lightboxPopup.button1method = "root.visible = false;"
|
||||||
|
lightboxPopup.button2text = "CONFIRM";
|
||||||
|
lightboxPopup.button2method = "Commerce.replaceContentSet('" + root.itemHref + "');" +
|
||||||
|
"root.visible = false;rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start();" +
|
||||||
|
"UserActivityLogger.commerceEntityRezzed('" + root.itemId + "', 'checkout', '" + root.itemType + "');";
|
||||||
|
lightboxPopup.visible = true;
|
||||||
|
} else if (root.itemType === "avatar") {
|
||||||
|
lightboxPopup.titleText = "Change Avatar";
|
||||||
|
lightboxPopup.bodyText = "This will change your current avatar to " + root.itemName + " while retaining your wearables.";
|
||||||
|
lightboxPopup.button1text = "CANCEL";
|
||||||
|
lightboxPopup.button1method = "root.visible = false;"
|
||||||
|
lightboxPopup.button2text = "CONFIRM";
|
||||||
|
lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + root.itemHref + "'); root.visible = false;";
|
||||||
|
lightboxPopup.visible = true;
|
||||||
|
} else if (root.itemType === "app") {
|
||||||
|
if (root.isInstalled) {
|
||||||
|
Commerce.openApp(root.itemHref);
|
||||||
|
} else {
|
||||||
|
Commerce.installApp(root.itemHref);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, itemType: root.itemType});
|
||||||
|
rezzedNotifContainer.visible = true;
|
||||||
|
rezzedNotifContainerTimer.start();
|
||||||
|
UserActivityLogger.commerceEntityRezzed(root.itemId, "checkout", root.itemType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: noPermissionText;
|
id: noPermissionText;
|
||||||
visible: !root.canRezCertifiedItems && !root.isWearable;
|
visible: !root.canRezCertifiedItems && root.itemType === "entity";
|
||||||
text: '<font color="' + hifi.colors.redAccent + '"><a href="#">You do not have Certified Rez permissions in this domain.</a></font>'
|
text: '<font color="' + hifi.colors.redAccent + '"><a href="#">You do not have Certified Rez permissions in this domain.</a></font>'
|
||||||
// Text size
|
// Text size
|
||||||
size: 16;
|
size: 16;
|
||||||
|
@ -640,7 +766,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: explainRezText;
|
id: explainRezText;
|
||||||
visible: !root.isWearable;
|
visible: root.itemType === "entity";
|
||||||
text: '<font color="' + hifi.colors.redAccent + '"><a href="#">What does "Rez" mean?</a></font>'
|
text: '<font color="' + hifi.colors.redAccent + '"><a href="#">What does "Rez" mean?</a></font>'
|
||||||
// Text size
|
// Text size
|
||||||
size: 16;
|
size: 16;
|
||||||
|
@ -663,9 +789,9 @@ Rectangle {
|
||||||
|
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: myPurchasesLink;
|
id: myPurchasesLink;
|
||||||
text: '<font color="' + hifi.colors.blueAccent + '"><a href="#">View this item in My Purchases</a></font>';
|
text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View this item in My Purchases</a></font>';
|
||||||
// Text size
|
// Text size
|
||||||
size: 20;
|
size: 18;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom);
|
anchors.top: explainRezText.visible ? explainRezText.bottom : (noPermissionText.visible ? noPermissionText.bottom : rezNowButton.bottom);
|
||||||
anchors.topMargin: 40;
|
anchors.topMargin: 40;
|
||||||
|
@ -685,12 +811,12 @@ Rectangle {
|
||||||
|
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: walletLink;
|
id: walletLink;
|
||||||
text: '<font color="' + hifi.colors.blueAccent + '"><a href="#">View receipt in Wallet</a></font>';
|
text: '<font color="' + hifi.colors.primaryHighlight + '"><a href="#">View receipt in Wallet</a></font>';
|
||||||
// Text size
|
// Text size
|
||||||
size: 20;
|
size: 18;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: myPurchasesLink.bottom;
|
anchors.top: myPurchasesLink.bottom;
|
||||||
anchors.topMargin: 20;
|
anchors.topMargin: 16;
|
||||||
height: paintedHeight;
|
height: paintedHeight;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
@ -708,12 +834,12 @@ Rectangle {
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: pendingText;
|
id: pendingText;
|
||||||
text: 'Your item is marked "pending" while your purchase is being confirmed. ' +
|
text: 'Your item is marked "pending" while your purchase is being confirmed. ' +
|
||||||
'<font color="' + hifi.colors.blueAccent + '"><a href="#">Learn More</a></font>';
|
'<b><font color="' + hifi.colors.primaryHighlight + '"><a href="#">Learn More</a></font></b>';
|
||||||
// Text size
|
// Text size
|
||||||
size: 20;
|
size: 18;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: walletLink.bottom;
|
anchors.top: walletLink.bottom;
|
||||||
anchors.topMargin: 60;
|
anchors.topMargin: 32;
|
||||||
height: paintedHeight;
|
height: paintedHeight;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
@ -739,11 +865,10 @@ Rectangle {
|
||||||
color: hifi.buttons.noneBorderlessGray;
|
color: hifi.buttons.noneBorderlessGray;
|
||||||
colorScheme: hifi.colorSchemes.light;
|
colorScheme: hifi.colorSchemes.light;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
anchors.bottomMargin: 20;
|
anchors.bottomMargin: 54;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 14;
|
width: 193;
|
||||||
width: parent.width/2 - anchors.rightMargin;
|
height: 44;
|
||||||
height: 60;
|
|
||||||
text: "Continue Shopping";
|
text: "Continue Shopping";
|
||||||
onClicked: {
|
onClicked: {
|
||||||
sendToScript({method: 'checkout_continueShopping', itemId: itemId});
|
sendToScript({method: 'checkout_continueShopping', itemId: itemId});
|
||||||
|
@ -851,7 +976,7 @@ Rectangle {
|
||||||
buyButton.color = hifi.buttons.red;
|
buyButton.color = hifi.buttons.red;
|
||||||
root.shouldBuyWithControlledFailure = true;
|
root.shouldBuyWithControlledFailure = true;
|
||||||
} else {
|
} else {
|
||||||
buyButton.text = (itemIsJson ? ((purchasesReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item");
|
buyButton.text = (root.isCertified ? ((ownershipStatusReceived && balanceReceived) ? (root.alreadyOwned ? "Buy Another" : "Buy"): "--") : "Get Item");
|
||||||
buyButton.color = hifi.buttons.blue;
|
buyButton.color = hifi.buttons.blue;
|
||||||
root.shouldBuyWithControlledFailure = false;
|
root.shouldBuyWithControlledFailure = false;
|
||||||
}
|
}
|
||||||
|
@ -883,7 +1008,7 @@ Rectangle {
|
||||||
itemHref = message.params.itemHref;
|
itemHref = message.params.itemHref;
|
||||||
referrer = message.params.referrer;
|
referrer = message.params.referrer;
|
||||||
itemAuthor = message.params.itemAuthor;
|
itemAuthor = message.params.itemAuthor;
|
||||||
setBuyText();
|
refreshBuyUI();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
|
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
|
||||||
|
@ -891,22 +1016,13 @@ Rectangle {
|
||||||
}
|
}
|
||||||
signal sendToScript(var message);
|
signal sendToScript(var message);
|
||||||
|
|
||||||
function purchasesContains(purchasesJson, id) {
|
function refreshBuyUI() {
|
||||||
for (var idx = 0; idx < purchasesJson.length; idx++) {
|
if (root.isCertified) {
|
||||||
if(purchasesJson[idx].id === id) {
|
if (root.ownershipStatusReceived && root.balanceReceived) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setBuyText() {
|
|
||||||
if (root.itemIsJson) {
|
|
||||||
if (root.purchasesReceived && root.balanceReceived) {
|
|
||||||
if (root.balanceAfterPurchase < 0) {
|
if (root.balanceAfterPurchase < 0) {
|
||||||
if (root.alreadyOwned) {
|
if (root.alreadyOwned) {
|
||||||
buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.<br>" +
|
buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item again.</b>";
|
||||||
'<font color="' + hifi.colors.blueAccent + '"><a href="#">View the copy you own in My Purchases</a></font></b>';
|
viewInMyPurchasesButton.visible = true;
|
||||||
} else {
|
} else {
|
||||||
buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item.</b>";
|
buyText.text = "<b>Your Wallet does not have sufficient funds to purchase this item.</b>";
|
||||||
}
|
}
|
||||||
|
@ -916,15 +1032,19 @@ Rectangle {
|
||||||
buyGlyph.size = 54;
|
buyGlyph.size = 54;
|
||||||
} else {
|
} else {
|
||||||
if (root.alreadyOwned) {
|
if (root.alreadyOwned) {
|
||||||
buyText.text = '<b>You already own this item.<br>Purchasing it will buy another copy.<br><font color="'
|
viewInMyPurchasesButton.visible = true;
|
||||||
+ hifi.colors.blueAccent + '"><a href="#">View this item in My Purchases</a></font></b>';
|
|
||||||
buyTextContainer.color = "#FFD6AD";
|
|
||||||
buyTextContainer.border.color = "#FAC07D";
|
|
||||||
buyGlyph.text = hifi.glyphs.alert;
|
|
||||||
buyGlyph.size = 46;
|
|
||||||
} else {
|
} else {
|
||||||
buyText.text = "";
|
buyText.text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root.itemType === "contentSet" && !Entities.canReplaceContent()) {
|
||||||
|
buyText.text = "The domain owner must enable 'Replace Content' permissions for you in this " +
|
||||||
|
"<b>domain's server settings</b> before you can replace this domain's content with <b>" + root.itemName + "</b>";
|
||||||
|
buyTextContainer.color = "#FFC3CD";
|
||||||
|
buyTextContainer.border.color = "#F3808F";
|
||||||
|
buyGlyph.text = hifi.glyphs.alert;
|
||||||
|
buyGlyph.size = 54;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buyText.text = "";
|
buyText.text = "";
|
||||||
|
@ -945,8 +1065,8 @@ Rectangle {
|
||||||
root.activeView = "checkoutSuccess";
|
root.activeView = "checkoutSuccess";
|
||||||
}
|
}
|
||||||
root.balanceReceived = false;
|
root.balanceReceived = false;
|
||||||
root.purchasesReceived = false;
|
root.ownershipStatusReceived = false;
|
||||||
Commerce.inventory();
|
Commerce.alreadyOwned(root.itemId);
|
||||||
Commerce.balance();
|
Commerce.balance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,10 @@ Rectangle {
|
||||||
size: 20;
|
size: 20;
|
||||||
verticalAlignment: Text.AlignTop;
|
verticalAlignment: Text.AlignTop;
|
||||||
wrapMode: Text.WordWrap;
|
wrapMode: Text.WordWrap;
|
||||||
|
|
||||||
|
onLinkActivated: {
|
||||||
|
sendToParent({ method: 'commerceLightboxLinkClicked', linkUrl: link });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
|
@ -90,11 +90,11 @@ Rectangle {
|
||||||
id: introText2;
|
id: introText2;
|
||||||
text: "My Purchases";
|
text: "My Purchases";
|
||||||
// Text size
|
// Text size
|
||||||
size: 28;
|
size: 22;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: introText1.bottom;
|
anchors.top: introText1.bottom;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 12;
|
anchors.leftMargin: 24;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
height: paintedHeight;
|
height: paintedHeight;
|
||||||
// Style
|
// Style
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
|
@ -208,6 +208,7 @@ Rectangle {
|
||||||
// able to click on a button/mouseArea underneath the popup/section.
|
// able to click on a button/mouseArea underneath the popup/section.
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
|
hoverEnabled: true;
|
||||||
propagateComposedEvents: false;
|
propagateComposedEvents: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import "../../../styles-uit"
|
||||||
import "../../../controls-uit" as HifiControlsUit
|
import "../../../controls-uit" as HifiControlsUit
|
||||||
import "../../../controls" as HifiControls
|
import "../../../controls" as HifiControls
|
||||||
import "../wallet" as HifiWallet
|
import "../wallet" as HifiWallet
|
||||||
|
import TabletScriptingInterface 1.0
|
||||||
|
|
||||||
// references XXX from root context
|
// references XXX from root context
|
||||||
|
|
||||||
|
@ -29,7 +30,6 @@ Item {
|
||||||
id: root;
|
id: root;
|
||||||
property string purchaseStatus;
|
property string purchaseStatus;
|
||||||
property bool purchaseStatusChanged;
|
property bool purchaseStatusChanged;
|
||||||
property bool canRezCertifiedItems: false;
|
|
||||||
property string itemName;
|
property string itemName;
|
||||||
property string itemId;
|
property string itemId;
|
||||||
property string itemPreviewImageUrl;
|
property string itemPreviewImageUrl;
|
||||||
|
@ -39,7 +39,15 @@ Item {
|
||||||
property int itemEdition;
|
property int itemEdition;
|
||||||
property int numberSold;
|
property int numberSold;
|
||||||
property int limitedRun;
|
property int limitedRun;
|
||||||
property bool isWearable;
|
property string itemType;
|
||||||
|
property var itemTypesArray: ["entity", "wearable", "contentSet", "app", "avatar"];
|
||||||
|
property var buttonTextNormal: ["REZ", "WEAR", "REPLACE", "INSTALL", "WEAR"];
|
||||||
|
property var buttonTextClicked: ["REZZED", "WORN", "REPLACED", "INSTALLED", "WORN"]
|
||||||
|
property var buttonGlyph: [hifi.glyphs.wand, hifi.glyphs.hat, hifi.glyphs.globe, hifi.glyphs.install, hifi.glyphs.avatar];
|
||||||
|
property bool showConfirmation: false;
|
||||||
|
property bool hasPermissionToRezThis;
|
||||||
|
property bool permissionExplanationCardVisible;
|
||||||
|
property bool isInstalled;
|
||||||
|
|
||||||
property string originalStatusText;
|
property string originalStatusText;
|
||||||
property string originalStatusColor;
|
property string originalStatusColor;
|
||||||
|
@ -47,6 +55,47 @@ Item {
|
||||||
height: 110;
|
height: 110;
|
||||||
width: parent.width;
|
width: parent.width;
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: Commerce;
|
||||||
|
|
||||||
|
onContentSetChanged: {
|
||||||
|
if (contentSetHref === root.itemHref) {
|
||||||
|
showConfirmation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onAppInstalled: {
|
||||||
|
if (appHref === root.itemHref) {
|
||||||
|
root.isInstalled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onAppUninstalled: {
|
||||||
|
if (appHref === root.itemHref) {
|
||||||
|
root.isInstalled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: MyAvatar;
|
||||||
|
|
||||||
|
onSkeletonModelURLChanged: {
|
||||||
|
if (skeletonModelURL === root.itemHref) {
|
||||||
|
showConfirmation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onItemTypeChanged: {
|
||||||
|
if ((itemType === "entity" && (!Entities.canRezCertified() && !Entities.canRezTmpCertified())) ||
|
||||||
|
(itemType === "contentSet" && !Entities.canReplaceContent())) {
|
||||||
|
root.hasPermissionToRezThis = false;
|
||||||
|
} else {
|
||||||
|
root.hasPermissionToRezThis = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onPurchaseStatusChangedChanged: {
|
onPurchaseStatusChangedChanged: {
|
||||||
if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") {
|
if (root.purchaseStatusChanged === true && root.purchaseStatus === "confirmed") {
|
||||||
root.originalStatusText = statusText.text;
|
root.originalStatusText = statusText.text;
|
||||||
|
@ -57,6 +106,15 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onShowConfirmationChanged: {
|
||||||
|
if (root.showConfirmation) {
|
||||||
|
rezzedNotifContainer.visible = true;
|
||||||
|
rezzedNotifContainerTimer.start();
|
||||||
|
UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.itemType);
|
||||||
|
root.showConfirmation = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
id: confirmedTimer;
|
id: confirmedTimer;
|
||||||
interval: 3000;
|
interval: 3000;
|
||||||
|
@ -73,10 +131,10 @@ Item {
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
// Size
|
// Size
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 8;
|
anchors.leftMargin: 16;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 8;
|
anchors.rightMargin: 16;
|
||||||
anchors.top: parent.top;
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
height: root.height - 10;
|
height: root.height - 10;
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
|
@ -96,15 +154,20 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: itemNameTextMetrics;
|
||||||
|
font: itemName.font;
|
||||||
|
text: itemName.text;
|
||||||
|
}
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
id: itemName;
|
id: itemName;
|
||||||
anchors.top: itemPreviewImage.top;
|
anchors.top: itemPreviewImage.top;
|
||||||
anchors.topMargin: 4;
|
anchors.topMargin: 4;
|
||||||
anchors.left: itemPreviewImage.right;
|
anchors.left: itemPreviewImage.right;
|
||||||
anchors.leftMargin: 8;
|
anchors.leftMargin: 8;
|
||||||
anchors.right: buttonContainer.left;
|
width: !noPermissionGlyph.visible ? (buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin) :
|
||||||
anchors.rightMargin: 8;
|
Math.min(itemNameTextMetrics.tightBoundingRect.width + 2,
|
||||||
|
buttonContainer.x - itemPreviewImage.x - itemPreviewImage.width - anchors.leftMargin - noPermissionGlyph.width + 2);
|
||||||
height: paintedHeight;
|
height: paintedHeight;
|
||||||
// Text size
|
// Text size
|
||||||
size: 24;
|
size: 24;
|
||||||
|
@ -130,6 +193,93 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HiFiGlyphs {
|
||||||
|
id: noPermissionGlyph;
|
||||||
|
visible: !root.hasPermissionToRezThis;
|
||||||
|
anchors.verticalCenter: itemName.verticalCenter;
|
||||||
|
anchors.left: itemName.right;
|
||||||
|
anchors.leftMargin: itemName.truncated ? -10 : -2;
|
||||||
|
text: hifi.glyphs.info;
|
||||||
|
// Size
|
||||||
|
size: 40;
|
||||||
|
width: 32;
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.redAccent;
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent;
|
||||||
|
hoverEnabled: true;
|
||||||
|
|
||||||
|
onEntered: {
|
||||||
|
noPermissionGlyph.color = hifi.colors.redHighlight;
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
noPermissionGlyph.color = hifi.colors.redAccent;
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
root.sendToPurchases({ method: 'openPermissionExplanationCard' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
id: permissionExplanationCard;
|
||||||
|
z: 995;
|
||||||
|
visible: root.permissionExplanationCardVisible;
|
||||||
|
anchors.fill: parent;
|
||||||
|
color: hifi.colors.white;
|
||||||
|
|
||||||
|
RalewayRegular {
|
||||||
|
id: permissionExplanationText;
|
||||||
|
text: {
|
||||||
|
if (root.itemType === "contentSet") {
|
||||||
|
"You do not have 'Replace Content' permissions in this domain. <a href='#replaceContentPermission'>Learn more</a>";
|
||||||
|
} else if (root.itemType === "entity") {
|
||||||
|
"You do not have 'Rez Certified' permissions in this domain. <a href='#rezCertifiedPermission'>Learn more</a>";
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size: 16;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
anchors.leftMargin: 30;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.right: permissionExplanationGlyph.left;
|
||||||
|
color: hifi.colors.baseGray;
|
||||||
|
wrapMode: Text.WordWrap;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
|
||||||
|
onLinkActivated: {
|
||||||
|
sendToPurchases({method: 'showPermissionsExplanation', itemType: root.itemType});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// "Close" button
|
||||||
|
HiFiGlyphs {
|
||||||
|
id: permissionExplanationGlyph;
|
||||||
|
text: hifi.glyphs.close;
|
||||||
|
color: hifi.colors.baseGray;
|
||||||
|
size: 26;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
width: 77;
|
||||||
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
verticalAlignment: Text.AlignVCenter;
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent;
|
||||||
|
hoverEnabled: true;
|
||||||
|
onEntered: {
|
||||||
|
parent.text = hifi.glyphs.closeInverted;
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
parent.text = hifi.glyphs.close;
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
root.sendToPurchases({ method: 'openPermissionExplanationCard', closeAll: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: certificateContainer;
|
id: certificateContainer;
|
||||||
|
@ -151,19 +301,19 @@ Item {
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
width: 32;
|
width: 32;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.lightGray;
|
color: hifi.colors.black;
|
||||||
}
|
}
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: viewCertificateText;
|
id: viewCertificateText;
|
||||||
text: "VIEW CERTIFICATE";
|
text: "VIEW CERTIFICATE";
|
||||||
size: 14;
|
size: 13;
|
||||||
anchors.left: certificateIcon.right;
|
anchors.left: certificateIcon.right;
|
||||||
anchors.leftMargin: 4;
|
anchors.leftMargin: 4;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
color: hifi.colors.lightGray;
|
color: hifi.colors.black;
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
@ -173,13 +323,13 @@ Item {
|
||||||
sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId});
|
sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId});
|
||||||
}
|
}
|
||||||
onEntered: {
|
onEntered: {
|
||||||
certificateIcon.color = hifi.colors.black;
|
|
||||||
viewCertificateText.color = hifi.colors.black;
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
certificateIcon.color = hifi.colors.lightGray;
|
certificateIcon.color = hifi.colors.lightGray;
|
||||||
viewCertificateText.color = hifi.colors.lightGray;
|
viewCertificateText.color = hifi.colors.lightGray;
|
||||||
}
|
}
|
||||||
|
onExited: {
|
||||||
|
certificateIcon.color = hifi.colors.black;
|
||||||
|
viewCertificateText.color = hifi.colors.black;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,14 +343,14 @@ Item {
|
||||||
anchors.right: buttonContainer.left;
|
anchors.right: buttonContainer.left;
|
||||||
anchors.rightMargin: 2;
|
anchors.rightMargin: 2;
|
||||||
|
|
||||||
FiraSansRegular {
|
RalewayRegular {
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
width: paintedWidth;
|
width: paintedWidth;
|
||||||
text: "#" + root.itemEdition;
|
text: "#" + root.itemEdition;
|
||||||
size: 15;
|
size: 13;
|
||||||
color: "#cc6a6a6a";
|
color: hifi.colors.black;
|
||||||
verticalAlignment: Text.AlignTop;
|
verticalAlignment: Text.AlignTop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,7 +461,7 @@ Item {
|
||||||
id: rezzedNotifContainer;
|
id: rezzedNotifContainer;
|
||||||
z: 998;
|
z: 998;
|
||||||
visible: false;
|
visible: false;
|
||||||
color: hifi.colors.blueHighlight;
|
color: "#1FC6A6";
|
||||||
anchors.fill: buttonContainer;
|
anchors.fill: buttonContainer;
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
|
@ -321,8 +471,8 @@ Item {
|
||||||
|
|
||||||
RalewayBold {
|
RalewayBold {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
text: "REZZED";
|
text: (root.buttonTextClicked)[itemTypesArray.indexOf(root.itemType)];
|
||||||
size: 18;
|
size: 15;
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
verticalAlignment: Text.AlignVCenter;
|
verticalAlignment: Text.AlignVCenter;
|
||||||
horizontalAlignment: Text.AlignHCenter;
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
@ -335,27 +485,89 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: appButtonContainer;
|
||||||
|
color: hifi.colors.white;
|
||||||
|
z: 994;
|
||||||
|
visible: root.isInstalled;
|
||||||
|
anchors.fill: buttonContainer;
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: openAppButton;
|
||||||
|
color: hifi.buttons.blue;
|
||||||
|
colorScheme: hifi.colorSchemes.light;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
width: 92;
|
||||||
|
height: 44;
|
||||||
|
text: "OPEN"
|
||||||
|
onClicked: {
|
||||||
|
Commerce.openApp(root.itemHref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: uninstallAppButton;
|
||||||
|
color: hifi.buttons.noneBorderless;
|
||||||
|
colorScheme: hifi.colorSchemes.light;
|
||||||
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.right: parent.right;
|
||||||
|
anchors.left: parent.left;
|
||||||
|
height: 44;
|
||||||
|
text: "UNINSTALL"
|
||||||
|
onClicked: {
|
||||||
|
Commerce.uninstallApp(root.itemHref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: buttonContainer;
|
id: buttonContainer;
|
||||||
property int color: hifi.buttons.red;
|
property int color: hifi.buttons.blue;
|
||||||
property int colorScheme: hifi.colorSchemes.light;
|
property int colorScheme: hifi.colorSchemes.light;
|
||||||
|
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
|
anchors.topMargin: 4;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
|
anchors.bottomMargin: 4;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
|
anchors.rightMargin: 4;
|
||||||
width: height;
|
width: height;
|
||||||
enabled: (root.canRezCertifiedItems || root.isWearable) && root.purchaseStatus !== "invalidated";
|
enabled: root.hasPermissionToRezThis &&
|
||||||
|
root.purchaseStatus !== "invalidated" &&
|
||||||
|
MyAvatar.skeletonModelURL !== root.itemHref;
|
||||||
|
|
||||||
|
onHoveredChanged: {
|
||||||
|
if (hovered) {
|
||||||
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onFocusChanged: {
|
||||||
|
if (focus) {
|
||||||
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable});
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
rezzedNotifContainer.visible = true;
|
if (root.itemType === "contentSet") {
|
||||||
rezzedNotifContainerTimer.start();
|
sendToPurchases({method: 'showReplaceContentLightbox', itemHref: root.itemHref});
|
||||||
UserActivityLogger.commerceEntityRezzed(root.itemId, "purchases", root.isWearable ? "rez" : "wear");
|
} else if (root.itemType === "avatar") {
|
||||||
|
sendToPurchases({method: 'showChangeAvatarLightbox', itemName: root.itemName, itemHref: root.itemHref});
|
||||||
|
} else if (root.itemType === "app") {
|
||||||
|
// "Run" and "Uninstall" buttons are separate.
|
||||||
|
Commerce.installApp(root.itemHref);
|
||||||
|
} else {
|
||||||
|
sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, itemType: root.itemType});
|
||||||
|
root.showConfirmation = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
style: ButtonStyle {
|
style: ButtonStyle {
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
|
radius: 4;
|
||||||
gradient: Gradient {
|
gradient: Gradient {
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.2
|
position: 0.2
|
||||||
|
@ -390,13 +602,13 @@ Item {
|
||||||
|
|
||||||
label: Item {
|
label: Item {
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
id: lightningIcon;
|
id: rezIcon;
|
||||||
text: hifi.glyphs.lightning;
|
text: (root.buttonGlyph)[itemTypesArray.indexOf(root.itemType)];
|
||||||
// Size
|
// Size
|
||||||
size: 32;
|
size: 60;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
anchors.topMargin: 12;
|
anchors.topMargin: 0;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
horizontalAlignment: Text.AlignHCenter;
|
horizontalAlignment: Text.AlignHCenter;
|
||||||
|
@ -405,18 +617,19 @@ Item {
|
||||||
: hifi.buttons.disabledTextColor[control.colorScheme]
|
: hifi.buttons.disabledTextColor[control.colorScheme]
|
||||||
}
|
}
|
||||||
RalewayBold {
|
RalewayBold {
|
||||||
anchors.top: lightningIcon.bottom;
|
id: rezIconLabel;
|
||||||
anchors.topMargin: -20;
|
anchors.top: rezIcon.bottom;
|
||||||
|
anchors.topMargin: -4;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
font.capitalization: Font.AllUppercase
|
font.capitalization: Font.AllUppercase
|
||||||
color: enabled ? hifi.buttons.textColor[control.color]
|
color: enabled ? hifi.buttons.textColor[control.color]
|
||||||
: hifi.buttons.disabledTextColor[control.colorScheme]
|
: hifi.buttons.disabledTextColor[control.colorScheme]
|
||||||
size: 16;
|
size: 15;
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
text: root.isWearable ? "Wear It" : "Rez It"
|
text: MyAvatar.skeletonModelURL === root.itemHref ? "CURRENT" : (root.buttonTextNormal)[itemTypesArray.indexOf(root.itemType)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,11 +638,11 @@ Item {
|
||||||
|
|
||||||
DropShadow {
|
DropShadow {
|
||||||
anchors.fill: mainContainer;
|
anchors.fill: mainContainer;
|
||||||
horizontalOffset: 3;
|
horizontalOffset: 0;
|
||||||
verticalOffset: 3;
|
verticalOffset: 4;
|
||||||
radius: 8.0;
|
radius: 4.0;
|
||||||
samples: 17;
|
samples: 9
|
||||||
color: "#80000000";
|
color: Qt.rgba(0, 0, 0, 0.25);
|
||||||
source: mainContainer;
|
source: mainContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,11 @@ Rectangle {
|
||||||
property bool securityImageResultReceived: false;
|
property bool securityImageResultReceived: false;
|
||||||
property bool purchasesReceived: false;
|
property bool purchasesReceived: false;
|
||||||
property bool punctuationMode: false;
|
property bool punctuationMode: false;
|
||||||
property bool canRezCertifiedItems: Entities.canRezCertified() || Entities.canRezTmpCertified();
|
|
||||||
property bool pendingInventoryReply: true;
|
property bool pendingInventoryReply: true;
|
||||||
property bool isShowingMyItems: false;
|
property bool isShowingMyItems: false;
|
||||||
property bool isDebuggingFirstUseTutorial: false;
|
property bool isDebuggingFirstUseTutorial: false;
|
||||||
property int pendingItemCount: 0;
|
property int pendingItemCount: 0;
|
||||||
|
property string installedApps;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
Connections {
|
Connections {
|
||||||
|
@ -62,6 +62,7 @@ Rectangle {
|
||||||
root.activeView = "firstUseTutorial";
|
root.activeView = "firstUseTutorial";
|
||||||
} else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") {
|
} else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") {
|
||||||
root.activeView = "purchasesMain";
|
root.activeView = "purchasesMain";
|
||||||
|
root.installedApps = Commerce.getInstalledApps();
|
||||||
Commerce.inventory();
|
Commerce.inventory();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,7 +149,11 @@ Rectangle {
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
onSendToParent: {
|
onSendToParent: {
|
||||||
sendToScript(msg);
|
if (msg.method === 'commerceLightboxLinkClicked') {
|
||||||
|
Qt.openUrlExternally(msg.linkUrl);
|
||||||
|
} else {
|
||||||
|
sendToScript(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,6 +271,7 @@ Rectangle {
|
||||||
case 'tutorial_finished':
|
case 'tutorial_finished':
|
||||||
Settings.setValue("isFirstUseOfPurchases", false);
|
Settings.setValue("isFirstUseOfPurchases", false);
|
||||||
root.activeView = "purchasesMain";
|
root.activeView = "purchasesMain";
|
||||||
|
root.installedApps = Commerce.getInstalledApps();
|
||||||
Commerce.inventory();
|
Commerce.inventory();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -297,7 +303,7 @@ Rectangle {
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 8;
|
anchors.leftMargin: 8;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.rightMargin: 12;
|
anchors.rightMargin: 16;
|
||||||
anchors.top: parent.top;
|
anchors.top: parent.top;
|
||||||
anchors.topMargin: 4;
|
anchors.topMargin: 4;
|
||||||
|
|
||||||
|
@ -308,11 +314,11 @@ Rectangle {
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
anchors.bottomMargin: 10;
|
anchors.bottomMargin: 10;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.leftMargin: 4;
|
anchors.leftMargin: 16;
|
||||||
width: paintedWidth;
|
width: paintedWidth;
|
||||||
text: isShowingMyItems ? "My Items" : "My Purchases";
|
text: isShowingMyItems ? "My Items" : "My Purchases";
|
||||||
color: hifi.colors.baseGray;
|
color: hifi.colors.black;
|
||||||
size: 28;
|
size: 22;
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControlsUit.TextField {
|
HifiControlsUit.TextField {
|
||||||
|
@ -323,8 +329,8 @@ Rectangle {
|
||||||
hasRoundedBorder: true;
|
hasRoundedBorder: true;
|
||||||
anchors.left: myText.right;
|
anchors.left: myText.right;
|
||||||
anchors.leftMargin: 16;
|
anchors.leftMargin: 16;
|
||||||
anchors.top: parent.top;
|
height: 39;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.verticalCenter: parent.verticalCenter;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
placeholderText: "filter items";
|
placeholderText: "filter items";
|
||||||
|
|
||||||
|
@ -345,7 +351,7 @@ Rectangle {
|
||||||
|
|
||||||
HifiControlsUit.Separator {
|
HifiControlsUit.Separator {
|
||||||
id: separator;
|
id: separator;
|
||||||
colorScheme: 1;
|
colorScheme: 2;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.right: parent.right;
|
anchors.right: parent.right;
|
||||||
anchors.top: filterBarContainer.bottom;
|
anchors.top: filterBarContainer.bottom;
|
||||||
|
@ -365,69 +371,6 @@ Rectangle {
|
||||||
id: filteredPurchasesModel;
|
id: filteredPurchasesModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: cantRezCertified;
|
|
||||||
visible: !root.canRezCertifiedItems;
|
|
||||||
color: "#FFC3CD";
|
|
||||||
radius: 4;
|
|
||||||
border.color: hifi.colors.redAccent;
|
|
||||||
border.width: 1;
|
|
||||||
anchors.top: separator.bottom;
|
|
||||||
anchors.topMargin: 12;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 16;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.rightMargin: 16;
|
|
||||||
height: 80;
|
|
||||||
|
|
||||||
HiFiGlyphs {
|
|
||||||
id: lightningIcon;
|
|
||||||
text: hifi.glyphs.lightning;
|
|
||||||
// Size
|
|
||||||
size: 36;
|
|
||||||
// Anchors
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.topMargin: 18;
|
|
||||||
anchors.left: parent.left;
|
|
||||||
anchors.leftMargin: 12;
|
|
||||||
horizontalAlignment: Text.AlignHCenter;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.lightGray;
|
|
||||||
}
|
|
||||||
|
|
||||||
RalewayRegular {
|
|
||||||
text: "You don't have permission to rez certified items in this domain. " +
|
|
||||||
'<b><font color="' + hifi.colors.blueAccent + '"><a href="#">Learn More</a></font></b>';
|
|
||||||
// Text size
|
|
||||||
size: 18;
|
|
||||||
// Anchors
|
|
||||||
anchors.top: parent.top;
|
|
||||||
anchors.topMargin: 4;
|
|
||||||
anchors.left: lightningIcon.right;
|
|
||||||
anchors.leftMargin: 8;
|
|
||||||
anchors.right: parent.right;
|
|
||||||
anchors.rightMargin: 8;
|
|
||||||
anchors.bottom: parent.bottom;
|
|
||||||
anchors.bottomMargin: 4;
|
|
||||||
// Style
|
|
||||||
color: hifi.colors.baseGray;
|
|
||||||
wrapMode: Text.WordWrap;
|
|
||||||
// Alignment
|
|
||||||
verticalAlignment: Text.AlignVCenter;
|
|
||||||
|
|
||||||
onLinkActivated: {
|
|
||||||
lightboxPopup.titleText = "Rez Permission Required";
|
|
||||||
lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.<br><br>" +
|
|
||||||
"Use the <b>GOTO app</b> to visit another domain or <b>go to your own sandbox.</b>";
|
|
||||||
lightboxPopup.button1text = "CLOSE";
|
|
||||||
lightboxPopup.button1method = "root.visible = false;"
|
|
||||||
lightboxPopup.button2text = "OPEN GOTO";
|
|
||||||
lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});";
|
|
||||||
lightboxPopup.visible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: purchasesContentsList;
|
id: purchasesContentsList;
|
||||||
visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0);
|
visible: (root.isShowingMyItems && filteredPurchasesModel.count !== 0) || (!root.isShowingMyItems && filteredPurchasesModel.count !== 0);
|
||||||
|
@ -436,13 +379,12 @@ Rectangle {
|
||||||
snapMode: ListView.SnapToItem;
|
snapMode: ListView.SnapToItem;
|
||||||
highlightRangeMode: ListView.StrictlyEnforceRange;
|
highlightRangeMode: ListView.StrictlyEnforceRange;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: root.canRezCertifiedItems ? separator.bottom : cantRezCertified.bottom;
|
anchors.top: separator.bottom;
|
||||||
anchors.topMargin: 12;
|
anchors.topMargin: 12;
|
||||||
anchors.left: parent.left;
|
anchors.left: parent.left;
|
||||||
anchors.bottom: parent.bottom;
|
anchors.bottom: parent.bottom;
|
||||||
width: parent.width;
|
width: parent.width;
|
||||||
delegate: PurchasedItem {
|
delegate: PurchasedItem {
|
||||||
canRezCertifiedItems: root.canRezCertifiedItems;
|
|
||||||
itemName: title;
|
itemName: title;
|
||||||
itemId: id;
|
itemId: id;
|
||||||
itemPreviewImageUrl: preview;
|
itemPreviewImageUrl: preview;
|
||||||
|
@ -454,16 +396,32 @@ Rectangle {
|
||||||
numberSold: model.number_sold;
|
numberSold: model.number_sold;
|
||||||
limitedRun: model.limited_run;
|
limitedRun: model.limited_run;
|
||||||
displayedItemCount: model.displayedItemCount;
|
displayedItemCount: model.displayedItemCount;
|
||||||
isWearable: model.categories.indexOf("Wearables") > -1;
|
permissionExplanationCardVisible: model.permissionExplanationCardVisible;
|
||||||
anchors.topMargin: 12;
|
isInstalled: model.isInstalled;
|
||||||
anchors.bottomMargin: 12;
|
itemType: {
|
||||||
|
if (model.root_file_url.indexOf(".fst") > -1) {
|
||||||
|
"avatar";
|
||||||
|
} else if (model.categories.indexOf("Wearables") > -1) {
|
||||||
|
"wearable";
|
||||||
|
} else if (model.root_file_url.endsWith('.json.gz')) {
|
||||||
|
"contentSet";
|
||||||
|
} else if (model.root_file_url.endsWith('.app.json')) {
|
||||||
|
"app";
|
||||||
|
} else if (model.root_file_url.endsWith('.json')) {
|
||||||
|
"entity";
|
||||||
|
} else {
|
||||||
|
"unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
anchors.topMargin: 10;
|
||||||
|
anchors.bottomMargin: 10;
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
onSendToPurchases: {
|
onSendToPurchases: {
|
||||||
if (msg.method === 'purchases_itemInfoClicked') {
|
if (msg.method === 'purchases_itemInfoClicked') {
|
||||||
sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId});
|
sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId});
|
||||||
} else if (msg.method === "purchases_rezClicked") {
|
} else if (msg.method === "purchases_rezClicked") {
|
||||||
sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, isWearable: isWearable});
|
sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, itemType: itemType});
|
||||||
} else if (msg.method === 'purchases_itemCertificateClicked') {
|
} else if (msg.method === 'purchases_itemCertificateClicked') {
|
||||||
inspectionCertificate.visible = true;
|
inspectionCertificate.visible = true;
|
||||||
inspectionCertificate.isLightbox = true;
|
inspectionCertificate.isLightbox = true;
|
||||||
|
@ -482,8 +440,51 @@ Rectangle {
|
||||||
lightboxPopup.button1text = "CLOSE";
|
lightboxPopup.button1text = "CLOSE";
|
||||||
lightboxPopup.button1method = "root.visible = false;"
|
lightboxPopup.button1method = "root.visible = false;"
|
||||||
lightboxPopup.visible = true;
|
lightboxPopup.visible = true;
|
||||||
|
} else if (msg.method === "showReplaceContentLightbox") {
|
||||||
|
lightboxPopup.titleText = "Replace Content";
|
||||||
|
lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " +
|
||||||
|
"If you want to save the state of the content in this domain, create a backup before proceeding.<br><br>" +
|
||||||
|
"For more information about backing up and restoring content, " +
|
||||||
|
"<a href='https://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content'>" +
|
||||||
|
"click here to open info on your desktop browser.";
|
||||||
|
lightboxPopup.button1text = "CANCEL";
|
||||||
|
lightboxPopup.button1method = "root.visible = false;"
|
||||||
|
lightboxPopup.button2text = "CONFIRM";
|
||||||
|
lightboxPopup.button2method = "Commerce.replaceContentSet('" + msg.itemHref + "'); root.visible = false;";
|
||||||
|
lightboxPopup.visible = true;
|
||||||
|
} else if (msg.method === "showChangeAvatarLightbox") {
|
||||||
|
lightboxPopup.titleText = "Change Avatar";
|
||||||
|
lightboxPopup.bodyText = "This will change your current avatar to " + msg.itemName + " while retaining your wearables.";
|
||||||
|
lightboxPopup.button1text = "CANCEL";
|
||||||
|
lightboxPopup.button1method = "root.visible = false;"
|
||||||
|
lightboxPopup.button2text = "CONFIRM";
|
||||||
|
lightboxPopup.button2method = "MyAvatar.useFullAvatarURL('" + msg.itemHref + "'); root.visible = false;";
|
||||||
|
lightboxPopup.visible = true;
|
||||||
|
} else if (msg.method === "showPermissionsExplanation") {
|
||||||
|
if (msg.itemType === "entity") {
|
||||||
|
lightboxPopup.titleText = "Rez Certified Permission";
|
||||||
|
lightboxPopup.bodyText = "You don't have permission to rez certified items in this domain.<br><br>" +
|
||||||
|
"Use the <b>GOTO app</b> to visit another domain or <b>go to your own sandbox.</b>";
|
||||||
|
lightboxPopup.button2text = "OPEN GOTO";
|
||||||
|
lightboxPopup.button2method = "sendToParent({method: 'purchases_openGoTo'});";
|
||||||
|
} else if (msg.itemType === "contentSet") {
|
||||||
|
lightboxPopup.titleText = "Replace Content Permission";
|
||||||
|
lightboxPopup.bodyText = "You do not have the permission 'Replace Content' in this <b>domain's server settings</b>. The domain owner " +
|
||||||
|
"must enable it for you before you can replace content sets in this domain.";
|
||||||
|
}
|
||||||
|
lightboxPopup.button1text = "CLOSE";
|
||||||
|
lightboxPopup.button1method = "root.visible = false;"
|
||||||
|
lightboxPopup.visible = true;
|
||||||
} else if (msg.method === "setFilterText") {
|
} else if (msg.method === "setFilterText") {
|
||||||
filterBar.text = msg.filterText;
|
filterBar.text = msg.filterText;
|
||||||
|
} else if (msg.method === "openPermissionExplanationCard") {
|
||||||
|
for (var i = 0; i < filteredPurchasesModel.count; i++) {
|
||||||
|
if (i !== index || msg.closeAll) {
|
||||||
|
filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", false);
|
||||||
|
} else {
|
||||||
|
filteredPurchasesModel.setProperty(i, "permissionExplanationCardVisible", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -683,8 +684,13 @@ Rectangle {
|
||||||
|
|
||||||
if (sameItemCount !== tempPurchasesModel.count || filterBar.text !== filterBar.previousText) {
|
if (sameItemCount !== tempPurchasesModel.count || filterBar.text !== filterBar.previousText) {
|
||||||
filteredPurchasesModel.clear();
|
filteredPurchasesModel.clear();
|
||||||
|
var currentId;
|
||||||
for (var i = 0; i < tempPurchasesModel.count; i++) {
|
for (var i = 0; i < tempPurchasesModel.count; i++) {
|
||||||
|
currentId = tempPurchasesModel.get(i).id;
|
||||||
|
|
||||||
filteredPurchasesModel.append(tempPurchasesModel.get(i));
|
filteredPurchasesModel.append(tempPurchasesModel.get(i));
|
||||||
|
filteredPurchasesModel.setProperty(i, 'permissionExplanationCardVisible', false);
|
||||||
|
filteredPurchasesModel.setProperty(i, 'isInstalled', ((root.installedApps).indexOf(currentId) > -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
populateDisplayedItemCounts();
|
populateDisplayedItemCounts();
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
import QtQuick 2.5
|
|
||||||
import Qt.labs.settings 1.0
|
|
||||||
|
|
||||||
import "../../dialogs"
|
|
||||||
|
|
||||||
PreferencesDialog {
|
|
||||||
id: root
|
|
||||||
objectName: "GraphicsPreferencesDialog"
|
|
||||||
title: "Graphics Settings"
|
|
||||||
showCategories: ["Graphics"]
|
|
||||||
property var settings: Settings {
|
|
||||||
category: root.objectName
|
|
||||||
property alias x: root.x
|
|
||||||
property alias y: root.y
|
|
||||||
property alias width: root.width
|
|
||||||
property alias height: root.height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -199,7 +199,7 @@ Rectangle {
|
||||||
var SHAPE_TYPE_BOX = 4;
|
var SHAPE_TYPE_BOX = 4;
|
||||||
var SHAPE_TYPE_SPHERE = 5;
|
var SHAPE_TYPE_SPHERE = 5;
|
||||||
|
|
||||||
var SHAPE_TYPES = [];ww
|
var SHAPE_TYPES = [];
|
||||||
SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision";
|
SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision";
|
||||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model";
|
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model";
|
||||||
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes";
|
SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls 2.2 // Need both for short-term fix
|
||||||
import QtWebEngine 1.1
|
import QtWebEngine 1.1
|
||||||
import QtWebChannel 1.0
|
import QtWebChannel 1.0
|
||||||
import QtQuick.Controls.Styles 1.4
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
@ -10,6 +11,7 @@ import "../../controls-uit" as HifiControls
|
||||||
import "../../styles-uit"
|
import "../../styles-uit"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TabView {
|
TabView {
|
||||||
id: editTabView
|
id: editTabView
|
||||||
// anchors.fill: parent
|
// anchors.fill: parent
|
||||||
|
@ -23,8 +25,27 @@ TabView {
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: "#404040"
|
color: "#404040"
|
||||||
|
id: container
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
height: parent.height
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
contentHeight: createEntitiesFlow.height + importButton.height + assetServerButton.height +
|
||||||
|
header.anchors.topMargin + createEntitiesFlow.anchors.topMargin +
|
||||||
|
assetServerButton.anchors.topMargin + importButton.anchors.topMargin
|
||||||
|
contentWidth: width
|
||||||
|
|
||||||
|
ScrollBar.vertical : ScrollBar {
|
||||||
|
visible: parent.contentHeight > parent.height
|
||||||
|
width: 20
|
||||||
|
background: Rectangle {
|
||||||
|
color: hifi.colors.tableScrollBackgroundDark
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
id: header
|
||||||
color: "#ffffff"
|
color: "#ffffff"
|
||||||
text: "Choose an Entity Type to Create:"
|
text: "Choose an Entity Type to Create:"
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
|
@ -176,6 +197,7 @@ TabView {
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControls.Button {
|
HifiControls.Button {
|
||||||
|
id: importButton
|
||||||
text: "Import Entities (.json)"
|
text: "Import Entities (.json)"
|
||||||
color: hifi.buttons.black
|
color: hifi.buttons.black
|
||||||
colorScheme: hifi.colorSchemes.dark
|
colorScheme: hifi.colorSchemes.dark
|
||||||
|
@ -192,6 +214,7 @@ TabView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // Flickable
|
||||||
}
|
}
|
||||||
|
|
||||||
Tab {
|
Tab {
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
//
|
|
||||||
// TabletGraphicsPreferences.qml
|
|
||||||
//
|
|
||||||
// Created by Vlad Stelmahovsky on 12 Mar 2017.
|
|
||||||
// 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
|
|
||||||
//
|
|
||||||
|
|
||||||
import QtQuick 2.5
|
|
||||||
import QtQuick.Controls 1.4
|
|
||||||
import "tabletWindows"
|
|
||||||
import "../../dialogs"
|
|
||||||
|
|
||||||
StackView {
|
|
||||||
id: profileRoot
|
|
||||||
initialItem: root
|
|
||||||
objectName: "stack"
|
|
||||||
property string title: "Graphics Settings"
|
|
||||||
|
|
||||||
signal sendToScript(var message);
|
|
||||||
|
|
||||||
function pushSource(path) {
|
|
||||||
profileRoot.push(Qt.resolvedUrl(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
function popSource() {
|
|
||||||
profileRoot.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
TabletPreferencesDialog {
|
|
||||||
id: root
|
|
||||||
objectName: "TabletGraphicsPreferences"
|
|
||||||
showCategories: ["Graphics"]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -218,7 +218,7 @@ Item {
|
||||||
readonly property var colorStart: [ colors.white, colors.primaryHighlight, "#d42043", "#343434", Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]
|
readonly property var colorStart: [ colors.white, colors.primaryHighlight, "#d42043", "#343434", Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]
|
||||||
readonly property var colorFinish: [ colors.lightGrayText, colors.blueAccent, "#94132e", colors.black, Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]
|
readonly property var colorFinish: [ colors.lightGrayText, colors.blueAccent, "#94132e", colors.black, Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0), Qt.rgba(0, 0, 0, 0) ]
|
||||||
readonly property var hoveredColor: [ colorStart[white], colorStart[blue], colorStart[red], colorFinish[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
|
readonly property var hoveredColor: [ colorStart[white], colorStart[blue], colorStart[red], colorFinish[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
|
||||||
readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
|
readonly property var pressedColor: [ colorFinish[white], colorFinish[blue], colorFinish[red], colorStart[black], colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colors.lightGrayText ]
|
||||||
readonly property var focusedColor: [ colors.lightGray50, colors.blueAccent, colors.redAccent, colors.darkGray, colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
|
readonly property var focusedColor: [ colors.lightGray50, colors.blueAccent, colors.redAccent, colors.darkGray, colorStart[none], colorStart[noneBorderless], colorStart[noneBorderlessWhite], colorStart[noneBorderlessGray] ]
|
||||||
readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight]
|
readonly property var disabledColorStart: [ colorStart[white], colors.baseGrayHighlight]
|
||||||
readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow]
|
readonly property var disabledColorFinish: [ colorFinish[white], colors.baseGrayShadow]
|
||||||
|
@ -354,5 +354,9 @@ Item {
|
||||||
readonly property string wallet: "\ue027"
|
readonly property string wallet: "\ue027"
|
||||||
readonly property string paperPlane: "\ue028"
|
readonly property string paperPlane: "\ue028"
|
||||||
readonly property string passphrase: "\ue029"
|
readonly property string passphrase: "\ue029"
|
||||||
|
readonly property string globe: "\ue02c"
|
||||||
|
readonly property string wand: "\ue02d"
|
||||||
|
readonly property string hat: "\ue02e"
|
||||||
|
readonly property string install: "\ue02f"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,6 @@
|
||||||
#include <Midi.h>
|
#include <Midi.h>
|
||||||
#include <AudioInjectorManager.h>
|
#include <AudioInjectorManager.h>
|
||||||
#include <AvatarBookmarks.h>
|
#include <AvatarBookmarks.h>
|
||||||
#include <AvatarEntitiesBookmarks.h>
|
|
||||||
#include <CursorManager.h>
|
#include <CursorManager.h>
|
||||||
#include <DebugDraw.h>
|
#include <DebugDraw.h>
|
||||||
#include <DeferredLightingEffect.h>
|
#include <DeferredLightingEffect.h>
|
||||||
|
@ -392,7 +391,7 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi
|
||||||
class DeadlockWatchdogThread : public QThread {
|
class DeadlockWatchdogThread : public QThread {
|
||||||
public:
|
public:
|
||||||
static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1;
|
static const unsigned long HEARTBEAT_UPDATE_INTERVAL_SECS = 1;
|
||||||
static const unsigned long MAX_HEARTBEAT_AGE_USECS = 30 * USECS_PER_SECOND;
|
static const unsigned long MAX_HEARTBEAT_AGE_USECS = 120 * USECS_PER_SECOND; // 2 mins with no checkin probably a deadlock
|
||||||
static const int WARNING_ELAPSED_HEARTBEAT = 500 * USECS_PER_MSEC; // warn if elapsed heartbeat average is large
|
static const int WARNING_ELAPSED_HEARTBEAT = 500 * USECS_PER_MSEC; // warn if elapsed heartbeat average is large
|
||||||
static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples
|
static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples
|
||||||
|
|
||||||
|
@ -785,7 +784,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
DependencyManager::set<GooglePolyScriptingInterface>();
|
DependencyManager::set<GooglePolyScriptingInterface>();
|
||||||
DependencyManager::set<OctreeStatsProvider>(nullptr, qApp->getOcteeSceneStats());
|
DependencyManager::set<OctreeStatsProvider>(nullptr, qApp->getOcteeSceneStats());
|
||||||
DependencyManager::set<AvatarBookmarks>();
|
DependencyManager::set<AvatarBookmarks>();
|
||||||
DependencyManager::set<AvatarEntitiesBookmarks>();
|
|
||||||
DependencyManager::set<LocationBookmarks>();
|
DependencyManager::set<LocationBookmarks>();
|
||||||
DependencyManager::set<Snapshot>();
|
DependencyManager::set<Snapshot>();
|
||||||
DependencyManager::set<CloseEventSender>();
|
DependencyManager::set<CloseEventSender>();
|
||||||
|
@ -1719,6 +1717,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
properties["has_async_reprojection"] = displayPlugin->hasAsyncReprojection();
|
properties["has_async_reprojection"] = displayPlugin->hasAsyncReprojection();
|
||||||
properties["hardware_stats"] = displayPlugin->getHardwareStats();
|
properties["hardware_stats"] = displayPlugin->getHardwareStats();
|
||||||
|
|
||||||
|
// deadlock watchdog related stats
|
||||||
|
properties["deadlock_watchdog_maxElapsed"] = (int)DeadlockWatchdogThread::_maxElapsed;
|
||||||
|
properties["deadlock_watchdog_maxElapsedAverage"] = (int)DeadlockWatchdogThread::_maxElapsedAverage;
|
||||||
|
|
||||||
auto bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
|
auto bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
|
||||||
properties["packet_rate_in"] = bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond();
|
properties["packet_rate_in"] = bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond();
|
||||||
properties["packet_rate_out"] = bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond();
|
properties["packet_rate_out"] = bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond();
|
||||||
|
@ -2606,7 +2608,6 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
|
||||||
surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
|
surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
|
||||||
surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||||
surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
|
surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
|
||||||
surfaceContext->setContextProperty("AvatarEntitiesBookmarks", DependencyManager::get<AvatarEntitiesBookmarks>().data());
|
|
||||||
surfaceContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
|
surfaceContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
|
||||||
|
|
||||||
// Caches
|
// Caches
|
||||||
|
@ -5987,7 +5988,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
||||||
scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
||||||
scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get<AudioScope>().data());
|
scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get<AudioScope>().data());
|
||||||
scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
|
scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
|
||||||
scriptEngine->registerGlobalObject("AvatarEntitiesBookmarks", DependencyManager::get<AvatarEntitiesBookmarks>().data());
|
|
||||||
scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
|
scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("RayPick", DependencyManager::get<RayPickScriptingInterface>().data());
|
scriptEngine->registerGlobalObject("RayPick", DependencyManager::get<RayPickScriptingInterface>().data());
|
||||||
|
@ -6284,6 +6284,24 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::replaceDomainContent(const QString& url) {
|
||||||
|
qCDebug(interfaceapp) << "Attempting to replace domain content: " << url;
|
||||||
|
QByteArray urlData(url.toUtf8());
|
||||||
|
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
||||||
|
limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) {
|
||||||
|
return node->getType() == NodeType::EntityServer && node->getActiveSocket();
|
||||||
|
}, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) {
|
||||||
|
auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true);
|
||||||
|
octreeFilePacket->write(urlData);
|
||||||
|
limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode);
|
||||||
|
});
|
||||||
|
auto addressManager = DependencyManager::get<AddressManager>();
|
||||||
|
addressManager->handleLookupString(DOMAIN_SPAWNING_POINT);
|
||||||
|
QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT;
|
||||||
|
qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress;
|
||||||
|
DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(newHomeAddress);
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::askToReplaceDomainContent(const QString& url) {
|
bool Application::askToReplaceDomainContent(const QString& url) {
|
||||||
QString methodDetails;
|
QString methodDetails;
|
||||||
const int MAX_CHARACTERS_PER_LINE = 90;
|
const int MAX_CHARACTERS_PER_LINE = 90;
|
||||||
|
@ -6303,21 +6321,7 @@ bool Application::askToReplaceDomainContent(const QString& url) {
|
||||||
QString details;
|
QString details;
|
||||||
if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) {
|
if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) {
|
||||||
// Given confirmation, send request to domain server to replace content
|
// Given confirmation, send request to domain server to replace content
|
||||||
qCDebug(interfaceapp) << "Attempting to replace domain content: " << url;
|
replaceDomainContent(url);
|
||||||
QByteArray urlData(url.toUtf8());
|
|
||||||
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
|
|
||||||
limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) {
|
|
||||||
return node->getType() == NodeType::EntityServer && node->getActiveSocket();
|
|
||||||
}, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) {
|
|
||||||
auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true);
|
|
||||||
octreeFilePacket->write(urlData);
|
|
||||||
limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode);
|
|
||||||
});
|
|
||||||
auto addressManager = DependencyManager::get<AddressManager>();
|
|
||||||
addressManager->handleLookupString(DOMAIN_SPAWNING_POINT);
|
|
||||||
QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT;
|
|
||||||
qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress;
|
|
||||||
DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(newHomeAddress);
|
|
||||||
details = "SuccessfulRequestToReplaceContent";
|
details = "SuccessfulRequestToReplaceContent";
|
||||||
} else {
|
} else {
|
||||||
details = "UserDeclinedToReplaceContent";
|
details = "UserDeclinedToReplaceContent";
|
||||||
|
@ -7538,6 +7542,18 @@ void Application::deadlockApplication() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cause main thread to be unresponsive for 35 seconds
|
||||||
|
void Application::unresponsiveApplication() {
|
||||||
|
// to avoid compiler warnings about a loop that will never exit
|
||||||
|
uint64_t start = usecTimestampNow();
|
||||||
|
uint64_t UNRESPONSIVE_FOR_SECONDS = 35;
|
||||||
|
uint64_t UNRESPONSIVE_FOR_USECS = UNRESPONSIVE_FOR_SECONDS * USECS_PER_SECOND;
|
||||||
|
qCDebug(interfaceapp) << "Intentionally cause Interface to be unresponsive for " << UNRESPONSIVE_FOR_SECONDS << " seconds";
|
||||||
|
while (usecTimestampNow() - start < UNRESPONSIVE_FOR_USECS) {
|
||||||
|
QThread::sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setActiveDisplayPlugin(const QString& pluginName) {
|
void Application::setActiveDisplayPlugin(const QString& pluginName) {
|
||||||
auto menu = Menu::getInstance();
|
auto menu = Menu::getInstance();
|
||||||
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
||||||
|
|
|
@ -266,9 +266,8 @@ public:
|
||||||
|
|
||||||
float getGameLoopRate() const { return _gameLoopCounter.rate(); }
|
float getGameLoopRate() const { return _gameLoopCounter.rate(); }
|
||||||
|
|
||||||
// Note that takeSnapshot has a default value, as this method is used internally.
|
|
||||||
void takeSnapshot(bool notify, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString());
|
void takeSnapshot(bool notify, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString());
|
||||||
void takeSecondaryCameraSnapshot(const QString& filename);
|
void takeSecondaryCameraSnapshot(const QString& filename = QString());
|
||||||
|
|
||||||
void shareSnapshot(const QString& filename, const QUrl& href = QUrl(""));
|
void shareSnapshot(const QString& filename, const QUrl& href = QUrl(""));
|
||||||
|
|
||||||
|
@ -286,6 +285,8 @@ public:
|
||||||
bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; }
|
bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; }
|
||||||
void saveNextPhysicsStats(QString filename);
|
void saveNextPhysicsStats(QString filename);
|
||||||
|
|
||||||
|
void replaceDomainContent(const QString& url);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void svoImportRequested(const QString& url);
|
void svoImportRequested(const QString& url);
|
||||||
|
|
||||||
|
@ -367,6 +368,7 @@ public slots:
|
||||||
void updateHeartbeat() const;
|
void updateHeartbeat() const;
|
||||||
|
|
||||||
static void deadlockApplication();
|
static void deadlockApplication();
|
||||||
|
static void unresponsiveApplication(); // cause main thread to be unresponsive for 35 seconds
|
||||||
|
|
||||||
void rotationModeChanged() const;
|
void rotationModeChanged() const;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <OffscreenUi.h>
|
#include <OffscreenUi.h>
|
||||||
#include <avatar/AvatarManager.h>
|
#include <avatar/AvatarManager.h>
|
||||||
|
#include <EntityItemID.h>
|
||||||
|
#include <EntityTree.h>
|
||||||
|
#include <PhysicalEntitySimulation.h>
|
||||||
|
#include <EntityEditPacketSender.h>
|
||||||
|
#include <VariantMapToScriptValue.h>
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
|
@ -29,6 +34,62 @@
|
||||||
|
|
||||||
#include <QtQuick/QQuickWindow>
|
#include <QtQuick/QQuickWindow>
|
||||||
|
|
||||||
|
|
||||||
|
void addAvatarEntities(const QVariantList& avatarEntities) {
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
const QUuid myNodeID = nodeList->getSessionUUID();
|
||||||
|
EntityTreePointer entityTree = DependencyManager::get<EntityTreeRenderer>()->getTree();
|
||||||
|
if (!entityTree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EntitySimulationPointer entitySimulation = entityTree->getSimulation();
|
||||||
|
PhysicalEntitySimulationPointer physicalEntitySimulation = std::static_pointer_cast<PhysicalEntitySimulation>(entitySimulation);
|
||||||
|
EntityEditPacketSender* entityPacketSender = physicalEntitySimulation->getPacketSender();
|
||||||
|
QScriptEngine scriptEngine;
|
||||||
|
for (int index = 0; index < avatarEntities.count(); index++) {
|
||||||
|
const QVariantMap& avatarEntityProperties = avatarEntities.at(index).toMap();
|
||||||
|
QVariant variantProperties = avatarEntityProperties["properties"];
|
||||||
|
QVariantMap asMap = variantProperties.toMap();
|
||||||
|
QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine);
|
||||||
|
EntityItemProperties entityProperties;
|
||||||
|
EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, entityProperties);
|
||||||
|
|
||||||
|
entityProperties.setParentID(myNodeID);
|
||||||
|
entityProperties.setClientOnly(true);
|
||||||
|
entityProperties.setOwningAvatarID(myNodeID);
|
||||||
|
entityProperties.setSimulationOwner(myNodeID, AVATAR_ENTITY_SIMULATION_PRIORITY);
|
||||||
|
entityProperties.markAllChanged();
|
||||||
|
|
||||||
|
EntityItemID id = EntityItemID(QUuid::createUuid());
|
||||||
|
bool success = true;
|
||||||
|
entityTree->withWriteLock([&] {
|
||||||
|
EntityItemPointer entity = entityTree->addEntity(id, entityProperties);
|
||||||
|
if (entity) {
|
||||||
|
if (entityProperties.queryAACubeRelatedPropertyChanged()) {
|
||||||
|
// due to parenting, the server may not know where something is in world-space, so include the bounding cube.
|
||||||
|
bool success;
|
||||||
|
AACube queryAACube = entity->getQueryAACube(success);
|
||||||
|
if (success) {
|
||||||
|
entityProperties.setQueryAACube(queryAACube);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entity->setLastBroadcast(usecTimestampNow());
|
||||||
|
// since we're creating this object we will immediately volunteer to own its simulation
|
||||||
|
entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY);
|
||||||
|
entityProperties.setLastEdited(entity->getLastEdited());
|
||||||
|
} else {
|
||||||
|
qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree";
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
entityPacketSender->queueEditEntityMessage(PacketType::EntityAdd, entityTree, id, entityProperties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AvatarBookmarks::AvatarBookmarks() {
|
AvatarBookmarks::AvatarBookmarks() {
|
||||||
_bookmarksFilename = PathUtils::getAppDataPath() + "/" + AVATARBOOKMARKS_FILENAME;
|
_bookmarksFilename = PathUtils::getAppDataPath() + "/" + AVATARBOOKMARKS_FILENAME;
|
||||||
readFromFile();
|
readFromFile();
|
||||||
|
@ -38,7 +99,7 @@ void AvatarBookmarks::readFromFile() {
|
||||||
// migrate old avatarbookmarks.json, used to be in 'local' folder on windows
|
// migrate old avatarbookmarks.json, used to be in 'local' folder on windows
|
||||||
QString oldConfigPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + AVATARBOOKMARKS_FILENAME;
|
QString oldConfigPath = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + AVATARBOOKMARKS_FILENAME;
|
||||||
QFile oldConfig(oldConfigPath);
|
QFile oldConfig(oldConfigPath);
|
||||||
|
|
||||||
// I imagine that in a year from now, this code for migrating (as well as the two lines above)
|
// I imagine that in a year from now, this code for migrating (as well as the two lines above)
|
||||||
// may be removed since all bookmarks should have been migrated by then
|
// may be removed since all bookmarks should have been migrated by then
|
||||||
// - Robbie Uvanni (6.8.2017)
|
// - Robbie Uvanni (6.8.2017)
|
||||||
|
@ -48,9 +109,9 @@ void AvatarBookmarks::readFromFile() {
|
||||||
} else {
|
} else {
|
||||||
qCDebug(interfaceapp) << "Failed to migrate" << AVATARBOOKMARKS_FILENAME;
|
qCDebug(interfaceapp) << "Failed to migrate" << AVATARBOOKMARKS_FILENAME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Bookmarks::readFromFile();
|
Bookmarks::readFromFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
||||||
|
@ -81,23 +142,27 @@ void AvatarBookmarks::changeToBookmarkedAvatar() {
|
||||||
myAvatar->useFullAvatarURL(action->data().toString());
|
myAvatar->useFullAvatarURL(action->data().toString());
|
||||||
qCDebug(interfaceapp) << " Using Legacy V1 Avatar Bookmark ";
|
qCDebug(interfaceapp) << " Using Legacy V1 Avatar Bookmark ";
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
const QMap<QString, QVariant> bookmark = action->data().toMap();
|
const QMap<QString, QVariant> bookmark = action->data().toMap();
|
||||||
// Not magic value. This is the current made version, and if it changes this interpreter should be updated to
|
// Not magic value. This is the current made version, and if it changes this interpreter should be updated to
|
||||||
// handle the new one separately.
|
// handle the new one separately.
|
||||||
// This is where the avatar bookmark entry is parsed. If adding new Value, make sure to have backward compatability with previous
|
// This is where the avatar bookmark entry is parsed. If adding new Value, make sure to have backward compatability with previous
|
||||||
if (bookmark.value(ENTRY_VERSION) == 3) {
|
if (bookmark.value(ENTRY_VERSION) == 3) {
|
||||||
const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString();
|
myAvatar->removeAvatarEntities();
|
||||||
myAvatar->useFullAvatarURL(avatarUrl);
|
const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString();
|
||||||
qCDebug(interfaceapp) << "Avatar On " << avatarUrl;
|
myAvatar->useFullAvatarURL(avatarUrl);
|
||||||
const QList<QVariant>& attachments = bookmark.value(ENTRY_AVATAR_ATTACHMENTS, QList<QVariant>()).toList();
|
qCDebug(interfaceapp) << "Avatar On " << avatarUrl;
|
||||||
|
const QList<QVariant>& attachments = bookmark.value(ENTRY_AVATAR_ATTACHMENTS, QList<QVariant>()).toList();
|
||||||
|
|
||||||
qCDebug(interfaceapp) << "Attach " << attachments;
|
qCDebug(interfaceapp) << "Attach " << attachments;
|
||||||
myAvatar->setAttachmentsVariant(attachments);
|
myAvatar->setAttachmentsVariant(attachments);
|
||||||
|
|
||||||
|
const float& qScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat();
|
||||||
|
myAvatar->setAvatarScale(qScale);
|
||||||
|
|
||||||
|
const QVariantList& avatarEntities = bookmark.value(ENTRY_AVATAR_ENTITIES, QVariantList()).toList();
|
||||||
|
addAvatarEntities(avatarEntities);
|
||||||
|
|
||||||
const float& qScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat();
|
|
||||||
myAvatar->setAvatarScale(qScale);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qCDebug(interfaceapp) << " Bookmark entry does not match client version, make sure client has a handler for the new AvatarBookmark";
|
qCDebug(interfaceapp) << " Bookmark entry does not match client version, make sure client has a handler for the new AvatarBookmark";
|
||||||
}
|
}
|
||||||
|
@ -126,6 +191,7 @@ void AvatarBookmarks::addBookmark() {
|
||||||
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
||||||
bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale);
|
bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale);
|
||||||
bookmark.insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant());
|
bookmark.insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant());
|
||||||
|
bookmark.insert(ENTRY_AVATAR_ENTITIES, myAvatar->getAvatarEntitiesVariant());
|
||||||
|
|
||||||
Bookmarks::addBookmarkToFile(bookmarkName, bookmark);
|
Bookmarks::addBookmarkToFile(bookmarkName, bookmark);
|
||||||
});
|
});
|
||||||
|
|
|
@ -34,6 +34,7 @@ private:
|
||||||
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
||||||
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
||||||
const QString ENTRY_AVATAR_ATTACHMENTS = "attachments";
|
const QString ENTRY_AVATAR_ATTACHMENTS = "attachments";
|
||||||
|
const QString ENTRY_AVATAR_ENTITIES = "avatarEntites";
|
||||||
const QString ENTRY_AVATAR_SCALE = "avatarScale";
|
const QString ENTRY_AVATAR_SCALE = "avatarScale";
|
||||||
const QString ENTRY_VERSION = "version";
|
const QString ENTRY_VERSION = "version";
|
||||||
|
|
||||||
|
|
|
@ -1,168 +0,0 @@
|
||||||
//
|
|
||||||
// AvatarEntitiesBookmarks.cpp
|
|
||||||
// interface/src
|
|
||||||
//
|
|
||||||
// Created by Dante Ruiz on 15/01/18.
|
|
||||||
// Copyright 2018 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QInputDialog>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QStandardPaths>
|
|
||||||
#include <QQmlContext>
|
|
||||||
#include <QList>
|
|
||||||
|
|
||||||
#include <Application.h>
|
|
||||||
#include <OffscreenUi.h>
|
|
||||||
#include <EntityItemProperties.h>
|
|
||||||
#include <GLMHelpers.h>
|
|
||||||
#include <avatar/AvatarManager.h>
|
|
||||||
#include <EntityItemID.h>
|
|
||||||
#include <EntityTree.h>
|
|
||||||
#include <PhysicalEntitySimulation.h>
|
|
||||||
#include <EntityEditPacketSender.h>
|
|
||||||
#include <VariantMapToScriptValue.h>
|
|
||||||
|
|
||||||
#include "MainWindow.h"
|
|
||||||
#include "Menu.h"
|
|
||||||
#include "AvatarEntitiesBookmarks.h"
|
|
||||||
#include "InterfaceLogging.h"
|
|
||||||
|
|
||||||
#include "QVariantGLM.h"
|
|
||||||
|
|
||||||
#include <QtQuick/QQuickWindow>
|
|
||||||
|
|
||||||
void addAvatarEntities(const QVariantList& avatarEntities) {
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
|
||||||
const QUuid myNodeID = nodeList->getSessionUUID();
|
|
||||||
EntityTreePointer entityTree = DependencyManager::get<EntityTreeRenderer>()->getTree();
|
|
||||||
if (!entityTree) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EntitySimulationPointer entitySimulation = entityTree->getSimulation();
|
|
||||||
PhysicalEntitySimulationPointer physicalEntitySimulation = std::static_pointer_cast<PhysicalEntitySimulation>(entitySimulation);
|
|
||||||
EntityEditPacketSender* entityPacketSender = physicalEntitySimulation->getPacketSender();
|
|
||||||
QScriptEngine scriptEngine;
|
|
||||||
for (int index = 0; index < avatarEntities.count(); index++) {
|
|
||||||
const QVariantMap& avatarEntityProperties = avatarEntities.at(index).toMap();
|
|
||||||
QVariant variantProperties = avatarEntityProperties["properties"];
|
|
||||||
QVariantMap asMap = variantProperties.toMap();
|
|
||||||
QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine);
|
|
||||||
EntityItemProperties entityProperties;
|
|
||||||
EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, entityProperties);
|
|
||||||
|
|
||||||
entityProperties.setParentID(myNodeID);
|
|
||||||
entityProperties.setClientOnly(true);
|
|
||||||
entityProperties.setOwningAvatarID(myNodeID);
|
|
||||||
entityProperties.setSimulationOwner(myNodeID, AVATAR_ENTITY_SIMULATION_PRIORITY);
|
|
||||||
entityProperties.markAllChanged();
|
|
||||||
|
|
||||||
EntityItemID id = EntityItemID(QUuid::createUuid());
|
|
||||||
bool success = true;
|
|
||||||
entityTree->withWriteLock([&] {
|
|
||||||
EntityItemPointer entity = entityTree->addEntity(id, entityProperties);
|
|
||||||
if (entity) {
|
|
||||||
if (entityProperties.queryAACubeRelatedPropertyChanged()) {
|
|
||||||
// due to parenting, the server may not know where something is in world-space, so include the bounding cube.
|
|
||||||
bool success;
|
|
||||||
AACube queryAACube = entity->getQueryAACube(success);
|
|
||||||
if (success) {
|
|
||||||
entityProperties.setQueryAACube(queryAACube);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->setLastBroadcast(usecTimestampNow());
|
|
||||||
// since we're creating this object we will immediately volunteer to own its simulation
|
|
||||||
entity->flagForOwnershipBid(VOLUNTEER_SIMULATION_PRIORITY);
|
|
||||||
entityProperties.setLastEdited(entity->getLastEdited());
|
|
||||||
} else {
|
|
||||||
qCDebug(entities) << "AvatarEntitiesBookmark failed to add new Entity to local Octree";
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
entityPacketSender->queueEditEntityMessage(PacketType::EntityAdd, entityTree, id, entityProperties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AvatarEntitiesBookmarks::AvatarEntitiesBookmarks() {
|
|
||||||
_bookmarksFilename = PathUtils::getAppDataPath() + "/" + AVATAR_ENTITIES_BOOKMARKS_FILENAME;
|
|
||||||
Bookmarks::readFromFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarEntitiesBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
|
||||||
auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkAvatarEntities);
|
|
||||||
QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(addBookmark()), Qt::QueuedConnection);
|
|
||||||
_bookmarksMenu = menu->addMenu(MenuOption::AvatarEntitiesBookmarks);
|
|
||||||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteAvatarEntitiesBookmark);
|
|
||||||
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
|
|
||||||
|
|
||||||
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it) {
|
|
||||||
addBookmarkToMenu(menubar, it.key(), it.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarEntitiesBookmarks::applyBookmarkedAvatarEntities() {
|
|
||||||
QAction* action = qobject_cast<QAction*>(sender());
|
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
|
||||||
|
|
||||||
const QMap<QString, QVariant> bookmark = action->data().toMap();
|
|
||||||
|
|
||||||
if (bookmark.value(ENTRY_VERSION) == AVATAR_ENTITIES_BOOKMARK_VERSION) {
|
|
||||||
myAvatar->removeAvatarEntities();
|
|
||||||
const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString();
|
|
||||||
myAvatar->useFullAvatarURL(avatarUrl);
|
|
||||||
const QVariantList& avatarEntities = bookmark.value(ENTRY_AVATAR_ENTITIES, QVariantList()).toList();
|
|
||||||
addAvatarEntities(avatarEntities);
|
|
||||||
const float& avatarScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat();
|
|
||||||
myAvatar->setAvatarScale(avatarScale);
|
|
||||||
} else {
|
|
||||||
qCDebug(interfaceapp) << " Bookmark entry does not match client version, make sure client has a handler for the new AvatarEntitiesBookmark";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarEntitiesBookmarks::addBookmark() {
|
|
||||||
ModalDialogListener* dlg = OffscreenUi::getTextAsync(OffscreenUi::ICON_PLACEMARK, "Bookmark Avatar Entities", "Name", QString());
|
|
||||||
connect(dlg, &ModalDialogListener::response, this, [=] (QVariant response) {
|
|
||||||
disconnect(dlg, &ModalDialogListener::response, this, nullptr);
|
|
||||||
auto bookmarkName = response.toString();
|
|
||||||
bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
|
|
||||||
if (bookmarkName.length() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
|
||||||
|
|
||||||
const QString& avatarUrl = myAvatar->getSkeletonModelURL().toString();
|
|
||||||
const QVariant& avatarScale = myAvatar->getAvatarScale();
|
|
||||||
|
|
||||||
QVariantMap bookmark;
|
|
||||||
bookmark.insert(ENTRY_VERSION, AVATAR_ENTITIES_BOOKMARK_VERSION);
|
|
||||||
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
|
||||||
bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale);
|
|
||||||
bookmark.insert(ENTRY_AVATAR_ENTITIES, myAvatar->getAvatarEntitiesVariant());
|
|
||||||
|
|
||||||
Bookmarks::addBookmarkToFile(bookmarkName, bookmark);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarEntitiesBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) {
|
|
||||||
QAction* changeAction = _bookmarksMenu->newAction();
|
|
||||||
changeAction->setData(bookmark);
|
|
||||||
connect(changeAction, SIGNAL(triggered()), this, SLOT(applyBookmarkedAvatarEntities()));
|
|
||||||
if (!_isMenuSorted) {
|
|
||||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole);
|
|
||||||
} else {
|
|
||||||
// TODO: this is aggressive but other alternatives have proved less fruitful so far.
|
|
||||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole);
|
|
||||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
//
|
|
||||||
// AvatarEntitiesBookmarks.h
|
|
||||||
// interface/src
|
|
||||||
//
|
|
||||||
// Created by Dante Ruiz on 15/01/18.
|
|
||||||
// Copyright 2018 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_AvatarEntitiesBookmarks_h
|
|
||||||
#define hifi_AvatarEntitiesBookmarks_h
|
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
|
||||||
#include "Bookmarks.h"
|
|
||||||
|
|
||||||
class AvatarEntitiesBookmarks: public Bookmarks, public Dependency {
|
|
||||||
Q_OBJECT
|
|
||||||
SINGLETON_DEPENDENCY
|
|
||||||
|
|
||||||
public:
|
|
||||||
AvatarEntitiesBookmarks();
|
|
||||||
void setupMenus(Menu* menubar, MenuWrapper* menu) override;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void addBookmark();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void addBookmarkToMenu(Menu* menubar, const QString& name, const QVariant& bookmark) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const QString AVATAR_ENTITIES_BOOKMARKS_FILENAME = "AvatarEntitiesBookmarks.json";
|
|
||||||
const QString ENTRY_AVATAR_URL = "AvatarUrl";
|
|
||||||
const QString ENTRY_AVATAR_SCALE = "AvatarScale";
|
|
||||||
const QString ENTRY_AVATAR_ENTITIES = "AvatarEntities";
|
|
||||||
const QString ENTRY_VERSION = "version";
|
|
||||||
|
|
||||||
const int AVATAR_ENTITIES_BOOKMARK_VERSION = 1;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void applyBookmarkedAvatarEntities();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include "audio/AudioScope.h"
|
#include "audio/AudioScope.h"
|
||||||
#include "avatar/AvatarManager.h"
|
#include "avatar/AvatarManager.h"
|
||||||
#include "AvatarBookmarks.h"
|
#include "AvatarBookmarks.h"
|
||||||
#include "AvatarEntitiesBookmarks.h"
|
|
||||||
#include "devices/DdeFaceTracker.h"
|
#include "devices/DdeFaceTracker.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "render/DrawStatus.h"
|
#include "render/DrawStatus.h"
|
||||||
|
@ -44,6 +43,7 @@
|
||||||
#include "ui/StandAloneJSConsole.h"
|
#include "ui/StandAloneJSConsole.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
#include "LocationBookmarks.h"
|
#include "LocationBookmarks.h"
|
||||||
|
#include "DeferredLightingEffect.h"
|
||||||
|
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||||
#include "SpeechRecognizer.h"
|
#include "SpeechRecognizer.h"
|
||||||
|
@ -207,10 +207,6 @@ Menu::Menu() {
|
||||||
auto avatarBookmarks = DependencyManager::get<AvatarBookmarks>();
|
auto avatarBookmarks = DependencyManager::get<AvatarBookmarks>();
|
||||||
avatarBookmarks->setupMenus(this, avatarMenu);
|
avatarBookmarks->setupMenus(this, avatarMenu);
|
||||||
|
|
||||||
auto avatarEntitiesBookmarks = DependencyManager::get<AvatarEntitiesBookmarks>();
|
|
||||||
avatarEntitiesBookmarks->setupMenus(this, avatarMenu);
|
|
||||||
|
|
||||||
|
|
||||||
// Display menu ----------------------------------
|
// Display menu ----------------------------------
|
||||||
// FIXME - this is not yet matching Alan's spec because it doesn't have
|
// FIXME - this is not yet matching Alan's spec because it doesn't have
|
||||||
// menus for "2D"/"3D" - we need to add support for detecting the appropriate
|
// menus for "2D"/"3D" - we need to add support for detecting the appropriate
|
||||||
|
@ -366,10 +362,15 @@ Menu::Menu() {
|
||||||
MenuWrapper* developerMenu = addMenu("Developer", "Developer");
|
MenuWrapper* developerMenu = addMenu("Developer", "Developer");
|
||||||
|
|
||||||
// Developer > Graphics...
|
// Developer > Graphics...
|
||||||
action = addActionToQMenuAndActionHash(developerMenu, "Graphics...");
|
MenuWrapper* graphicsOptionsMenu = developerMenu->addMenu("Render");
|
||||||
connect(action, &QAction::triggered, [] {
|
action = addCheckableActionToQMenuAndActionHash(graphicsOptionsMenu, MenuOption::Shadows, 0, true);
|
||||||
qApp->showDialog(QString("hifi/dialogs/GraphicsPreferencesDialog.qml"),
|
connect(action, &QAction::triggered, [action] {
|
||||||
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
|
DependencyManager::get<DeferredLightingEffect>()->setShadowMapEnabled(action->isChecked());
|
||||||
|
});
|
||||||
|
|
||||||
|
action = addCheckableActionToQMenuAndActionHash(graphicsOptionsMenu, MenuOption::AmbientOcclusion, 0, false);
|
||||||
|
connect(action, &QAction::triggered, [action] {
|
||||||
|
DependencyManager::get<DeferredLightingEffect>()->setAmbientOcclusionEnabled(action->isChecked());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Developer > UI >>>
|
// Developer > UI >>>
|
||||||
|
@ -713,6 +714,7 @@ Menu::Menu() {
|
||||||
MenuWrapper* crashMenu = developerMenu->addMenu("Crash");
|
MenuWrapper* crashMenu = developerMenu->addMenu("Crash");
|
||||||
|
|
||||||
addActionToQMenuAndActionHash(crashMenu, MenuOption::DeadlockInterface, 0, qApp, SLOT(deadlockApplication()));
|
addActionToQMenuAndActionHash(crashMenu, MenuOption::DeadlockInterface, 0, qApp, SLOT(deadlockApplication()));
|
||||||
|
addActionToQMenuAndActionHash(crashMenu, MenuOption::UnresponsiveInterface, 0, qApp, SLOT(unresponsiveApplication()));
|
||||||
|
|
||||||
action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashPureVirtualFunction);
|
action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashPureVirtualFunction);
|
||||||
connect(action, &QAction::triggered, qApp, []() { crash::pureVirtualCall(); });
|
connect(action, &QAction::triggered, qApp, []() { crash::pureVirtualCall(); });
|
||||||
|
|
|
@ -46,7 +46,6 @@ namespace MenuOption {
|
||||||
const QString AutoMuteAudio = "Auto Mute Microphone";
|
const QString AutoMuteAudio = "Auto Mute Microphone";
|
||||||
const QString AvatarReceiveStats = "Show Receive Stats";
|
const QString AvatarReceiveStats = "Show Receive Stats";
|
||||||
const QString AvatarBookmarks = "Avatar Bookmarks";
|
const QString AvatarBookmarks = "Avatar Bookmarks";
|
||||||
const QString AvatarEntitiesBookmarks = "Avatar Entities Bookmarks";
|
|
||||||
const QString Back = "Back";
|
const QString Back = "Back";
|
||||||
const QString BinaryEyelidControl = "Binary Eyelid Control";
|
const QString BinaryEyelidControl = "Binary Eyelid Control";
|
||||||
const QString BookmarkAvatar = "Bookmark Avatar";
|
const QString BookmarkAvatar = "Bookmark Avatar";
|
||||||
|
@ -77,6 +76,7 @@ namespace MenuOption {
|
||||||
const QString CrashNewFault = "New Fault";
|
const QString CrashNewFault = "New Fault";
|
||||||
const QString CrashNewFaultThreaded = "New Fault (threaded)";
|
const QString CrashNewFaultThreaded = "New Fault (threaded)";
|
||||||
const QString DeadlockInterface = "Deadlock Interface";
|
const QString DeadlockInterface = "Deadlock Interface";
|
||||||
|
const QString UnresponsiveInterface = "Unresponsive Interface";
|
||||||
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
||||||
const QString DefaultSkybox = "Default Skybox";
|
const QString DefaultSkybox = "Default Skybox";
|
||||||
const QString DeleteAvatarBookmark = "Delete Avatar Bookmark...";
|
const QString DeleteAvatarBookmark = "Delete Avatar Bookmark...";
|
||||||
|
@ -204,6 +204,8 @@ namespace MenuOption {
|
||||||
const QString WorldAxes = "World Axes";
|
const QString WorldAxes = "World Axes";
|
||||||
const QString DesktopTabletToToolbar = "Desktop Tablet Becomes Toolbar";
|
const QString DesktopTabletToToolbar = "Desktop Tablet Becomes Toolbar";
|
||||||
const QString HMDTabletToToolbar = "HMD Tablet Becomes Toolbar";
|
const QString HMDTabletToToolbar = "HMD Tablet Becomes Toolbar";
|
||||||
|
const QString Shadows = "Shadows";
|
||||||
|
const QString AmbientOcclusion = "AmbientOcclusion";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // hifi_Menu_h
|
#endif // hifi_Menu_h
|
||||||
|
|
|
@ -1112,6 +1112,7 @@ void MyAvatar::setEnableDebugDrawIKChains(bool isEnabled) {
|
||||||
|
|
||||||
void MyAvatar::setEnableMeshVisible(bool isEnabled) {
|
void MyAvatar::setEnableMeshVisible(bool isEnabled) {
|
||||||
_skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true);
|
_skeletonModel->setVisibleInScene(isEnabled, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true);
|
||||||
|
_skeletonModel->setCanCastShadow(isEnabled, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::setEnableInverseKinematics(bool isEnabled) {
|
void MyAvatar::setEnableInverseKinematics(bool isEnabled) {
|
||||||
|
@ -1464,6 +1465,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
int skeletonModelChangeCount = _skeletonModelChangeCount;
|
int skeletonModelChangeCount = _skeletonModelChangeCount;
|
||||||
Avatar::setSkeletonModelURL(skeletonModelURL);
|
Avatar::setSkeletonModelURL(skeletonModelURL);
|
||||||
_skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true);
|
_skeletonModel->setVisibleInScene(true, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true);
|
||||||
|
_skeletonModel->setCanCastShadow(true, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true);
|
||||||
_headBoneSet.clear();
|
_headBoneSet.clear();
|
||||||
_cauterizationNeedsUpdate = true;
|
_cauterizationNeedsUpdate = true;
|
||||||
|
|
||||||
|
@ -1479,7 +1481,7 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
});
|
});
|
||||||
saveAvatarUrl();
|
saveAvatarUrl();
|
||||||
emit skeletonChanged();
|
emit skeletonChanged();
|
||||||
|
emit skeletonModelURLChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::removeAvatarEntities() {
|
void MyAvatar::removeAvatarEntities() {
|
||||||
|
@ -1819,12 +1821,6 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName,
|
||||||
Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved);
|
Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::setVisibleInSceneIfReady(Model* model, const render::ScenePointer& scene, bool visible) {
|
|
||||||
if (model->isActive() && model->isRenderable()) {
|
|
||||||
model->setVisibleInScene(visible, scene, render::ItemKey::TAG_BITS_NONE, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::initHeadBones() {
|
void MyAvatar::initHeadBones() {
|
||||||
int neckJointIndex = -1;
|
int neckJointIndex = -1;
|
||||||
if (_skeletonModel->isLoaded()) {
|
if (_skeletonModel->isLoaded()) {
|
||||||
|
@ -2014,8 +2010,11 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) {
|
||||||
_attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 ||
|
_attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 ||
|
||||||
_attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 ||
|
_attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 ||
|
||||||
_attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) {
|
_attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) {
|
||||||
|
|
||||||
_attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(),
|
_attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene(),
|
||||||
render::ItemKey::TAG_BITS_NONE, true);
|
render::ItemKey::TAG_BITS_NONE, true);
|
||||||
|
|
||||||
|
_attachmentModels[i]->setCanCastShadow(shouldDrawHead, qApp->getMain3DScene(), render::ItemKey::TAG_BITS_NONE, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -677,8 +677,6 @@ private:
|
||||||
// These are made private for MyAvatar so that you will use the "use" methods instead
|
// These are made private for MyAvatar so that you will use the "use" methods instead
|
||||||
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||||
|
|
||||||
void setVisibleInSceneIfReady(Model* model, const render::ScenePointer& scene, bool visiblity);
|
|
||||||
|
|
||||||
virtual void updatePalms() override {}
|
virtual void updatePalms() override {}
|
||||||
void lateUpdatePalms();
|
void lateUpdatePalms();
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ Handler(balance)
|
||||||
Handler(inventory)
|
Handler(inventory)
|
||||||
Handler(transferHfcToNode)
|
Handler(transferHfcToNode)
|
||||||
Handler(transferHfcToUsername)
|
Handler(transferHfcToUsername)
|
||||||
|
Handler(alreadyOwned)
|
||||||
|
|
||||||
void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, 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>();
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
|
@ -336,3 +337,12 @@ void Ledger::transferHfcToUsername(const QString& hfc_key, const QString& userna
|
||||||
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
|
auto transactionString = transactionDoc.toJson(QJsonDocument::Compact);
|
||||||
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure");
|
signedSend("transaction", transactionString, hfc_key, "transfer_hfc_to_user", "transferHfcToUsernameSuccess", "transferHfcToUsernameFailure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ledger::alreadyOwned(const QString& marketplaceId) {
|
||||||
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
|
QString endpoint = "already_owned";
|
||||||
|
QJsonObject request;
|
||||||
|
request["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys());
|
||||||
|
request["marketplace_item_id"] = marketplaceId;
|
||||||
|
send(endpoint, "alreadyOwnedSuccess", "alreadyOwnedFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, request);
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
void certificateInfo(const QString& certificateId);
|
void certificateInfo(const QString& certificateId);
|
||||||
void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage);
|
void transferHfcToNode(const QString& hfc_key, const QString& nodeID, const int& amount, const QString& optionalMessage);
|
||||||
void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage);
|
void transferHfcToUsername(const QString& hfc_key, const QString& username, const int& amount, const QString& optionalMessage);
|
||||||
|
void alreadyOwned(const QString& marketplaceId);
|
||||||
|
|
||||||
enum CertificateStatus {
|
enum CertificateStatus {
|
||||||
CERTIFICATE_STATUS_UNKNOWN = 0,
|
CERTIFICATE_STATUS_UNKNOWN = 0,
|
||||||
|
@ -55,6 +56,7 @@ signals:
|
||||||
void certificateInfoResult(QJsonObject result);
|
void certificateInfoResult(QJsonObject result);
|
||||||
void transferHfcToNodeResult(QJsonObject result);
|
void transferHfcToNodeResult(QJsonObject result);
|
||||||
void transferHfcToUsernameResult(QJsonObject result);
|
void transferHfcToUsernameResult(QJsonObject result);
|
||||||
|
void alreadyOwnedResult(QJsonObject result);
|
||||||
|
|
||||||
void updateCertificateStatus(const QString& certID, uint certStatus);
|
void updateCertificateStatus(const QString& certID, uint certStatus);
|
||||||
|
|
||||||
|
@ -79,6 +81,8 @@ public slots:
|
||||||
void transferHfcToNodeFailure(QNetworkReply& reply);
|
void transferHfcToNodeFailure(QNetworkReply& reply);
|
||||||
void transferHfcToUsernameSuccess(QNetworkReply& reply);
|
void transferHfcToUsernameSuccess(QNetworkReply& reply);
|
||||||
void transferHfcToUsernameFailure(QNetworkReply& reply);
|
void transferHfcToUsernameFailure(QNetworkReply& reply);
|
||||||
|
void alreadyOwnedSuccess(QNetworkReply& reply);
|
||||||
|
void alreadyOwnedFailure(QNetworkReply& reply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QJsonObject apiResponse(const QString& label, QNetworkReply& reply);
|
QJsonObject apiResponse(const QString& label, QNetworkReply& reply);
|
||||||
|
|
|
@ -10,11 +10,17 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "QmlCommerce.h"
|
#include "QmlCommerce.h"
|
||||||
|
#include "CommerceLogging.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "DependencyManager.h"
|
#include "DependencyManager.h"
|
||||||
#include "Ledger.h"
|
#include "Ledger.h"
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
|
#include <Application.h>
|
||||||
|
#include <UserActivityLogger.h>
|
||||||
|
#include <ScriptEngines.h>
|
||||||
|
#include <ui/TabletScriptingInterface.h>
|
||||||
|
#include "scripting/HMDScriptingInterface.h"
|
||||||
|
|
||||||
QmlCommerce::QmlCommerce() {
|
QmlCommerce::QmlCommerce() {
|
||||||
auto ledger = DependencyManager::get<Ledger>();
|
auto ledger = DependencyManager::get<Ledger>();
|
||||||
|
@ -28,14 +34,18 @@ QmlCommerce::QmlCommerce() {
|
||||||
connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult);
|
connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult);
|
||||||
connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult);
|
connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult);
|
||||||
connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult);
|
connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult);
|
||||||
|
connect(ledger.data(), &Ledger::alreadyOwnedResult, this, &QmlCommerce::alreadyOwnedResult);
|
||||||
connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus);
|
connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus);
|
||||||
connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult);
|
connect(ledger.data(), &Ledger::transferHfcToNodeResult, this, &QmlCommerce::transferHfcToNodeResult);
|
||||||
connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult);
|
connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult);
|
||||||
|
connect(ledger.data(), &Ledger::transferHfcToUsernameResult, this, &QmlCommerce::transferHfcToUsernameResult);
|
||||||
|
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() {
|
connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() {
|
||||||
setPassphrase("");
|
setPassphrase("");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_appsPath = PathUtils::getAppDataPath() + "Apps/";
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlCommerce::getWalletStatus() {
|
void QmlCommerce::getWalletStatus() {
|
||||||
|
@ -163,3 +173,164 @@ void QmlCommerce::transferHfcToUsername(const QString& username, const int& amou
|
||||||
QString key = keys[0];
|
QString key = keys[0];
|
||||||
ledger->transferHfcToUsername(key, username, amount, optionalMessage);
|
ledger->transferHfcToUsername(key, username, amount, optionalMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlCommerce::replaceContentSet(const QString& itemHref) {
|
||||||
|
qApp->replaceDomainContent(itemHref);
|
||||||
|
QJsonObject messageProperties = {
|
||||||
|
{ "status", "SuccessfulRequestToReplaceContent" },
|
||||||
|
{ "content_set_url", itemHref }
|
||||||
|
};
|
||||||
|
UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties);
|
||||||
|
|
||||||
|
emit contentSetChanged(itemHref);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlCommerce::alreadyOwned(const QString& marketplaceId) {
|
||||||
|
auto ledger = DependencyManager::get<Ledger>();
|
||||||
|
ledger->alreadyOwned(marketplaceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlCommerce::getInstalledApps() {
|
||||||
|
QString installedAppsFromMarketplace;
|
||||||
|
QStringList runningScripts = DependencyManager::get<ScriptEngines>()->getRunningScripts();
|
||||||
|
|
||||||
|
QDir directory(_appsPath);
|
||||||
|
QStringList apps = directory.entryList(QStringList("*.app.json"));
|
||||||
|
foreach(QString appFileName, apps) {
|
||||||
|
installedAppsFromMarketplace += appFileName;
|
||||||
|
installedAppsFromMarketplace += ",";
|
||||||
|
QFile appFile(_appsPath + appFileName);
|
||||||
|
if (appFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll());
|
||||||
|
|
||||||
|
appFile.close();
|
||||||
|
|
||||||
|
QJsonObject appFileJsonObject = appFileJsonDocument.object();
|
||||||
|
QString scriptURL = appFileJsonObject["scriptURL"].toString();
|
||||||
|
|
||||||
|
// If the script .app.json is on the user's local disk but the associated script isn't running
|
||||||
|
// for some reason, start that script again.
|
||||||
|
if (!runningScripts.contains(scriptURL)) {
|
||||||
|
if ((DependencyManager::get<ScriptEngines>()->loadScript(scriptURL.trimmed())).isNull()) {
|
||||||
|
qCDebug(commerce) << "Couldn't start script while checking installed apps.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qCDebug(commerce) << "Couldn't open local .app.json file for reading.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return installedAppsFromMarketplace;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlCommerce::installApp(const QString& itemHref) {
|
||||||
|
if (!QDir(_appsPath).exists()) {
|
||||||
|
if (!QDir().mkdir(_appsPath)) {
|
||||||
|
qCDebug(commerce) << "Couldn't make _appsPath directory.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl appHref(itemHref);
|
||||||
|
|
||||||
|
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(this, appHref);
|
||||||
|
|
||||||
|
if (!request) {
|
||||||
|
qCDebug(commerce) << "Couldn't create resource request for app.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(request, &ResourceRequest::finished, this, [=]() {
|
||||||
|
if (request->getResult() != ResourceRequest::Success) {
|
||||||
|
qCDebug(commerce) << "Failed to get .app.json file from remote.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the .app.json to the apps directory inside %AppData%/High Fidelity/Interface
|
||||||
|
auto requestData = request->getData();
|
||||||
|
QFile appFile(_appsPath + "/" + appHref.fileName());
|
||||||
|
if (!appFile.open(QIODevice::WriteOnly)) {
|
||||||
|
qCDebug(commerce) << "Couldn't open local .app.json file for creation.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (appFile.write(requestData) == -1) {
|
||||||
|
qCDebug(commerce) << "Couldn't write to local .app.json file.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Close the file
|
||||||
|
appFile.close();
|
||||||
|
|
||||||
|
// Read from the returned datastream to know what .js to add to Running Scripts
|
||||||
|
QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(requestData);
|
||||||
|
QJsonObject appFileJsonObject = appFileJsonDocument.object();
|
||||||
|
QString scriptUrl = appFileJsonObject["scriptURL"].toString();
|
||||||
|
|
||||||
|
if ((DependencyManager::get<ScriptEngines>()->loadScript(scriptUrl.trimmed())).isNull()) {
|
||||||
|
qCDebug(commerce) << "Couldn't load script.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit appInstalled(itemHref);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
request->send();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlCommerce::uninstallApp(const QString& itemHref) {
|
||||||
|
QUrl appHref(itemHref);
|
||||||
|
|
||||||
|
// Read from the file to know what .js script to stop
|
||||||
|
QFile appFile(_appsPath + "/" + appHref.fileName());
|
||||||
|
if (!appFile.open(QIODevice::ReadOnly)) {
|
||||||
|
qCDebug(commerce) << "Couldn't open local .app.json file for deletion.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll());
|
||||||
|
QJsonObject appFileJsonObject = appFileJsonDocument.object();
|
||||||
|
QString scriptUrl = appFileJsonObject["scriptURL"].toString();
|
||||||
|
|
||||||
|
if (!DependencyManager::get<ScriptEngines>()->stopScript(scriptUrl.trimmed(), false)) {
|
||||||
|
qCDebug(commerce) << "Couldn't stop script.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the .app.json from the filesystem
|
||||||
|
// remove() closes the file first.
|
||||||
|
if (!appFile.remove()) {
|
||||||
|
qCDebug(commerce) << "Couldn't delete local .app.json file.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit appUninstalled(itemHref);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlCommerce::openApp(const QString& itemHref) {
|
||||||
|
QUrl appHref(itemHref);
|
||||||
|
|
||||||
|
// Read from the file to know what .html or .qml document to open
|
||||||
|
QFile appFile(_appsPath + "/" + appHref.fileName());
|
||||||
|
if (!appFile.open(QIODevice::ReadOnly)) {
|
||||||
|
qCDebug(commerce) << "Couldn't open local .app.json file.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QJsonDocument appFileJsonDocument = QJsonDocument::fromJson(appFile.readAll());
|
||||||
|
QJsonObject appFileJsonObject = appFileJsonDocument.object();
|
||||||
|
QString homeUrl = appFileJsonObject["homeURL"].toString();
|
||||||
|
|
||||||
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
|
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
|
||||||
|
if (homeUrl.contains(".qml", Qt::CaseInsensitive)) {
|
||||||
|
tablet->loadQMLSource(homeUrl);
|
||||||
|
} else if (homeUrl.contains(".html", Qt::CaseInsensitive)) {
|
||||||
|
tablet->gotoWebScreen(homeUrl);
|
||||||
|
} else {
|
||||||
|
qCDebug(commerce) << "Attempted to open unknown type of homeURL!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DependencyManager::get<HMDScriptingInterface>()->openTablet();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -42,12 +42,18 @@ signals:
|
||||||
void historyResult(QJsonObject result);
|
void historyResult(QJsonObject result);
|
||||||
void accountResult(QJsonObject result);
|
void accountResult(QJsonObject result);
|
||||||
void certificateInfoResult(QJsonObject result);
|
void certificateInfoResult(QJsonObject result);
|
||||||
|
void alreadyOwnedResult(QJsonObject result);
|
||||||
|
|
||||||
void updateCertificateStatus(const QString& certID, uint certStatus);
|
void updateCertificateStatus(const QString& certID, uint certStatus);
|
||||||
|
|
||||||
void transferHfcToNodeResult(QJsonObject result);
|
void transferHfcToNodeResult(QJsonObject result);
|
||||||
void transferHfcToUsernameResult(QJsonObject result);
|
void transferHfcToUsernameResult(QJsonObject result);
|
||||||
|
|
||||||
|
void contentSetChanged(const QString& contentSetHref);
|
||||||
|
|
||||||
|
void appInstalled(const QString& appHref);
|
||||||
|
void appUninstalled(const QString& appHref);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Q_INVOKABLE void getWalletStatus();
|
Q_INVOKABLE void getWalletStatus();
|
||||||
|
|
||||||
|
@ -68,9 +74,20 @@ protected:
|
||||||
Q_INVOKABLE void account();
|
Q_INVOKABLE void account();
|
||||||
|
|
||||||
Q_INVOKABLE void certificateInfo(const QString& certificateId);
|
Q_INVOKABLE void certificateInfo(const QString& certificateId);
|
||||||
|
Q_INVOKABLE void alreadyOwned(const QString& marketplaceId);
|
||||||
|
|
||||||
Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage);
|
Q_INVOKABLE void transferHfcToNode(const QString& nodeID, const int& amount, const QString& optionalMessage);
|
||||||
Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage);
|
Q_INVOKABLE void transferHfcToUsername(const QString& username, const int& amount, const QString& optionalMessage);
|
||||||
|
|
||||||
|
Q_INVOKABLE void replaceContentSet(const QString& itemHref);
|
||||||
|
|
||||||
|
Q_INVOKABLE QString getInstalledApps();
|
||||||
|
Q_INVOKABLE bool installApp(const QString& appHref);
|
||||||
|
Q_INVOKABLE bool uninstallApp(const QString& appHref);
|
||||||
|
Q_INVOKABLE bool openApp(const QString& appHref);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _appsPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_QmlCommerce_h
|
#endif // hifi_QmlCommerce_h
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include "SceneScriptingInterface.h"
|
#include "SceneScriptingInterface.h"
|
||||||
|
|
||||||
OctreePacketProcessor::OctreePacketProcessor() {
|
OctreePacketProcessor::OctreePacketProcessor() {
|
||||||
|
setObjectName("Octree Packet Processor");
|
||||||
|
|
||||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||||
|
|
||||||
packetReceiver.registerDirectListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
packetReceiver.registerDirectListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
||||||
|
|
|
@ -38,7 +38,7 @@ class AccountServicesScriptingInterface : public QObject {
|
||||||
Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged)
|
Q_PROPERTY(QString username READ getUsername NOTIFY myUsernameChanged)
|
||||||
Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged)
|
Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged)
|
||||||
Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged)
|
Q_PROPERTY(QString findableBy READ getFindableBy WRITE setFindableBy NOTIFY findableByChanged)
|
||||||
Q_PROPERTY(QUrl metaverseServerURL READ getMetaverseServerURL)
|
Q_PROPERTY(QUrl metaverseServerURL READ getMetaverseServerURL CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static AccountServicesScriptingInterface* getInstance();
|
static AccountServicesScriptingInterface* getInstance();
|
||||||
|
|
|
@ -305,6 +305,7 @@ public slots:
|
||||||
* {@link Window.stillSnapshotTaken|stillSnapshotTaken} is emitted; when a still image plus moving images are captured,
|
* {@link Window.stillSnapshotTaken|stillSnapshotTaken} is emitted; when a still image plus moving images are captured,
|
||||||
* {@link Window.processingGifStarted|processingGifStarted} and {@link Window.processingGifCompleted|processingGifCompleted}
|
* {@link Window.processingGifStarted|processingGifStarted} and {@link Window.processingGifCompleted|processingGifCompleted}
|
||||||
* are emitted. The path to store the snapshots and the length of the animated GIF to capture are specified in Settings >
|
* are emitted. The path to store the snapshots and the length of the animated GIF to capture are specified in Settings >
|
||||||
|
* NOTE: to provide a non-default value - all previous parameters must be provided.
|
||||||
* General > Snapshots.
|
* General > Snapshots.
|
||||||
* @function Window.takeSnapshot
|
* @function Window.takeSnapshot
|
||||||
* @param {boolean} notify=true - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken}
|
* @param {boolean} notify=true - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken}
|
||||||
|
@ -314,8 +315,10 @@ public slots:
|
||||||
* @param {number} aspectRatio=0 - The width/height ratio of the snapshot required. If the value is <code>0</code> the
|
* @param {number} aspectRatio=0 - The width/height ratio of the snapshot required. If the value is <code>0</code> the
|
||||||
* full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the
|
* full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the
|
||||||
* dimensions is adjusted in order to match the aspect ratio.
|
* dimensions is adjusted in order to match the aspect ratio.
|
||||||
* @param {string} filename=QString() - If this value is not null then the image will be saved to this filename, with an appended ",jpg".
|
* @param {string} filename="" - If this parameter is not given, the image will be saved as 'hifi-snap-by-<user name>-YYYY-MM-DD_HH-MM-SS'.
|
||||||
* otherwise, the image will be saved as 'hifi-snap-by-<user name>-YYYY-MM-DD_HH-MM-SS'
|
* If this parameter is <code>""</code> then the image will be saved as ".jpg".
|
||||||
|
* Otherwise, the image will be saved to this filename, with an appended ".jpg".
|
||||||
|
*
|
||||||
* @example <caption>Using the snapshot function and signals.</caption>
|
* @example <caption>Using the snapshot function and signals.</caption>
|
||||||
* function onStillSnapshotTaken(path, notify) {
|
* function onStillSnapshotTaken(path, notify) {
|
||||||
* print("Still snapshot taken: " + path);
|
* print("Still snapshot taken: " + path);
|
||||||
|
@ -337,15 +340,18 @@ public slots:
|
||||||
* var notify = true;
|
* var notify = true;
|
||||||
* var animated = true;
|
* var animated = true;
|
||||||
* var aspect = 1920 / 1080;
|
* var aspect = 1920 / 1080;
|
||||||
* var filename = QString();
|
* var filename = "";
|
||||||
* Window.takeSnapshot(notify, animated, aspect, filename);
|
* Window.takeSnapshot(notify, animated, aspect, filename);
|
||||||
*/
|
*/
|
||||||
void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString());
|
void takeSnapshot(bool notify = true, bool includeAnimated = false, float aspectRatio = 0.0f, const QString& filename = QString());
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Takes a still snapshot of the current view from the secondary camera that can be set up through the {@link Render} API.
|
* Takes a still snapshot of the current view from the secondary camera that can be set up through the {@link Render} API.
|
||||||
|
* NOTE: to provide a non-default value - all previous parameters must be provided.
|
||||||
* @function Window.takeSecondaryCameraSnapshot
|
* @function Window.takeSecondaryCameraSnapshot
|
||||||
* @param {string} filename=QString() - If this value is not null then the image will be saved to this filename, with an appended ".jpg"
|
* @param {string} filename="" - If this parameter is not given, the image will be saved as 'hifi-snap-by-<user name>-YYYY-MM-DD_HH-MM-SS'.
|
||||||
|
* If this parameter is <code>""</code> then the image will be saved as ".jpg".
|
||||||
|
* Otherwise, the image will be saved to this filename, with an appended ".jpg".
|
||||||
*
|
*
|
||||||
* var filename = QString();
|
* var filename = QString();
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -373,7 +373,7 @@ class AvatarData : public QObject, public SpatiallyNestable {
|
||||||
// The result is unique among all avatars present at the time.
|
// The result is unique among all avatars present at the time.
|
||||||
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged)
|
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged)
|
||||||
Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
||||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript)
|
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
|
||||||
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)
|
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)
|
||||||
|
|
||||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||||
|
@ -702,6 +702,7 @@ public:
|
||||||
signals:
|
signals:
|
||||||
void displayNameChanged();
|
void displayNameChanged();
|
||||||
void sessionDisplayNameChanged();
|
void sessionDisplayNameChanged();
|
||||||
|
void skeletonModelURLChanged();
|
||||||
void lookAtSnappingChanged(bool enabled);
|
void lookAtSnappingChanged(bool enabled);
|
||||||
void sessionUUIDChanged();
|
void sessionUUIDChanged();
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ ScriptAvatarData::ScriptAvatarData(AvatarSharedPointer avatarData) :
|
||||||
{
|
{
|
||||||
QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged);
|
QObject::connect(avatarData.get(), &AvatarData::displayNameChanged, this, &ScriptAvatarData::displayNameChanged);
|
||||||
QObject::connect(avatarData.get(), &AvatarData::sessionDisplayNameChanged, this, &ScriptAvatarData::sessionDisplayNameChanged);
|
QObject::connect(avatarData.get(), &AvatarData::sessionDisplayNameChanged, this, &ScriptAvatarData::sessionDisplayNameChanged);
|
||||||
|
QObject::connect(avatarData.get(), &AvatarData::skeletonModelURLChanged, this, &ScriptAvatarData::skeletonModelURLChanged);
|
||||||
QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged);
|
QObject::connect(avatarData.get(), &AvatarData::lookAtSnappingChanged, this, &ScriptAvatarData::lookAtSnappingChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ class ScriptAvatarData : public QObject {
|
||||||
//
|
//
|
||||||
// ATTACHMENT AND JOINT PROPERTIES
|
// ATTACHMENT AND JOINT PROPERTIES
|
||||||
//
|
//
|
||||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript)
|
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
|
||||||
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData)
|
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData)
|
||||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||||
|
|
||||||
|
@ -132,6 +132,7 @@ public:
|
||||||
signals:
|
signals:
|
||||||
void displayNameChanged();
|
void displayNameChanged();
|
||||||
void sessionDisplayNameChanged();
|
void sessionDisplayNameChanged();
|
||||||
|
void skeletonModelURLChanged();
|
||||||
void lookAtSnappingChanged(bool enabled);
|
void lookAtSnappingChanged(bool enabled);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -164,7 +164,12 @@ ItemKey EntityRenderer::getKey() {
|
||||||
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
// This allows shapes to cast shadows
|
||||||
|
if (_canCastShadow) {
|
||||||
|
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1).withShadowCaster();
|
||||||
|
} else {
|
||||||
|
return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) {
|
uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) {
|
||||||
|
@ -377,6 +382,7 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa
|
||||||
|
|
||||||
_moving = entity->isMovingRelativeToParent();
|
_moving = entity->isMovingRelativeToParent();
|
||||||
_visible = entity->getVisible();
|
_visible = entity->getVisible();
|
||||||
|
_canCastShadow = entity->getCanCastShadow();
|
||||||
_cauterized = entity->getCauterized();
|
_cauterized = entity->getCauterized();
|
||||||
_needsRenderUpdate = false;
|
_needsRenderUpdate = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -126,6 +126,7 @@ protected:
|
||||||
bool _isFading{ _entitiesShouldFadeFunction() };
|
bool _isFading{ _entitiesShouldFadeFunction() };
|
||||||
bool _prevIsTransparent { false };
|
bool _prevIsTransparent { false };
|
||||||
bool _visible { false };
|
bool _visible { false };
|
||||||
|
bool _canCastShadow { false };
|
||||||
bool _cauterized { false };
|
bool _cauterized { false };
|
||||||
bool _moving { false };
|
bool _moving { false };
|
||||||
bool _needsRenderUpdate { false };
|
bool _needsRenderUpdate { false };
|
||||||
|
|
|
@ -1361,6 +1361,10 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
||||||
}
|
}
|
||||||
// TODO? early exit here when not visible?
|
// TODO? early exit here when not visible?
|
||||||
|
|
||||||
|
if (model->canCastShadow() != _canCastShadow) {
|
||||||
|
model->setCanCastShadow(_canCastShadow, scene, viewTaskBits, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (_needsCollisionGeometryUpdate) {
|
if (_needsCollisionGeometryUpdate) {
|
||||||
setCollisionMeshKey(entity->getCollisionMeshKey());
|
setCollisionMeshKey(entity->getCollisionMeshKey());
|
||||||
_needsCollisionGeometryUpdate = false;
|
_needsCollisionGeometryUpdate = false;
|
||||||
|
|
|
@ -330,6 +330,7 @@ void ZoneEntityRenderer::updateKeySunFromEntity(const TypedEntityPointer& entity
|
||||||
sunLight->setColor(ColorUtils::toVec3(_keyLightProperties.getColor()));
|
sunLight->setColor(ColorUtils::toVec3(_keyLightProperties.getColor()));
|
||||||
sunLight->setIntensity(_keyLightProperties.getIntensity());
|
sunLight->setIntensity(_keyLightProperties.getIntensity());
|
||||||
sunLight->setDirection(entity->getTransform().getRotation() * _keyLightProperties.getDirection());
|
sunLight->setDirection(entity->getTransform().getRotation() * _keyLightProperties.getDirection());
|
||||||
|
sunLight->setCastShadows(_keyLightProperties.getCastShadows());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZoneEntityRenderer::updateAmbientLightFromEntity(const TypedEntityPointer& entity) {
|
void ZoneEntityRenderer::updateAmbientLightFromEntity(const TypedEntityPointer& entity) {
|
||||||
|
|
|
@ -91,6 +91,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
||||||
requestedProperties += PROP_REGISTRATION_POINT;
|
requestedProperties += PROP_REGISTRATION_POINT;
|
||||||
requestedProperties += PROP_ANGULAR_DAMPING;
|
requestedProperties += PROP_ANGULAR_DAMPING;
|
||||||
requestedProperties += PROP_VISIBLE;
|
requestedProperties += PROP_VISIBLE;
|
||||||
|
requestedProperties += PROP_CAN_CAST_SHADOW;
|
||||||
requestedProperties += PROP_COLLISIONLESS;
|
requestedProperties += PROP_COLLISIONLESS;
|
||||||
requestedProperties += PROP_COLLISION_MASK;
|
requestedProperties += PROP_COLLISION_MASK;
|
||||||
requestedProperties += PROP_DYNAMIC;
|
requestedProperties += PROP_DYNAMIC;
|
||||||
|
@ -249,6 +250,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
||||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint());
|
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping());
|
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, getVisible());
|
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, getVisible());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_COLLISIONLESS, getCollisionless());
|
APPEND_ENTITY_PROPERTY(PROP_COLLISIONLESS, getCollisionless());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_MASK, getCollisionMask());
|
APPEND_ENTITY_PROPERTY(PROP_COLLISION_MASK, getCollisionMask());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_DYNAMIC, getDynamic());
|
APPEND_ENTITY_PROPERTY(PROP_DYNAMIC, getDynamic());
|
||||||
|
@ -799,6 +801,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, setAngularDamping);
|
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, setAngularDamping);
|
||||||
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
|
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow);
|
||||||
READ_ENTITY_PROPERTY(PROP_COLLISIONLESS, bool, setCollisionless);
|
READ_ENTITY_PROPERTY(PROP_COLLISIONLESS, bool, setCollisionless);
|
||||||
READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint8_t, setCollisionMask);
|
READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint8_t, setCollisionMask);
|
||||||
READ_ENTITY_PROPERTY(PROP_DYNAMIC, bool, setDynamic);
|
READ_ENTITY_PROPERTY(PROP_DYNAMIC, bool, setDynamic);
|
||||||
|
@ -1234,6 +1237,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularDamping, getAngularDamping);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularDamping, getAngularDamping);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRenderAlpha, getLocalRenderAlpha);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRenderAlpha, getLocalRenderAlpha);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(visible, getVisible);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(visible, getVisible);
|
||||||
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionless, getCollisionless);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionless, getCollisionless);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionMask, getCollisionMask);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionMask, getCollisionMask);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(dynamic, getDynamic);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(dynamic, getDynamic);
|
||||||
|
@ -1346,6 +1350,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
|
||||||
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
||||||
|
|
||||||
// Certifiable Properties
|
// Certifiable Properties
|
||||||
|
@ -2723,6 +2728,28 @@ void EntityItem::setVisible(bool value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntityItem::getCanCastShadow() const {
|
||||||
|
bool result;
|
||||||
|
withReadLock([&] {
|
||||||
|
result = _canCastShadow;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityItem::setCanCastShadow(bool value) {
|
||||||
|
bool changed = false;
|
||||||
|
withWriteLock([&] {
|
||||||
|
if (_canCastShadow != value) {
|
||||||
|
changed = true;
|
||||||
|
_canCastShadow = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
emit requestRenderUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool EntityItem::isChildOfMyAvatar() const {
|
bool EntityItem::isChildOfMyAvatar() const {
|
||||||
QUuid ancestorID = findAncestorOfType(NestableType::Avatar);
|
QUuid ancestorID = findAncestorOfType(NestableType::Avatar);
|
||||||
return !ancestorID.isNull() && (ancestorID == Physics::getSessionUUID() || ancestorID == AVATAR_SELF_ID);
|
return !ancestorID.isNull() && (ancestorID == Physics::getSessionUUID() || ancestorID == AVATAR_SELF_ID);
|
||||||
|
|
|
@ -274,6 +274,10 @@ public:
|
||||||
|
|
||||||
bool getVisible() const;
|
bool getVisible() const;
|
||||||
void setVisible(bool value);
|
void setVisible(bool value);
|
||||||
|
|
||||||
|
bool getCanCastShadow() const;
|
||||||
|
void setCanCastShadow(bool value);
|
||||||
|
|
||||||
inline bool isVisible() const { return getVisible(); }
|
inline bool isVisible() const { return getVisible(); }
|
||||||
inline bool isInvisible() const { return !getVisible(); }
|
inline bool isInvisible() const { return !getVisible(); }
|
||||||
|
|
||||||
|
@ -551,6 +555,7 @@ protected:
|
||||||
glm::vec3 _registrationPoint { ENTITY_ITEM_DEFAULT_REGISTRATION_POINT };
|
glm::vec3 _registrationPoint { ENTITY_ITEM_DEFAULT_REGISTRATION_POINT };
|
||||||
float _angularDamping { ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING };
|
float _angularDamping { ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING };
|
||||||
bool _visible { ENTITY_ITEM_DEFAULT_VISIBLE };
|
bool _visible { ENTITY_ITEM_DEFAULT_VISIBLE };
|
||||||
|
bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW };
|
||||||
bool _collisionless { ENTITY_ITEM_DEFAULT_COLLISIONLESS };
|
bool _collisionless { ENTITY_ITEM_DEFAULT_COLLISIONLESS };
|
||||||
uint8_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT };
|
uint8_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT };
|
||||||
bool _dynamic { ENTITY_ITEM_DEFAULT_DYNAMIC };
|
bool _dynamic { ENTITY_ITEM_DEFAULT_DYNAMIC };
|
||||||
|
|
|
@ -316,6 +316,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
||||||
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
|
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible);
|
CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible);
|
||||||
|
CHECK_PROPERTY_CHANGE(PROP_CAN_CAST_SHADOW, canCastShadow);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_REGISTRATION_POINT, registrationPoint);
|
CHECK_PROPERTY_CHANGE(PROP_REGISTRATION_POINT, registrationPoint);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_ANGULAR_VELOCITY, angularVelocity);
|
CHECK_PROPERTY_CHANGE(PROP_ANGULAR_VELOCITY, angularVelocity);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_ANGULAR_DAMPING, angularDamping);
|
CHECK_PROPERTY_CHANGE(PROP_ANGULAR_DAMPING, angularDamping);
|
||||||
|
@ -490,6 +491,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_VELOCITY, angularVelocity);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_VELOCITY, angularVelocity);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_DAMPING, angularDamping);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ANGULAR_DAMPING, angularDamping);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE, visible);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_VISIBLE, visible);
|
||||||
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CAN_CAST_SHADOW, canCastShadow);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISIONLESS, collisionless);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISIONLESS, collisionless);
|
||||||
COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_COLLISIONLESS, collisionless, ignoreForCollisions, getCollisionless()); // legacy support
|
COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_COLLISIONLESS, collisionless, ignoreForCollisions, getCollisionless()); // legacy support
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISION_MASK, collisionMask);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLLISION_MASK, collisionMask);
|
||||||
|
@ -751,6 +753,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, glmVec3, setAngularVelocity);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularVelocity, glmVec3, setAngularVelocity);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularDamping, float, setAngularDamping);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(angularDamping, float, setAngularDamping);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(visible, bool, setVisible);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(visible, bool, setVisible);
|
||||||
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(canCastShadow, bool, setCanCastShadow);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(color, xColor, setColor);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(color, xColor, setColor);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(colorSpread, xColor, setColorSpread);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(colorSpread, xColor, setColorSpread);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(colorStart, xColor, setColorStart);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(colorStart, xColor, setColorStart);
|
||||||
|
@ -922,6 +925,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
|
||||||
COPY_PROPERTY_IF_CHANGED(angularVelocity);
|
COPY_PROPERTY_IF_CHANGED(angularVelocity);
|
||||||
COPY_PROPERTY_IF_CHANGED(angularDamping);
|
COPY_PROPERTY_IF_CHANGED(angularDamping);
|
||||||
COPY_PROPERTY_IF_CHANGED(visible);
|
COPY_PROPERTY_IF_CHANGED(visible);
|
||||||
|
COPY_PROPERTY_IF_CHANGED(canCastShadow);
|
||||||
COPY_PROPERTY_IF_CHANGED(color);
|
COPY_PROPERTY_IF_CHANGED(color);
|
||||||
COPY_PROPERTY_IF_CHANGED(colorSpread);
|
COPY_PROPERTY_IF_CHANGED(colorSpread);
|
||||||
COPY_PROPERTY_IF_CHANGED(colorStart);
|
COPY_PROPERTY_IF_CHANGED(colorStart);
|
||||||
|
@ -1094,6 +1098,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
||||||
|
|
||||||
std::call_once(initMap, [](){
|
std::call_once(initMap, [](){
|
||||||
ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool);
|
ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool);
|
||||||
|
ADD_PROPERTY_TO_MAP(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool);
|
||||||
ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3);
|
ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3);
|
||||||
ADD_PROPERTY_TO_MAP(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3);
|
ADD_PROPERTY_TO_MAP(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3);
|
||||||
ADD_PROPERTY_TO_MAP(PROP_ROTATION, Rotation, rotation, glm::quat);
|
ADD_PROPERTY_TO_MAP(PROP_ROTATION, Rotation, rotation, glm::quat);
|
||||||
|
@ -1187,6 +1192,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
||||||
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor);
|
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor);
|
||||||
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float);
|
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_INTENSITY, KeyLightIntensity, keyLightIntensity, float);
|
||||||
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3);
|
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_DIRECTION, KeyLightDirection, keyLightDirection, glm::vec3);
|
||||||
|
ADD_PROPERTY_TO_MAP(PROP_KEYLIGHT_CAST_SHADOW, KeyLightCastShadows, keyLightCastShadows, bool);
|
||||||
|
|
||||||
ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3);
|
ADD_PROPERTY_TO_MAP(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3);
|
||||||
ADD_PROPERTY_TO_MAP(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray);
|
ADD_PROPERTY_TO_MAP(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray);
|
||||||
ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t);
|
ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t);
|
||||||
|
@ -1412,6 +1419,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, properties.getAngularVelocity());
|
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, properties.getAngularVelocity());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, properties.getAngularDamping());
|
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, properties.getAngularDamping());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, properties.getVisible());
|
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, properties.getVisible());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, properties.getCanCastShadow());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_COLLISIONLESS, properties.getCollisionless());
|
APPEND_ENTITY_PROPERTY(PROP_COLLISIONLESS, properties.getCollisionless());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_MASK, properties.getCollisionMask());
|
APPEND_ENTITY_PROPERTY(PROP_COLLISION_MASK, properties.getCollisionMask());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_DYNAMIC, properties.getDynamic());
|
APPEND_ENTITY_PROPERTY(PROP_DYNAMIC, properties.getDynamic());
|
||||||
|
@ -1784,6 +1792,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_VELOCITY, glm::vec3, setAngularVelocity);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_VELOCITY, glm::vec3, setAngularVelocity);
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_DAMPING, float, setAngularDamping);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANGULAR_DAMPING, float, setAngularDamping);
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible);
|
||||||
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow);
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONLESS, bool, setCollisionless);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONLESS, bool, setCollisionless);
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint8_t, setCollisionMask);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint8_t, setCollisionMask);
|
||||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DYNAMIC, bool, setDynamic);
|
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DYNAMIC, bool, setDynamic);
|
||||||
|
@ -2053,6 +2062,7 @@ void EntityItemProperties::markAllChanged() {
|
||||||
_angularDampingChanged = true;
|
_angularDampingChanged = true;
|
||||||
_nameChanged = true;
|
_nameChanged = true;
|
||||||
_visibleChanged = true;
|
_visibleChanged = true;
|
||||||
|
_canCastShadowChanged = true;
|
||||||
_colorChanged = true;
|
_colorChanged = true;
|
||||||
_alphaChanged = true;
|
_alphaChanged = true;
|
||||||
_modelURLChanged = true;
|
_modelURLChanged = true;
|
||||||
|
@ -2250,6 +2260,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
||||||
if (visibleChanged()) {
|
if (visibleChanged()) {
|
||||||
out += "visible";
|
out += "visible";
|
||||||
}
|
}
|
||||||
|
if (canCastShadowChanged()) {
|
||||||
|
out += "canCastShadow";
|
||||||
|
}
|
||||||
if (rotationChanged()) {
|
if (rotationChanged()) {
|
||||||
out += "rotation";
|
out += "rotation";
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,7 @@ public:
|
||||||
// bool _fooChanged { false };
|
// bool _fooChanged { false };
|
||||||
|
|
||||||
DEFINE_PROPERTY(PROP_VISIBLE, Visible, visible, bool, ENTITY_ITEM_DEFAULT_VISIBLE);
|
DEFINE_PROPERTY(PROP_VISIBLE, Visible, visible, bool, ENTITY_ITEM_DEFAULT_VISIBLE);
|
||||||
|
DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW);
|
||||||
DEFINE_PROPERTY_REF_WITH_SETTER(PROP_POSITION, Position, position, glm::vec3, ENTITY_ITEM_ZERO_VEC3);
|
DEFINE_PROPERTY_REF_WITH_SETTER(PROP_POSITION, Position, position, glm::vec3, ENTITY_ITEM_ZERO_VEC3);
|
||||||
DEFINE_PROPERTY_REF(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3, ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
DEFINE_PROPERTY_REF(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3, ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
||||||
DEFINE_PROPERTY_REF(PROP_ROTATION, Rotation, rotation, glm::quat, ENTITY_ITEM_DEFAULT_ROTATION);
|
DEFINE_PROPERTY_REF(PROP_ROTATION, Rotation, rotation, glm::quat, ENTITY_ITEM_DEFAULT_ROTATION);
|
||||||
|
@ -426,6 +427,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Velocity, velocity, "in meters");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Velocity, velocity, "in meters");
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Name, name, "");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Name, name, "");
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Visible, visible, "");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Visible, visible, "");
|
||||||
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CanCastShadow, canCastShadow, "");
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Rotation, rotation, "");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Rotation, rotation, "");
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Density, density, "");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Density, density, "");
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Gravity, gravity, "");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Gravity, gravity, "");
|
||||||
|
|
|
@ -46,6 +46,7 @@ const quint32 ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION = 0;
|
||||||
const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f;
|
const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f;
|
||||||
const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f;
|
const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f;
|
||||||
const bool ENTITY_ITEM_DEFAULT_VISIBLE = true;
|
const bool ENTITY_ITEM_DEFAULT_VISIBLE = true;
|
||||||
|
const bool ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW { true };
|
||||||
|
|
||||||
const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString("");
|
const QString ENTITY_ITEM_DEFAULT_SCRIPT = QString("");
|
||||||
const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0;
|
const quint64 ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP = 0;
|
||||||
|
|
|
@ -20,6 +20,7 @@ enum EntityPropertyList {
|
||||||
|
|
||||||
// these properties are supported by the EntityItem base class
|
// these properties are supported by the EntityItem base class
|
||||||
PROP_VISIBLE,
|
PROP_VISIBLE,
|
||||||
|
PROP_CAN_CAST_SHADOW,
|
||||||
PROP_POSITION,
|
PROP_POSITION,
|
||||||
PROP_DIMENSIONS,
|
PROP_DIMENSIONS,
|
||||||
PROP_ROTATION,
|
PROP_ROTATION,
|
||||||
|
@ -205,6 +206,11 @@ enum EntityPropertyList {
|
||||||
|
|
||||||
PROP_HAZE_MODE,
|
PROP_HAZE_MODE,
|
||||||
|
|
||||||
|
PROP_KEYLIGHT_COLOR,
|
||||||
|
PROP_KEYLIGHT_INTENSITY,
|
||||||
|
PROP_KEYLIGHT_DIRECTION,
|
||||||
|
PROP_KEYLIGHT_CAST_SHADOW,
|
||||||
|
|
||||||
PROP_HAZE_RANGE,
|
PROP_HAZE_RANGE,
|
||||||
PROP_HAZE_COLOR,
|
PROP_HAZE_COLOR,
|
||||||
PROP_HAZE_GLARE_COLOR,
|
PROP_HAZE_GLARE_COLOR,
|
||||||
|
@ -254,10 +260,6 @@ enum EntityPropertyList {
|
||||||
// Aliases/Piggyback properties for Zones. These properties intentionally reuse the enum values for
|
// Aliases/Piggyback properties for Zones. These properties intentionally reuse the enum values for
|
||||||
// other properties which will never overlap with each other. We do this so that we don't have to expand
|
// other properties which will never overlap with each other. We do this so that we don't have to expand
|
||||||
// the size of the properties bitflags mask
|
// the size of the properties bitflags mask
|
||||||
PROP_KEYLIGHT_COLOR = PROP_COLOR,
|
|
||||||
PROP_KEYLIGHT_INTENSITY = PROP_INTENSITY,
|
|
||||||
PROP_KEYLIGHT_DIRECTION = PROP_EXPONENT,
|
|
||||||
|
|
||||||
PROP_SKYBOX_COLOR = PROP_ANIMATION_URL,
|
PROP_SKYBOX_COLOR = PROP_ANIMATION_URL,
|
||||||
PROP_SKYBOX_URL = PROP_ANIMATION_FPS,
|
PROP_SKYBOX_URL = PROP_ANIMATION_FPS,
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,11 @@ bool EntityScriptingInterface::canWriteAssets() {
|
||||||
return nodeList->getThisNodeCanWriteAssets();
|
return nodeList->getThisNodeCanWriteAssets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntityScriptingInterface::canReplaceContent() {
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
return nodeList->getThisNodeCanReplaceContent();
|
||||||
|
}
|
||||||
|
|
||||||
void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {
|
void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) {
|
||||||
if (_entityTree) {
|
if (_entityTree) {
|
||||||
disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity);
|
disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity);
|
||||||
|
|
|
@ -144,6 +144,12 @@ public slots:
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE bool canWriteAssets();
|
Q_INVOKABLE bool canWriteAssets();
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @function Entities.canReplaceContent
|
||||||
|
* @return {bool} `true` if the DomainServer will allow this Node/Avatar to replace the domain's content set
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE bool canReplaceContent();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Add a new entity with the specified properties. If `clientOnly` is true, the entity will
|
* Add a new entity with the specified properties. If `clientOnly` is true, the entity will
|
||||||
* not be sent to the server and will only be visible/accessible on the local client.
|
* not be sent to the server and will only be visible/accessible on the local client.
|
||||||
|
|
|
@ -97,6 +97,7 @@ EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const
|
||||||
auto mutableProperties = properties;
|
auto mutableProperties = properties;
|
||||||
mutableProperties.markAllChanged();
|
mutableProperties.markAllChanged();
|
||||||
newEntityItem = factory(entityID, mutableProperties);
|
newEntityItem = factory(entityID, mutableProperties);
|
||||||
|
newEntityItem->moveToThread(qApp->thread());
|
||||||
}
|
}
|
||||||
return newEntityItem;
|
return newEntityItem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ const xColor KeyLightPropertyGroup::DEFAULT_KEYLIGHT_COLOR = { 255, 255, 255 };
|
||||||
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_INTENSITY = 1.0f;
|
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_INTENSITY = 1.0f;
|
||||||
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY = 0.5f;
|
const float KeyLightPropertyGroup::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY = 0.5f;
|
||||||
const glm::vec3 KeyLightPropertyGroup::DEFAULT_KEYLIGHT_DIRECTION = { 0.0f, -1.0f, 0.0f };
|
const glm::vec3 KeyLightPropertyGroup::DEFAULT_KEYLIGHT_DIRECTION = { 0.0f, -1.0f, 0.0f };
|
||||||
|
const bool KeyLightPropertyGroup::DEFAULT_KEYLIGHT_CAST_SHADOWS { false };
|
||||||
|
|
||||||
void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties,
|
void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties,
|
||||||
QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
|
||||||
|
@ -28,23 +29,27 @@ void KeyLightPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desired
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_COLOR, KeyLight, keyLight, Color, color);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_COLOR, KeyLight, keyLight, Color, color);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_INTENSITY, KeyLight, keyLight, Intensity, intensity);
|
||||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_DIRECTION, KeyLight, keyLight, Direction, direction);
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_DIRECTION, KeyLight, keyLight, Direction, direction);
|
||||||
|
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_KEYLIGHT_CAST_SHADOW, KeyLight, keyLight, CastShadows, castShadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
void KeyLightPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) {
|
||||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, color, xColor, setColor);
|
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, color, xColor, setColor);
|
||||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, intensity, float, setIntensity);
|
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, intensity, float, setIntensity);
|
||||||
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, direction, glmVec3, setDirection);
|
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, direction, glmVec3, setDirection);
|
||||||
|
COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(keyLight, castShadows, bool, setCastShadows);
|
||||||
|
|
||||||
// legacy property support
|
// legacy property support
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightColor, xColor, setColor, getColor);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightColor, xColor, setColor, getColor);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightIntensity, float, setIntensity, getIntensity);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightIntensity, float, setIntensity, getIntensity);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightDirection, glmVec3, setDirection, getDirection);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightDirection, glmVec3, setDirection, getDirection);
|
||||||
|
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(keyLightCastShadows, bool, setCastShadows, getCastShadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyLightPropertyGroup::merge(const KeyLightPropertyGroup& other) {
|
void KeyLightPropertyGroup::merge(const KeyLightPropertyGroup& other) {
|
||||||
COPY_PROPERTY_IF_CHANGED(color);
|
COPY_PROPERTY_IF_CHANGED(color);
|
||||||
COPY_PROPERTY_IF_CHANGED(intensity);
|
COPY_PROPERTY_IF_CHANGED(intensity);
|
||||||
COPY_PROPERTY_IF_CHANGED(direction);
|
COPY_PROPERTY_IF_CHANGED(direction);
|
||||||
|
COPY_PROPERTY_IF_CHANGED(castShadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyLightPropertyGroup::debugDump() const {
|
void KeyLightPropertyGroup::debugDump() const {
|
||||||
|
@ -52,6 +57,7 @@ void KeyLightPropertyGroup::debugDump() const {
|
||||||
qCDebug(entities) << " color:" << getColor(); // << "," << getColor()[1] << "," << getColor()[2];
|
qCDebug(entities) << " color:" << getColor(); // << "," << getColor()[1] << "," << getColor()[2];
|
||||||
qCDebug(entities) << " intensity:" << getIntensity();
|
qCDebug(entities) << " intensity:" << getIntensity();
|
||||||
qCDebug(entities) << " direction:" << getDirection();
|
qCDebug(entities) << " direction:" << getDirection();
|
||||||
|
qCDebug(entities) << " castShadows:" << getCastShadows();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyLightPropertyGroup::listChangedProperties(QList<QString>& out) {
|
void KeyLightPropertyGroup::listChangedProperties(QList<QString>& out) {
|
||||||
|
@ -64,6 +70,9 @@ void KeyLightPropertyGroup::listChangedProperties(QList<QString>& out) {
|
||||||
if (directionChanged()) {
|
if (directionChanged()) {
|
||||||
out << "keyLight-direction";
|
out << "keyLight-direction";
|
||||||
}
|
}
|
||||||
|
if (castShadowsChanged()) {
|
||||||
|
out << "keyLight-castShadows";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
|
bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
|
||||||
|
@ -71,19 +80,21 @@ bool KeyLightPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
|
||||||
EntityPropertyFlags& propertyFlags,
|
EntityPropertyFlags& propertyFlags,
|
||||||
EntityPropertyFlags& propertiesDidntFit,
|
EntityPropertyFlags& propertiesDidntFit,
|
||||||
int& propertyCount,
|
int& propertyCount,
|
||||||
OctreeElement::AppendState& appendState) const {
|
OctreeElement::AppendState& appendState) const
|
||||||
|
{
|
||||||
|
|
||||||
bool successPropertyFits = true;
|
bool successPropertyFits = true;
|
||||||
|
|
||||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, getColor());
|
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, getColor());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity());
|
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection());
|
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt,
|
bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt,
|
||||||
int& processedBytes) {
|
int& processedBytes) {
|
||||||
|
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
bool overwriteLocalData = true;
|
bool overwriteLocalData = true;
|
||||||
|
@ -92,11 +103,13 @@ bool KeyLightPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFl
|
||||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, xColor, setColor);
|
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, xColor, setColor);
|
||||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity);
|
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity);
|
||||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection);
|
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows);
|
||||||
|
|
||||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_COLOR, Color);
|
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_COLOR, Color);
|
||||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_INTENSITY, Intensity);
|
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_INTENSITY, Intensity);
|
||||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_DIRECTION, Direction);
|
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_DIRECTION, Direction);
|
||||||
|
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_KEYLIGHT_CAST_SHADOW, CastShadows);
|
||||||
|
|
||||||
processedBytes += bytesRead;
|
processedBytes += bytesRead;
|
||||||
|
|
||||||
Q_UNUSED(somethingChanged);
|
Q_UNUSED(somethingChanged);
|
||||||
|
@ -108,6 +121,7 @@ void KeyLightPropertyGroup::markAllChanged() {
|
||||||
_colorChanged = true;
|
_colorChanged = true;
|
||||||
_intensityChanged = true;
|
_intensityChanged = true;
|
||||||
_directionChanged = true;
|
_directionChanged = true;
|
||||||
|
_castShadowsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const {
|
EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const {
|
||||||
|
@ -116,7 +130,8 @@ EntityPropertyFlags KeyLightPropertyGroup::getChangedProperties() const {
|
||||||
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_COLOR, color);
|
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_COLOR, color);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, intensity);
|
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, intensity);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, direction);
|
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_DIRECTION, direction);
|
||||||
|
CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_CAST_SHADOW, castShadows);
|
||||||
|
|
||||||
return changedProperties;
|
return changedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +139,7 @@ void KeyLightPropertyGroup::getProperties(EntityItemProperties& properties) cons
|
||||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Color, getColor);
|
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Color, getColor);
|
||||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Intensity, getIntensity);
|
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Intensity, getIntensity);
|
||||||
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Direction, getDirection);
|
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, Direction, getDirection);
|
||||||
|
COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(KeyLight, CastShadows, getCastShadows);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties) {
|
bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties) {
|
||||||
|
@ -132,6 +148,7 @@ bool KeyLightPropertyGroup::setProperties(const EntityItemProperties& properties
|
||||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Color, color, setColor);
|
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Color, color, setColor);
|
||||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Intensity, intensity, setIntensity);
|
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Intensity, intensity, setIntensity);
|
||||||
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Direction, direction, setDirection);
|
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, Direction, direction, setDirection);
|
||||||
|
SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(KeyLight, CastShadows, castShadows, setCastShadows);
|
||||||
|
|
||||||
return somethingChanged;
|
return somethingChanged;
|
||||||
}
|
}
|
||||||
|
@ -142,6 +159,7 @@ EntityPropertyFlags KeyLightPropertyGroup::getEntityProperties(EncodeBitstreamPa
|
||||||
requestedProperties += PROP_KEYLIGHT_COLOR;
|
requestedProperties += PROP_KEYLIGHT_COLOR;
|
||||||
requestedProperties += PROP_KEYLIGHT_INTENSITY;
|
requestedProperties += PROP_KEYLIGHT_INTENSITY;
|
||||||
requestedProperties += PROP_KEYLIGHT_DIRECTION;
|
requestedProperties += PROP_KEYLIGHT_DIRECTION;
|
||||||
|
requestedProperties += PROP_KEYLIGHT_CAST_SHADOW;
|
||||||
|
|
||||||
return requestedProperties;
|
return requestedProperties;
|
||||||
}
|
}
|
||||||
|
@ -159,6 +177,7 @@ void KeyLightPropertyGroup::appendSubclassData(OctreePacketData* packetData, Enc
|
||||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, getColor());
|
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, getColor());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity());
|
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, getIntensity());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection());
|
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, getDirection());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, getCastShadows());
|
||||||
}
|
}
|
||||||
|
|
||||||
int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||||
|
@ -172,6 +191,7 @@ int KeyLightPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char*
|
||||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, xColor, setColor);
|
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, xColor, setColor);
|
||||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity);
|
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, float, setIntensity);
|
||||||
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection);
|
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, glm::vec3, setDirection);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, bool, setCastShadows);
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,10 +78,12 @@ public:
|
||||||
static const float DEFAULT_KEYLIGHT_INTENSITY;
|
static const float DEFAULT_KEYLIGHT_INTENSITY;
|
||||||
static const float DEFAULT_KEYLIGHT_AMBIENT_INTENSITY;
|
static const float DEFAULT_KEYLIGHT_AMBIENT_INTENSITY;
|
||||||
static const glm::vec3 DEFAULT_KEYLIGHT_DIRECTION;
|
static const glm::vec3 DEFAULT_KEYLIGHT_DIRECTION;
|
||||||
|
static const bool DEFAULT_KEYLIGHT_CAST_SHADOWS;
|
||||||
|
|
||||||
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, Color, color, xColor, DEFAULT_KEYLIGHT_COLOR);
|
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, Color, color, xColor, DEFAULT_KEYLIGHT_COLOR);
|
||||||
DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, Intensity, intensity, float, DEFAULT_KEYLIGHT_INTENSITY);
|
DEFINE_PROPERTY(PROP_KEYLIGHT_INTENSITY, Intensity, intensity, float, DEFAULT_KEYLIGHT_INTENSITY);
|
||||||
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, Direction, direction, glm::vec3, DEFAULT_KEYLIGHT_DIRECTION);
|
DEFINE_PROPERTY_REF(PROP_KEYLIGHT_DIRECTION, Direction, direction, glm::vec3, DEFAULT_KEYLIGHT_DIRECTION);
|
||||||
|
DEFINE_PROPERTY(PROP_KEYLIGHT_CAST_SHADOW, CastShadows, castShadows, bool, DEFAULT_KEYLIGHT_CAST_SHADOWS);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_KeyLightPropertyGroup_h
|
#endif // hifi_KeyLightPropertyGroup_h
|
||||||
|
|
|
@ -53,6 +53,7 @@ void ModelEntityItem::setTextures(const QString& textures) {
|
||||||
|
|
||||||
EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||||
|
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
|
||||||
|
@ -64,6 +65,7 @@ EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredP
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointTranslations, getJointTranslations);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointTranslations, getJointTranslations);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(relayParentJoints, getRelayParentJoints);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(relayParentJoints, getRelayParentJoints);
|
||||||
_animationProperties.getProperties(properties);
|
_animationProperties.getProperties(properties);
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,8 +193,6 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
||||||
APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations());
|
APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// added update function back for property fix
|
// added update function back for property fix
|
||||||
void ModelEntityItem::update(const quint64& now) {
|
void ModelEntityItem::update(const quint64& now) {
|
||||||
|
|
||||||
|
@ -571,15 +571,16 @@ QVector<bool> ModelEntityItem::getJointTranslationsSet() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xColor ModelEntityItem::getXColor() const {
|
xColor ModelEntityItem::getXColor() const {
|
||||||
xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color;
|
xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelEntityItem::hasModel() const {
|
bool ModelEntityItem::hasModel() const {
|
||||||
return resultWithReadLock<bool>([&] {
|
return resultWithReadLock<bool>([&] {
|
||||||
return !_modelURL.isEmpty();
|
return !_modelURL.isEmpty();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelEntityItem::hasCompoundShapeURL() const {
|
bool ModelEntityItem::hasCompoundShapeURL() const {
|
||||||
return !_compoundShapeURL.get().isEmpty();
|
return !_compoundShapeURL.get().isEmpty();
|
||||||
}
|
}
|
||||||
|
@ -659,7 +660,6 @@ bool ModelEntityItem::getAnimationLoop() const {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ModelEntityItem::setAnimationHold(bool hold) {
|
void ModelEntityItem::setAnimationHold(bool hold) {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_animationProperties.setHold(hold);
|
_animationProperties.setHold(hold);
|
||||||
|
|
|
@ -92,6 +92,7 @@ EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredP
|
||||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||||
properties.setColor(getXColor());
|
properties.setColor(getXColor());
|
||||||
properties.setShape(entity::stringFromShape(getShape()));
|
properties.setShape(entity::stringFromShape(getShape()));
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +167,7 @@ EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams&
|
||||||
requestedProperties += PROP_SHAPE;
|
requestedProperties += PROP_SHAPE;
|
||||||
requestedProperties += PROP_COLOR;
|
requestedProperties += PROP_COLOR;
|
||||||
requestedProperties += PROP_ALPHA;
|
requestedProperties += PROP_ALPHA;
|
||||||
|
|
||||||
return requestedProperties;
|
return requestedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,4 +370,3 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||||
ShapeType ShapeEntityItem::getShapeType() const {
|
ShapeType ShapeEntityItem::getShapeType() const {
|
||||||
return _collisionShapeType;
|
return _collisionShapeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,8 @@ protected:
|
||||||
//! ellipsoids.
|
//! ellipsoids.
|
||||||
ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_ELLIPSOID };
|
ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_ELLIPSOID };
|
||||||
|
|
||||||
|
bool _canCastShadow { ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW };
|
||||||
|
|
||||||
std::shared_ptr<graphics::Material> _material;
|
std::shared_ptr<graphics::Material> _material;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,14 @@ const Vec3& Light::getDirection() const {
|
||||||
return _lightSchemaBuffer->volume.direction;
|
return _lightSchemaBuffer->volume.direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Light::setCastShadows(const bool castShadows) {
|
||||||
|
_castShadows = castShadows;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Light::getCastShadows() const {
|
||||||
|
return _castShadows;
|
||||||
|
}
|
||||||
|
|
||||||
void Light::setColor(const Color& color) {
|
void Light::setColor(const Color& color) {
|
||||||
_lightSchemaBuffer.edit().irradiance.color = color;
|
_lightSchemaBuffer.edit().irradiance.color = color;
|
||||||
updateLightRadius();
|
updateLightRadius();
|
||||||
|
@ -132,7 +140,6 @@ void Light::setSpotExponent(float exponent) {
|
||||||
_lightSchemaBuffer.edit().irradiance.falloffSpot = exponent;
|
_lightSchemaBuffer.edit().irradiance.falloffSpot = exponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Light::setAmbientIntensity(float intensity) {
|
void Light::setAmbientIntensity(float intensity) {
|
||||||
_ambientSchemaBuffer.edit().intensity = intensity;
|
_ambientSchemaBuffer.edit().intensity = intensity;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,9 @@ public:
|
||||||
void setDirection(const Vec3& direction);
|
void setDirection(const Vec3& direction);
|
||||||
const Vec3& getDirection() const;
|
const Vec3& getDirection() const;
|
||||||
|
|
||||||
|
void setCastShadows(const bool castShadows);
|
||||||
|
bool getCastShadows() const;
|
||||||
|
|
||||||
void setOrientation(const Quat& orientation);
|
void setOrientation(const Quat& orientation);
|
||||||
const glm::quat& getOrientation() const { return _transform.getRotation(); }
|
const glm::quat& getOrientation() const { return _transform.getRotation(); }
|
||||||
|
|
||||||
|
@ -191,6 +194,8 @@ protected:
|
||||||
|
|
||||||
void updateLightRadius();
|
void updateLightRadius();
|
||||||
|
|
||||||
|
bool _castShadows{ false };
|
||||||
|
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr< Light > LightPointer;
|
typedef std::shared_ptr< Light > LightPointer;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
case PacketType::EntityEdit:
|
case PacketType::EntityEdit:
|
||||||
case PacketType::EntityData:
|
case PacketType::EntityData:
|
||||||
case PacketType::EntityPhysics:
|
case PacketType::EntityPhysics:
|
||||||
return static_cast<PacketVersion>(EntityVersion::MaterialEntities);
|
return static_cast<PacketVersion>(EntityVersion::ShadowControl);
|
||||||
case PacketType::EntityQuery:
|
case PacketType::EntityQuery:
|
||||||
return static_cast<PacketVersion>(EntityQueryPacketVersion::RemovedJurisdictions);
|
return static_cast<PacketVersion>(EntityQueryPacketVersion::RemovedJurisdictions);
|
||||||
case PacketType::AvatarIdentity:
|
case PacketType::AvatarIdentity:
|
||||||
|
|
|
@ -218,7 +218,8 @@ enum class EntityVersion : PacketVersion {
|
||||||
ZoneLightInheritModes = 82,
|
ZoneLightInheritModes = 82,
|
||||||
ZoneStageRemoved,
|
ZoneStageRemoved,
|
||||||
SoftEntities,
|
SoftEntities,
|
||||||
MaterialEntities
|
MaterialEntities,
|
||||||
|
ShadowControl
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EntityScriptCallMethodVersion : PacketVersion {
|
enum class EntityScriptCallMethodVersion : PacketVersion {
|
||||||
|
|
|
@ -214,6 +214,7 @@ void CauterizedModel::updateRenderItems() {
|
||||||
|
|
||||||
bool isWireframe = self->isWireframe();
|
bool isWireframe = self->isWireframe();
|
||||||
bool isVisible = self->isVisible();
|
bool isVisible = self->isVisible();
|
||||||
|
bool canCastShadow = self->canCastShadow();
|
||||||
bool isLayeredInFront = self->isLayeredInFront();
|
bool isLayeredInFront = self->isLayeredInFront();
|
||||||
bool isLayeredInHUD = self->isLayeredInHUD();
|
bool isLayeredInHUD = self->isLayeredInHUD();
|
||||||
bool enableCauterization = self->getEnableCauterization();
|
bool enableCauterization = self->getEnableCauterization();
|
||||||
|
@ -231,7 +232,7 @@ void CauterizedModel::updateRenderItems() {
|
||||||
bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning();
|
bool useDualQuaternionSkinning = self->getUseDualQuaternionSkinning();
|
||||||
|
|
||||||
transaction.updateItem<CauterizedMeshPartPayload>(itemID, [modelTransform, meshState, useDualQuaternionSkinning, cauterizedMeshState, invalidatePayloadShapeKey,
|
transaction.updateItem<CauterizedMeshPartPayload>(itemID, [modelTransform, meshState, useDualQuaternionSkinning, cauterizedMeshState, invalidatePayloadShapeKey,
|
||||||
isWireframe, isVisible, isLayeredInFront, isLayeredInHUD, enableCauterization](CauterizedMeshPartPayload& data) {
|
isWireframe, isVisible, isLayeredInFront, isLayeredInHUD, canCastShadow, enableCauterization](CauterizedMeshPartPayload& data) {
|
||||||
if (useDualQuaternionSkinning) {
|
if (useDualQuaternionSkinning) {
|
||||||
data.updateClusterBuffer(meshState.clusterDualQuaternions,
|
data.updateClusterBuffer(meshState.clusterDualQuaternions,
|
||||||
cauterizedMeshState.clusterDualQuaternions);
|
cauterizedMeshState.clusterDualQuaternions);
|
||||||
|
@ -273,7 +274,7 @@ void CauterizedModel::updateRenderItems() {
|
||||||
data.updateTransformForCauterizedMesh(renderTransform);
|
data.updateTransformForCauterizedMesh(renderTransform);
|
||||||
|
|
||||||
data.setEnableCauterization(enableCauterization);
|
data.setEnableCauterization(enableCauterization);
|
||||||
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, render::ItemKey::TAG_BITS_ALL);
|
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, render::ItemKey::TAG_BITS_ALL);
|
||||||
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
||||||
data.setShapeKey(invalidatePayloadShapeKey, isWireframe, useDualQuaternionSkinning);
|
data.setShapeKey(invalidatePayloadShapeKey, isWireframe, useDualQuaternionSkinning);
|
||||||
});
|
});
|
||||||
|
|
|
@ -492,7 +492,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
||||||
batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, deferredFramebuffer->getPrimaryDepthTexture());
|
batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, deferredFramebuffer->getPrimaryDepthTexture());
|
||||||
|
|
||||||
// FIXME: Different render modes should have different tasks
|
// FIXME: Different render modes should have different tasks
|
||||||
if (args->_renderMode == RenderArgs::DEFAULT_RENDER_MODE && deferredLightingEffect->isAmbientOcclusionEnabled()) {
|
if (args->_renderMode == RenderArgs::DEFAULT_RENDER_MODE && deferredLightingEffect->isAmbientOcclusionEnabled() && ambientOcclusionFramebuffer) {
|
||||||
batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, ambientOcclusionFramebuffer->getOcclusionTexture());
|
batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, ambientOcclusionFramebuffer->getOcclusionTexture());
|
||||||
} else {
|
} else {
|
||||||
// need to assign the white texture if ao is off
|
// need to assign the white texture if ao is off
|
||||||
|
@ -537,15 +537,25 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
||||||
|
|
||||||
auto keyLight = lightAndShadow.first;
|
auto keyLight = lightAndShadow.first;
|
||||||
|
|
||||||
graphics::LightPointer keyAmbientLight;
|
graphics::LightPointer ambientLight;
|
||||||
if (lightStage && lightStage->_currentFrame._ambientLights.size()) {
|
if (lightStage && lightStage->_currentFrame._ambientLights.size()) {
|
||||||
keyAmbientLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front());
|
ambientLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front());
|
||||||
}
|
}
|
||||||
bool hasAmbientMap = (keyAmbientLight != nullptr);
|
bool hasAmbientMap = (ambientLight != nullptr);
|
||||||
|
|
||||||
// Setup the global directional pass pipeline
|
// Setup the global directional pass pipeline
|
||||||
{
|
{
|
||||||
if (deferredLightingEffect->_shadowMapEnabled) {
|
// Check if keylight casts shadows
|
||||||
|
bool keyLightCastShadows { false };
|
||||||
|
|
||||||
|
if (lightStage && lightStage->_currentFrame._sunLights.size()) {
|
||||||
|
graphics::LightPointer keyLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front());
|
||||||
|
if (keyLight) {
|
||||||
|
keyLightCastShadows = keyLight->getCastShadows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deferredLightingEffect->_shadowMapEnabled && keyLightCastShadows) {
|
||||||
|
|
||||||
// If the keylight has an ambient Map then use the Skybox version of the pass
|
// If the keylight has an ambient Map then use the Skybox version of the pass
|
||||||
// otherwise use the ambient sphere version
|
// otherwise use the ambient sphere version
|
||||||
|
|
|
@ -61,7 +61,7 @@ public:
|
||||||
private:
|
private:
|
||||||
DeferredLightingEffect() = default;
|
DeferredLightingEffect() = default;
|
||||||
|
|
||||||
bool _shadowMapEnabled{ false };
|
bool _shadowMapEnabled{ true }; // note that this value is overwritten in the ::configure method
|
||||||
bool _ambientOcclusionEnabled{ false };
|
bool _ambientOcclusionEnabled{ false };
|
||||||
|
|
||||||
graphics::MeshPointer _pointLightMesh;
|
graphics::MeshPointer _pointLightMesh;
|
||||||
|
|
|
@ -77,7 +77,7 @@ void MeshPartPayload::removeMaterial(graphics::MaterialPointer material) {
|
||||||
_drawMaterials.remove(material);
|
_drawMaterials.remove(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits, bool isGroupCulled) {
|
void MeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) {
|
||||||
ItemKey::Builder builder;
|
ItemKey::Builder builder;
|
||||||
builder.withTypeShape();
|
builder.withTypeShape();
|
||||||
|
|
||||||
|
@ -91,6 +91,10 @@ void MeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits,
|
||||||
builder.withLayered();
|
builder.withLayered();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (canCastShadow) {
|
||||||
|
builder.withShadowCaster();
|
||||||
|
}
|
||||||
|
|
||||||
if (isGroupCulled) {
|
if (isGroupCulled) {
|
||||||
builder.withSubMetaCulled();
|
builder.withSubMetaCulled();
|
||||||
}
|
}
|
||||||
|
@ -328,7 +332,8 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render
|
||||||
_worldBound.transform(boundTransform);
|
_worldBound.transform(boundTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits, bool isGroupCulled) {
|
// Note that this method is called for models but not for shapes
|
||||||
|
void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled) {
|
||||||
ItemKey::Builder builder;
|
ItemKey::Builder builder;
|
||||||
builder.withTypeShape();
|
builder.withTypeShape();
|
||||||
|
|
||||||
|
@ -342,6 +347,10 @@ void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tag
|
||||||
builder.withLayered();
|
builder.withLayered();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (canCastShadow) {
|
||||||
|
builder.withShadowCaster();
|
||||||
|
}
|
||||||
|
|
||||||
if (isGroupCulled) {
|
if (isGroupCulled) {
|
||||||
builder.withSubMetaCulled();
|
builder.withSubMetaCulled();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
typedef render::Payload<MeshPartPayload> Payload;
|
typedef render::Payload<MeshPartPayload> Payload;
|
||||||
typedef Payload::DataPointer Pointer;
|
typedef Payload::DataPointer Pointer;
|
||||||
|
|
||||||
virtual void updateKey(bool isVisible, bool isLayered, uint8_t tagBits, bool isGroupCulled = false);
|
virtual void updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled = false);
|
||||||
|
|
||||||
virtual void updateMeshPart(const std::shared_ptr<const graphics::Mesh>& drawMesh, int partIndex);
|
virtual void updateMeshPart(const std::shared_ptr<const graphics::Mesh>& drawMesh, int partIndex);
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ public:
|
||||||
|
|
||||||
void notifyLocationChanged() override;
|
void notifyLocationChanged() override;
|
||||||
|
|
||||||
void updateKey(bool isVisible, bool isLayered, uint8_t tagBits, bool isGroupCulled = false) override;
|
void updateKey(bool isVisible, bool isLayered, bool canCastShadow, uint8_t tagBits, bool isGroupCulled = false) override;
|
||||||
|
|
||||||
// matrix palette skinning
|
// matrix palette skinning
|
||||||
void updateClusterBuffer(const std::vector<glm::mat4>& clusterMatrices);
|
void updateClusterBuffer(const std::vector<glm::mat4>& clusterMatrices);
|
||||||
|
|
|
@ -102,6 +102,7 @@ Model::Model(QObject* parent, SpatiallyNestable* spatiallyNestableOverride) :
|
||||||
_snappedToRegistrationPoint(false),
|
_snappedToRegistrationPoint(false),
|
||||||
_url(HTTP_INVALID_COM),
|
_url(HTTP_INVALID_COM),
|
||||||
_isVisible(true),
|
_isVisible(true),
|
||||||
|
_canCastShadow(false),
|
||||||
_blendNumber(0),
|
_blendNumber(0),
|
||||||
_appliedBlendNumber(0),
|
_appliedBlendNumber(0),
|
||||||
_isWireframe(false)
|
_isWireframe(false)
|
||||||
|
@ -268,6 +269,7 @@ void Model::updateRenderItems() {
|
||||||
|
|
||||||
bool isWireframe = self->isWireframe();
|
bool isWireframe = self->isWireframe();
|
||||||
bool isVisible = self->isVisible();
|
bool isVisible = self->isVisible();
|
||||||
|
bool canCastShadow = self->canCastShadow();
|
||||||
uint8_t viewTagBits = self->getViewTagBits();
|
uint8_t viewTagBits = self->getViewTagBits();
|
||||||
bool isLayeredInFront = self->isLayeredInFront();
|
bool isLayeredInFront = self->isLayeredInFront();
|
||||||
bool isLayeredInHUD = self->isLayeredInHUD();
|
bool isLayeredInHUD = self->isLayeredInHUD();
|
||||||
|
@ -286,7 +288,7 @@ void Model::updateRenderItems() {
|
||||||
|
|
||||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, meshState, useDualQuaternionSkinning,
|
transaction.updateItem<ModelMeshPartPayload>(itemID, [modelTransform, meshState, useDualQuaternionSkinning,
|
||||||
invalidatePayloadShapeKey, isWireframe, isVisible,
|
invalidatePayloadShapeKey, isWireframe, isVisible,
|
||||||
viewTagBits, isLayeredInFront,
|
canCastShadow, viewTagBits, isLayeredInFront,
|
||||||
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
||||||
if (useDualQuaternionSkinning) {
|
if (useDualQuaternionSkinning) {
|
||||||
data.updateClusterBuffer(meshState.clusterDualQuaternions);
|
data.updateClusterBuffer(meshState.clusterDualQuaternions);
|
||||||
|
@ -311,7 +313,7 @@ void Model::updateRenderItems() {
|
||||||
}
|
}
|
||||||
data.updateTransformForSkinnedMesh(renderTransform, modelTransform);
|
data.updateTransformForSkinnedMesh(renderTransform, modelTransform);
|
||||||
|
|
||||||
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled);
|
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled);
|
||||||
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
||||||
data.setShapeKey(invalidatePayloadShapeKey, isWireframe, useDualQuaternionSkinning);
|
data.setShapeKey(invalidatePayloadShapeKey, isWireframe, useDualQuaternionSkinning);
|
||||||
});
|
});
|
||||||
|
@ -704,46 +706,66 @@ void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene,
|
||||||
|
|
||||||
bool isLayeredInFront = _isLayeredInFront;
|
bool isLayeredInFront = _isLayeredInFront;
|
||||||
bool isLayeredInHUD = _isLayeredInHUD;
|
bool isLayeredInHUD = _isLayeredInHUD;
|
||||||
|
bool canCastShadow = _canCastShadow;
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
foreach (auto item, _modelMeshRenderItemsMap.keys()) {
|
foreach (auto item, _modelMeshRenderItemsMap.keys()) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront,
|
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow,
|
||||||
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
||||||
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled);
|
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
foreach(auto item, _collisionRenderItemsMap.keys()) {
|
foreach(auto item, _collisionRenderItemsMap.keys()) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront,
|
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow,
|
||||||
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
||||||
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled);
|
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Model::setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene, uint8_t viewTagBits, bool isGroupCulled) {
|
||||||
|
if (_canCastShadow != canCastShadow) {
|
||||||
|
_canCastShadow = canCastShadow;
|
||||||
|
|
||||||
|
bool isVisible = _isVisible;
|
||||||
|
bool isLayeredInFront = _isLayeredInFront;
|
||||||
|
bool isLayeredInHUD = _isLayeredInHUD;
|
||||||
|
|
||||||
|
render::Transaction transaction;
|
||||||
|
foreach (auto item, _modelMeshRenderItemsMap.keys()) {
|
||||||
|
transaction.updateItem<ModelMeshPartPayload>(item,
|
||||||
|
[isVisible, viewTagBits, canCastShadow, isLayeredInFront, isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
||||||
|
data.updateKey(isVisible, viewTagBits, canCastShadow, isLayeredInFront || isLayeredInHUD, isGroupCulled);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
scene->enqueueTransaction(transaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Model::setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene) {
|
void Model::setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene) {
|
||||||
if (_isLayeredInFront != isLayeredInFront) {
|
if (_isLayeredInFront != isLayeredInFront) {
|
||||||
_isLayeredInFront = isLayeredInFront;
|
_isLayeredInFront = isLayeredInFront;
|
||||||
|
|
||||||
bool isVisible = _isVisible;
|
bool isVisible = _isVisible;
|
||||||
|
bool canCastShadow = _canCastShadow;
|
||||||
uint8_t viewTagBits = _viewTagBits;
|
uint8_t viewTagBits = _viewTagBits;
|
||||||
bool isLayeredInHUD = _isLayeredInHUD;
|
bool isLayeredInHUD = _isLayeredInHUD;
|
||||||
bool isGroupCulled = _isGroupCulled;
|
bool isGroupCulled = _isGroupCulled;
|
||||||
|
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
foreach(auto item, _modelMeshRenderItemsMap.keys()) {
|
foreach(auto item, _modelMeshRenderItemsMap.keys()) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront,
|
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow,
|
||||||
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
||||||
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled);
|
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled);
|
||||||
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
foreach(auto item, _collisionRenderItemsMap.keys()) {
|
foreach(auto item, _collisionRenderItemsMap.keys()) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront,
|
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow,
|
||||||
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
||||||
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled);
|
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled);
|
||||||
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -756,22 +778,23 @@ void Model::setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& sce
|
||||||
_isLayeredInHUD = isLayeredInHUD;
|
_isLayeredInHUD = isLayeredInHUD;
|
||||||
|
|
||||||
bool isVisible = _isVisible;
|
bool isVisible = _isVisible;
|
||||||
|
bool canCastShadow = _canCastShadow;
|
||||||
uint8_t viewTagBits = _viewTagBits;
|
uint8_t viewTagBits = _viewTagBits;
|
||||||
bool isLayeredInFront = _isLayeredInFront;
|
bool isLayeredInFront = _isLayeredInFront;
|
||||||
bool isGroupCulled = _isGroupCulled;
|
bool isGroupCulled = _isGroupCulled;
|
||||||
|
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
foreach(auto item, _modelMeshRenderItemsMap.keys()) {
|
foreach(auto item, _modelMeshRenderItemsMap.keys()) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront,
|
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow,
|
||||||
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
||||||
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled);
|
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled);
|
||||||
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
foreach(auto item, _collisionRenderItemsMap.keys()) {
|
foreach(auto item, _collisionRenderItemsMap.keys()) {
|
||||||
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront,
|
transaction.updateItem<ModelMeshPartPayload>(item, [isVisible, viewTagBits, isLayeredInFront, canCastShadow,
|
||||||
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
isLayeredInHUD, isGroupCulled](ModelMeshPartPayload& data) {
|
||||||
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, viewTagBits, isGroupCulled);
|
data.updateKey(isVisible, isLayeredInFront || isLayeredInHUD, canCastShadow, viewTagBits, isGroupCulled);
|
||||||
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
data.setLayer(isLayeredInFront, isLayeredInHUD);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1581,15 +1604,16 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par
|
||||||
uint8_t viewTagBits = getViewTagBits();
|
uint8_t viewTagBits = getViewTagBits();
|
||||||
bool layeredInFront = isLayeredInFront();
|
bool layeredInFront = isLayeredInFront();
|
||||||
bool layeredInHUD = isLayeredInHUD();
|
bool layeredInHUD = isLayeredInHUD();
|
||||||
|
bool canCastShadow = _canCastShadow;
|
||||||
bool wireframe = isWireframe();
|
bool wireframe = isWireframe();
|
||||||
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
||||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
||||||
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
||||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits,
|
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, canCastShadow,
|
||||||
invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) {
|
invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) {
|
||||||
data.addMaterial(material);
|
data.addMaterial(material);
|
||||||
// if the material changed, we might need to update our item key or shape key
|
// if the material changed, we might need to update our item key or shape key
|
||||||
data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits);
|
data.updateKey(visible, layeredInFront || layeredInHUD, canCastShadow, viewTagBits);
|
||||||
data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning);
|
data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1607,15 +1631,16 @@ void Model::removeMaterial(graphics::MaterialPointer material, const std::string
|
||||||
uint8_t viewTagBits = getViewTagBits();
|
uint8_t viewTagBits = getViewTagBits();
|
||||||
bool layeredInFront = isLayeredInFront();
|
bool layeredInFront = isLayeredInFront();
|
||||||
bool layeredInHUD = isLayeredInHUD();
|
bool layeredInHUD = isLayeredInHUD();
|
||||||
|
bool canCastShadow = _canCastShadow;
|
||||||
bool wireframe = isWireframe();
|
bool wireframe = isWireframe();
|
||||||
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex;
|
||||||
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex);
|
||||||
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
bool useDualQuaternionSkinning = _useDualQuaternionSkinning;
|
||||||
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits,
|
transaction.updateItem<ModelMeshPartPayload>(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, canCastShadow,
|
||||||
invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) {
|
invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning](ModelMeshPartPayload& data) {
|
||||||
data.removeMaterial(material);
|
data.removeMaterial(material);
|
||||||
// if the material changed, we might need to update our item key or shape key
|
// if the material changed, we might need to update our item key or shape key
|
||||||
data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits);
|
data.updateKey(visible, layeredInFront || layeredInHUD, canCastShadow, viewTagBits);
|
||||||
data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning);
|
data.setShapeKey(invalidatePayloadShapeKey, wireframe, useDualQuaternionSkinning);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,10 @@ public:
|
||||||
|
|
||||||
// new Scene/Engine rendering support
|
// new Scene/Engine rendering support
|
||||||
void setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewTagBits, bool isGroupCulled);
|
void setVisibleInScene(bool isVisible, const render::ScenePointer& scene, uint8_t viewTagBits, bool isGroupCulled);
|
||||||
|
|
||||||
|
bool canCastShadow() const { return _canCastShadow; }
|
||||||
|
void setCanCastShadow(bool canCastShadow, const render::ScenePointer& scene, uint8_t viewTagBits, bool isGroupCulled);
|
||||||
|
|
||||||
void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene);
|
void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene);
|
||||||
void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene);
|
void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene);
|
||||||
bool needsFixupInScene() const;
|
bool needsFixupInScene() const;
|
||||||
|
@ -400,6 +404,8 @@ protected:
|
||||||
bool _isVisible;
|
bool _isVisible;
|
||||||
uint8_t _viewTagBits{ render::ItemKey::TAG_BITS_ALL };
|
uint8_t _viewTagBits{ render::ItemKey::TAG_BITS_ALL };
|
||||||
|
|
||||||
|
bool _canCastShadow;
|
||||||
|
|
||||||
gpu::Buffers _blendedVertexBuffers;
|
gpu::Buffers _blendedVertexBuffers;
|
||||||
|
|
||||||
QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures;
|
QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures;
|
||||||
|
|
|
@ -218,7 +218,10 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
||||||
const auto setupOutput = task.addJob<RenderShadowSetup>("ShadowSetup");
|
const auto setupOutput = task.addJob<RenderShadowSetup>("ShadowSetup");
|
||||||
const auto queryResolution = setupOutput.getN<RenderShadowSetup::Outputs>(2);
|
const auto queryResolution = setupOutput.getN<RenderShadowSetup::Outputs>(2);
|
||||||
// Fetch and cull the items from the scene
|
// Fetch and cull the items from the scene
|
||||||
static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask);
|
|
||||||
|
// Enable models to not cast shadows (otherwise, models will always cast shadows)
|
||||||
|
static const auto shadowCasterFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask).withShadowCaster();
|
||||||
|
|
||||||
const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying();
|
const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterFilter, queryResolution).asVarying();
|
||||||
const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowTree", fetchInput);
|
const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowTree", fetchInput);
|
||||||
const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying();
|
const auto selectionInputs = FetchSpatialSelection::Inputs(shadowSelection, shadowCasterFilter).asVarying();
|
||||||
|
@ -297,8 +300,14 @@ void RenderShadowSetup::setSlopeBias(int cascadeIndex, float value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Outputs& output) {
|
void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Outputs& output) {
|
||||||
|
// Abort all jobs if not casting shadows
|
||||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||||
assert(lightStage);
|
assert(lightStage);
|
||||||
|
if (!lightStage->getCurrentKeyLight() || !lightStage->getCurrentKeyLight()->getCastShadows()) {
|
||||||
|
renderContext->taskFlow.abortTask();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Cache old render args
|
// Cache old render args
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
|
|
||||||
|
@ -378,12 +387,13 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
|
||||||
void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderContext, Outputs& output) {
|
void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderContext, Outputs& output) {
|
||||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||||
assert(lightStage);
|
assert(lightStage);
|
||||||
|
|
||||||
// Cache old render args
|
// Cache old render args
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
|
|
||||||
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
const auto globalShadow = lightStage->getCurrentKeyShadow();
|
||||||
if (globalShadow && _cascadeIndex<globalShadow->getCascadeCount()) {
|
if (globalShadow && _cascadeIndex<globalShadow->getCascadeCount()) {
|
||||||
output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask);
|
output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask).withShadowCaster();
|
||||||
|
|
||||||
// Set the keylight render args
|
// Set the keylight render args
|
||||||
auto& cascade = globalShadow->getCascade(_cascadeIndex);
|
auto& cascade = globalShadow->getCascade(_cascadeIndex);
|
||||||
|
|
|
@ -38,7 +38,7 @@ class RenderShadowTaskConfig : public render::Task::Config::Persistent {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty)
|
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty)
|
||||||
public:
|
public:
|
||||||
RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", false) {}
|
RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", true) {}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dirty();
|
void dirty();
|
||||||
|
|
|
@ -226,7 +226,6 @@ public:
|
||||||
Builder& withVisible() { _value.reset(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); }
|
Builder& withVisible() { _value.reset(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); }
|
||||||
Builder& withInvisible() { _value.set(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); }
|
Builder& withInvisible() { _value.set(ItemKey::INVISIBLE); _mask.set(ItemKey::INVISIBLE); return (*this); }
|
||||||
|
|
||||||
Builder& withNoShadowCaster() { _value.reset(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); }
|
|
||||||
Builder& withShadowCaster() { _value.set(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); }
|
Builder& withShadowCaster() { _value.set(ItemKey::SHADOW_CASTER); _mask.set(ItemKey::SHADOW_CASTER); return (*this); }
|
||||||
|
|
||||||
Builder& withoutLayered() { _value.reset(ItemKey::LAYERED); _mask.set(ItemKey::LAYERED); return (*this); }
|
Builder& withoutLayered() { _value.reset(ItemKey::LAYERED); _mask.set(ItemKey::LAYERED); return (*this); }
|
||||||
|
|
|
@ -42,8 +42,9 @@ function onClicked() {
|
||||||
// for toolbar-mode: go back to home screen, this will close the window.
|
// for toolbar-mode: go back to home screen, this will close the window.
|
||||||
tablet.gotoHomeScreen();
|
tablet.gotoHomeScreen();
|
||||||
} else {
|
} else {
|
||||||
var entity = HMD.tabletID;
|
if (HMD.tabletID) {
|
||||||
Entities.editEntity(entity, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
|
Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
|
||||||
|
}
|
||||||
tablet.loadQMLSource(AUDIO_QML_SOURCE);
|
tablet.loadQMLSource(AUDIO_QML_SOURCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setIgnorePointerItems = function() {
|
this.setIgnorePointerItems = function() {
|
||||||
if (HMD.tabletID !== this.tabletID) {
|
if (HMD.tabletID && HMD.tabletID !== this.tabletID) {
|
||||||
this.tabletID = HMD.tabletID;
|
this.tabletID = HMD.tabletID;
|
||||||
Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist);
|
Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist);
|
||||||
Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist);
|
Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist);
|
||||||
|
@ -479,7 +479,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function mouseReleaseOnOverlay(overlayID, event) {
|
function mouseReleaseOnOverlay(overlayID, event) {
|
||||||
if (overlayID === HMD.homeButtonID && event.button === "Primary") {
|
if (HMD.homeButtonID && overlayID === HMD.homeButtonID && event.button === "Primary") {
|
||||||
Messages.sendLocalMessage("home", overlayID);
|
Messages.sendLocalMessage("home", overlayID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
|
|
||||||
this.nearTablet = function(overlays) {
|
this.nearTablet = function(overlays) {
|
||||||
for (var i = 0; i < overlays.length; i++) {
|
for (var i = 0; i < overlays.length; i++) {
|
||||||
if (overlays[i] === HMD.tabletID) {
|
if (HMD.tabletID && overlays[i] === HMD.tabletID) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,8 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.pointingAtTablet = function(objectID) {
|
this.pointingAtTablet = function(objectID) {
|
||||||
return objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID;
|
return (HMD.tabletScreenID && objectID === HMD.tabletScreenID)
|
||||||
|
|| (HMD.homeButtonID && objectID === HMD.homeButtonID);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.sendPickData = function(controllerData) {
|
this.sendPickData = function(controllerData) {
|
||||||
|
@ -106,7 +107,7 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
if (nearOverlay) {
|
if (nearOverlay) {
|
||||||
var nearOverlayReady = nearOverlay.isReady(controllerData);
|
var nearOverlayReady = nearOverlay.isReady(controllerData);
|
||||||
|
|
||||||
if (nearOverlayReady.active && nearOverlay.grabbedThingID === HMD.tabletID) {
|
if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) {
|
||||||
return this.exitModule();
|
return this.exitModule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
);
|
);
|
||||||
|
|
||||||
this.pointingAtTablet = function (objectID) {
|
this.pointingAtTablet = function (objectID) {
|
||||||
return objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID;
|
return (HMD.tabletScreenID && objectID === HMD.tabletScreenID)
|
||||||
|
|| (HMD.homeButtonID && objectID === HMD.homeButtonID);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.isReady = function (controllerData) {
|
this.isReady = function (controllerData) {
|
||||||
|
@ -76,7 +77,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
: "LeftNearParentingGrabOverlay");
|
: "LeftNearParentingGrabOverlay");
|
||||||
if (nearOverlay) {
|
if (nearOverlay) {
|
||||||
var nearOverlayReady = nearOverlay.isReady(controllerData);
|
var nearOverlayReady = nearOverlay.isReady(controllerData);
|
||||||
if (nearOverlayReady.active && nearOverlay.grabbedThingID === HMD.tabletID) {
|
if (nearOverlayReady.active && HMD.tabletID && nearOverlay.grabbedThingID === HMD.tabletID) {
|
||||||
return makeRunningValues(false, [], []);
|
return makeRunningValues(false, [], []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
Overlays.editOverlay(this.grabbedThingID, reparentProps);
|
Overlays.editOverlay(this.grabbedThingID, reparentProps);
|
||||||
|
|
||||||
// resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix
|
// resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix
|
||||||
if (this.grabbedThingID === HMD.tabletID) {
|
if (HMD.tabletID && this.grabbedThingID === HMD.tabletID) {
|
||||||
resizeTablet(getTabletWidthFromSettings(), reparentProps.parentJointIndex);
|
resizeTablet(getTabletWidthFromSettings(), reparentProps.parentJointIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ Script.include("/~/system/libraries/utils.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
// resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix
|
// resizeTablet to counter adjust offsets to account for change of scale from sensorToWorldMatrix
|
||||||
if (this.grabbedThingID === HMD.tabletID) {
|
if (HMD.tabletID && this.grabbedThingID === HMD.tabletID) {
|
||||||
resizeTablet(getTabletWidthFromSettings(), this.previousParentJointIndex[this.grabbedThingID]);
|
resizeTablet(getTabletWidthFromSettings(), this.previousParentJointIndex[this.grabbedThingID]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
var stylusTargetIDs = [];
|
var stylusTargetIDs = [];
|
||||||
for (var index = 0; index < stylusTargets.length; index++) {
|
for (var index = 0; index < stylusTargets.length; index++) {
|
||||||
var stylusTarget = stylusTargets[index];
|
var stylusTarget = stylusTargets[index];
|
||||||
if (stylusTarget.distance <= maxNormalDistance && stylusTarget.id !== HMD.tabletID) {
|
if (stylusTarget.distance <= maxNormalDistance && !(HMD.tabletID && stylusTarget.id === HMD.tabletID)) {
|
||||||
stylusTargetIDs.push(stylusTarget.id);
|
stylusTargetIDs.push(stylusTarget.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ Script.include("/~/system/libraries/controllers.js");
|
||||||
var i, stylusTarget;
|
var i, stylusTarget;
|
||||||
|
|
||||||
for (i = 0; i < candidateOverlays.length; i++) {
|
for (i = 0; i < candidateOverlays.length; i++) {
|
||||||
if (candidateOverlays[i] !== HMD.tabletID &&
|
if (!(HMD.tabletID && candidateOverlays[i] === HMD.tabletID) &&
|
||||||
Overlays.getProperty(candidateOverlays[i], "visible")) {
|
Overlays.getProperty(candidateOverlays[i], "visible")) {
|
||||||
stylusTarget = getOverlayDistance(controllerPosition, candidateOverlays[i]);
|
stylusTarget = getOverlayDistance(controllerPosition, candidateOverlays[i]);
|
||||||
if (stylusTarget) {
|
if (stylusTarget) {
|
||||||
|
|
|
@ -263,7 +263,10 @@ function Grabber() {
|
||||||
filter: Picks.PICK_OVERLAYS,
|
filter: Picks.PICK_OVERLAYS,
|
||||||
enabled: true
|
enabled: true
|
||||||
});
|
});
|
||||||
RayPick.setIncludeItems(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
|
var tabletItems = getMainTabletIDs();
|
||||||
|
if (tabletItems.length > 0) {
|
||||||
|
RayPick.setIncludeItems(this.mouseRayOverlays, tabletItems);
|
||||||
|
}
|
||||||
var renderStates = [{name: "grabbed", end: beacon}];
|
var renderStates = [{name: "grabbed", end: beacon}];
|
||||||
this.mouseRayEntities = Pointers.createPointer(PickType.Ray, {
|
this.mouseRayEntities = Pointers.createPointer(PickType.Ray, {
|
||||||
joint: "Mouse",
|
joint: "Mouse",
|
||||||
|
|
|
@ -31,6 +31,7 @@ Script.include([
|
||||||
"libraries/entityCameraTool.js",
|
"libraries/entityCameraTool.js",
|
||||||
"libraries/gridTool.js",
|
"libraries/gridTool.js",
|
||||||
"libraries/entityList.js",
|
"libraries/entityList.js",
|
||||||
|
"libraries/utils.js",
|
||||||
"particle_explorer/particleExplorerTool.js",
|
"particle_explorer/particleExplorerTool.js",
|
||||||
"libraries/entityIconOverlayManager.js"
|
"libraries/entityIconOverlayManager.js"
|
||||||
]);
|
]);
|
||||||
|
@ -775,8 +776,7 @@ function findClickedEntity(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
var overlayResult = Overlays.findRayIntersection(pickRay, true, getMainTabletIDs());
|
||||||
var overlayResult = Overlays.findRayIntersection(pickRay, true, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
|
|
||||||
if (overlayResult.intersects) {
|
if (overlayResult.intersects) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -964,7 +964,7 @@ function mouseReleaseEvent(event) {
|
||||||
|
|
||||||
function wasTabletClicked(event) {
|
function wasTabletClicked(event) {
|
||||||
var rayPick = Camera.computePickRay(event.x, event.y);
|
var rayPick = Camera.computePickRay(event.x, event.y);
|
||||||
var result = Overlays.findRayIntersection(rayPick, true, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
|
var result = Overlays.findRayIntersection(rayPick, true, getMainTabletIDs());
|
||||||
return result.intersects;
|
return result.intersects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,7 +987,7 @@ function mouseClickEvent(event) {
|
||||||
toolBar.setActive(true);
|
toolBar.setActive(true);
|
||||||
var pickRay = result.pickRay;
|
var pickRay = result.pickRay;
|
||||||
var foundEntity = result.entityID;
|
var foundEntity = result.entityID;
|
||||||
if (foundEntity === HMD.tabletID) {
|
if (HMD.tabletID && foundEntity === HMD.tabletID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
properties = Entities.getEntityProperties(foundEntity);
|
properties = Entities.getEntityProperties(foundEntity);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
(function() { // BEGIN LOCAL_SCOPE
|
(function() { // BEGIN LOCAL_SCOPE
|
||||||
|
|
||||||
var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png";
|
var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png";
|
||||||
|
var HELP_URL = Script.resourcesPath() + "html/tabletHelp.html";
|
||||||
var buttonName = "HELP";
|
var buttonName = "HELP";
|
||||||
var onHelpScreen = false;
|
var onHelpScreen = false;
|
||||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
@ -30,9 +31,8 @@
|
||||||
if (onHelpScreen) {
|
if (onHelpScreen) {
|
||||||
tablet.gotoHomeScreen();
|
tablet.gotoHomeScreen();
|
||||||
} else {
|
} else {
|
||||||
var tabletEntity = HMD.tabletID;
|
if (HMD.tabletID) {
|
||||||
if (tabletEntity) {
|
Entities.editEntity(HMD.tabletID, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})});
|
||||||
Entities.editEntity(tabletEntity, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})});
|
|
||||||
}
|
}
|
||||||
Menu.triggerOption('Help...');
|
Menu.triggerOption('Help...');
|
||||||
onHelpScreen = true;
|
onHelpScreen = true;
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function onScreenChanged(type, url) {
|
function onScreenChanged(type, url) {
|
||||||
onHelpScreen = type === "Web" && url.startsWith("../../../html/tabletHelp.html");
|
onHelpScreen = type === "Web" && url.startsWith(HELP_URL);
|
||||||
button.editProperties({ isActive: onHelpScreen });
|
button.editProperties({ isActive: onHelpScreen });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,25 +42,28 @@
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
<fieldset id="general" class="major">
|
<fieldset id="general" class="major">
|
||||||
<div class="shape-group shape-section property dropdown" id="shape-list">
|
<div class="shape-group shape-section property dropdown" id="shape-list">
|
||||||
<label for="property-shape">Shape</label>
|
<label for="property-shape">Shape</label>
|
||||||
<select name="SelectShape" id="property-shape">
|
<select name="SelectShape" id="property-shape">
|
||||||
<option value="Cube">Box</option>
|
<option value="Cube">Box</option>
|
||||||
<option value="Sphere">Sphere</option>
|
<option value="Sphere">Sphere</option>
|
||||||
<option value="Tetrahedron">Tetrahedron</option>
|
<option value="Tetrahedron">Tetrahedron</option>
|
||||||
<option value="Octahedron">Octahedron</option>
|
<option value="Octahedron">Octahedron</option>
|
||||||
<option value="Icosahedron">Icosahedron</option>
|
<option value="Icosahedron">Icosahedron</option>
|
||||||
<option value="Dodecahedron">Dodecahedron</option>
|
<option value="Dodecahedron">Dodecahedron</option>
|
||||||
<option value="Hexagon">Hexagon</option>
|
<option value="Hexagon">Hexagon</option>
|
||||||
<option value="Triangle">Triangle</option>
|
<option value="Triangle">Triangle</option>
|
||||||
<option value="Octagon">Octagon</option>
|
<option value="Octagon">Octagon</option>
|
||||||
<option value="Cylinder">Cylinder</option>
|
<option value="Cylinder">Cylinder</option>
|
||||||
<option value="Cone">Cone</option>
|
<option value="Cone">Cone</option>
|
||||||
<option value="Circle">Circle</option>
|
<option value="Circle">Circle</option>
|
||||||
<option value="Quad">Quad</option>
|
<option value="Quad">Quad</option>
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="can-cast-shadow-section property checkbox">
|
||||||
|
<input type="checkbox" id="property-can-cast-shadow">
|
||||||
|
<label for="property-can-cast-shadow">Can cast shadow</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="property text">
|
<div class="property text">
|
||||||
<label for="property-name">Name</label>
|
<label for="property-name">Name</label>
|
||||||
|
@ -293,7 +296,6 @@
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
<fieldset id="behavior" class="major">
|
<fieldset id="behavior" class="major">
|
||||||
<legend class="section-header behavior-group">
|
<legend class="section-header behavior-group">
|
||||||
Behavior<span class=".collapse-icon">M</span>
|
Behavior<span class=".collapse-icon">M</span>
|
||||||
|
@ -365,8 +367,6 @@
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<fieldset id="light" class="major">
|
<fieldset id="light" class="major">
|
||||||
<legend class="section-header light-group light-section">
|
<legend class="section-header light-group light-section">
|
||||||
Light<span class=".collapse-icon">M</span>
|
Light<span class=".collapse-icon">M</span>
|
||||||
|
@ -400,7 +400,6 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
<fieldset id="model" class="major">
|
<fieldset id="model" class="major">
|
||||||
<legend class="section-header model-group model-section zone-section">
|
<legend class="section-header model-group model-section zone-section">
|
||||||
Model<span class=".collapse-icon">M</span>
|
Model<span class=".collapse-icon">M</span>
|
||||||
|
@ -484,7 +483,6 @@
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
<fieldset id="zone" class="major">
|
<fieldset id="zone" class="major">
|
||||||
<legend class="section-header zone-group zone-section">
|
<legend class="section-header zone-group zone-section">
|
||||||
Zone<span class=".collapse-icon">M</span>
|
Zone<span class=".collapse-icon">M</span>
|
||||||
|
@ -532,6 +530,10 @@
|
||||||
<div></div>
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="zone-group zone-section keylight-section property checkbox">
|
||||||
|
<input type="checkbox" id="property-zone-key-light-cast-shadows">
|
||||||
|
<label for="property-zone-key-light-cast-shadows">Cast Shadows</label>
|
||||||
|
</div>
|
||||||
<fieldset class="minor">
|
<fieldset class="minor">
|
||||||
<legend class="sub-section-header zone-group zone-section background-section">
|
<legend class="sub-section-header zone-group zone-section background-section">
|
||||||
Skybox
|
Skybox
|
||||||
|
@ -676,7 +678,7 @@
|
||||||
min="-1000" max="50000" step="10"></div>
|
min="-1000" max="50000" step="10"></div>
|
||||||
</div>
|
</div>
|
||||||
</fieldset-->
|
</fieldset-->
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset id="text" class="major">
|
<fieldset id="text" class="major">
|
||||||
<legend class="section-header text-group text-section">
|
<legend class="section-header text-group text-section">
|
||||||
|
|
|
@ -616,6 +616,8 @@ function loaded() {
|
||||||
|
|
||||||
var elShape = document.getElementById("property-shape");
|
var elShape = document.getElementById("property-shape");
|
||||||
|
|
||||||
|
var elCanCastShadow = document.getElementById("property-can-cast-shadow");
|
||||||
|
|
||||||
var elLightSpotLight = document.getElementById("property-light-spot-light");
|
var elLightSpotLight = document.getElementById("property-light-spot-light");
|
||||||
var elLightColor = document.getElementById("property-light-color");
|
var elLightColor = document.getElementById("property-light-color");
|
||||||
var elLightColorRed = document.getElementById("property-light-color-red");
|
var elLightColorRed = document.getElementById("property-light-color-red");
|
||||||
|
@ -687,6 +689,8 @@ function loaded() {
|
||||||
var elZoneKeyLightDirectionX = document.getElementById("property-zone-key-light-direction-x");
|
var elZoneKeyLightDirectionX = document.getElementById("property-zone-key-light-direction-x");
|
||||||
var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y");
|
var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y");
|
||||||
|
|
||||||
|
var elZoneKeyLightCastShadows = document.getElementById("property-zone-key-light-cast-shadows");
|
||||||
|
|
||||||
// Skybox
|
// Skybox
|
||||||
var elZoneSkyboxModeInherit = document.getElementById("property-zone-skybox-mode-inherit");
|
var elZoneSkyboxModeInherit = document.getElementById("property-zone-skybox-mode-inherit");
|
||||||
var elZoneSkyboxModeDisabled = document.getElementById("property-zone-skybox-mode-disabled");
|
var elZoneSkyboxModeDisabled = document.getElementById("property-zone-skybox-mode-disabled");
|
||||||
|
@ -844,7 +848,6 @@ function loaded() {
|
||||||
|
|
||||||
elLocked.checked = properties.locked;
|
elLocked.checked = properties.locked;
|
||||||
|
|
||||||
|
|
||||||
elName.value = properties.name;
|
elName.value = properties.name;
|
||||||
|
|
||||||
elVisible.checked = properties.visible;
|
elVisible.checked = properties.visible;
|
||||||
|
@ -1011,6 +1014,12 @@ function loaded() {
|
||||||
properties.color.green + "," + properties.color.blue + ")";
|
properties.color.green + "," + properties.color.blue + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties.type === "Model" ||
|
||||||
|
properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") {
|
||||||
|
|
||||||
|
elCanCastShadow.checked = properties.canCastShadow;
|
||||||
|
}
|
||||||
|
|
||||||
if (properties.type === "Model") {
|
if (properties.type === "Model") {
|
||||||
elModelURL.value = properties.modelURL;
|
elModelURL.value = properties.modelURL;
|
||||||
elShapeType.value = properties.shapeType;
|
elShapeType.value = properties.shapeType;
|
||||||
|
@ -1060,7 +1069,6 @@ function loaded() {
|
||||||
elLightFalloffRadius.value = properties.falloffRadius.toFixed(1);
|
elLightFalloffRadius.value = properties.falloffRadius.toFixed(1);
|
||||||
elLightExponent.value = properties.exponent.toFixed(2);
|
elLightExponent.value = properties.exponent.toFixed(2);
|
||||||
elLightCutoff.value = properties.cutoff.toFixed(2);
|
elLightCutoff.value = properties.cutoff.toFixed(2);
|
||||||
|
|
||||||
} else if (properties.type === "Zone") {
|
} else if (properties.type === "Zone") {
|
||||||
// Key light
|
// Key light
|
||||||
elZoneKeyLightModeInherit.checked = (properties.keyLightMode === 'inherit');
|
elZoneKeyLightModeInherit.checked = (properties.keyLightMode === 'inherit');
|
||||||
|
@ -1076,6 +1084,8 @@ function loaded() {
|
||||||
elZoneKeyLightDirectionX.value = properties.keyLight.direction.x.toFixed(2);
|
elZoneKeyLightDirectionX.value = properties.keyLight.direction.x.toFixed(2);
|
||||||
elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2);
|
elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2);
|
||||||
|
|
||||||
|
elZoneKeyLightCastShadows.checked = properties.keyLight.castShadows;
|
||||||
|
|
||||||
// Skybox
|
// Skybox
|
||||||
elZoneSkyboxModeInherit.checked = (properties.skyboxMode === 'inherit');
|
elZoneSkyboxModeInherit.checked = (properties.skyboxMode === 'inherit');
|
||||||
elZoneSkyboxModeDisabled.checked = (properties.skyboxMode === 'disabled');
|
elZoneSkyboxModeDisabled.checked = (properties.skyboxMode === 'disabled');
|
||||||
|
@ -1139,13 +1149,15 @@ function loaded() {
|
||||||
// Show/hide sections as required
|
// Show/hide sections as required
|
||||||
showElements(document.getElementsByClassName('skybox-section'),
|
showElements(document.getElementsByClassName('skybox-section'),
|
||||||
elZoneSkyboxModeEnabled.checked);
|
elZoneSkyboxModeEnabled.checked);
|
||||||
|
|
||||||
showElements(document.getElementsByClassName('keylight-section'),
|
showElements(document.getElementsByClassName('keylight-section'),
|
||||||
elZoneKeyLightModeEnabled.checked);
|
elZoneKeyLightModeEnabled.checked);
|
||||||
|
|
||||||
showElements(document.getElementsByClassName('ambient-section'),
|
showElements(document.getElementsByClassName('ambient-section'),
|
||||||
elZoneAmbientLightModeEnabled.checked);
|
elZoneAmbientLightModeEnabled.checked);
|
||||||
|
|
||||||
showElements(document.getElementsByClassName('haze-section'),
|
showElements(document.getElementsByClassName('haze-section'),
|
||||||
elZoneHazeModeEnabled.checked);
|
elZoneHazeModeEnabled.checked);
|
||||||
|
|
||||||
} else if (properties.type === "PolyVox") {
|
} else if (properties.type === "PolyVox") {
|
||||||
elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2);
|
elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2);
|
||||||
elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2);
|
elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2);
|
||||||
|
@ -1176,6 +1188,15 @@ function loaded() {
|
||||||
elMaterialMappingRot.value = properties.materialMappingRot.toFixed(2);
|
elMaterialMappingRot.value = properties.materialMappingRot.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only these types can cast a shadow
|
||||||
|
if (properties.type === "Model" ||
|
||||||
|
properties.type === "Shape" || properties.type === "Box" || properties.type === "Sphere") {
|
||||||
|
|
||||||
|
showElements(document.getElementsByClassName('can-cast-shadow-section'), true);
|
||||||
|
} else {
|
||||||
|
showElements(document.getElementsByClassName('can-cast-shadow-section'), false);
|
||||||
|
}
|
||||||
|
|
||||||
if (properties.locked) {
|
if (properties.locked) {
|
||||||
disableProperties();
|
disableProperties();
|
||||||
elLocked.removeAttribute('disabled');
|
elLocked.removeAttribute('disabled');
|
||||||
|
@ -1432,6 +1453,8 @@ function loaded() {
|
||||||
|
|
||||||
elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape'));
|
elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape'));
|
||||||
|
|
||||||
|
elCanCastShadow.addEventListener('change', createEmitCheckedPropertyUpdateFunction('canCastShadow'));
|
||||||
|
|
||||||
elImageURL.addEventListener('change', createImageURLUpdateFunction('textures'));
|
elImageURL.addEventListener('change', createImageURLUpdateFunction('textures'));
|
||||||
|
|
||||||
elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl'));
|
elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl'));
|
||||||
|
@ -1590,6 +1613,9 @@ function loaded() {
|
||||||
elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction);
|
elZoneKeyLightDirectionX.addEventListener('change', zoneKeyLightDirectionChangeFunction);
|
||||||
elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction);
|
elZoneKeyLightDirectionY.addEventListener('change', zoneKeyLightDirectionChangeFunction);
|
||||||
|
|
||||||
|
elZoneKeyLightCastShadows.addEventListener('change',
|
||||||
|
createEmitGroupCheckedPropertyUpdateFunction('keyLight', 'castShadows'));
|
||||||
|
|
||||||
// Skybox
|
// Skybox
|
||||||
var skyboxModeChanged = createZoneComponentModeChangedFunction('skyboxMode',
|
var skyboxModeChanged = createZoneComponentModeChangedFunction('skyboxMode',
|
||||||
elZoneSkyboxModeInherit, elZoneSkyboxModeDisabled, elZoneSkyboxModeEnabled);
|
elZoneSkyboxModeInherit, elZoneSkyboxModeDisabled, elZoneSkyboxModeEnabled);
|
||||||
|
|
|
@ -331,7 +331,7 @@ WebTablet.prototype.destroy = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
WebTablet.prototype.geometryChanged = function (geometry) {
|
WebTablet.prototype.geometryChanged = function (geometry) {
|
||||||
if (!HMD.active) {
|
if (!HMD.active && HMD.tabletID) {
|
||||||
var tabletProperties = {};
|
var tabletProperties = {};
|
||||||
// compute position, rotation & parentJointIndex of the tablet
|
// compute position, rotation & parentJointIndex of the tablet
|
||||||
this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties);
|
this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties);
|
||||||
|
@ -459,6 +459,9 @@ WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMou
|
||||||
};
|
};
|
||||||
|
|
||||||
WebTablet.prototype.onHmdChanged = function () {
|
WebTablet.prototype.onHmdChanged = function () {
|
||||||
|
if (!HMD.tabletID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var tabletProperties = {};
|
var tabletProperties = {};
|
||||||
// compute position, rotation & parentJointIndex of the tablet
|
// compute position, rotation & parentJointIndex of the tablet
|
||||||
this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties);
|
this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties);
|
||||||
|
|
|
@ -21,7 +21,10 @@ SPACE_LOCAL = "local";
|
||||||
SPACE_WORLD = "world";
|
SPACE_WORLD = "world";
|
||||||
HIGHLIGHT_LIST_NAME = "editHandleHighlightList";
|
HIGHLIGHT_LIST_NAME = "editHandleHighlightList";
|
||||||
|
|
||||||
Script.include("./controllers.js");
|
Script.include([
|
||||||
|
"./controllers.js",
|
||||||
|
"./utils.js"
|
||||||
|
]);
|
||||||
|
|
||||||
SelectionManager = (function() {
|
SelectionManager = (function() {
|
||||||
var that = {};
|
var that = {};
|
||||||
|
@ -668,7 +671,7 @@ SelectionDisplay = (function() {
|
||||||
|
|
||||||
var pickRay = generalComputePickRay(event.x, event.y);
|
var pickRay = generalComputePickRay(event.x, event.y);
|
||||||
// TODO_Case6491: Move this out to setup just to make it once
|
// TODO_Case6491: Move this out to setup just to make it once
|
||||||
var interactiveOverlays = [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID];
|
var interactiveOverlays = getMainTabletIDs();
|
||||||
for (var key in handleTools) {
|
for (var key in handleTools) {
|
||||||
if (handleTools.hasOwnProperty(key)) {
|
if (handleTools.hasOwnProperty(key)) {
|
||||||
interactiveOverlays.push(key);
|
interactiveOverlays.push(key);
|
||||||
|
@ -681,8 +684,8 @@ SelectionDisplay = (function() {
|
||||||
var results = testRayIntersect(pickRay, interactiveOverlays);
|
var results = testRayIntersect(pickRay, interactiveOverlays);
|
||||||
if (results.intersects) {
|
if (results.intersects) {
|
||||||
var hitOverlayID = results.overlayID;
|
var hitOverlayID = results.overlayID;
|
||||||
if ((hitOverlayID === HMD.tabletID) || (hitOverlayID === HMD.tabletScreenID) ||
|
if ((HMD.tabletID && hitOverlayID === HMD.tabletID) || (HMD.tabletScreenID && hitOverlayID === HMD.tabletScreenID)
|
||||||
(hitOverlayID === HMD.homeButtonID)) {
|
|| (HMD.homeButtonID && hitOverlayID === HMD.homeButtonID)) {
|
||||||
// EARLY EXIT-(mouse clicks on the tablet should override the edit affordances)
|
// EARLY EXIT-(mouse clicks on the tablet should override the edit affordances)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,3 +428,17 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
|
||||||
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getMainTabletIDs = function () {
|
||||||
|
var tabletIDs = [];
|
||||||
|
if (HMD.tabletID) {
|
||||||
|
tabletIDs.push(HMD.tabletID);
|
||||||
|
}
|
||||||
|
if (HMD.tabletScreenID) {
|
||||||
|
tabletIDs.push(HMD.tabletScreenID);
|
||||||
|
}
|
||||||
|
if (HMD.homeButtonID) {
|
||||||
|
tabletIDs.push(HMD.homeButtonID);
|
||||||
|
}
|
||||||
|
return tabletIDs;
|
||||||
|
};
|
|
@ -75,11 +75,11 @@ var selectionDisplay = null; // for gridTool.js to ignore
|
||||||
tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH);
|
tablet.pushOntoStack(MARKETPLACE_CHECKOUT_QML_PATH);
|
||||||
tablet.sendToQml({
|
tablet.sendToQml({
|
||||||
method: 'updateCheckoutQML', params: {
|
method: 'updateCheckoutQML', params: {
|
||||||
itemId: '0d90d21c-ce7a-4990-ad18-e9d2cf991027',
|
itemId: '424611a2-73d0-4c03-9087-26a6a279257b',
|
||||||
itemName: 'Test Flaregun',
|
itemName: '2018-02-15 Finnegon',
|
||||||
itemPrice: (debugError ? 10 : 17),
|
itemPrice: (debugError ? 10 : 3),
|
||||||
itemHref: 'http://mpassets.highfidelity.com/0d90d21c-ce7a-4990-ad18-e9d2cf991027-v1/flaregun.json',
|
itemHref: 'http://devmpassets.highfidelity.com/424611a2-73d0-4c03-9087-26a6a279257b-v1/finnigon.fst',
|
||||||
categories: ["Wearables", "Miscellaneous"]
|
categories: ["Miscellaneous"]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -104,8 +104,9 @@ var selectionDisplay = null; // for gridTool.js to ignore
|
||||||
tablet.gotoHomeScreen();
|
tablet.gotoHomeScreen();
|
||||||
} else {
|
} else {
|
||||||
Wallet.refreshWalletStatus();
|
Wallet.refreshWalletStatus();
|
||||||
var entity = HMD.tabletID;
|
if (HMD.tabletID) {
|
||||||
Entities.editEntity(entity, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
|
Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
|
||||||
|
}
|
||||||
showMarketplace();
|
showMarketplace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,13 +233,19 @@ var selectionDisplay = null; // for gridTool.js to ignore
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
function rezEntity(itemHref, isWearable) {
|
function rezEntity(itemHref, itemType) {
|
||||||
|
var isWearable = itemType === "wearable";
|
||||||
var success = Clipboard.importEntities(itemHref);
|
var success = Clipboard.importEntities(itemHref);
|
||||||
var wearableLocalPosition = null;
|
var wearableLocalPosition = null;
|
||||||
var wearableLocalRotation = null;
|
var wearableLocalRotation = null;
|
||||||
var wearableLocalDimensions = null;
|
var wearableLocalDimensions = null;
|
||||||
var wearableDimensions = null;
|
var wearableDimensions = null;
|
||||||
|
|
||||||
|
if (itemType === "contentSet") {
|
||||||
|
console.log("Item is a content set; codepath shouldn't go here.")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isWearable) {
|
if (isWearable) {
|
||||||
var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms");
|
var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms");
|
||||||
if (!wearableTransforms) {
|
if (!wearableTransforms) {
|
||||||
|
@ -544,7 +551,7 @@ var selectionDisplay = null; // for gridTool.js to ignore
|
||||||
break;
|
break;
|
||||||
case 'checkout_rezClicked':
|
case 'checkout_rezClicked':
|
||||||
case 'purchases_rezClicked':
|
case 'purchases_rezClicked':
|
||||||
rezEntity(message.itemHref, message.isWearable);
|
rezEntity(message.itemHref, message.itemType);
|
||||||
break;
|
break;
|
||||||
case 'header_marketplaceImageClicked':
|
case 'header_marketplaceImageClicked':
|
||||||
case 'purchases_backClicked':
|
case 'purchases_backClicked':
|
||||||
|
|
|
@ -28,8 +28,9 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-
|
||||||
// for toolbar-mode: go back to home screen, this will close the window.
|
// for toolbar-mode: go back to home screen, this will close the window.
|
||||||
tablet.gotoHomeScreen();
|
tablet.gotoHomeScreen();
|
||||||
} else {
|
} else {
|
||||||
var entity = HMD.tabletID;
|
if (HMD.tabletID) {
|
||||||
Entities.editEntity(entity, {textures: JSON.stringify({"tex.close": HOME_BUTTON_TEXTURE})});
|
Entities.editEntity(HMD.tabletID, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) });
|
||||||
|
}
|
||||||
tablet.gotoMenuScreen();
|
tablet.gotoMenuScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,14 +41,14 @@
|
||||||
if (!UIWebTablet) {
|
if (!UIWebTablet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Overlays.getProperty(HMD.tabletID, "type") != "model") {
|
if (Overlays.getProperty(HMD.tabletID, "type") !== "model") {
|
||||||
if (debugTablet) {
|
if (debugTablet) {
|
||||||
print("TABLET is invalid due to frame: " + JSON.stringify(Overlays.getProperty(HMD.tabletID, "type")));
|
print("TABLET is invalid due to frame: " + JSON.stringify(Overlays.getProperty(HMD.tabletID, "type")));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Overlays.getProperty(HMD.homeButtonID, "type") != "circle3d" ||
|
if (Overlays.getProperty(HMD.homeButtonID, "type") !== "circle3d" ||
|
||||||
Overlays.getProperty(HMD.tabletScreenID, "type") != "web3d") {
|
Overlays.getProperty(HMD.tabletScreenID, "type") !== "web3d") {
|
||||||
if (debugTablet) {
|
if (debugTablet) {
|
||||||
print("TABLET is invalid due to other");
|
print("TABLET is invalid due to other");
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function showTabletUI() {
|
function showTabletUI() {
|
||||||
checkTablet()
|
checkTablet();
|
||||||
|
|
||||||
if (!tabletRezzed || !tabletIsValid()) {
|
if (!tabletRezzed || !tabletIsValid()) {
|
||||||
closeTabletUI();
|
closeTabletUI();
|
||||||
|
@ -157,7 +157,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeTabletUI() {
|
function closeTabletUI() {
|
||||||
checkTablet()
|
checkTablet();
|
||||||
gTablet.tabletShown = false;
|
gTablet.tabletShown = false;
|
||||||
if (UIWebTablet) {
|
if (UIWebTablet) {
|
||||||
if (UIWebTablet.onClose) {
|
if (UIWebTablet.onClose) {
|
||||||
|
@ -178,14 +178,14 @@
|
||||||
print("TABLET closeTabletUI, UIWebTablet is null");
|
print("TABLET closeTabletUI, UIWebTablet is null");
|
||||||
}
|
}
|
||||||
tabletRezzed = false;
|
tabletRezzed = false;
|
||||||
gTablet = null
|
gTablet = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function updateShowTablet() {
|
function updateShowTablet() {
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
|
|
||||||
checkTablet()
|
checkTablet();
|
||||||
|
|
||||||
// close the WebTablet if it we go into toolbar mode.
|
// close the WebTablet if it we go into toolbar mode.
|
||||||
var tabletShown = gTablet.tabletShown;
|
var tabletShown = gTablet.tabletShown;
|
||||||
|
@ -270,7 +270,7 @@
|
||||||
}
|
}
|
||||||
if (channel === "home") {
|
if (channel === "home") {
|
||||||
if (UIWebTablet) {
|
if (UIWebTablet) {
|
||||||
checkTablet()
|
checkTablet();
|
||||||
gTablet.landscape = false;
|
gTablet.landscape = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,8 @@
|
||||||
// for toolbar-mode: go back to home screen, this will close the window.
|
// for toolbar-mode: go back to home screen, this will close the window.
|
||||||
tablet.gotoHomeScreen();
|
tablet.gotoHomeScreen();
|
||||||
} else {
|
} else {
|
||||||
var tabletEntity = HMD.tabletID;
|
if (HMD.tabletID) {
|
||||||
if (tabletEntity) {
|
Entities.editEntity(HMD.tabletID, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})});
|
||||||
Entities.editEntity(tabletEntity, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})});
|
|
||||||
}
|
}
|
||||||
shouldActivateButton = true;
|
shouldActivateButton = true;
|
||||||
tablet.gotoWebScreen(USERS_URL);
|
tablet.gotoWebScreen(USERS_URL);
|
||||||
|
|
|
@ -173,8 +173,18 @@ Laser = function (side) {
|
||||||
// Normal laser operation with trigger.
|
// Normal laser operation with trigger.
|
||||||
intersection = Overlays.findRayIntersection(pickRay, PRECISION_PICKING, NO_INCLUDE_IDS, NO_EXCLUDE_IDS,
|
intersection = Overlays.findRayIntersection(pickRay, PRECISION_PICKING, NO_INCLUDE_IDS, NO_EXCLUDE_IDS,
|
||||||
VISIBLE_ONLY);
|
VISIBLE_ONLY);
|
||||||
|
var tabletIDs = [];
|
||||||
|
if (HMD.tabletID) {
|
||||||
|
tabletIDs.push(HMD.tabletID);
|
||||||
|
}
|
||||||
|
if (HMD.tabletScreenID) {
|
||||||
|
tabletIDs.push(HMD.tabletScreenID);
|
||||||
|
}
|
||||||
|
if (HMD.homeButtonID) {
|
||||||
|
tabletIDs.push(HMD.homeButtonID);
|
||||||
|
}
|
||||||
if (Reticle.pointingAtSystemOverlay || (intersection.overlayID
|
if (Reticle.pointingAtSystemOverlay || (intersection.overlayID
|
||||||
&& [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID].indexOf(intersection.overlayID) !== -1)) {
|
&& tabletIDs.indexOf(intersection.overlayID) !== -1)) {
|
||||||
// No laser if pointing at HUD overlay or tablet; system provides lasers for these cases.
|
// No laser if pointing at HUD overlay or tablet; system provides lasers for these cases.
|
||||||
if (isLaserOn) {
|
if (isLaserOn) {
|
||||||
isLaserOn = false;
|
isLaserOn = false;
|
||||||
|
|
Loading…
Reference in a new issue