Merged request changes from shadow

This commit is contained in:
Olivier Prat 2017-11-15 17:51:06 +01:00
commit e4818f1b4f
40 changed files with 568 additions and 263 deletions

View file

@ -68,7 +68,7 @@ module.exports = {
"eqeqeq": ["error", "always"],
"indent": ["error", 4, { "SwitchCase": 1 }],
"keyword-spacing": ["error", { "before": true, "after": true }],
"max-len": ["error", 192, 4],
"max-len": ["error", 128, 4],
"new-cap": ["error"],
"no-floating-decimal": ["error"],
//"no-magic-numbers": ["error", { "ignore": [0, 1], "ignoreArrayIndexes": true }],

View file

@ -307,7 +307,6 @@ table .headers + .headers td {
margin-right: 20px;
}
#visit-domain-link,
.blue-link {
font-size: 14px;
text-decoration-line: underline;

View file

@ -39,7 +39,7 @@
<li><a href="/settings/">Settings</a></li>
</ul>
<ul class="nav navbar-right navbar-nav">
<li><a id="visit-domain-link" target="_blank" style="display: none;">Visit domain in VR</a></li>
<li><a id="visit-domain-link" class="blue-link" target="_blank" style="display: none;">Visit domain in VR</a></li>
<li><a href="#" id="restart-server"><span class="glyphicon glyphicon-refresh"></span> Restart</a></li>
</ul>
</div>

View file

@ -31,6 +31,12 @@ label {
color: #373A3C;
}
.wizard-link {
font-size: 16px;
font-weight: normal;
color: #2F80ED;
}
#admin-row {
margin-top: 20px;
margin-bottom: 20px;
@ -84,6 +90,14 @@ label {
height: 169px;
}
#visit-domain-row {
margin-bottom: 68px;
#congratulation-text {
margin-bottom: 59px;
}
#visit-domain-checkbox {
margin-bottom: 23px;
}
#visit-domain-checkbox label {
margin: 0 0;
}

View file

@ -60,8 +60,7 @@
</div>
<div id="admin-row" class="row">
<p class="col-md-6">
<span id="admin-description" class="step-info"><b>Add your High Fidelity username</b> and any other usernames to grant administrator privileges.</span>
<span class='glyphicon glyphicon-info-sign' data-toggle="tooltip" title="Users who will have all the permissions for this domain."></span>
<span class="step-info"><span id="admin-description"><b>Add your High Fidelity username</b> and any other usernames</span> to grant <span class='wizard-link' data-toggle="tooltip" title="Users who will have all the permissions for this domain.">administrator privileges</span></span>
</p>
<div class="col-md-6">
<input id="admin-usernames" type="text" class="form-control">
@ -78,7 +77,7 @@
<div class="row">
<div class="col-md-12">
<p id="connect-question" class="step-info">
Who can connect to your domain?
Who can <a href='#' class='wizard-link perms-link'>connect</a> to your domain?
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='You can set this to allow a user to connect to this domain.'></span>
</p>
</div>
@ -87,25 +86,21 @@
<p class="col-md-2">
<label>
<input id="connect-none" name="connect-radio" type="radio" value="none" checked> None
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Only the admins of this domain'></span>
</label>
</p>
<p class="col-md-3">
<label>
<input id="connect-friends" name="connect-radio" type="radio" value="friends"> Friends
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Users who are your Friends in High Fidelity'></span>
</label>
</p>
<p class="col-md-5">
<label>
<input id="connect-logged-in" name="connect-radio" type="radio" value="logged-in"> Users logged in to High Fidelity
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Users who are currently logged into High Fidelity'></span>
<input id="connect-logged-in" name="connect-radio" type="radio" value="logged-in"> Users logged into High Fidelity
</label>
</p>
<p class="col-md-2">
<label>
<input id="connect-everyone" name="connect-radio" type="radio" value="everyone"> Everyone
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title="Users who aren't logged into High Fidelity"></span>
</label>
</p>
</div>
@ -113,7 +108,7 @@
<div class="row">
<div class="col-md-12">
<p class="step-info">
Who can rez items in your domain?
Who can <a href='#' class='wizard-link perms-link'>rez items</a> in your domain?
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='You can set this to allow a user to create entities in this domain.'></span>
</p>
</div>
@ -122,33 +117,32 @@
<p class="col-md-2">
<label>
<input id="rez-none" name="rez-radio" type="radio" value="none" checked> None
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Only the admins of this domain'></span>
</label>
</p>
<p class="col-md-3">
<label>
<input id="rez-friends" name="rez-radio" type="radio" value="friends"> Friends
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Users who are your Friends in High Fidelity'></span>
<input id="rez-friends" name="rez-radio" type="radio" value="friends" disabled> Friends
</label>
</p>
<p class="col-md-5">
<label>
<input id="rez-logged-in" name="rez-radio" type="radio" value="logged-in"> Users logged in to High Fidelity
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Users who are currently logged into High Fidelity'></span>
<input id="rez-logged-in" name="rez-radio" type="radio" value="logged-in" disabled> Users logged into High Fidelity
</label>
</p>
<p class="col-md-2">
<label>
<input id="rez-everyone" name="rez-radio" type="radio" value="everyone"> Everyone
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title="Users who aren't logged into High Fidelity"></span>
<input id="rez-everyone" name="rez-radio" type="radio" value="everyone" disabled> Everyone
</label>
</p>
</div>
<div class="row">
<div class="col-md-3 col-md-offset-9">
<dd class="col-md-3">
<button type="button" class="btn btn-md btn-block btn-default back-button">Back</button>
</dd>
<dd class="col-md-3 col-md-offset-6">
<button id="save-permissions" type="button" class="btn btn-md btn-block btn-primary">Next</button>
</div>
</dd>
</div>
</div>
@ -188,35 +182,37 @@
</dl>
<dl class="row">
<dd class="col-md-3 col-md-offset-9">
<dd class="col-md-3">
<button type="button" class="btn btn-md btn-block btn-default back-button">Back</button>
</dd>
<dd class="col-md-3 col-md-offset-6">
<button id="save-username-password" type="button" class="btn btn-md btn-block btn-primary">Finish</button>
</dd>
</dl>
</div>
<div class="wizard-step cloud-only col-md-7 col-centered" style="display: none;">
<div class="wizard-step cloud-only col-xs-12 col-sm-12 col-md-9 col-lg-7 col-centered" style="display: none;">
<div class="row">
<div class="col-xs-4 col-centered">
<div class="col-xs-12" align="center">
<img id="checkmark-image" src="../images/checkmark.svg">
</div>
</div>
<div class="row">
<div class="col-md-12">
<div id="congratulation-text" class="row">
<div class="col-xs-12">
<p class="step-info">Congratulations! You have successfully setup and configured your cloud hosted domain.</p>
</div>
</div>
<div id="visit-domain-row" class="row">
<div class="col-md-12">
<label><input id="go-to-domain" class="form-check-input" type="checkbox"> Visit domain in VR now</label>
</div>
</div>
<dl class="row">
<dd class="col-md-5 col-md-offset-7">
<button id="explore-settings" type="button" class="btn btn-md btn-block btn-primary">Explore all domain server settings</button>
</dd>
<div class="col-xs-12">
<div class="pull-right">
<div id="visit-domain-checkbox">
<label><input id="go-to-domain" class="form-check-input" type="checkbox"> Visit domain in VR now</label>
</div>
<button id="explore-settings" type="button" class="btn btn-md btn-primary">Explore all domain server settings</button>
</div>
</div>
</dl>
</div>

