- Add your High Fidelity username and any other usernames to grant administrator privileges.
-
+ Add your High Fidelity username and any other usernames to grant administrator privileges
@@ -78,7 +77,7 @@
- Who can connect to your domain?
+ Who can connect to your domain?
@@ -87,25 +86,21 @@
@@ -113,7 +108,7 @@
- Who can rez items in your domain?
+ Who can rez items in your domain?
@@ -122,33 +117,32 @@
-
+
+
+
+
-
+
@@ -188,35 +182,37 @@
-
+
+
+
+
-
+
-
+
-
-
+
+
Congratulations! You have successfully setup and configured your cloud hosted domain.
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/domain-server/resources/web/wizard/js/wizard.js b/domain-server/resources/web/wizard/js/wizard.js
index 1af3f305b7..57e85973f4 100644
--- a/domain-server/resources/web/wizard/js/wizard.js
+++ b/domain-server/resources/web/wizard/js/wizard.js
@@ -2,6 +2,8 @@ var Metaverse = {
accessToken: null
}
+var currentStepNumber;
+
$(document).ready(function(){
Strings.ADD_PLACE_NOT_CONNECTED_MESSAGE = "You must have an access token to query your High Fidelity places.
" +
"Please go back and connect your account.";
@@ -9,6 +11,22 @@ $(document).ready(function(){
$('#connect-account-btn').attr('href', URLs.METAVERSE_URL + "/user/tokens/new?for_domain_server=true");
$('[data-toggle="tooltip"]').tooltip();
+
+ $('.perms-link').on('click', function() {
+ var modal_body = '
';
+ modal_body += 'None - No one will have permissions. Only you and the users your have given administrator privileges to will have permissions.';
+ modal_body += 'Friends - Users who are your Friends in High Fidelity.';
+ modal_body += 'Users logged into High Fidelity - Users who are currently logged into High Fidelity.';
+ modal_body += 'Everyone - Anyone who uses High Fidelity.';
+ modal_body += '
';
+
+ dialog = bootbox.dialog({
+ title: "User definition",
+ message: modal_body,
+ closeButton: true
+ });
+ return false;
+ });
$('body').on('click', '.next-button', function() {
goToNextStep();
@@ -56,6 +74,36 @@ $(document).ready(function(){
exploreSettings();
});
+ $('input[type=radio][name=connect-radio]').change(function() {
+ var inputs = $('input[type=radio][name=rez-radio]');
+ var disabled = [];
+
+ switch (this.value) {
+ case 'none':
+ disabled = inputs.splice(1);
+ break;
+ case 'friends':
+ disabled = inputs.splice(2);
+ break;
+ case 'logged-in':
+ disabled = inputs.splice(3);
+ break;
+ case 'everyone':
+ disabled = inputs.splice(4);
+ break;
+ }
+
+ $.each(inputs, function() {
+ $(this).prop('disabled', false);
+ });
+ $.each(disabled, function() {
+ if ($(this).prop('checked')) {
+ $(inputs.last()).prop('checked', true);
+ }
+ $(this).prop('disabled', true);
+ });
+ });
+
reloadSettings(function(success) {
if (success) {
getDomainFromAPI();
@@ -73,12 +121,12 @@ $(document).ready(function(){
});
function setupWizardSteps() {
- var stepsCompleted = Settings.data.values.wizard.steps_completed;
+ currentStepNumber = Settings.data.values.wizard.steps_completed;
var steps = null;
if (Settings.data.values.wizard.cloud_domain) {
$('.desktop-only').remove();
- $('.wizard-step').find('.back-button').hide();
+ $('.wizard-step:first').find('.back-button').hide();
steps = $('.wizard-step');
$(steps).each(function(i) {
@@ -86,7 +134,7 @@ function setupWizardSteps() {
});
$('#permissions-description').html('You have been assigned administrator privileges to this domain.');
- $('#admin-description').html('Add more High Fidelity usernames to grant administrator privileges.');
+ $('#admin-description').html('Add more High Fidelity usernames');
} else {
$('.cloud-only').remove();
$('#save-permissions').text("Finish");
@@ -96,12 +144,12 @@ function setupWizardSteps() {
$(this).children(".step-title").text("Step " + (i + 1) + " of " + steps.length);
});
- if (stepsCompleted == 0) {
+ if (currentStepNumber == 0) {
$('#skip-wizard-button').show();
}
}
- var currentStep = steps[stepsCompleted];
+ var currentStep = steps[currentStepNumber];
$(currentStep).show();
}
@@ -204,7 +252,7 @@ function goToNextStep() {
currentStep.hide();
nextStep.show();
- var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) + 1;
+ currentStepNumber += 1;
postSettings({
"wizard": {
@@ -233,7 +281,7 @@ function goToPreviousStep() {
currentStep.hide();
previousStep.show();
- var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) - 1;
+ currentStepNumber -= 1;
postSettings({
"wizard": {
@@ -439,7 +487,7 @@ function saveUsernamePassword() {
return;
}
- var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) + 1;
+ currentStepNumber += 1;
var formJSON = {
"security": {
diff --git a/interface/resources/fonts/hifi-glyphs.ttf b/interface/resources/fonts/hifi-glyphs.ttf
index 3db48602b1..4cc5a0fe4f 100644
Binary files a/interface/resources/fonts/hifi-glyphs.ttf and b/interface/resources/fonts/hifi-glyphs.ttf differ
diff --git a/interface/resources/images/lowerKeyboard.png b/interface/resources/images/lowerKeyboard.png
new file mode 100644
index 0000000000..d379b028ab
Binary files /dev/null and b/interface/resources/images/lowerKeyboard.png differ
diff --git a/interface/resources/qml/controls-uit/Key.qml b/interface/resources/qml/controls-uit/Key.qml
index e54250c872..b0e965e79f 100644
--- a/interface/resources/qml/controls-uit/Key.qml
+++ b/interface/resources/qml/controls-uit/Key.qml
@@ -5,10 +5,16 @@ Item {
id: keyItem
width: 45
height: 50
+
+ property int contentPadding: 4
property string glyph: "a"
property bool toggle: false // does this button have the toggle behaivor?
property bool toggled: false // is this button currently toggled?
property alias mouseArea: mouseArea1
+ property alias fontFamily: letter.font.family;
+ property alias fontPixelSize: letter.font.pixelSize
+ property alias verticalAlignment: letter.verticalAlignment
+ property alias letterAnchors: letter.anchors
function resetToggledMode(mode) {
toggled = mode;
@@ -105,14 +111,8 @@ Item {
color: "#121212"
radius: 2
border.color: "#00000000"
- anchors.right: parent.right
- anchors.rightMargin: 4
- anchors.left: parent.left
- anchors.leftMargin: 4
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 4
- anchors.top: parent.top
- anchors.topMargin: 4
+ anchors.fill: parent
+ anchors.margins: contentPadding
}
Text {
diff --git a/interface/resources/qml/controls-uit/Keyboard.qml b/interface/resources/qml/controls-uit/Keyboard.qml
index 66a61742c9..76b66178d4 100644
--- a/interface/resources/qml/controls-uit/Keyboard.qml
+++ b/interface/resources/qml/controls-uit/Keyboard.qml
@@ -8,7 +8,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
-import QtQuick 2.0
+import QtQuick 2.7
+import QtGraphicalEffects 1.0
import "."
Rectangle {
@@ -55,6 +56,8 @@ Rectangle {
return ">";
} else if (str === "/") {
return "?";
+ } else if (str === "-") {
+ return "_";
} else {
return str.toUpperCase(str);
}
@@ -67,6 +70,8 @@ Rectangle {
return ".";
} else if (str === "?") {
return "/";
+ } else if (str === "_") {
+ return "-";
} else {
return str.toLowerCase(str);
}
@@ -85,7 +90,7 @@ Rectangle {
onShiftModeChanged: {
forEachKey(function (key) {
- if (/[a-z]/i.test(key.glyph)) {
+ if (/[a-z-_]/i.test(key.glyph)) {
if (shiftMode) {
key.glyph = keyboardBase.toUpper(key.glyph);
} else {
@@ -112,8 +117,6 @@ Rectangle {
}
Rectangle {
- y: 0
- x: 0
height: showMirrorText ? mirrorTextHeight : 0
width: keyboardWidth
color: "#252525"
@@ -122,13 +125,18 @@ Rectangle {
TextInput {
id: mirrorText
visible: showMirrorText
- FontLoader { id: ralewaySemiBold; source: "../../fonts/Raleway-SemiBold.ttf"; }
- font.family: ralewaySemiBold.name
- font.pointSize: 13.5
+ FontLoader { id: font; source: "../../fonts/FiraSans-Regular.ttf"; }
+ font.family: font.name
+ font.pixelSize: 20
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
- color: "#FFFFFF";
- anchors.fill: parent
+ color: "#00B4EF";
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+
wrapMode: Text.WordWrap
readOnly: false // we need this to allow control to accept QKeyEvent
selectByMouse: false
@@ -140,16 +148,15 @@ Rectangle {
event.accepted = true;
}
}
- }
- MouseArea { // ... and we need this mouse area to prevent mirrorText from getting mouse events to ensure it will never get focus
- anchors.fill: parent
+ MouseArea { // ... and we need this mouse area to prevent mirrorText from getting mouse events to ensure it will never get focus
+ anchors.fill: parent
+ }
}
}
Rectangle {
id: keyboardRect
- x: 0
y: showMirrorText ? mirrorTextHeight : 0
width: keyboardWidth
height: raisedHeight
@@ -158,6 +165,8 @@ Rectangle {
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
+ FontLoader { id: hiFiGlyphs; source: pathToFonts + "fonts/hifi-glyphs.ttf"; }
+
Column {
id: columnAlpha
width: keyboardWidth
@@ -221,7 +230,7 @@ Rectangle {
Key { width: 43; glyph: "b"; }
Key { width: 43; glyph: "n"; }
Key { width: 43; glyph: "m"; }
- Key { width: 43; glyph: "_"; }
+ Key { width: 43; glyph: "-"; }
Key { width: 43; glyph: "/"; }
Key { width: 43; glyph: "?"; }
}
@@ -240,8 +249,13 @@ Rectangle {
Key { width: 231; glyph: " "; }
Key { width: 43; glyph: ","; }
Key { width: 43; glyph: "."; }
- Key { width: 43; glyph: "\u276C"; }
- Key { width: 43; glyph: "\u276D"; }
+ Key {
+ fontFamily: hiFiGlyphs.name;
+ fontPixelSize: 48;
+ letterAnchors.topMargin: -4;
+ verticalAlignment: Text.AlignVCenter;
+ width: 86; glyph: "\ue02b";
+ }
}
}
@@ -328,8 +342,13 @@ Rectangle {
Key { width: 231; glyph: " "; }
Key { width: 43; glyph: ","; }
Key { width: 43; glyph: "."; }
- Key { width: 43; glyph: "\u276C"; }
- Key { width: 43; glyph: "\u276D"; }
+ Key {
+ fontFamily: hiFiGlyphs.name;
+ fontPixelSize: 48;
+ letterAnchors.topMargin: -4;
+ verticalAlignment: Text.AlignVCenter;
+ width: 86; glyph: "\ue02b";
+ }
}
}
}
diff --git a/interface/resources/qml/controls/FlickableWebViewCore.qml b/interface/resources/qml/controls/FlickableWebViewCore.qml
index cbc4d19334..29944781c1 100644
--- a/interface/resources/qml/controls/FlickableWebViewCore.qml
+++ b/interface/resources/qml/controls/FlickableWebViewCore.qml
@@ -27,6 +27,12 @@ Item {
id: hifi
}
+ function unfocus() {
+ webViewCore.runJavaScript("if (document.activeElement) document.activeElement.blur();", function(result) {
+ console.log('unfocus completed: ', result);
+ });
+ }
+
function onLoadingChanged(loadRequest) {
if (WebEngineView.LoadStartedStatus === loadRequest.status) {
diff --git a/interface/resources/qml/controls/TabletWebScreen.qml b/interface/resources/qml/controls/TabletWebScreen.qml
index e06ff51569..501e321f0d 100644
--- a/interface/resources/qml/controls/TabletWebScreen.qml
+++ b/interface/resources/qml/controls/TabletWebScreen.qml
@@ -10,6 +10,11 @@ Item {
property alias urlTag: webroot.urlTag
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
property bool keyboardRaised: false
+ onKeyboardRaisedChanged: {
+ if(!keyboardRaised) {
+ webroot.unfocus();
+ }
+ }
property bool punctuationMode: false
// FIXME - Keyboard HMD only: Make Interface either set keyboardRaised property directly in OffscreenQmlSurface
diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml
index 8cd61bc90b..477422cfa1 100644
--- a/interface/resources/qml/controls/TabletWebView.qml
+++ b/interface/resources/qml/controls/TabletWebView.qml
@@ -15,6 +15,11 @@ Item {
property string scriptURL
property bool keyboardEnabled: false
property bool keyboardRaised: false
+ onKeyboardRaisedChanged: {
+ if(!keyboardRaised) {
+ webroot.unfocus();
+ }
+ }
property bool punctuationMode: false
property bool passwordField: false
property bool isDesktop: false
diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml
index 923c8f3fa1..931c64e1ef 100644
--- a/interface/resources/qml/controls/WebView.qml
+++ b/interface/resources/qml/controls/WebView.qml
@@ -12,6 +12,11 @@ Item {
property alias urlTag: webroot.urlTag
property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false
property bool keyboardRaised: false
+ onKeyboardRaisedChanged: {
+ if(!keyboardRaised) {
+ webroot.unfocus();
+ }
+ }
property bool punctuationMode: false
property bool passwordField: false
property alias flickable: webroot.interactive
diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml
index dfe0c319e5..3e7c23f2dd 100644
--- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml
+++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml
@@ -476,9 +476,7 @@ Rectangle {
commerce.buy(itemId, itemPrice, true);
}
} else {
- if (urlHandler.canHandleUrl(itemHref)) {
- urlHandler.handleUrl(itemHref);
- }
+ sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable});
}
}
}
diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml
index b6c29a1fad..14ed9ece67 100644
--- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml
+++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml
@@ -113,21 +113,6 @@ Rectangle {
}
}
- onVisibleChanged: {
- if (!visible) {
- titleBarText.text = "Certificate";
- popText.text = "PROOF OF PURCHASE";
- root.certificateId = "";
- root.itemName = "--";
- root.itemOwner = "--";
- root.itemEdition = "--";
- root.dateOfPurchase = "--";
- root.marketplaceUrl = "";
- root.isMyCert = false;
- errorText.text = "";
- }
- }
-
// This object is always used in a popup.
// This MouseArea is used to prevent a user from being
// able to click on a button/mouseArea underneath the popup.
@@ -420,6 +405,18 @@ Rectangle {
case 'inspectionCertificate_setCertificateId':
root.certificateId = message.certificateId;
break;
+ case 'inspectionCertificate_resetCert':
+ titleBarText.text = "Certificate";
+ popText.text = "PROOF OF PURCHASE";
+ root.certificateId = "";
+ root.itemName = "--";
+ root.itemOwner = "--";
+ root.itemEdition = "--";
+ root.dateOfPurchase = "--";
+ root.marketplaceUrl = "";
+ root.isMyCert = false;
+ errorText.text = "";
+ break;
default:
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
}
diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml
index fb42865ba4..15ebada0c4 100644
--- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml
+++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml
@@ -346,9 +346,7 @@ Item {
enabled: (root.canRezCertifiedItems || root.isWearable) && root.purchaseStatus !== "invalidated";
onClicked: {
- if (urlHandler.canHandleUrl(root.itemHref)) {
- urlHandler.handleUrl(root.itemHref);
- }
+ sendToPurchases({method: 'purchases_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable});
rezzedNotifContainer.visible = true;
rezzedNotifContainerTimer.start();
}
diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
index f292f9603e..1ea488ac98 100644
--- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
+++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml
@@ -442,6 +442,8 @@ Rectangle {
onSendToPurchases: {
if (msg.method === 'purchases_itemInfoClicked') {
sendToScript({method: 'purchases_itemInfoClicked', itemId: itemId});
+ } else if (msg.method === "purchases_rezClicked") {
+ sendToScript({method: 'purchases_rezClicked', itemHref: itemHref, isWearable: isWearable});
} else if (msg.method === 'purchases_itemCertificateClicked') {
inspectionCertificate.visible = true;
inspectionCertificate.isLightbox = true;
diff --git a/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml b/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml
index 80c1b58444..83f91c78c5 100644
--- a/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml
+++ b/interface/resources/qml/hifi/dialogs/TabletRunningScripts.qml
@@ -32,6 +32,8 @@ Rectangle {
color: hifi.colors.baseGray
+ property bool keyboardEnabled: HMD.active
+ property bool keyboardRaised: false
LetterboxMessage {
id: letterBoxMessage
@@ -380,7 +382,7 @@ Rectangle {
Component.onCompleted: scriptsModel.filterRegExp = new RegExp("^.*$", "i")
onActiveFocusChanged: {
// raise the keyboard
- keyboard.raised = activeFocus;
+ root.keyboardRaised = activeFocus;
// scroll to the bottom of the content area.
if (activeFocus) {
@@ -481,7 +483,7 @@ Rectangle {
HifiControls.Keyboard {
id: keyboard
- raised: false
+ raised: parent.keyboardEnabled && parent.keyboardRaised
numeric: false
anchors {
bottom: parent.bottom
diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml
index 4d9a83817a..649a8e6259 100644
--- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml
+++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml
@@ -366,7 +366,7 @@ StackView {
HifiControls.Keyboard {
id: keyboard
- raised: parent.keyboardEnabled
+ raised: parent.keyboardEnabled && parent.keyboardRaised
numeric: parent.punctuationMode
anchors {
bottom: parent.bottom
diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp
index 1f839b25eb..b31376fcf6 100644
--- a/libraries/render-utils/src/RenderDeferredTask.cpp
+++ b/libraries/render-utils/src/RenderDeferredTask.cpp
@@ -448,6 +448,11 @@ void CompositeHUD::run(const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_context);
+ // We do not want to render HUD elements in secondary camera
+ if (renderContext->args->_renderMode == RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) {
+ return;
+ }
+
// Grab the HUD texture
gpu::doInBatch(renderContext->args->_context, [&](gpu::Batch& batch) {
if (renderContext->args->_hudOperator) {
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
index ecd07a5874..01f8f4580a 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp
@@ -1038,6 +1038,7 @@ static const uint8_t BACKSPACE_SYMBOL[] = { 0xE2, 0x86, 0x90, 0x00 };
static const uint8_t LEFT_ARROW[] = { 0xE2, 0x9D, 0xAC, 0x00 };
static const uint8_t RIGHT_ARROW[] = { 0xE2, 0x9D, 0xAD, 0x00 };
static const uint8_t RETURN_SYMBOL[] = { 0xE2, 0x8F, 0x8E, 0x00 };
+static const uint8_t COLLAPSE_KEYBOARD[] = { 0xEE, 0x80, 0xAB, 0x00 };
static const char PUNCTUATION_STRING[] = "123";
static const char ALPHABET_STRING[] = "abc";
@@ -1061,6 +1062,9 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key, QObject* targetOverrid
if (equals(utf8Key, SHIFT_ARROW) || equals(utf8Key, NUMERIC_SHIFT_ARROW) ||
equals(utf8Key, (uint8_t*)PUNCTUATION_STRING) || equals(utf8Key, (uint8_t*)ALPHABET_STRING)) {
return; // ignore
+ } else if (equals(utf8Key, COLLAPSE_KEYBOARD)) {
+ lowerKeyboard();
+ return;
} else if (equals(utf8Key, BACKSPACE_SYMBOL)) {
scanCode = Qt::Key_Backspace;
keyString = "\x08";
@@ -1082,7 +1086,19 @@ void OffscreenQmlSurface::synthesizeKeyPress(QString key, QObject* targetOverrid
}
}
+void OffscreenQmlSurface::lowerKeyboard() {
+
+ QSignalBlocker blocker(_quickWindow);
+
+ if (_currentFocusItem) {
+ _currentFocusItem->setFocus(false);
+ setKeyboardRaised(_currentFocusItem, false);
+ }
+}
+
void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool numeric, bool passwordField) {
+ qCDebug(uiLogging) << "setKeyboardRaised: " << object << ", raised: " << raised << ", numeric: " << numeric << ", password: " << passwordField;
+
#if Q_OS_ANDROID
return;
#endif
@@ -1117,6 +1133,10 @@ void OffscreenQmlSurface::setKeyboardRaised(QObject* object, bool raised, bool n
item->setProperty("passwordField", QVariant(passwordField));
}
+ if (raised) {
+ item->setProperty("keyboardRaised", QVariant(!raised));
+ }
+
item->setProperty("keyboardRaised", QVariant(raised));
return;
}
diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.h b/libraries/ui/src/ui/OffscreenQmlSurface.h
index 12ee9e59a1..5acdeb4f40 100644
--- a/libraries/ui/src/ui/OffscreenQmlSurface.h
+++ b/libraries/ui/src/ui/OffscreenQmlSurface.h
@@ -84,6 +84,7 @@ public:
void setKeyboardRaised(QObject* object, bool raised, bool numeric = false, bool passwordField = false);
Q_INVOKABLE void synthesizeKeyPress(QString key, QObject* targetOverride = nullptr);
+ Q_INVOKABLE void lowerKeyboard();
using TextureAndFence = std::pair;
// Checks to see if a new texture is available. If one is, the function returns true and
diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js
index f0044084f6..80990402d7 100644
--- a/scripts/system/marketplaces/marketplaces.js
+++ b/scripts/system/marketplaces/marketplaces.js
@@ -128,6 +128,12 @@
} else {
ContextOverlay.isInMarketplaceInspectionMode = false;
}
+
+ if (!onCommerceScreen) {
+ tablet.sendToQml({
+ method: 'inspectionCertificate_resetCert'
+ });
+ }
}
function openWallet() {
@@ -162,6 +168,106 @@
}));
}
+ var HALF_TREE_SCALE = 16384;
+ function getPositionToCreateEntity(extra) {
+ var CREATE_DISTANCE = 2;
+ var position;
+ var delta = extra !== undefined ? extra : 0;
+ if (Camera.mode === "entity" || Camera.mode === "independent") {
+ position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getForward(Camera.orientation), CREATE_DISTANCE + delta));
+ } else {
+ position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getForward(MyAvatar.orientation), CREATE_DISTANCE + delta));
+ position.y += 0.5;
+ }
+
+ if (position.x > HALF_TREE_SCALE || position.y > HALF_TREE_SCALE || position.z > HALF_TREE_SCALE) {
+ return null;
+ }
+ return position;
+ }
+
+ function rezEntity(itemHref, isWearable) {
+ var success = Clipboard.importEntities(itemHref);
+
+ if (success) {
+ var VERY_LARGE = 10000;
+ var isLargeImport = Clipboard.getClipboardContentsLargestDimension() >= VERY_LARGE;
+ var position = Vec3.ZERO;
+ if (!isLargeImport) {
+ position = getPositionToCreateEntity(Clipboard.getClipboardContentsLargestDimension() / 2);
+ }
+ if (position !== null && position !== undefined) {
+ var pastedEntityIDs = Clipboard.pasteEntities(position);
+ if (!isLargeImport) {
+ // The first entity in Clipboard gets the specified position with the rest being relative to it. Therefore, move
+ // entities after they're imported so that they're all the correct distance in front of and with geometric mean
+ // centered on the avatar/camera direction.
+ var deltaPosition = Vec3.ZERO;
+ var entityPositions = [];
+ var entityParentIDs = [];
+
+ var propType = Entities.getEntityProperties(pastedEntityIDs[0], ["type"]).type;
+ var NO_ADJUST_ENTITY_TYPES = ["Zone", "Light", "ParticleEffect"];
+ if (NO_ADJUST_ENTITY_TYPES.indexOf(propType) === -1) {
+ var targetDirection;
+ if (Camera.mode === "entity" || Camera.mode === "independent") {
+ targetDirection = Camera.orientation;
+ } else {
+ targetDirection = MyAvatar.orientation;
+ }
+ targetDirection = Vec3.multiplyQbyV(targetDirection, Vec3.UNIT_Z);
+
+ var targetPosition = getPositionToCreateEntity();
+ var deltaParallel = HALF_TREE_SCALE; // Distance to move entities parallel to targetDirection.
+ var deltaPerpendicular = Vec3.ZERO; // Distance to move entities perpendicular to targetDirection.
+ for (var i = 0, length = pastedEntityIDs.length; i < length; i++) {
+ var curLoopEntityProps = Entities.getEntityProperties(pastedEntityIDs[i], ["position", "dimensions",
+ "registrationPoint", "rotation", "parentID"]);
+ var adjustedPosition = adjustPositionPerBoundingBox(targetPosition, targetDirection,
+ curLoopEntityProps.registrationPoint, curLoopEntityProps.dimensions, curLoopEntityProps.rotation);
+ var delta = Vec3.subtract(adjustedPosition, curLoopEntityProps.position);
+ var distance = Vec3.dot(delta, targetDirection);
+ deltaParallel = Math.min(distance, deltaParallel);
+ deltaPerpendicular = Vec3.sum(Vec3.subtract(delta, Vec3.multiply(distance, targetDirection)),
+ deltaPerpendicular);
+ entityPositions[i] = curLoopEntityProps.position;
+ entityParentIDs[i] = curLoopEntityProps.parentID;
+ }
+ deltaPerpendicular = Vec3.multiply(1 / pastedEntityIDs.length, deltaPerpendicular);
+ deltaPosition = Vec3.sum(Vec3.multiply(deltaParallel, targetDirection), deltaPerpendicular);
+ }
+
+ if (grid.getSnapToGrid()) {
+ var firstEntityProps = Entities.getEntityProperties(pastedEntityIDs[0], ["position", "dimensions",
+ "registrationPoint"]);
+ var positionPreSnap = Vec3.sum(deltaPosition, firstEntityProps.position);
+ position = grid.snapToSurface(grid.snapToGrid(positionPreSnap, false, firstEntityProps.dimensions,
+ firstEntityProps.registrationPoint), firstEntityProps.dimensions, firstEntityProps.registrationPoint);
+ deltaPosition = Vec3.subtract(position, firstEntityProps.position);
+ }
+
+ if (!Vec3.equal(deltaPosition, Vec3.ZERO)) {
+ for (var editEntityIndex = 0, numEntities = pastedEntityIDs.length; editEntityIndex < numEntities; editEntityIndex++) {
+ if (Uuid.isNull(entityParentIDs[editEntityIndex])) {
+ Entities.editEntity(pastedEntityIDs[editEntityIndex], {
+ position: Vec3.sum(deltaPosition, entityPositions[editEntityIndex])
+ });
+ }
+ }
+ }
+ }
+
+ if (isActive) {
+ selectionManager.setSelections(pastedEntityIDs);
+ }
+ } else {
+ Window.notifyEditError("Can't import entities: entities would be out of bounds.");
+ }
+ } else {
+ Window.notifyEditError("There was an error importing the entity file.");
+ }
+ }
+
marketplaceButton.clicked.connect(onClick);
tablet.screenChanged.connect(onScreenChanged);
Entities.canWriteAssetsChanged.connect(onCanWriteAssetsChanged);
@@ -324,6 +430,10 @@
tablet.gotoWebScreen(MARKETPLACE_URL + '/items/' + itemId, MARKETPLACES_INJECT_SCRIPT_URL);
}
break;
+ case 'checkout_rezClicked':
+ case 'purchases_rezClicked':
+ rezEntity(message.itemHref, message.isWearable);
+ break;
case 'header_marketplaceImageClicked':
case 'purchases_backClicked':
tablet.gotoWebScreen(message.referrerURL, MARKETPLACES_INJECT_SCRIPT_URL);