-
+
+
Congratulations! You have successfully setup and configured your cloud hosted domain.
-
-
- Visit domain in VR now
-
-
-
-
- Explore all domain server settings
-
+
+
+
+ Visit domain in VR now
+
+
Explore all domain server settings
+
+
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/interface/src/Application.cpp b/interface/src/Application.cpp
index b21588958e..bd31fc398e 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -4441,7 +4441,7 @@ void Application::cameraModeChanged() {
void Application::cameraMenuChanged() {
auto menu = Menu::getInstance();
if (menu->isOptionChecked(MenuOption::FullscreenMirror)) {
- if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
+ if (!isHMDMode() && _myCamera.getMode() != CAMERA_MODE_MIRROR) {
_myCamera.setMode(CAMERA_MODE_MIRROR);
getMyAvatar()->reset(false, false, false); // to reset any active MyAvatar::FollowHelpers
}
@@ -7271,6 +7271,10 @@ void Application::updateDisplayMode() {
menu->setIsOptionChecked(MenuOption::FirstPerson, true);
cameraMenuChanged();
}
+
+ // Remove the mirror camera option from menu if in HMD mode
+ auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror);
+ mirrorAction->setVisible(!isHmd);
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
}
diff --git a/libraries/model/src/model/Haze.cpp b/libraries/model/src/model/Haze.cpp
index c9c73bcee9..b56932e131 100644
--- a/libraries/model/src/model/Haze.cpp
+++ b/libraries/model/src/model/Haze.cpp
@@ -8,8 +8,8 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
-#include
+#include
#include "Haze.h"
using namespace model;
diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp
index dcb16c08f8..646b19198b 100644
--- a/libraries/render-utils/src/DeferredLightingEffect.cpp
+++ b/libraries/render-utils/src/DeferredLightingEffect.cpp
@@ -620,7 +620,7 @@ void RenderDeferredLocals::run(const render::RenderContextPointer& renderContext
auto& lightIndices = lightClusters->_visibleLightIndices;
if (!lightIndices.empty() && lightIndices[0] > 0) {
// Bind the global list of lights and the visible lights this frame
- batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->_lightArrayBuffer);
+ batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->getLightArrayBuffer());
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer);
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer);
diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp
index ab1e194498..eedb9053c7 100644
--- a/libraries/render-utils/src/LightClusters.cpp
+++ b/libraries/render-utils/src/LightClusters.cpp
@@ -727,7 +727,7 @@ void DebugLightClusters::run(const render::RenderContextPointer& renderContext,
batch.setModelTransform(Transform());
// Bind the Light CLuster data strucutre
- batch.setUniformBuffer(LIGHT_GPU_SLOT, lightClusters->_lightStage->_lightArrayBuffer);
+ batch.setUniformBuffer(LIGHT_GPU_SLOT, lightClusters->_lightStage->getLightArrayBuffer());
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer);
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer);
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer);
diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp
index f75a4d32e0..188cb46157 100644
--- a/libraries/render-utils/src/LightStage.cpp
+++ b/libraries/render-utils/src/LightStage.cpp
@@ -32,11 +32,17 @@ LightStage::Shadow::Schema::Schema() :
}
+gpu::FramebufferPointer LightStage::Shadow::framebuffer;
+gpu::TexturePointer LightStage::Shadow::map;
+
LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared() } {
- framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE));
- map = framebuffer->getDepthStencilBuffer();
Schema schema;
_schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema);
+
+ if (!framebuffer) {
+ framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE));
+ map = framebuffer->getDepthStencilBuffer();
+ }
}
void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum,
@@ -127,11 +133,9 @@ LightStage::Index LightStage::findLight(const LightPointer& light) const {
} else {
return (*found).second;
}
-
}
LightStage::Index LightStage::addLight(const LightPointer& light) {
-
auto found = _lightMap.find(light);
if (found == _lightMap.end()) {
auto lightId = _lights.newElement(light);
@@ -142,6 +146,7 @@ LightStage::Index LightStage::addLight(const LightPointer& light) {
if (lightId >= (Index) _descs.size()) {
_descs.emplace_back(Desc());
} else {
+ assert(_descs[lightId].shadowId == INVALID_INDEX);
_descs.emplace(_descs.begin() + lightId, Desc());
}
@@ -160,6 +165,7 @@ LightStage::Index LightStage::addShadow(Index lightIndex) {
auto light = getLight(lightIndex);
Index shadowId = INVALID_INDEX;
if (light) {
+ assert(_descs[lightIndex].shadowId == INVALID_INDEX);
shadowId = _shadows.newElement(std::make_shared(light));
_descs[lightIndex].shadowId = shadowId;
}
@@ -167,18 +173,20 @@ LightStage::Index LightStage::addShadow(Index lightIndex) {
}
LightStage::LightPointer LightStage::removeLight(Index index) {
- LightPointer removed = _lights.freeElement(index);
-
- if (removed) {
+ LightPointer removedLight = _lights.freeElement(index);
+ if (removedLight) {
auto shadowId = _descs[index].shadowId;
// Remove shadow if one exists for this light
if (shadowId != INVALID_INDEX) {
- _shadows.freeElement(shadowId);
+ auto removedShadow = _shadows.freeElement(shadowId);
+ assert(removedShadow);
+ assert(removedShadow->getLight() == removedLight);
}
- _lightMap.erase(removed);
+ _lightMap.erase(removedLight);
_descs[index] = Desc();
}
- return removed;
+ assert(_descs.size() <= index || _descs[index].shadowId == INVALID_INDEX);
+ return removedLight;
}
LightStage::LightPointer LightStage::getCurrentKeyLight() const {
@@ -202,7 +210,9 @@ LightStage::ShadowPointer LightStage::getCurrentKeyShadow() const {
if (!_currentFrame._sunLights.empty()) {
keyLightId = _currentFrame._sunLights.front();
}
- return getShadow(keyLightId);
+ auto shadow = getShadow(keyLightId);
+ assert(shadow == nullptr || shadow->getLight() == getLight(keyLightId));
+ return shadow;
}
LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow() const {
@@ -210,7 +220,18 @@ LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow() const {
if (!_currentFrame._sunLights.empty()) {
keyLightId = _currentFrame._sunLights.front();
}
- return LightAndShadow(getLight(keyLightId), getShadow(keyLightId));
+ auto shadow = getShadow(keyLightId);
+ auto light = getLight(keyLightId);
+ assert(shadow == nullptr || shadow->getLight() == light);
+ return LightAndShadow(light, shadow);
+}
+
+LightStage::Index LightStage::getShadowId(Index lightId) const {
+ if (checkLightId(lightId)) {
+ return _descs[lightId].shadowId;
+ } else {
+ return INVALID_INDEX;
+ }
}
void LightStage::updateLightArrayBuffer(Index lightId) {
diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h
index ebc77df570..e1f175f653 100644
--- a/libraries/render-utils/src/LightStage.h
+++ b/libraries/render-utils/src/LightStage.h
@@ -58,8 +58,12 @@ public:
const UniformBufferView& getBuffer() const { return _schemaBuffer; }
- gpu::FramebufferPointer framebuffer;
- gpu::TexturePointer map;
+ // Shadow maps are shared among all lights for the moment as only one key light
+ // is used.
+ static gpu::FramebufferPointer framebuffer;
+ static gpu::TexturePointer map;
+
+ const model::LightPointer& getLight() const { return _light; }
protected:
@@ -80,16 +84,11 @@ public:
};
UniformBufferView _schemaBuffer = nullptr;
- friend class Light;
};
+
using ShadowPointer = std::shared_ptr;
using Shadows = render::indexed_container::IndexedPointerVector;
- struct Desc {
- Index shadowId { INVALID_INDEX };
- };
- using Descs = std::vector;
-
Index findLight(const LightPointer& light) const;
Index addLight(const LightPointer& light);
@@ -107,20 +106,18 @@ public:
return _lights.get(lightId);
}
- Index getShadowId(Index lightId) const {
- if (checkLightId(lightId)) {
- return _descs[lightId].shadowId;
- } else {
- return INVALID_INDEX;
- }
- }
+ Index getShadowId(Index lightId) const;
+
ShadowPointer getShadow(Index lightId) const {
return _shadows.get(getShadowId(lightId));
}
using LightAndShadow = std::pair;
LightAndShadow getLightAndShadow(Index lightId) const {
- return LightAndShadow(getLight(lightId), getShadow(lightId));
+ auto light = getLight(lightId);
+ auto shadow = getShadow(lightId);
+ assert(shadow == nullptr || shadow->getLight() == light);
+ return LightAndShadow(light, shadow);
}
LightPointer getCurrentKeyLight() const;
@@ -130,9 +127,8 @@ public:
LightStage();
- Lights _lights;
- LightMap _lightMap;
- Descs _descs;
+ gpu::BufferPointer getLightArrayBuffer() const { return _lightArrayBuffer; }
+ void updateLightArrayBuffer(Index lightId);
class Frame {
public:
@@ -161,15 +157,24 @@ public:
Frame _currentFrame;
- gpu::BufferPointer _lightArrayBuffer;
- void updateLightArrayBuffer(Index lightId);
+protected:
+ struct Desc {
+ Index shadowId{ INVALID_INDEX };
+ };
+ using Descs = std::vector;
+
+ gpu::BufferPointer _lightArrayBuffer;
+
+ Lights _lights;
Shadows _shadows;
+ Descs _descs;
+ LightMap _lightMap;
+
};
using LightStagePointer = std::shared_ptr;
-
class LightStageSetup {
public:
using JobModel = render::Job::Model;
diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp
index 15d307d2e4..4261b14a9b 100644
--- a/libraries/render-utils/src/RenderDeferredTask.cpp
+++ b/libraries/render-utils/src/RenderDeferredTask.cpp
@@ -44,8 +44,6 @@
#include "DrawHaze.h"
#include "HighlightEffect.h"
-#include
-
#include
using namespace render;
@@ -193,14 +191,18 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
task.addJob("HighlightRangeTimer", outlineRangeTimer);
- { // DEbug the bounds of the rendered items, still look at the zbuffer
+ { // Debug the bounds of the rendered items, still look at the zbuffer
task.addJob("DrawMetaBounds", metas);
task.addJob("DrawOpaqueBounds", opaques);
task.addJob("DrawTransparentBounds", transparents);
task.addJob("DrawLightBounds", lights);
task.addJob("DrawZones", zones);
- task.addJob("DrawFrustums");
+ const auto frustums = task.addJob("ExtractFrustums");
+ const auto viewFrustum = frustums.getN(ExtractFrustums::VIEW_FRUSTUM);
+ const auto shadowFrustum = frustums.getN(ExtractFrustums::SHADOW_FRUSTUM);
+ task.addJob("DrawViewFrustum", viewFrustum, glm::vec3(1.0f, 1.0f, 0.0f));
+ task.addJob("DrawShadowFrustum", shadowFrustum, glm::vec3(0.0f, 0.0f, 1.0f));
// Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true
task.addJob("DrawSelectionBounds", selectedItems);
@@ -449,6 +451,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) {
@@ -528,88 +535,32 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer
});
}
-void DrawFrustums::configure(const Config& configuration) {
- _updateFrustums = !configuration.isFrozen;
-}
-
-void DrawFrustums::run(const render::RenderContextPointer& renderContext) {
+void ExtractFrustums::run(const render::RenderContextPointer& renderContext, Output& output) {
assert(renderContext->args);
assert(renderContext->args->_context);
RenderArgs* args = renderContext->args;
- static uint8_t indexData[] = { 0, 1, 2, 3, 0, 4, 5, 6, 7, 4, 5, 1, 2, 6, 7, 3 };
- if (!_frustumMeshIndices._buffer) {
- auto indices = std::make_shared(sizeof(indexData), indexData);
- _frustumMeshIndices = gpu::BufferView(indices, gpu::Element(gpu::SCALAR, gpu::UINT8, gpu::INDEX));
- _viewFrustumMeshVertices = gpu::BufferView(std::make_shared(sizeof(glm::vec3) * 8, nullptr), gpu::Element::VEC3F_XYZ);
- _viewFrustumMeshStream.addBuffer(_viewFrustumMeshVertices._buffer, _viewFrustumMeshVertices._offset, _viewFrustumMeshVertices._stride);
- _shadowFrustumMeshVertices = gpu::BufferView(std::make_shared(sizeof(glm::vec3) * 8, nullptr), gpu::Element::VEC3F_XYZ);
- _shadowFrustumMeshStream.addBuffer(_shadowFrustumMeshVertices._buffer, _shadowFrustumMeshVertices._offset, _shadowFrustumMeshVertices._stride);
+ // Return view frustum
+ auto& viewFrustum = output[VIEW_FRUSTUM].edit();
+ if (!viewFrustum) {
+ viewFrustum = std::make_shared(args->getViewFrustum());
+ } else {
+ *viewFrustum = args->getViewFrustum();
}
- if (_updateFrustums) {
- updateFrustum(args->getViewFrustum(), _viewFrustumMeshVertices);
+ // Return shadow frustum
+ auto& shadowFrustum = output[SHADOW_FRUSTUM].edit();
+ auto lightStage = args->_scene->getStage(LightStage::getName());
+ if (lightStage) {
+ auto globalShadow = lightStage->getCurrentKeyShadow();
- auto lightStage = renderContext->_scene->getStage();
- assert(lightStage);
-
- const auto globalShadow = lightStage->getCurrentKeyShadow();
if (globalShadow) {
- updateFrustum(*globalShadow->getFrustum(), _shadowFrustumMeshVertices);
+ shadowFrustum = globalShadow->getFrustum();
+ } else {
+ shadowFrustum.reset();
}
+ } else {
+ shadowFrustum.reset();
}
-
- if (!_pipeline) {
- auto vs = gpu::StandardShaderLib::getDrawTransformVertexPositionVS();
- auto ps = gpu::StandardShaderLib::getDrawColorPS();
- gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
-
- gpu::Shader::BindingSet slotBindings;
- slotBindings.insert(gpu::Shader::Binding("color", 0));
- gpu::Shader::makeProgram(*program, slotBindings);
-
- gpu::StatePointer state = gpu::StatePointer(new gpu::State());
- state->setDepthTest(gpu::State::DepthTest(true, false));
- _pipeline = gpu::Pipeline::create(program, state);
- }
-
- // Render the frustums in wireframe
- gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
- args->_batch = &batch;
- batch.setViewportTransform(args->_viewport);
- batch.setStateScissorRect(args->_viewport);
-
- glm::mat4 projMat;
- Transform viewMat;
- args->getViewFrustum().evalProjectionMatrix(projMat);
- args->getViewFrustum().evalViewTransform(viewMat);
-
- batch.setProjectionTransform(projMat);
- batch.setViewTransform(viewMat);
- batch.setPipeline(_pipeline);
- batch.setIndexBuffer(_frustumMeshIndices);
-
- batch._glUniform4f(0, 1.0f, 1.0f, 0.0f, 1.0f);
- batch.setInputStream(0, _viewFrustumMeshStream);
- batch.drawIndexed(gpu::LINE_STRIP, sizeof(indexData) / sizeof(indexData[0]), 0U);
-
- batch._glUniform4f(0, 1.0f, 0.0f, 0.0f, 1.0f);
- batch.setInputStream(0, _shadowFrustumMeshStream);
- batch.drawIndexed(gpu::LINE_STRIP, sizeof(indexData) / sizeof(indexData[0]), 0U);
-
- args->_batch = nullptr;
- });
-}
-
-void DrawFrustums::updateFrustum(const ViewFrustum& frustum, gpu::BufferView& vertexBuffer) {
- auto& vertices = vertexBuffer.edit >();
- vertices[0] = frustum.getNearTopLeft();
- vertices[1] = frustum.getNearTopRight();
- vertices[2] = frustum.getNearBottomRight();
- vertices[3] = frustum.getNearBottomLeft();
- vertices[4] = frustum.getFarTopLeft();
- vertices[5] = frustum.getFarTopRight();
- vertices[6] = frustum.getFarBottomRight();
- vertices[7] = frustum.getFarBottomLeft();
}
diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h
index bf457d7fcb..40ae503fb7 100644
--- a/libraries/render-utils/src/RenderDeferredTask.h
+++ b/libraries/render-utils/src/RenderDeferredTask.h
@@ -170,38 +170,20 @@ public:
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer);
};
-class DrawFrustumsConfig : public render::Job::Config {
- Q_OBJECT
- Q_PROPERTY(bool isFrozen MEMBER isFrozen NOTIFY dirty)
+class ExtractFrustums {
public:
- DrawFrustumsConfig(bool enabled = false) : JobConfig(enabled) {}
+ enum Frustum {
+ VIEW_FRUSTUM,
+ SHADOW_FRUSTUM,
- bool isFrozen{ false };
-signals:
- void dirty();
+ FRUSTUM_COUNT
+ };
-};
+ using Output = render::VaryingArray;
+ using JobModel = render::Job::ModelO;
-class DrawFrustums {
-public:
- using Config = DrawFrustumsConfig;
- using JobModel = render::Job::Model;
-
- void configure(const Config& configuration);
- void run(const render::RenderContextPointer& renderContext);
-
-private:
-
- bool _updateFrustums{ true };
- gpu::PipelinePointer _pipeline;
- gpu::BufferView _frustumMeshIndices;
- gpu::BufferView _viewFrustumMeshVertices;
- gpu::BufferView _shadowFrustumMeshVertices;
- gpu::BufferStream _viewFrustumMeshStream;
- gpu::BufferStream _shadowFrustumMeshStream;
-
- static void updateFrustum(const ViewFrustum& frustum, gpu::BufferView& vertexBuffer);
+ void run(const render::RenderContextPointer& renderContext, Output& output);
};
class RenderDeferredTaskConfig : public render::Task::Config {
diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp
index 710507bd79..0f4137e38d 100755
--- a/libraries/render/src/render/DrawTask.cpp
+++ b/libraries/render/src/render/DrawTask.cpp
@@ -20,7 +20,7 @@
#include
#include
#include
-
+#include
#include
#include
@@ -215,3 +215,85 @@ void DrawBounds::run(const RenderContextPointer& renderContext,
});
}
+gpu::PipelinePointer DrawFrustum::_pipeline;
+gpu::BufferView DrawFrustum::_frustumMeshIndices;
+
+DrawFrustum::DrawFrustum(const glm::vec3& color) :
+ _color{ color } {
+ _frustumMeshVertices = gpu::BufferView(std::make_shared(sizeof(glm::vec3) * 8, nullptr), gpu::Element::VEC3F_XYZ);
+ _frustumMeshStream.addBuffer(_frustumMeshVertices._buffer, _frustumMeshVertices._offset, _frustumMeshVertices._stride);
+}
+
+void DrawFrustum::configure(const Config& configuration) {
+ _updateFrustum = !configuration.isFrozen;
+}
+
+void DrawFrustum::run(const render::RenderContextPointer& renderContext, const Input& input) {
+ assert(renderContext->args);
+ assert(renderContext->args->_context);
+
+ RenderArgs* args = renderContext->args;
+ if (input) {
+ const auto& frustum = *input;
+
+ static uint8_t indexData[] = { 0, 1, 2, 3, 0, 4, 5, 6, 7, 4, 5, 1, 2, 6, 7, 3 };
+
+ if (!_frustumMeshIndices._buffer) {
+ auto indices = std::make_shared(sizeof(indexData), indexData);
+ _frustumMeshIndices = gpu::BufferView(indices, gpu::Element(gpu::SCALAR, gpu::UINT8, gpu::INDEX));
+ }
+
+ if (!_pipeline) {
+ auto vs = gpu::StandardShaderLib::getDrawTransformVertexPositionVS();
+ auto ps = gpu::StandardShaderLib::getDrawColorPS();
+ gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
+
+ gpu::Shader::BindingSet slotBindings;
+ slotBindings.insert(gpu::Shader::Binding("color", 0));
+ gpu::Shader::makeProgram(*program, slotBindings);
+
+ gpu::StatePointer state = gpu::StatePointer(new gpu::State());
+ state->setDepthTest(gpu::State::DepthTest(true, false));
+ _pipeline = gpu::Pipeline::create(program, state);
+ }
+
+ if (_updateFrustum) {
+ updateFrustum(frustum);
+ }
+
+ // Render the frustums in wireframe
+ gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
+ args->_batch = &batch;
+ batch.setViewportTransform(args->_viewport);
+ batch.setStateScissorRect(args->_viewport);
+
+ glm::mat4 projMat;
+ Transform viewMat;
+ args->getViewFrustum().evalProjectionMatrix(projMat);
+ args->getViewFrustum().evalViewTransform(viewMat);
+
+ batch.setProjectionTransform(projMat);
+ batch.setViewTransform(viewMat);
+ batch.setPipeline(_pipeline);
+ batch.setIndexBuffer(_frustumMeshIndices);
+
+ batch._glUniform4f(0, _color.x, _color.y, _color.z, 1.0f);
+ batch.setInputStream(0, _frustumMeshStream);
+ batch.drawIndexed(gpu::LINE_STRIP, sizeof(indexData) / sizeof(indexData[0]), 0U);
+
+ args->_batch = nullptr;
+ });
+ }
+}
+
+void DrawFrustum::updateFrustum(const ViewFrustum& frustum) {
+ auto& vertices = _frustumMeshVertices.edit >();
+ vertices[0] = frustum.getNearTopLeft();
+ vertices[1] = frustum.getNearTopRight();
+ vertices[2] = frustum.getNearBottomRight();
+ vertices[3] = frustum.getNearBottomLeft();
+ vertices[4] = frustum.getFarTopLeft();
+ vertices[5] = frustum.getFarTopRight();
+ vertices[6] = frustum.getFarBottomRight();
+ vertices[7] = frustum.getFarBottomLeft();
+}
diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h
index 896ccef842..5d98c37c21 100755
--- a/libraries/render/src/render/DrawTask.h
+++ b/libraries/render/src/render/DrawTask.h
@@ -70,6 +70,43 @@ private:
int _colorLocation { -1 };
};
+class DrawFrustumConfig : public render::JobConfig {
+ Q_OBJECT
+ Q_PROPERTY(bool isFrozen MEMBER isFrozen NOTIFY dirty)
+public:
+
+ DrawFrustumConfig(bool enabled = false) : JobConfig(enabled) {}
+
+ bool isFrozen{ false };
+signals:
+ void dirty();
+
+};
+
+class DrawFrustum {
+public:
+ using Config = DrawFrustumConfig;
+ using Input = ViewFrustumPointer;
+ using JobModel = render::Job::ModelI;
+
+ DrawFrustum(const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f));
+
+ void configure(const Config& configuration);
+ void run(const render::RenderContextPointer& renderContext, const Input& input);
+
+private:
+
+ static gpu::PipelinePointer _pipeline;
+ static gpu::BufferView _frustumMeshIndices;
+
+ bool _updateFrustum{ true };
+ gpu::BufferView _frustumMeshVertices;
+ gpu::BufferStream _frustumMeshStream;
+ glm::vec3 _color;
+
+ void updateFrustum(const ViewFrustum& frustum);
+};
+
}
#endif // hifi_render_DrawTask_h
diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp
index 0a23960382..5b53b5d403 100644
--- a/libraries/render/src/render/SortTask.cpp
+++ b/libraries/render/src/render/SortTask.cpp
@@ -90,9 +90,9 @@ void render::depthSortItems(const RenderContextPointer& renderContext, bool fron
}
for (auto& item : itemBoundSorts) {
if (item._id != previousID) {
- *bounds += item._bounds;
outItems.emplace_back(ItemBound(item._id, item._bounds));
previousID = item._id;
+ *bounds += item._bounds;
}
}
}
@@ -150,11 +150,7 @@ void DepthSortShapesAndComputeBounds::run(const RenderContextPointer& renderCont
AABox bounds;
depthSortItems(renderContext, _frontToBack, inItems, outItems->second, &bounds);
- if (!outBounds.isNull()) {
- outBounds += bounds;
- } else {
- outBounds = bounds;
- }
+ outBounds += bounds;
}
}
diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp
index e502d44a08..2ee761a1f7 100644
--- a/libraries/shared/src/GeometryUtil.cpp
+++ b/libraries/shared/src/GeometryUtil.cpp
@@ -338,8 +338,6 @@ int clipTriangleWithPlane(const Triangle& triangle, const Plane& plane, Triangle
int clippedTriangleCount = 0;
int i;
- assert(clippedTriangleCount > 0);
-
for (i = 0; i < 3; i++) {
pointDistanceToPlane[i] = plane.distance(triangleVertices[i]);
arePointsClipped.set(i, pointDistanceToPlane[i] < 0.0f);
diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h
index 71d8b6c915..7a39314f4d 100644
--- a/libraries/shared/src/Transform.h
+++ b/libraries/shared/src/Transform.h
@@ -149,7 +149,7 @@ public:
Vec4 transform(const Vec4& pos) const;
Vec3 transform(const Vec3& pos) const;
- Vec3 transformDirection(const Vec3& pos) const;
+ Vec3 transformDirection(const Vec3& dir) const;
bool containsNaN() const { return isNaN(_rotation) || isNaN(glm::dot(_scale, _translation)); }
@@ -542,10 +542,10 @@ inline Transform::Vec3 Transform::transform(const Vec3& pos) const {
return Vec3(result.x / result.w, result.y / result.w, result.z / result.w);
}
-inline Transform::Vec3 Transform::transformDirection(const Vec3& pos) const {
+inline Transform::Vec3 Transform::transformDirection(const Vec3& dir) const {
Mat4 m;
getMatrix(m);
- Vec4 result = m * Vec4(pos, 0.0f);
+ Vec4 result = m * Vec4(dir, 0.0f);
return Vec3(result.x, result.y, result.z);
}
diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp
index 297ed9ca50..252c08a1f0 100644
--- a/libraries/ui/src/OffscreenUi.cpp
+++ b/libraries/ui/src/OffscreenUi.cpp
@@ -720,7 +720,7 @@ QString OffscreenUi::fileDialog(const QVariantMap& properties) {
return QString();
}
qCDebug(uiLogging) << result.toString();
- return result.toUrl().toLocalFile();
+ return result.toString();
}
ModalDialogListener* OffscreenUi::fileDialogAsync(const QVariantMap& properties) {
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/developer/utilities/render/shadow.qml b/scripts/developer/utilities/render/shadow.qml
index 1b4e647c77..8548ba4119 100644
--- a/scripts/developer/utilities/render/shadow.qml
+++ b/scripts/developer/utilities/render/shadow.qml
@@ -14,20 +14,24 @@ import QtQuick.Controls 1.4
Column {
id: root
spacing: 8
- property var config: Render.getConfig("RenderMainView.DrawFrustums");
+ property var viewConfig: Render.getConfig("RenderMainView.DrawViewFrustum");
+ property var shadowConfig: Render.getConfig("RenderMainView.DrawShadowFrustum");
Component.onCompleted: {
- config.enabled = true;
+ viewConfig.enabled = true;
+ shadowConfig.enabled = true;
}
Component.onDestruction: {
- config.enabled = false;
+ viewConfig.enabled = false;
+ shadowConfig.enabled = false;
}
CheckBox {
text: "Freeze Frustums"
checked: false
onCheckedChanged: {
- config.isFrozen = checked;
+ viewConfig.isFrozen = checked;
+ shadowConfig.isFrozen = checked;
}
}
Row {
@@ -39,7 +43,7 @@ Column {
}
Label {
text: "Shadow"
- color: "red"
+ color: "blue"
font.italic: true
}
}
diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html
index 9453b476ee..8b2a088d83 100644
--- a/scripts/system/html/entityProperties.html
+++ b/scripts/system/html/entityProperties.html
@@ -623,7 +623,7 @@