View file

@ -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.<br><br>" +
"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 = '<div>';
modal_body += '<b>None</b> - No one will have permissions. Only you and the users your have given administrator privileges to will have permissions.</br></br>';
modal_body += '<b>Friends</b> - Users who are your Friends in High Fidelity.</br></br>';
modal_body += '<b>Users logged into High Fidelity</b> - Users who are currently logged into High Fidelity.</br></br>';
modal_body += '<b>Everyone</b> - Anyone who uses High Fidelity.';
modal_body += '</div>';
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 <span id="username-display"></span>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": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -366,7 +366,7 @@ StackView {
HifiControls.Keyboard {
id: keyboard
raised: parent.keyboardEnabled
raised: parent.keyboardEnabled && parent.keyboardRaised
numeric: parent.punctuationMode
anchors {
bottom: parent.bottom

View file

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

View file

@ -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 <memory>
#include <memory>
#include "Haze.h"
using namespace model;

View file

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

View file

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

View file

@ -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<ViewFrustum>() } {
framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE));
map = framebuffer->getDepthStencilBuffer();
Schema schema;
_schemaBuffer = std::make_shared<gpu::Buffer>(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<Shadow>(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) {

View file

@ -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<Shadow>;
using Shadows = render::indexed_container::IndexedPointerVector<Shadow>;
struct Desc {
Index shadowId { INVALID_INDEX };
};
using Descs = std::vector<Desc>;
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<LightPointer, ShadowPointer>;
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<Desc>;
gpu::BufferPointer _lightArrayBuffer;
Lights _lights;
Shadows _shadows;
Descs _descs;
LightMap _lightMap;
};
using LightStagePointer = std::shared_ptr<LightStage>;
class LightStageSetup {
public:
using JobModel = render::Job::Model<LightStageSetup>;

View file

@ -44,8 +44,6 @@
#include "DrawHaze.h"
#include "HighlightEffect.h"
#include <gpu/StandardShaderLib.h>
#include <sstream>
using namespace render;
@ -193,14 +191,18 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
task.addJob<EndGPURangeTimer>("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<DrawBounds>("DrawMetaBounds", metas);
task.addJob<DrawBounds>("DrawOpaqueBounds", opaques);
task.addJob<DrawBounds>("DrawTransparentBounds", transparents);
task.addJob<DrawBounds>("DrawLightBounds", lights);
task.addJob<DrawBounds>("DrawZones", zones);
task.addJob<DrawFrustums>("DrawFrustums");
const auto frustums = task.addJob<ExtractFrustums>("ExtractFrustums");
const auto viewFrustum = frustums.getN<ExtractFrustums::Output>(ExtractFrustums::VIEW_FRUSTUM);
const auto shadowFrustum = frustums.getN<ExtractFrustums::Output>(ExtractFrustums::SHADOW_FRUSTUM);
task.addJob<DrawFrustum>("DrawViewFrustum", viewFrustum, glm::vec3(1.0f, 1.0f, 0.0f));
task.addJob<DrawFrustum>("DrawShadowFrustum", shadowFrustum, glm::vec3(0.0f, 0.0f, 1.0f));
// Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true
task.addJob<DrawBounds>("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<gpu::Buffer>(sizeof(indexData), indexData);
_frustumMeshIndices = gpu::BufferView(indices, gpu::Element(gpu::SCALAR, gpu::UINT8, gpu::INDEX));
_viewFrustumMeshVertices = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(glm::vec3) * 8, nullptr), gpu::Element::VEC3F_XYZ);
_viewFrustumMeshStream.addBuffer(_viewFrustumMeshVertices._buffer, _viewFrustumMeshVertices._offset, _viewFrustumMeshVertices._stride);
_shadowFrustumMeshVertices = gpu::BufferView(std::make_shared<gpu::Buffer>(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<ViewFrustumPointer>();
if (!viewFrustum) {
viewFrustum = std::make_shared<ViewFrustum>(args->getViewFrustum());
} else {
*viewFrustum = args->getViewFrustum();
}
if (_updateFrustums) {
updateFrustum(args->getViewFrustum(), _viewFrustumMeshVertices);
// Return shadow frustum
auto& shadowFrustum = output[SHADOW_FRUSTUM].edit<ViewFrustumPointer>();
auto lightStage = args->_scene->getStage<LightStage>(LightStage::getName());
if (lightStage) {
auto globalShadow = lightStage->getCurrentKeyShadow();
auto lightStage = renderContext->_scene->getStage<LightStage>();
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<std::array<glm::vec3, 8U> >();
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();
}

View file

@ -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<ViewFrustumPointer, FRUSTUM_COUNT>;
using JobModel = render::Job::ModelO<ExtractFrustums, Output>;
class DrawFrustums {
public:
using Config = DrawFrustumsConfig;
using JobModel = render::Job::Model<DrawFrustums, Config>;
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 {

View file

@ -20,7 +20,7 @@
#include <PerfStat.h>
#include <ViewFrustum.h>
#include <gpu/Context.h>
#include <gpu/StandardShaderLib.h>
#include <drawItemBounds_vert.h>
#include <drawItemBounds_frag.h>
@ -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<gpu::Buffer>(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<gpu::Buffer>(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<std::array<glm::vec3, 8U> >();
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();
}

View file

@ -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, Input, Config>;
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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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<uint32_t, void*>;
// Checks to see if a new texture is available. If one is, the function returns true and

View file

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

View file

@ -623,7 +623,7 @@
</div>
</div>
</fieldset>
<div class="zone-group zone-section haze-section property checkbox">
<!--div class="zone-group zone-section haze-section property checkbox">
<input type="checkbox" id="property-zone-haze-attenuate-keylight">
<label for="property-zone-haze-attenuate-keylight">Attenuate Keylight</label>
</div>
@ -634,7 +634,7 @@
<div><label>Altitude<span class="unit">m</span></label><input type="number" id="property-zone-haze-keylight-altitude"
min="-1000" max="50000" step="10"></div>
</div>
</fieldset>
</fieldset-->
</fieldset>
<fieldset class="minor">
<legend class="sub-section-header zone-group zone-section stage-section">

View file

@ -1069,9 +1069,9 @@ function loaded() {
elZoneHazeBackgroundBlend.value = properties.haze.hazeBackgroundBlend.toFixed(2);
elZoneHazeAttenuateKeyLight.checked = properties.haze.hazeAttenuateKeyLight;
elZoneHazeKeyLightRange.value = properties.haze.hazeKeyLightRange.toFixed(0);
elZoneHazeKeyLightAltitude.value = properties.haze.hazeKeyLightAltitude.toFixed(0);
// elZoneHazeAttenuateKeyLight.checked = properties.haze.hazeAttenuateKeyLight;
// elZoneHazeKeyLightRange.value = properties.haze.hazeKeyLightRange.toFixed(0);
// elZoneHazeKeyLightAltitude.value = properties.haze.hazeKeyLightAltitude.toFixed(0);
elZoneStageLatitude.value = properties.stage.latitude.toFixed(2);
elZoneStageLongitude.value = properties.stage.longitude.toFixed(2);
@ -1533,9 +1533,9 @@ function loaded() {
elZoneHazeBackgroundBlend.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeBackgroundBlend'));
elZoneHazeAttenuateKeyLight.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('haze', 'hazeAttenuateKeyLight'));
elZoneHazeKeyLightRange.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeKeyLightRange'));
elZoneHazeKeyLightAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeKeyLightAltitude'));
// elZoneHazeAttenuateKeyLight.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('haze', 'hazeAttenuateKeyLight'));
// elZoneHazeKeyLightRange.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeKeyLightRange'));
// elZoneHazeKeyLightAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeKeyLightAltitude'));
elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'latitude'));
elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'longitude'));

View file

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