Merge branch 'master' into audio-louder-mastergain

This commit is contained in:
Ken Cooke 2017-11-01 08:10:55 -07:00
commit 82d9827571
57 changed files with 2824 additions and 1142 deletions

View file

@ -13,7 +13,7 @@ ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/draco-1.1.0.zip
URL_MD5 208f8b04c91d5f1c73d731a3ea37c5bb
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> ${EXTRA_CMAKE_FLAGS}
CONFIGURE_COMMAND CMAKE_ARGS ${ANDROID_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>-$<CONFIG> ${EXTRA_CMAKE_FLAGS}
LOG_DOWNLOAD 1
LOG_CONFIGURE 1
LOG_BUILD 1
@ -23,10 +23,11 @@ ExternalProject_Add(
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
set(SUFFIXED_INSTALL_DIR "${INSTALL_DIR}-$<CONFIG>")
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "List of Draco include directories")
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SUFFIXED_INSTALL_DIR}/include CACHE PATH "List of Draco include directories")
if (UNIX)
set(LIB_PREFIX "lib")
@ -35,6 +36,6 @@ elseif (WIN32)
set(LIB_EXT "lib")
endif ()
set(${EXTERNAL_NAME_UPPER}_LIBRARY ${INSTALL_DIR}/lib/${LIB_PREFIX}draco.${LIB_EXT} CACHE FILEPATH "Path to Draco release library")
set(${EXTERNAL_NAME_UPPER}_ENCODER_LIBRARY ${INSTALL_DIR}/lib/${LIB_PREFIX}dracoenc.${LIB_EXT} CACHE FILEPATH "Path to Draco encoder release library")
set(${EXTERNAL_NAME_UPPER}_DECODER_LIBRARY ${INSTALL_DIR}/lib/${LIB_PREFIX}dracodec.${LIB_EXT} CACHE FILEPATH "Path to Draco decoder release library")
set(${EXTERNAL_NAME_UPPER}_LIBRARY ${SUFFIXED_INSTALL_DIR}/lib/${LIB_PREFIX}draco.${LIB_EXT} CACHE FILEPATH "Path to Draco release library")
set(${EXTERNAL_NAME_UPPER}_ENCODER_LIBRARY ${SUFFIXED_INSTALL_DIR}/lib/${LIB_PREFIX}dracoenc.${LIB_EXT} CACHE FILEPATH "Path to Draco encoder release library")
set(${EXTERNAL_NAME_UPPER}_DECODER_LIBRARY ${SUFFIXED_INSTALL_DIR}/lib/${LIB_PREFIX}dracodec.${LIB_EXT} CACHE FILEPATH "Path to Draco decoder release library")

View file

@ -1,6 +1,12 @@
{
"version": 1.9,
"version": 2.0,
"settings": [
{
"name": "label",
"label": "Label",
"settings": [
]
},
{
"name": "metaverse",
"label": "Metaverse / Networking",
@ -14,7 +20,8 @@
{
"name": "id",
"label": "Domain ID",
"help": "This is your High Fidelity domain ID. If you do not want your domain to be registered in the High Fidelity metaverse you can leave this blank."
"help": "This is your High Fidelity domain ID. If you do not want your domain to be registered in the High Fidelity metaverse you can leave this blank.",
"advanced": true
},
{
"name": "automatic_networking",
@ -82,11 +89,13 @@
{
"name": "description",
"label": "Description",
"advanced": true,
"help": "A description of your domain (256 character limit)."
},
{
"name": "maturity",
"label": "Maturity",
"advanced": true,
"help": "A maturity rating, available as a guideline for content on your domain.",
"default": "unrated",
"type": "select",
@ -116,6 +125,7 @@
{
"name": "hosts",
"label": "Hosts",
"advanced": true,
"type": "table",
"can_add_new_rows": true,
"help": "Usernames of hosts who can reliably show your domain to new visitors.",
@ -131,6 +141,7 @@
{
"name": "tags",
"label": "Tags",
"advanced": true,
"type": "table",
"can_add_new_rows": true,
"help": "Common categories under which your domain falls.",
@ -1625,6 +1636,29 @@
]
}
]
},
{
"name": "wizard",
"label": "Setup Wizard",
"restart": false,
"hidden": true,
"settings": [
{
"name": "cloud_domain",
"type": "checkbox",
"default": false
},
{
"name": "steps_completed",
"type": "int",
"default": 0
},
{
"name": "completed_once",
"type": "checkbox",
"default": false
}
]
}
]
}
}

View file

@ -1,6 +1,7 @@
body {
position: relative;
padding-bottom: 30px;
margin-top: 70px;
}
[hidden] {
@ -27,14 +28,14 @@ body {
.table .value-row td,
.table .value-category td,
.table .inputs td {
vertical-align: middle;
vertical-align: middle;
}
.table .table-checkbox {
/* Fix IE sizing checkboxes to fill table cell */
width: auto;
margin-left: auto;
margin-right: auto;
/* Fix IE sizing checkboxes to fill table cell */
width: auto;
margin-left: auto;
margin-right: auto;
}
.value-category:not(.inputs) {
@ -80,8 +81,10 @@ span.port {
}
#setup-sidebar.affix {
position: fixed;
top: 15px;
/* This overrides a case where going to the bottom of the page,
* then scrolling up, causes `position: relative` to be added to the style
*/
position: fixed !important;
}
#setup-sidebar button {
@ -145,55 +148,55 @@ table {
}
caption {
color: #333;
font-weight: 700;
padding-top: 0;
color: #333;
font-weight: 700;
padding-top: 0;
}
table > tbody > .headers > td {
vertical-align: middle;
vertical-align: middle;
}
table .headers + .headers td {
font-size: 13px;
color: #222;
font-size: 13px;
color: #222;
}
#security table .headers td + td {
text-align: center;
text-align: center;
}
.tooltip.top .tooltip-arrow {
border-top-color: #fff;
border-width: 10px 10px 0;
margin-bottom: -5px;
border-top-color: #fff;
border-width: 10px 10px 0;
margin-bottom: -5px;
}
.tooltip-inner {
padding: 20px 20px 10px 20px;
font-size: 14px;
text-align: left;
color: #333;
background-color: #fff;
box-shadow: 0 3px 8px 8px #e8e8e8;
padding: 20px 20px 10px 20px;
font-size: 14px;
text-align: left;
color: #333;
background-color: #fff;
box-shadow: 0 3px 8px 8px #e8e8e8;
}
.tooltip.in {
opacity: 1;
opacity: 1;
}
.tooltip-inner ul {
padding-left: 0;
margin-bottom: 15px;
padding-left: 0;
margin-bottom: 15px;
}
.tooltip-inner li {
list-style-type: none;
margin-bottom: 5px;
list-style-type: none;
margin-bottom: 5px;
}
#security .tooltip-inner {
max-width: 520px;
max-width: 520px;
}
#xs-advanced-container {
@ -241,6 +244,20 @@ table .headers + .headers td {
animation-delay: -0.16s;
}
.col-centered {
float: none;
margin: 0 auto;
}
.centered-hack-parent {
text-align: center;
}
.centered-hack {
text-align: left;
display: inline-block;
}
@-webkit-keyframes bouncedelay {
0%, 80%, 100% { -webkit-transform: scale(0.0) }
40% { -webkit-transform: scale(1.0) }
@ -255,3 +272,50 @@ table .headers + .headers td {
-webkit-transform: scale(1.0);
}
}
/* From https://gist.github.com/alexandrevicenzi/680147013e902a4eaa5d */
.glyphicon-refresh-animate {
-animation: spin .7s infinite linear;
-ms-animation: spin .7s infinite linear;
-webkit-animation: spinw .7s infinite linear;
-moz-animation: spinm .7s infinite linear;
}
@keyframes spin {
from { transform: scale(1) rotate(0deg); }
to { transform: scale(1) rotate(360deg); }
}
@-webkit-keyframes spinw {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(360deg); }
}
@-moz-keyframes spinm {
from { -moz-transform: rotate(0deg); }
to { -moz-transform: rotate(360deg); }
}
.warning-text {
padding-top: 10px;
color: #EB5757;
}
.account-connected-header {
color: #6FCF97;
font-size: 30px;
margin-right: 20px;
}
#visit-domain-link,
.blue-link {
font-size: 14px;
text-decoration-line: underline;
font-weight: normal;
color: #2F80ED;
}
#manage-cloud-domains-link {
text-align: center;
margin-top: 20px;
}

Binary file not shown.

After

Width: 32px  |  Height: 32px  |  Size: 5.3 KiB

View file

@ -13,7 +13,7 @@
<script src='/js/sweetalert.min.js'></script>
</head>
<body>
<nav class="navbar navbar-default" role="navigation">
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
@ -23,7 +23,6 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">domain-server</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
@ -40,6 +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 href="#" id="restart-server"><span class="glyphicon glyphicon-refresh"></span> Restart</a></li>
</ul>
</div>

View file

@ -0,0 +1,25 @@
<svg width="676" height="676" viewBox="0 0 676 676" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>CongratulationImage</title>
<desc>Created using Figma</desc>
<g id="Canvas" transform="matrix(4 0 0 4 -21208 -17980)">
<g id="CongratulationImage">
<g id="Ellipse">
<use xlink:href="#path0_fill" transform="translate(5302 4495)" fill="#FFFFFF"/>
<mask id="mask0_outline_ins">
<use xlink:href="#path0_fill" fill="white" transform="translate(5302 4495)"/>
</mask>
<g mask="url(#mask0_outline_ins)">
<use xlink:href="#path1_stroke_2x" transform="translate(5302 4495)" fill="#219653"/>
</g>
</g>
<g id="Vector 2">
<use xlink:href="#path2_stroke" transform="translate(5355 4559)" fill="#219653"/>
</g>
</g>
</g>
<defs>
<path id="path0_fill" d="M 169 84.5C 169 131.168 131.168 169 84.5 169C 37.8319 169 0 131.168 0 84.5C 0 37.8319 37.8319 0 84.5 0C 131.168 0 169 37.8319 169 84.5Z"/>
<path id="path1_stroke_2x" d="M 154 84.5C 154 122.884 122.884 154 84.5 154L 84.5 184C 139.452 184 184 139.452 184 84.5L 154 84.5ZM 84.5 154C 46.1162 154 15 122.884 15 84.5L -15 84.5C -15 139.452 29.5477 184 84.5 184L 84.5 154ZM 15 84.5C 15 46.1162 46.1162 15 84.5 15L 84.5 -15C 29.5477 -15 -15 29.5477 -15 84.5L 15 84.5ZM 84.5 15C 122.884 15 154 46.1162 154 84.5L 184 84.5C 184 29.5477 139.452 -15 84.5 -15L 84.5 15Z"/>
<path id="path2_stroke" d="M 5.18747 19.8031C 2.19593 16.9382 -2.5517 17.0408 -5.41666 20.0323C -8.28162 23.0238 -8.17901 27.7715 -5.18747 30.6364L 5.18747 19.8031ZM 20.6541 45L 15.4667 50.4167C 18.3816 53.2083 22.9831 53.1924 25.8787 50.3809L 20.6541 45ZM 72.2246 5.38085C 75.1964 2.49539 75.2663 -2.25283 72.3809 -5.2246C 69.4954 -8.19636 64.7472 -8.26632 61.7754 -5.38085L 72.2246 5.38085ZM -5.18747 30.6364L 15.4667 50.4167L 25.8416 39.5833L 5.18747 19.8031L -5.18747 30.6364ZM 25.8787 50.3809L 72.2246 5.38085L 61.7754 -5.38085L 15.4295 39.6191L 25.8787 50.3809Z"/>
</defs>
</svg>

After

(image error) Size: 1.9 KiB

View file

@ -32,7 +32,6 @@ $(document).ready(function(){
$('ul.nav a').filter(function() {
return this.href == url;
}).parent().addClass('active');
$('body').on('click', '#restart-server', function(e) {
swal( {
title: "Are you sure?",
@ -46,4 +45,4 @@ $(document).ready(function(){
});
return false;
});
});
});

View file

@ -0,0 +1,393 @@
var Settings = {
showAdvanced: false,
ADVANCED_CLASS: 'advanced-setting',
DEPRECATED_CLASS: 'deprecated-setting',
TRIGGER_CHANGE_CLASS: 'trigger-change',
DATA_ROW_CLASS: 'value-row',
DATA_COL_CLASS: 'value-col',
DATA_CATEGORY_CLASS: 'value-category',
ADD_ROW_BUTTON_CLASS: 'add-row',
ADD_ROW_SPAN_CLASSES: 'glyphicon glyphicon-plus add-row',
DEL_ROW_BUTTON_CLASS: 'del-row',
DEL_ROW_SPAN_CLASSES: 'glyphicon glyphicon-remove del-row',
ADD_CATEGORY_BUTTON_CLASS: 'add-category',
ADD_CATEGORY_SPAN_CLASSES: 'glyphicon glyphicon-plus add-category',
TOGGLE_CATEGORY_COLUMN_CLASS: 'toggle-category',
TOGGLE_CATEGORY_SPAN_CLASS: 'toggle-category-icon',
TOGGLE_CATEGORY_SPAN_CLASSES: 'glyphicon toggle-category-icon',
TOGGLE_CATEGORY_EXPANDED_CLASS: 'glyphicon-triangle-bottom',
TOGGLE_CATEGORY_CONTRACTED_CLASS: 'glyphicon-triangle-right',
DEL_CATEGORY_BUTTON_CLASS: 'del-category',
DEL_CATEGORY_SPAN_CLASSES: 'glyphicon glyphicon-remove del-category',
MOVE_UP_BUTTON_CLASS: 'move-up',
MOVE_UP_SPAN_CLASSES: 'glyphicon glyphicon-chevron-up move-up',
MOVE_DOWN_BUTTON_CLASS: 'move-down',
MOVE_DOWN_SPAN_CLASSES: 'glyphicon glyphicon-chevron-down move-down',
TABLE_BUTTONS_CLASS: 'buttons',
ADD_DEL_BUTTONS_CLASS: 'add-del-buttons',
ADD_DEL_BUTTONS_CLASSES: 'buttons add-del-buttons',
REORDER_BUTTONS_CLASS: 'reorder-buttons',
REORDER_BUTTONS_CLASSES: 'buttons reorder-buttons',
NEW_ROW_CLASS: 'new-row',
CONNECT_ACCOUNT_BTN_ID: 'connect-account-btn',
DISCONNECT_ACCOUNT_BTN_ID: 'disconnect-account-btn',
CREATE_DOMAIN_ID_BTN_ID: 'create-domain-btn',
CHOOSE_DOMAIN_ID_BTN_ID: 'choose-domain-btn',
GET_TEMPORARY_NAME_BTN_ID: 'get-temp-name-btn',
DOMAIN_ID_SELECTOR: '[name="metaverse.id"]',
ACCESS_TOKEN_SELECTOR: '[name="metaverse.access_token"]',
PLACES_TABLE_ID: 'places-table',
ADD_PLACE_BTN_ID: 'add-place-btn',
FORM_ID: 'settings-form',
INVALID_ROW_CLASS: 'invalid-input',
DATA_ROW_INDEX: 'data-row-index'
};
var URLs = {
// STABLE METAVERSE_URL: https://metaverse.highfidelity.com
// STAGING METAVERSE_URL: https://staging.highfidelity.com
METAVERSE_URL: 'https://metaverse.highfidelity.com',
PLACE_URL: 'https://hifi.place',
};
var Strings = {
LOADING_SETTINGS_ERROR: "There was a problem loading the domain settings.\nPlease refresh the page to try again.",
CHOOSE_DOMAIN_BUTTON: "Choose from my domains",
CREATE_DOMAIN_BUTTON: "Create new domain ID",
CREATE_DOMAIN_SUCCESS_JUST_CONNECTED: "We connnected your High Fidelity account and created a new domain ID for this machine.",
CREATE_DOMAIN_SUCCESS: "We created a new domain ID for this machine.",
// When a place modification fails, they will be brought back to the previous
// dialog with new path still set, allowing them to retry immediately, and without
// having to type the new path in again.
EDIT_PLACE_TITLE: "Modify Viewpoint or Path",
EDIT_PLACE_ERROR: "Failed to update place path. Please try again.",
EDIT_PLACE_CONFIRM_BUTTON: "Save",
EDIT_PLACE_CONFIRM_BUTTON_PENDING: "Saving...",
EDIT_PLACE_CANCEL_BUTTON: "Cancel",
REMOVE_PLACE_TITLE: "Are you sure you want to remove <strong>{{place}}</strong>?",
REMOVE_PLACE_ERROR: "Failed to remove place. Please try again.",
REMOVE_PLACE_DELETE_BUTTON: "Delete",
REMOVE_PLACE_DELETE_BUTTON_PENDING: "Deleting...",
REMOVE_PLACE_CANCEL_BUTTON: "Cancel",
ADD_PLACE_TITLE: "Choose a place",
ADD_PLACE_MESSAGE: "Choose the High Fidelity place to point at this domain server.",
ADD_PLACE_CONFIRM_BUTTON: "Choose place",
ADD_PLACE_CONFIRM_BUTTON_PENDING: "Saving...",
ADD_PLACE_CANCEL_BUTTON: "Cancel",
ADD_PLACE_UNKNOWN_ERROR: "There was an error adding this place name.",
ADD_PLACE_NO_PLACES_MESSAGE: "<p>You do not have any places in your High Fidelity account."
+ "<br/><br/>Go to your <a href='https://metaverse.highfidelity.com/user/places/new'>places page</a> to create a new one. Once your place is created re-open this dialog to select it.</p>",
ADD_PLACE_NO_PLACES_BUTTON: "Create new place",
ADD_PLACE_UNABLE_TO_LOAD_ERROR: "We were unable to load your place names. Please try again later.",
ADD_PLACE_LOADING_DIALOG: "Loading your places...",
ADD_PLACE_NOT_CONNECTED_TITLE: "Access token required",
ADD_PLACE_NOT_CONNECTED_MESSAGE: "You must have an access token to query your High Fidelity places.<br><br>Please follow the instructions on the settings page to add an access token.",
};
var DOMAIN_ID_TYPE_NONE = 0;
var DOMAIN_ID_TYPE_TEMP = 1;
var DOMAIN_ID_TYPE_FULL = 2;
var DOMAIN_ID_TYPE_UNKNOWN = 3;
function domainIDIsSet() {
return Settings.data.values.metaverse.id.length > 0;
}
function getCurrentDomainIDType() {
if (!domainIDIsSet()) {
return DOMAIN_ID_TYPE_NONE;
}
if (typeof DomainInfo === 'undefined') {
return DOMAIN_ID_TYPE_UNKNOWN;
}
if (DomainInfo !== null) {
if (DomainInfo.name !== undefined) {
return DOMAIN_ID_TYPE_TEMP;
}
return DOMAIN_ID_TYPE_FULL;
}
return DOMAIN_ID_TYPE_UNKNOWN;
}
function showLoadingDialog(msg) {
var message = '<div class="text-center">';
message += '<span class="glyphicon glyphicon-refresh glyphicon-refresh-animate"></span> ' + msg;
message += '</div>';
return bootbox.dialog({
message: message,
closeButton: false
});
}
function sendUpdatePlaceRequest(id, path, domainID, clearDomainID, onSuccess, onError) {
var data = {
place_id: id,
path: path
};
if (domainID) {
data.domain_id = domainID;
}
if (clearDomainID) {
data.domain_id = null;
}
$.ajax({
url: '/api/places',
type: 'PUT',
data: data,
success: onSuccess,
error: onError
});
}
function chooseFromHighFidelityPlaces(accessToken, forcePathTo, onSuccessfullyAdded) {
if (accessToken) {
var loadingDialog = showLoadingDialog(Strings.ADD_PLACE_LOADING_DIALOG);
$.ajax("/api/places", {
dataType: 'json',
jsonp: false,
success: function(data) {
if (data.status == 'success') {
var modal_buttons = {
cancel: {
label: Strings.ADD_PLACE_CANCEL_BUTTON,
className: 'add-place-cancel-button btn-default'
}
};
var dialog;
var modal_body;
if (data.data.places.length) {
var places_by_id = {};
modal_body = $('<div>');
modal_body.append($("<p>Choose a place name that you own or <a href='" + URLs.METAVERSE_URL + "/user/places' target='_blank'>register a new place name</a></p>"));
var currentDomainIDType = getCurrentDomainIDType();
if (currentDomainIDType === DOMAIN_ID_TYPE_TEMP) {
var warning = "<div class='domain-loading-error alert alert-warning'>";
warning += "If you choose a place name it will replace your current temporary place name.";
warning += "</div>";
modal_body.append(warning);
}
// setup a select box for the returned places
modal_body.append($("<label for='place-name-select'>Places</label>"));
place_select = $("<select id='place-name-select' class='form-control'></select>");
_.each(data.data.places, function(place) {
places_by_id[place.id] = place;
place_select.append("<option value='" + place.id + "'>" + place.name + "</option>");
})
modal_body.append(place_select);
modal_body.append($("<p id='place-name-warning' class='warning-text' style='display: none'>This place name already points to a place or path. Saving this would overwrite the previous settings associated with it.</p>"));
if (forcePathTo === undefined || forcePathTo === null) {
var path = "<div class='form-group'>";
path += "<label for='place-path-input' class='control-label'>Path</label>";
path += "<input type='text' id='place-path-input' class='form-control' value='/'>";
path += "</div>";
modal_body.append($(path));
}
var place_select = modal_body.find("#place-name-select")
place_select.change(function(ev) {
var warning = modal_body.find("#place-name-warning");
var place = places_by_id[$(this).val()];
if (place === undefined || place.pointee === null) {
warning.hide();
} else {
warning.show();
}
});
place_select.trigger('change');
modal_buttons["success"] = {
label: Strings.ADD_PLACE_CONFIRM_BUTTON,
className: 'add-place-confirm-button btn btn-primary',
callback: function() {
var placeID = $('#place-name-select').val();
// set the place ID on the form
$(Settings.place_ID_SELECTOR).val(placeID).change();
if (forcePathTo === undefined || forcePathTo === null) {
var placePath = $('#place-path-input').val();
} else {
var placePath = forcePathTo;
}
$('.add-place-confirm-button').attr('disabled', 'disabled');
$('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON_PENDING);
$('.add-place-cancel-button').attr('disabled', 'disabled');
function finalizeSaveDomainID(domainID) {
var jsonSettings = {
metaverse: {
id: domainID
}
}
var dialog = showLoadingDialog("Waiting for Domain Server to restart...");
$.ajax('/settings.json', {
data: JSON.stringify(jsonSettings),
contentType: 'application/json',
type: 'POST'
}).done(function(data) {
if (data.status == "success") {
waitForDomainServerRestart(function() {
dialog.modal('hide');
if (onSuccessfullyAdded) {
onSuccessfullyAdded(places_by_id[placeID].name, domainID);
}
});
} else {
bootbox.alert("Failed to add place");
}
}).fail(function() {
bootbox.alert("Failed to add place");
});
}
function finishSettingUpPlace(domainID) {
sendUpdatePlaceRequest(
placeID,
placePath,
domainID,
false,
function(data) {
$(Settings.DOMAIN_ID_SELECTOR).val(domainID).change();
dialog.modal('hide')
if (domainID) {
finalizeSaveDomainID(domainID);
} else {
if (onSuccessfullyAdded) {
onSuccessfullyAdded(places_by_id[placeID].name);
}
}
},
function(data) {
$('.add-place-confirm-button').removeAttr('disabled');
$('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON);
$('.add-place-cancel-button').removeAttr('disabled');
bootbox.alert(Strings.ADD_PLACE_UNKNOWN_ERROR);
}
);
}
if (currentDomainIDType === DOMAIN_ID_TYPE_FULL) {
finishSettingUpPlace();
} else {
sendCreateDomainRequest(function(domainID) {
console.log("Created domain", domainID);
finishSettingUpPlace(domainID);
}, function() {
$('.add-place-confirm-button').removeAttr('disabled');
$('.add-place-confirm-button').html(Strings.ADD_PLACE_CONFIRM_BUTTON);
$('.add-place-cancel-button').removeAttr('disabled');
bootbox.alert(Strings.ADD_PLACE_UNKNOWN_ERROR);
bootbox.alert("FAIL");
});
}
return false;
}
}
} else {
modal_buttons["success"] = {
label: Strings.ADD_PLACE_NO_PLACES_BUTTON,
callback: function() {
window.open(URLs.METAVERSE_URL + "/user/places", '_blank');
}
}
modal_body = Strings.ADD_PLACE_NO_PLACES_MESSAGE;
}
dialog = bootbox.dialog({
title: Strings.ADD_PLACE_TITLE,
message: modal_body,
closeButton: false,
buttons: modal_buttons
});
} else {
bootbox.alert(Strings.ADD_PLACE_UNABLE_TO_LOAD_ERROR);
}
},
error: function() {
bootbox.alert(Strings.ADD_PLACE_UNABLE_TO_LOAD_ERROR);
},
complete: function() {
loadingDialog.modal('hide');
}
});
} else {
bootbox.alert({
title: Strings.ADD_PLACE_NOT_CONNECTED_TITLE,
message: Strings.ADD_PLACE_NOT_CONNECTED_MESSAGE
})
}
}
function sendCreateDomainRequest(onSuccess, onError) {
$.ajax({
url: '/api/domains',
dataType: 'json',
type: 'POST',
data: { label: "" },
success: function(data) {
onSuccess(data.domain.id);
},
error: onError
});
}
function waitForDomainServerRestart(callback) {
function checkForDomainUp() {
$.ajax('', {
success: function() {
callback();
},
error: function() {
setTimeout(checkForDomainUp, 50);
}
});
}
setTimeout(checkForDomainUp, 10);
}
function prepareAccessTokenPrompt(callback) {
swal({
title: "Connect Account",
type: "input",
text: "Paste your created access token here." +
"</br></br>If you did not successfully create an access token click cancel below and attempt to connect your account again.</br></br>",
showCancelButton: true,
closeOnConfirm: false,
html: true
}, function(inputValue){
if (inputValue === false) {
return false;
}
if (inputValue === "") {
swal.showInputError("Please paste your access token in the input field.")
return false
}
if (callback) {
callback(inputValue);
}
swal.close();
});
}

View file

@ -9,16 +9,18 @@
<div class="row">
<div class="col-md-3 col-sm-3" id="setup-sidebar-col">
<div id="setup-sidebar" class="hidden-xs" data-spy="affix" data-offset-top="55" data-clampedwidth="#setup-sidebar-col">
<div id="setup-sidebar" data-clampedwidth="#setup-sidebar-col">
<script id="list-group-template" type="text/template">
<% _.each(descriptions, function(group){ %>
<% panelID = group.name ? group.name : group.html_id %>
<li>
<a href="#<%- panelID %>" class="list-group-item">
<span class="badge"></span>
<%- group.label %>
</a>
</li>
<% if (!group.hidden) { %>
<% panelID = group.name ? group.name : group.html_id %>
<li>
<a href="#<%- panelID %>" class="list-group-item">
<span class="badge"></span>
<%- group.label %>
</a>
</li>
<% } %>
<% }); %>
</script>
@ -26,49 +28,63 @@
</ul>
<button id="advanced-toggle-button" class="btn btn-info advanced-toggle">Show advanced</button>
<button class="btn btn-success save-button">Save</button>
<button class="btn btn-success save-button" disabled>Save</button>
<div id="manage-cloud-domains-link" style="display: none;">
<a href="https://highfidelity.com/user/cloud_domains" target="_blank" class="blue-link">Manage Cloud Hosted Domains</a>
</div>
</div>
</div>
<div class="col-md-9 col-sm-9 col-xs-12">
<div id="xs-advanced-container" class="col-xs-12 hidden-sm hidden-md hidden-lg">
<button id="advanced-toggle-button-xs" class="btn btn-info advanced-toggle">Show advanced</button>
</div>
<div class="col-xs-12">
<div id="cloud-domains-alert" class="alert alert-info alert-dismissible" role="alert" style="display: none;">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<span class="alert-link">
<a href="https://highfidelity.com/user/cloud_domains" target="_blank" class="blue-link">Visit Cloud Hosted Domains</a> to manage all your cloud domains
</span>
</div>
<form id="settings-form" role="form">
<script id="panels-template" type="text/template">
<% _.each(descriptions, function(group){ %>
<% var settings = _.partition(group.settings, function(value, index) { return !value.deprecated })[0] %>
<% split_settings = _.partition(settings, function(value, index) { return !value.advanced }) %>
<% isAdvanced = _.isEmpty(split_settings[0]) %>
<% if (isAdvanced) { %>
<% $("a[href=#" + group.name + "]").addClass('advanced-setting').hide() %>
<% } %>
<% if (!group.hidden) { %>
<% var settings = _.partition(group.settings, function(value, index) { return !value.deprecated })[0] %>
<% split_settings = _.partition(settings, function(value, index) { return !value.advanced }) %>
<% isAdvanced = _.isEmpty(split_settings[0]) && !_.isEmpty(split_settings[1]) %>
<% if (isAdvanced) { %>
<% $("a[href=#" + group.name + "]").addClass('advanced-setting').hide() %>
<% } %>
<% isGrouped = !!group.name %>
<% panelID = isGrouped ? group.name : group.html_id %>
<% isGrouped = !!group.name %>
<% panelID = isGrouped ? group.name : group.html_id %>
<div class="panel panel-default<%- (isAdvanced) ? ' advanced-setting' : '' %><%- (isGrouped) ? ' grouped' : '' %>"
id="<%- panelID %>">
<div class="panel-heading">
<h3 class="panel-title"><%- group.label %></h3>
</div>
<div class="panel-body">
<% _.each(split_settings[0], function(setting) { %>
<% keypath = isGrouped ? group.name + "." + setting.name : setting.name %>
<%= getFormGroup(keypath, setting, values, false) %>
<% }); %>
<% if (!_.isEmpty(split_settings[1])) { %>
<% $("#advanced-toggle-button").show() %>
<% _.each(split_settings[1], function(setting) { %>
<div class="panel panel-default<%- (isAdvanced) ? ' advanced-setting' : '' %><%- (isGrouped) ? ' grouped' : '' %>"
id="<%- panelID %>">
<div class="panel-heading">
<h3 class="panel-title"><%- group.label %></h3>
</div>
<div class="panel-body">
<% _.each(split_settings[0], function(setting) { %>
<% keypath = isGrouped ? group.name + "." + setting.name : setting.name %>
<%= getFormGroup(keypath, setting, values, true) %>
<%= getFormGroup(keypath, setting, values, false) %>
<% }); %>
<% }%>
<% if (!_.isEmpty(split_settings[1])) { %>
<% $("#advanced-toggle-button").show() %>
<% _.each(split_settings[1], function(setting) { %>
<% keypath = isGrouped ? group.name + "." + setting.name : setting.name %>
<%= getFormGroup(keypath, setting, values, true) %>
<% }); %>
<% }%>
</div>
</div>
</div>
<% } %>
<% }); %>
</script>
<div id="panels"></div>
@ -85,8 +101,9 @@
<script src='/js/underscore-min.js'></script>
<script src='/js/underscore-keypath.min.js'></script>
<script src='/js/bootbox.min.js'></script>
<script src='js/bootstrap-switch.min.js'></script>
<script src='js/settings.js'></script>
<script src='/js/sha256.js'></script>
<script src='js/form2js.min.js'></script>
<script src='js/sha256.js'></script>
<script src='js/bootstrap-switch.min.js'></script>
<script src='/js/shared.js'></script>
<script src='js/settings.js'></script>
<!--#include virtual="page-end.html"-->

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,89 @@
label {
font-style: normal;
font-weight: normal;
line-height: 24px;
font-size: 16px;
color: #373A3C;
}
.step-title {
margin-bottom: 20px;
line-height: 26px;
font-size: 24px;
color: #373A3C;
}
.step-description {
line-height: 24px;
font-size: 16px;
color: #818A91;
}
.step-info {
font-style: normal;
font-weight: normal;
line-height: 24px;
font-size: 16px;
color: #373A3C;
}
#admin-row {
margin-top: 20px;
margin-bottom: 20px;
}
#connect-question {
margin-top: 10px;
}
#connect-account-btn {
margin-top: 30px;
margin-bottom: 205px;
}
#place-name-group {
margin-top: 42px;
margin-bottom: 140px;
display: inline-block;
}
#place-name-link {
line-height: 38px;
font-size: 32px;
display: inline-block;
color: #373A3C;
}
#place-name-edit {
text-align: right;
}
#change-place-name {
line-height: 24px;
font-size: 18px;
}
#rez-options-row {
margin-bottom: 60px;
}
#verify-password-row {
margin-bottom: 33px;
}
#checkmark-image {
margin-top: 66px;
margin-bottom: 59px;
width: 169px;
height: 169px;
}
#visit-domain-row {
margin-bottom: 68px;
}

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>domain-server</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="/css/style.css" rel="stylesheet" media="screen">
<link href="/wizard/css/style.css" rel="stylesheet" media="screen">
<link href="/css/sweetalert.css" rel="stylesheet" media="screen">
<link href="/css/bootstrap-switch.min.css" rel="stylesheet" media="screen">
<script src='/js/sweetalert.min.js'></script>
</head>
<body>
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid">
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<a class="navbar-brand step-info" href="#">Setup Wizard (Domain Server Settings)</a>
<div class="navbar-form navbar-right">
<button id="skip-wizard-button" type="button" class="btn btn-default" style="display:none;">Skip Wizard</button>
</div>
</div>
</div><!-- /.container-fluid -->
</nav>
<div class="container">

View file

@ -0,0 +1,229 @@
<!--#include virtual="wizard/header.html"-->
<div class="wizard-step desktop-only col-md-6 col-centered" style="display: none;">
<h4 class="step-title"></h4>
<dl class="row">
<dd class="col-md-12">
<span class='step-description'>By connecting your High Fidelity Account you will be granting access to your account information.</span>
</dd>
</dl>
<dl class="row">
<dd class="col-md-12">
<a id="connect-account-btn" role="button" class="btn btn-primary btn-md btn-block" target="_blank">Connect your High Fidelity account</a>
</dd>
</dl>
<dl class="row">
<dd class="col-md-3">
<button type="button" class="btn btn-md btn-block btn-default next-button">Skip</button>
</dd>
</dl>
</div>
<div class="wizard-step col-md-8 col-centered" style="display: none;">
<h4 class="step-title"></h4>
<div class="row">
<div class="col-md-12">
<span class='step-description'>
<a target='_blank' href='https://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/place-names'>Place names</a> are similar to web addresses. Users who want to visit your domain can
enter its Place Name in High Fidelity's Interface. You can choose a Place Name for your domain.</br>
People can also use your <b>domain's IP address (shown below)</b> to visit your High Fidelity domain.
</span>
</div>
</div>
<div class="row">
<div class="centered-hack-parent">
<div id="place-name-group" class="centered-hack">
<p id="place-name-link"></p>
<div id="place-name-edit">
<span class='glyphicon glyphicon-pencil'></span>
<a href="#" id="change-place-name">Choose a custom Place Name instead</a>
</div>
</div>
</div>
</div>
<dl class="row">
<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 type="button" class="btn btn-md btn-block btn-primary next-button">Next</button>
</dd>
</dl>
</div>
<div class="wizard-step col-md-9 col-centered" style="display: none;">
<h4 class="step-title"></h4>
<div class="row">
<p id="permissions-description" class="col-md-12 step-info"><b>Localhost</b> has been granted administrator privileges to this domain. (Localhost is any</br>user on the same machine as the High Fidelity Server)</p>
</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>
</p>
<div class="col-md-6">
<input id="admin-usernames" type="text" class="form-control">
<span class="help-block text-right">separate by commas (user1, user2,..)</span>
</div>
</div>
<div class="row">
<div class="col-md-12">
<span class="step-description">Grant basic permissions to other users. You can change these later.</span>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p id="connect-question" class="step-info">
Who can connect 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>
</div>
<div class="row">
<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>
</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>
<div class="row">
<div class="col-md-12">
<p class="step-info">
Who can rez items 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>
</div>
<div id="rez-options-row" class="row">
<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>
</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>
</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>
</label>
</p>
</div>
<div class="row">
<div class="col-md-3 col-md-offset-9">
<button id="save-permissions" type="button" class="btn btn-md btn-block btn-primary">Next</button>
</div>
</div>
</div>
<div class="wizard-step cloud-only col-md-7 col-centered" style="display: none;">
<h4 class="step-title"></h4>
<dl class="row">
<dd class="col-md-12">
<span class='step-description'>
Your server settings are currently accessible without a username and password.
Adding credentials will ensure that only authorized users have access to modify the settings.
</span>
</dd>
</dl>
<div class="row">
<p class="col-md-12 step-info">Create a username and password to secure the access to your domain server settings.</p>
</div>
<dl class="row">
<dt class="col-md-4 step-info">Username</dt>
<dd class="col-md-8">
<input id="http_username" type="text" class="form-control">
<span class='help-block'>This does not have to be your High Fidelity username</span>
</dd>
</dl>
<dl class="row">
<dt class="col-md-4 step-info">Enter password</dt>
<dd class="col-md-8">
<input id="http_password" type="password" class="form-control">
<span class='help-block'>This should not be the same as your High Fidelity password</span>
</dd>
</dl>
<dl id="verify-password-row" class="row">
<dt class="col-md-4 step-info">Re-enter password</dt>
<dd class="col-md-8">
<input id="verify_http_password" type="password" class="form-control">
</dd>
</dl>
<dl class="row">
<dd class="col-md-3 col-md-offset-9">
<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="row">
<div class="col-xs-4 col-centered">
<img id="checkmark-image" src="../images/checkmark.svg">
</div>
</div>
<div class="row">
<div class="col-md-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>
</dl>
</div>
<!--#include virtual="footer.html"-->
<script src='/js/underscore-min.js'></script>
<script src='/js/bootbox.min.js'></script>
<script src='/js/sha256.js'></script>
<script src='/js/shared.js'></script>
<script src='js/wizard.js'></script>
<!--#include virtual="page-end.html"-->

View file

@ -0,0 +1,471 @@
var Metaverse = {
accessToken: null
}
$(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.";
$('#connect-account-btn').attr('href', URLs.METAVERSE_URL + "/user/tokens/new?for_domain_server=true");
$('[data-toggle="tooltip"]').tooltip();
$('body').on('click', '.next-button', function() {
goToNextStep();
});
$('body').on('click', '.back-button', function() {
goToPreviousStep();
});
$('body').on('click', '#skip-wizard-button', function() {
skipWizard();
})
$('body').on('click', '#connect-account-btn', function() {
$(this).blur();
prepareAccessTokenPrompt(function(accessToken) {
Metaverse.accessToken = accessToken;
saveAccessToken();
});
});
$('body').on('click', '#save-permissions', function() {
savePermissions();
});
function triggerSaveUsernamePassword(event) {
if (event.keyCode === 13) {
$("#save-username-password").click();
}
}
$("#http_username").keyup(triggerSaveUsernamePassword);
$("#http_password").keyup(triggerSaveUsernamePassword);
$("#verify_http_password").keyup(triggerSaveUsernamePassword);
$('body').on('click', '#save-username-password', function() {
saveUsernamePassword();
});
$('body').on('click', '#change-place-name', function() {
chooseFromHighFidelityPlaces(Settings.data.values.metaverse.access_token, "/0,-10,0", function(placeName) {
updatePlaceNameLink(placeName);
});
});
$('body').on('click', '#explore-settings', function() {
exploreSettings();
});
reloadSettings(function(success) {
if (success) {
setupWizardSteps();
updatePlaceNameDisplay();
updateUsernameDisplay();
} else {
swal({
title: '',
type: 'error',
text: "There was a problem loading the domain settings.\nPlease refresh the page to try again.",
});
}
});
});
function setupWizardSteps() {
var stepsCompleted = 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();
steps = $('.wizard-step');
$(steps).each(function(i) {
$(this).children(".step-title").text("Step " + (i + 1) + " of " + (steps.length - 1));
});
$('#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.');
} else {
$('.cloud-only').remove();
$('#save-permissions').text("Finish");
steps = $('.wizard-step');
$(steps).each(function(i) {
$(this).children(".step-title").text("Step " + (i + 1) + " of " + steps.length);
});
if (stepsCompleted == 0) {
$('#skip-wizard-button').show();
}
}
var currentStep = steps[stepsCompleted];
$(currentStep).show();
}
function updatePlaceNameLink(address) {
if (address) {
$('#place-name-link').html('Your domain is reachable at: <a target="_blank" href="' + URLs.PLACE_URL + '/' + address + '">' + address + '</a>');
}
}
function updatePlaceNameDisplay() {
if (Settings.data.values.metaverse.id) {
$.getJSON(URLs.METAVERSE_URL + '/api/v1/domains/' + Settings.data.values.metaverse.id, function(data) {
if (data.status === 'success') {
if (data.domain.default_place_name) {
// Place name
updatePlaceNameLink(data.domain.default_place_name);
} else if (data.domain.name) {
// Temporary name
updatePlaceNameLink(data.domain.name);
} else if (data.domain.network_address) {
if (data.domain.network_port !== 40102) {
// IP:PORT
updatePlaceNameLink(data.domain.network_address + ':' + data.domain.network_port);
} else {
// IP
updatePlaceNameLink(data.domain.network_address);
}
}
} else {
console.warn('Request Failed');
}
}).fail(function() {
console.warn('Request Failed');
});
} else {
console.warn('No metaverse domain ID!');
}
}
function updateUsernameDisplay() {
var permissions = Settings.data.values.security.permissions;
if (permissions.length > 0) {
$('#username-display').html('<b>(' + permissions[0].permissions_id + ')</b> ');
}
}
function reloadSettings(callback) {
$.getJSON('/settings.json', function(data){
Settings.data = data;
if (callback) {
// call the callback now that settings are loaded
callback(true);
}
}).fail(function() {
if (callback) {
// call the failure object since settings load failed
callback(false)
}
});
}
function postSettings(jsonSettings, callback) {
console.log("----- SAVING ------");
console.log(JSON.stringify(jsonSettings));
// POST the form JSON to the domain-server settings.json endpoint so the settings are saved
$.ajax('/settings.json', {
data: JSON.stringify(jsonSettings),
contentType: 'application/json',
type: 'POST'
}).done(function(data){
if (data.status == "success") {
if (callback) {
callback();
}
reloadSettings();
} else {
swal("Error", Strings.LOADING_SETTINGS_ERROR)
reloadSettings();
}
}).fail(function(){
swal("Error", Strings.LOADING_SETTINGS_ERROR)
reloadSettings();
});
}
function goToNextStep() {
$('#skip-wizard-button').hide();
var currentStep = $('body').find('.wizard-step:visible');
var nextStep = currentStep.next('.wizard-step');
var formJSON = {
"wizard": {}
}
if (nextStep.length > 0) {
currentStep.hide();
nextStep.show();
var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) + 1;
postSettings({
"wizard": {
"steps_completed": currentStepNumber.toString()
}
});
} else {
postSettings({
"wizard": {
"steps_completed": "0",
"completed_once": true
}
}, redirectToSettings);
}
}
function goToPreviousStep() {
var currentStep = $('body').find('.wizard-step:visible');
var previousStep = currentStep.prev('.wizard-step');
var formJSON = {
"wizard": {}
}
if (previousStep.length > 0) {
currentStep.hide();
previousStep.show();
var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) - 1;
postSettings({
"wizard": {
"steps_completed": currentStepNumber.toString()
}
});
}
}
function skipWizard() {
postSettings({
"wizard": {
"steps_completed": "0",
"completed_once": true
}
}, redirectToSettings);
}
function redirectToSettings() {
var redirectURL = "/settings" + location.search;
if (Settings.data.values.wizard.cloud_domain) {
if (location.search.length > 0) {
redirectURL += "&";
} else {
redirectURL += "?";
}
redirectURL += "cloud-wizard-exit";
}
location.href = redirectURL;
}
function saveAccessToken() {
var formJSON = {
"metaverse": {}
}
if (Metaverse.accessToken) {
formJSON.metaverse.access_token = Metaverse.accessToken;
}
// remove focus from the button
$(this).blur();
// POST the form JSON to the domain-server settings.json endpoint so the settings are saved
postSettings(formJSON, goToNextStep);
}
function getSettingDescriptionForKey(groupKey, settingKey) {
for (var i in Settings.data.descriptions) {
var group = Settings.data.descriptions[i];
if (group.name === groupKey) {
for (var j in group.settings) {
var setting = group.settings[j];
if (setting.name === settingKey) {
return setting;
}
}
}
}
}
function savePermissions() {
var localhostPermissions = (Settings.data.values.wizard.cloud_domain !== true)
var anonymousCanConnect = false;
var friendsCanConnect = false;
var loggedInCanConnect = false;
var anonymousCanRez = false;
var friendsCanRez = false;
var loggedInCanRez = false;
var connectValue = $('input[name=connect-radio]:checked').val();
var rezValue = $('input[name=rez-radio]:checked').val();
switch (connectValue) {
case "friends":
friendsCanConnect = true;
break;
case "logged-in":
friendsCanConnect = true;
loggedInCanConnect = true;
break;
case "everyone":
anonymousCanConnect = true;
friendsCanConnect = true;
loggedInCanConnect = true;
break;
}
switch (rezValue) {
case "friends":
friendsCanRez = true;
break;
case "logged-in":
friendsCanRez = true;
loggedInCanRez = true;
break;
case "everyone":
anonymousCanRez = true;
friendsCanRez = true;
loggedInCanRez = true;
break;
}
var admins = $('#admin-usernames').val().split(',');
var existingAdmins = Settings.data.values.security.permissions.map(function(value) {
return value.permissions_id;
});
admins = admins.concat(existingAdmins);
// Filter out unique values
admins = _.uniq(admins.map(function(username) {
return username.trim();
})).filter(function(username) {
return username !== "";
});
var formJSON = {
"security": {
"standard_permissions": [
{
"id_can_connect": anonymousCanConnect,
"id_can_rez": anonymousCanRez,
"id_can_rez_certified": anonymousCanRez,
"id_can_rez_tmp": anonymousCanRez,
"id_can_rez_tmp_certified": anonymousCanRez,
"permissions_id": "anonymous"
},
{
"id_can_connect": friendsCanConnect,
"id_can_rez": friendsCanRez,
"id_can_rez_certified": friendsCanRez,
"id_can_rez_tmp": friendsCanRez,
"id_can_rez_tmp_certified": friendsCanRez,
"permissions_id": "friends"
},
{
"id_can_connect": loggedInCanConnect,
"id_can_rez": loggedInCanRez,
"id_can_rez_certified": loggedInCanRez,
"id_can_rez_tmp": loggedInCanRez,
"id_can_rez_tmp_certified": loggedInCanRez,
"permissions_id": "logged-in"
},
{
"id_can_adjust_locks": localhostPermissions,
"id_can_connect": localhostPermissions,
"id_can_connect_past_max_capacity": localhostPermissions,
"id_can_kick": localhostPermissions,
"id_can_replace_content": localhostPermissions,
"id_can_rez": localhostPermissions,
"id_can_rez_certified": localhostPermissions,
"id_can_rez_tmp": localhostPermissions,
"id_can_rez_tmp_certified": localhostPermissions,
"id_can_write_to_asset_server": localhostPermissions,
"permissions_id": "localhost"
}
]
}
}
if (admins.length > 0) {
formJSON.security.permissions = [];
var permissionsDesc = getSettingDescriptionForKey("security", "permissions");
for (var i in admins) {
var admin = admins[i];
var perms = {};
for (var i in permissionsDesc.columns) {
var name = permissionsDesc.columns[i].name;
if (name === "permissions_id") {
perms[name] = admin;
} else {
perms[name] = true;
}
}
formJSON.security.permissions.push(perms);
}
}
// remove focus from the button
$(this).blur();
postSettings(formJSON, goToNextStep);
}
function saveUsernamePassword() {
var username = $("#http_username").val();
var password = $("#http_password").val();
var verify_password = $("#verify_http_password").val();
if (username.length == 0) {
bootbox.alert({ "message": "You must set a username!", "title": "Username Error" });
return;
}
if (password.length == 0) {
bootbox.alert({ "message": "You must set a password!", "title": "Password Error" });
return;
}
if (password != verify_password) {
bootbox.alert({ "message": "Passwords must match!", "title": "Password Error" });
return;
}
var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) + 1;
var formJSON = {
"security": {
"http_username": username,
"http_password": sha256_digest(password)
},
"wizard": {
"steps_completed": currentStepNumber.toString()
}
}
// remove focus from the button
$(this).blur();
// POST the form JSON to the domain-server settings.json endpoint so the settings are saved
postSettings(formJSON, function() {
location.reload();
});
}
function exploreSettings() {
if ($('#go-to-domain').is(":checked")) {
var link = $('#place-name-link a:first');
if (link.length > 0) {
window.open(link.attr("href"));
}
}
goToNextStep();
}

View file

@ -46,6 +46,8 @@
#include "DomainServerNodeData.h"
#include "NodeConnectionData.h"
const QString ACCESS_TOKEN_KEY_PATH = "metaverse.access_token";
int const DomainServer::EXIT_CODE_REBOOT = 234923;
#if USE_STABLE_GLOBAL_SERVICES
@ -54,6 +56,82 @@ const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.com";
const QString ICE_SERVER_DEFAULT_HOSTNAME = "dev-ice.highfidelity.com";
#endif
bool DomainServer::forwardMetaverseAPIRequest(HTTPConnection* connection,
const QString& metaversePath,
const QString& requestSubobjectKey,
std::initializer_list<QString> requiredData,
std::initializer_list<QString> optionalData,
bool requireAccessToken) {
auto accessTokenVariant = valueForKeyPath(_settingsManager.getSettingsMap(), ACCESS_TOKEN_KEY_PATH);
if (accessTokenVariant == nullptr && requireAccessToken) {
connection->respond(HTTPConnection::StatusCode400, "User access token has not been set");
return true;
}
QJsonObject subobject;
auto params = connection->parseUrlEncodedForm();
for (auto& key : requiredData) {
auto it = params.find(key);
if (it == params.end()) {
auto error = "Bad request, expected param '" + key + "'";
connection->respond(HTTPConnection::StatusCode400, error.toLatin1());
return true;
}
subobject.insert(key, it.value());
}
for (auto& key : optionalData) {
auto it = params.find(key);
if (it != params.end()) {
subobject.insert(key, it.value());
}
}
QJsonObject root;
root.insert(requestSubobjectKey, subobject);
QJsonDocument doc { root };
QUrl url { NetworkingConstants::METAVERSE_SERVER_URL.toString() + metaversePath };
QNetworkRequest req(url);
req.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
if (accessTokenVariant != nullptr) {
auto accessTokenHeader = QString("Bearer ") + accessTokenVariant->toString();
req.setRawHeader("Authorization", accessTokenHeader.toLatin1());
}
QNetworkReply* reply;
auto method = connection->requestOperation();
if (method == QNetworkAccessManager::GetOperation) {
reply = NetworkAccessManager::getInstance().get(req);
} else if (method == QNetworkAccessManager::PostOperation) {
reply = NetworkAccessManager::getInstance().post(req, doc.toJson());
} else if (method == QNetworkAccessManager::PutOperation) {
reply = NetworkAccessManager::getInstance().put(req, doc.toJson());
} else {
connection->respond(HTTPConnection::StatusCode400, "Error forwarding request, unsupported method");
return true;
}
connect(reply, &QNetworkReply::finished, this, [reply, connection]() {
if (reply->error() != QNetworkReply::NoError) {
auto data = reply->readAll();
qDebug() << "Got error response from metaverse server (" << reply->url() << "): " << data << reply->errorString();
connection->respond(HTTPConnection::StatusCode400, data);
return;
}
connection->respond(HTTPConnection::StatusCode200, reply->readAll());
});
return true;
}
DomainServer::DomainServer(int argc, char* argv[]) :
QCoreApplication(argc, argv),
_gatekeeper(this),
@ -614,8 +692,6 @@ void DomainServer::setupNodeListAndAssignments() {
nodeList->setPacketFilterOperator(&DomainServer::isPacketVerified);
}
const QString ACCESS_TOKEN_KEY_PATH = "metaverse.access_token";
bool DomainServer::resetAccountManagerAccessToken() {
if (!_oauthProviderURL.isEmpty()) {
// check for an access-token in our settings, can optionally be overidden by env value
@ -1731,6 +1807,8 @@ QString DomainServer::pathForRedirect(QString path) const {
return "http://" + _hostname + ":" + QString::number(_httpManager.serverPort()) + path;
}
const QString URI_OAUTH = "/oauth";
bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler) {
const QString JSON_MIME_TYPE = "application/json";
@ -1740,15 +1818,23 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
const QString URI_SETTINGS = "/settings";
const QString URI_ENTITY_FILE_UPLOAD = "/content/upload";
const QString URI_RESTART = "/restart";
const QString URI_API_PLACES = "/api/places";
const QString URI_API_DOMAINS = "/api/domains";
const QString URI_API_DOMAINS_ID = "/api/domains/";
const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
auto nodeList = DependencyManager::get<LimitedNodeList>();
// allow sub-handlers to handle requests that do not require authentication
if (_settingsManager.handlePublicHTTPRequest(connection, url)) {
auto getSetting = [this](QString keyPath, QVariant& value) -> bool {
QVariantMap& settingsMap = _settingsManager.getSettingsMap();
QVariant* var = valueForKeyPath(settingsMap, keyPath);
if (var == nullptr) {
return false;
}
value = *var;
return true;
}
};
// check if this is a request for a scripted assignment (with a temp unique UUID)
const QString ASSIGNMENT_REGEX_STRING = QString("\\%1\\/(%2)\\/?$").arg(URI_ASSIGNMENT).arg(UUID_REGEX_STRING);
@ -1810,6 +1896,31 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
return true;
}
// Check if we should redirect/prevent access to the wizard
if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
const QString URI_WIZARD = "/wizard/";
const QString WIZARD_COMPLETED_ONCE_KEY_PATH = "wizard.completed_once";
const QVariant* wizardCompletedOnce = valueForKeyPath(_settingsManager.getSettingsMap(), WIZARD_COMPLETED_ONCE_KEY_PATH);
const bool completedOnce = wizardCompletedOnce && wizardCompletedOnce->toBool();
if (url.path() != URI_WIZARD && url.path().endsWith('/') && !completedOnce) {
// First visit, redirect to the wizard
QUrl redirectedURL = url;
redirectedURL.setPath(URI_WIZARD);
Headers redirectHeaders;
redirectHeaders.insert("Location", redirectedURL.toEncoded());
connection->respond(HTTPConnection::StatusCode302,
QByteArray(), HTTPConnection::DefaultContentType, redirectHeaders);
return true;
} else if (url.path() == URI_WIZARD && completedOnce) {
// Wizard already completed, return 404
connection->respond(HTTPConnection::StatusCode404, "Resource not found.");
return true;
}
}
if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
if (url.path() == "/assignments.json") {
// user is asking for json list of assignments
@ -1899,6 +2010,13 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
connection->respond(HTTPConnection::StatusCode200);
restart();
return true;
} else if (url.path() == URI_API_DOMAINS) {
return forwardMetaverseAPIRequest(connection, "/api/v1/domains", "");
} else if (url.path().startsWith(URI_API_DOMAINS_ID)) {
auto id = url.path().mid(URI_API_DOMAINS_ID.length());
return forwardMetaverseAPIRequest(connection, "/api/v1/domains/" + id, "", {}, {}, false);
} else if (url.path() == URI_API_PLACES) {
return forwardMetaverseAPIRequest(connection, "/api/v1/user/places", "");
} else {
// check if this is for json stats for a node
const QString NODE_JSON_REGEX_STRING = QString("\\%1\\/(%2).json\\/?$").arg(URI_NODES).arg(UUID_REGEX_STRING);
@ -1978,8 +2096,6 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
// this is an entity file upload, ask the HTTPConnection to parse the data
QList<FormData> formData = connection->parseFormData();
Headers redirectHeaders;
if (formData.size() > 0 && formData[0].second.size() > 0) {
// invoke our method to hand the new octree file off to the octree server
QMetaObject::invokeMethod(this, "handleOctreeFileReplacement",
@ -1993,7 +2109,98 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
}
return true;
} else if (url.path() == "/domain_settings") {
auto accessTokenVariant = valueForKeyPath(_settingsManager.getSettingsMap(), ACCESS_TOKEN_KEY_PATH);
if (!accessTokenVariant) {
connection->respond(HTTPConnection::StatusCode400);
return true;
}
} else if (url.path() == URI_API_DOMAINS) {
return forwardMetaverseAPIRequest(connection, "/api/v1/domains", "domain", { "label" });
}
} else if (connection->requestOperation() == QNetworkAccessManager::PutOperation) {
if (url.path() == URI_API_DOMAINS) {
QVariant domainSetting;
if (!getSetting(METAVERSE_DOMAIN_ID_KEY_PATH, domainSetting)) {
connection->respond(HTTPConnection::StatusCode400, "Domain id has not been set");
return true;
}
auto domainID = domainSetting.toString();
return forwardMetaverseAPIRequest(connection, "/api/v1/domains/" + domainID, "domain",
{ }, { "network_address", "network_port", "label" });
} else if (url.path() == URI_API_PLACES) {
auto accessTokenVariant = valueForKeyPath(_settingsManager.getSettingsMap(), ACCESS_TOKEN_KEY_PATH);
if (!accessTokenVariant->isValid()) {
connection->respond(HTTPConnection::StatusCode400, "User access token has not been set");
return true;
}
auto params = connection->parseUrlEncodedForm();
auto it = params.find("place_id");
if (it == params.end()) {
connection->respond(HTTPConnection::StatusCode400);
return true;
}
QString place_id = it.value();
it = params.find("path");
if (it == params.end()) {
connection->respond(HTTPConnection::StatusCode400);
return true;
}
QString path = it.value();
it = params.find("domain_id");
QString domainID;
if (it == params.end()) {
QVariant domainSetting;
if (!getSetting(METAVERSE_DOMAIN_ID_KEY_PATH, domainSetting)) {
connection->respond(HTTPConnection::StatusCode400);
return true;
}
domainID = domainSetting.toString();
} else {
domainID = it.value();
}
QJsonObject root {
{
"place",
QJsonObject({
{ "pointee_query", domainID },
{ "path", path }
})
}
};
QJsonDocument doc(root);
QUrl url { NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/api/v1/places/" + place_id };
url.setQuery("access_token=" + accessTokenVariant->toString());
QNetworkRequest req(url);
req.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply* reply = NetworkAccessManager::getInstance().put(req, doc.toJson());
connect(reply, &QNetworkReply::finished, this, [reply, connection]() {
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Got error response from metaverse server: " << reply->readAll();
connection->respond(HTTPConnection::StatusCode500,
"Error communicating with Metaverse");
return;
}
connection->respond(HTTPConnection::StatusCode200, reply->readAll());
});
return true;
}
} else if (connection->requestOperation() == QNetworkAccessManager::DeleteOperation) {
const QString ALL_NODE_DELETE_REGEX_STRING = QString("\\%1\\/?$").arg(URI_NODES);
const QString NODE_DELETE_REGEX_STRING = QString("\\%1\\/(%2)\\/$").arg(URI_NODES).arg(UUID_REGEX_STRING);
@ -2037,7 +2244,6 @@ static const QString HIFI_SESSION_COOKIE_KEY = "DS_WEB_SESSION_UUID";
static const QString STATE_QUERY_KEY = "state";
bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &url, bool skipSubHandler) {
qDebug() << "HTTPS request received at" << url.toString();
if (url.path() == URI_OAUTH) {
QUrlQuery codeURLQuery(url);
@ -2298,6 +2504,8 @@ QNetworkReply* DomainServer::profileRequestGivenTokenReply(QNetworkReply* tokenR
profileURL.setPath("/api/v1/user/profile");
profileURL.setQuery(QString("%1=%2").arg(OAUTH_JSON_ACCESS_TOKEN_KEY, accessToken));
qDebug() << "Sending profile request to: " << profileURL;
QNetworkRequest profileRequest(profileURL);
profileRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
profileRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);

View file

@ -187,6 +187,13 @@ private:
HTTPSConnection* connectionFromReplyWithState(QNetworkReply* reply);
bool forwardMetaverseAPIRequest(HTTPConnection* connection,
const QString& metaversePath,
const QString& requestSubobject,
std::initializer_list<QString> requiredData = { },
std::initializer_list<QString> optionalData = { },
bool requireAccessToken = true);
SubnetList _acSubnetWhitelist;
std::vector<QString> _replicatedUsernames;

View file

@ -310,6 +310,16 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
_standardAgentPermissions[NodePermissions::standardNameLocalhost]->set(NodePermissions::Permission::canRezTemporaryCertifiedEntities);
packPermissions();
}
if (oldVersion < 2.0) {
const QString WIZARD_COMPLETED_ONCE = "wizard.completed_once";
QVariant* wizardCompletedOnce = _configMap.valueForKeyPath(WIZARD_COMPLETED_ONCE, true);
*wizardCompletedOnce = QVariant(true);
// write the new settings to the json file
persistToFile();
}
}
unpackPermissions();
@ -960,29 +970,6 @@ QVariant DomainServerSettingsManager::valueOrDefaultValueForKeyPath(const QStrin
return QVariant();
}
bool DomainServerSettingsManager::handlePublicHTTPRequest(HTTPConnection* connection, const QUrl &url) {
if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == SETTINGS_PATH_JSON) {
// this is a GET operation for our settings
// check if there is a query parameter for settings affecting a particular type of assignment
const QString SETTINGS_TYPE_QUERY_KEY = "type";
QUrlQuery settingsQuery(url);
QString typeValue = settingsQuery.queryItemValue(SETTINGS_TYPE_QUERY_KEY);
if (!typeValue.isEmpty()) {
QJsonObject responseObject = responseObjectForType(typeValue);
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(responseObject).toJson(), "application/json");
return true;
} else {
return false;
}
}
return false;
}
bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection *connection, const QUrl &url) {
if (connection->requestOperation() == QNetworkAccessManager::PostOperation && url.path() == SETTINGS_PATH_JSON) {
// this is a POST operation to change one or more settings
@ -1214,6 +1201,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
static const QString SECURITY_ROOT_KEY = "security";
static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist";
static const QString BROADCASTING_KEY = "broadcasting";
static const QString WIZARD_KEY = "wizard";
static const QString DESCRIPTION_ROOT_KEY = "descriptors";
auto& settingsVariant = _configMap.getConfig();
@ -1266,7 +1254,8 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
if (!matchingDescriptionObject.isEmpty()) {
updateSetting(rootKey, rootValue, *thisMap, matchingDescriptionObject);
if (rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY && rootKey != SETTINGS_PATHS_KEY ) {
if (rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY &&
rootKey != SETTINGS_PATHS_KEY && rootKey != WIZARD_KEY) {
needRestart = true;
}
} else {
@ -1282,8 +1271,9 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
if (!matchingDescriptionObject.isEmpty()) {
const QJsonValue& settingValue = rootValue.toObject()[settingKey];
updateSetting(settingKey, settingValue, *thisMap, matchingDescriptionObject);
if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY && rootKey != DESCRIPTION_ROOT_KEY)
|| settingKey == AC_SUBNET_WHITELIST_KEY) {
if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY &&
rootKey != DESCRIPTION_ROOT_KEY && rootKey != WIZARD_KEY) ||
settingKey == AC_SUBNET_WHITELIST_KEY) {
needRestart = true;
}
} else {

View file

@ -43,7 +43,6 @@ class DomainServerSettingsManager : public QObject {
Q_OBJECT
public:
DomainServerSettingsManager();
bool handlePublicHTTPRequest(HTTPConnection* connection, const QUrl& url);
bool handleAuthenticatedHTTPRequest(HTTPConnection* connection, const QUrl& url);
void setupConfigMap(const QStringList& argumentList);

View file

@ -219,7 +219,7 @@ Item {
function setShown(value) {
if (value === true) {
HMD.openTablet()
HMD.openTablet(HMD.tabletContextualMode) // pass in current contextual mode flag to maintain flag (otherwise uses default false argument)
} else {
HMD.closeTablet()
}

View file

@ -31,7 +31,7 @@ Item {
BaseWebView {
id: webview
url: (Account.metaverseServerURL + "/marketplace?category=avatars)"
url: (Account.metaverseServerURL + "/marketplace?category=avatars")
focus: true
anchors {

View file

@ -100,10 +100,21 @@ void HMDScriptingInterface::deactivateHMDHandMouse() {
void HMDScriptingInterface::closeTablet() {
_showTablet = false;
_tabletContextualMode = false;
}
void HMDScriptingInterface::openTablet() {
void HMDScriptingInterface::openTablet(bool contextualMode) {
_showTablet = true;
_tabletContextualMode = contextualMode;
}
void HMDScriptingInterface::toggleShouldShowTablet() {
setShouldShowTablet(!getShouldShowTablet());
}
void HMDScriptingInterface::setShouldShowTablet(bool value) {
_showTablet = value;
_tabletContextualMode = false;
}
QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) {

View file

@ -30,6 +30,7 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen
Q_PROPERTY(glm::quat orientation READ getOrientation)
Q_PROPERTY(bool mounted READ isMounted NOTIFY mountedChanged)
Q_PROPERTY(bool showTablet READ getShouldShowTablet)
Q_PROPERTY(bool tabletContextualMode READ getTabletContextualMode)
Q_PROPERTY(QUuid tabletID READ getCurrentTabletFrameID WRITE setCurrentTabletFrameID)
Q_PROPERTY(QUuid homeButtonID READ getCurrentHomeButtonID WRITE setCurrentHomeButtonID)
Q_PROPERTY(QUuid homeButtonHighlightID READ getCurrentHomeButtonHightlightID WRITE setCurrentHomeButtonHightlightID)
@ -75,7 +76,7 @@ public:
Q_INVOKABLE void closeTablet();
Q_INVOKABLE void openTablet();
Q_INVOKABLE void openTablet(bool contextualMode = false);
signals:
bool shouldShowHandControllersChanged();
@ -88,9 +89,10 @@ public:
bool isMounted() const;
void toggleShouldShowTablet() { _showTablet = !_showTablet; }
void setShouldShowTablet(bool value) { _showTablet = value; }
void toggleShouldShowTablet();
void setShouldShowTablet(bool value);
bool getShouldShowTablet() const { return _showTablet; }
bool getTabletContextualMode() const { return _tabletContextualMode; }
void setCurrentTabletFrameID(QUuid tabletID) { _tabletUIID = tabletID; }
QUuid getCurrentTabletFrameID() const { return _tabletUIID; }
@ -106,6 +108,7 @@ public:
private:
bool _showTablet { false };
bool _tabletContextualMode { false };
QUuid _tabletUIID; // this is the entityID of the tablet frame
QUuid _tabletScreenID; // this is the overlayID which is part of (a child of) the tablet-ui.
QUuid _homeButtonID;

View file

@ -17,6 +17,7 @@
#include "HTTPConnection.h"
#include "EmbeddedWebserverLogging.h"
#include "HTTPManager.h"
#include <QUrlQuery>
const char* HTTPConnection::StatusCode200 = "200 OK";
const char* HTTPConnection::StatusCode301 = "301 Moved Permanently";
@ -52,10 +53,31 @@ HTTPConnection::~HTTPConnection() {
}
}
QHash<QString, QString> HTTPConnection::parseUrlEncodedForm() {
// make sure we have the correct MIME type
QList<QByteArray> elements = _requestHeaders.value("Content-Type").split(';');
QString contentType = elements.at(0).trimmed();
if (contentType != "application/x-www-form-urlencoded") {
return QHash<QString, QString>();
}
QUrlQuery form { _requestContent };
QHash<QString, QString> pairs;
for (auto pair : form.queryItems()) {
pairs[QUrl::fromPercentEncoding(pair.first.toLatin1())] = QUrl::fromPercentEncoding(pair.second.toLatin1());
}
return pairs;
}
QList<FormData> HTTPConnection::parseFormData() const {
// make sure we have the correct MIME type
QList<QByteArray> elements = _requestHeaders.value("Content-Type").split(';');
if (elements.at(0).trimmed() != "multipart/form-data") {
QString contentType = elements.at(0).trimmed();
if (contentType != "multipart/form-data") {
return QList<FormData>();
}

View file

@ -79,6 +79,10 @@ public:
/// Parses the request content as form data, returning a list of header/content pairs.
QList<FormData> parseFormData () const;
/// Parses the request content as a url encoded form, returning a hash of key/value pairs.
/// Duplicate keys are not supported.
QHash<QString, QString> parseUrlEncodedForm();
/// Sends a response and closes the connection.
void respond (const char* code, const QByteArray& content = QByteArray(),
const char* contentType = DefaultContentType,

View file

@ -342,23 +342,23 @@ void ZoneEntityRenderer::updateHazeFromEntity(const TypedEntityPointer& entity)
haze->setHazeActive(hazeMode == COMPONENT_MODE_ENABLED);
haze->setAltitudeBased(_hazeProperties.getHazeAltitudeEffect());
haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeRange()));
haze->setHazeRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeRange()));
xColor hazeColor = _hazeProperties.getHazeColor();
haze->setHazeColor(glm::vec3(hazeColor.red / 255.0, hazeColor.green / 255.0, hazeColor.blue / 255.0));
xColor hazeGlareColor = _hazeProperties.getHazeGlareColor();
haze->setDirectionalLightColor(glm::vec3(hazeGlareColor.red / 255.0, hazeGlareColor.green / 255.0, hazeGlareColor.blue / 255.0));
haze->setHazeGlareColor(glm::vec3(hazeGlareColor.red / 255.0, hazeGlareColor.green / 255.0, hazeGlareColor.blue / 255.0));
haze->setHazeEnableGlare(_hazeProperties.getHazeEnableGlare());
haze->setDirectionalLightBlend(model::convertDirectionalLightAngleToPower(_hazeProperties.getHazeGlareAngle()));
haze->setHazeGlareBlend(model::Haze::convertGlareAngleToPower(_hazeProperties.getHazeGlareAngle()));
float hazeAltitude = _hazeProperties.getHazeCeiling() - _hazeProperties.getHazeBaseRef();
haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(hazeAltitude));
haze->setHazeAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(hazeAltitude));
haze->setHazeBaseReference(_hazeProperties.getHazeBaseRef());
haze->setHazeBackgroundBlendValue(_hazeProperties.getHazeBackgroundBlend());
haze->setHazeBackgroundBlend(_hazeProperties.getHazeBackgroundBlend());
haze->setHazeAttenuateKeyLight(_hazeProperties.getHazeAttenuateKeyLight());
haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeKeyLightRange()));
haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(_hazeProperties.getHazeKeyLightAltitude()));
haze->setHazeKeyLightRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(_hazeProperties.getHazeKeyLightRange()));
haze->setHazeKeyLightAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(_hazeProperties.getHazeKeyLightAltitude()));
haze->setZoneTransform(entity->getTransform().getMatrix());
}

View file

@ -1,4 +1,4 @@
set(TARGET_NAME entities)
setup_hifi_library(Network Script)
include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")
link_hifi_libraries(shared networking octree avatars)
link_hifi_libraries(shared networking octree avatars model)

View file

@ -1769,7 +1769,6 @@ void EntityItem::updateDimensions(const glm::vec3& value) {
setDimensions(value);
markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS);
_queryAACubeSet = false;
dimensionsChanged();
}
}

View file

@ -202,6 +202,24 @@ enum EntityPropertyList {
PROP_ENTITY_INSTANCE_NUMBER,
PROP_CERTIFICATE_ID,
PROP_HAZE_MODE,
PROP_HAZE_RANGE,
PROP_HAZE_COLOR,
PROP_HAZE_GLARE_COLOR,
PROP_HAZE_ENABLE_GLARE,
PROP_HAZE_GLARE_ANGLE,
PROP_HAZE_ALTITUDE_EFFECT,
PROP_HAZE_CEILING,
PROP_HAZE_BASE_REF,
PROP_HAZE_BACKGROUND_BLEND,
PROP_HAZE_ATTENUATE_KEYLIGHT,
PROP_HAZE_KEYLIGHT_RANGE,
PROP_HAZE_KEYLIGHT_ALTITUDE,
////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties to end of list just ABOVE this line
PROP_AFTER_LAST_ITEM,
@ -234,24 +252,6 @@ enum EntityPropertyList {
PROP_STAGE_AUTOMATIC_HOURDAY = PROP_ANIMATION_FRAME_INDEX,
PROP_BACKGROUND_MODE = PROP_MODEL_URL,
PROP_HAZE_MODE = PROP_COLOR,
PROP_HAZE_RANGE = PROP_INTENSITY,
PROP_HAZE_COLOR = PROP_CUTOFF,
PROP_HAZE_GLARE_COLOR = PROP_EXPONENT,
PROP_HAZE_ENABLE_GLARE = PROP_IS_SPOTLIGHT,
PROP_HAZE_GLARE_ANGLE = PROP_DIFFUSE_COLOR,
PROP_HAZE_ALTITUDE_EFFECT = PROP_AMBIENT_COLOR_UNUSED,
PROP_HAZE_CEILING = PROP_SPECULAR_COLOR_UNUSED,
PROP_HAZE_BASE_REF = PROP_LINEAR_ATTENUATION_UNUSED,
PROP_HAZE_BACKGROUND_BLEND = PROP_QUADRATIC_ATTENUATION_UNUSED,
PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_ANIMATION_FRAME_INDEX,
PROP_HAZE_KEYLIGHT_RANGE = PROP_MODEL_URL,
PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_ANIMATION_URL,
PROP_SKYBOX_COLOR = PROP_ANIMATION_URL,
PROP_SKYBOX_URL = PROP_ANIMATION_FPS,
PROP_KEYLIGHT_AMBIENT_URL = PROP_ANIMATION_PLAYING,

View file

@ -15,19 +15,6 @@
#include "EntityItemProperties.h"
#include "EntityItemPropertiesMacros.h"
const float HazePropertyGroup::DEFAULT_HAZE_RANGE{ 1000.0f };
const xColor HazePropertyGroup::DEFAULT_HAZE_COLOR{ 128, 154, 179 }; // Bluish
const xColor HazePropertyGroup::DEFAULT_HAZE_GLARE_COLOR{ 255, 229, 179 }; // Yellowish
const float HazePropertyGroup::DEFAULT_HAZE_GLARE_ANGLE{ 20.0 };
const float HazePropertyGroup::DEFAULT_HAZE_CEILING{ 200.0f };
const float HazePropertyGroup::DEFAULT_HAZE_BASE_REF{ 0.0f };
const float HazePropertyGroup::DEFAULT_HAZE_BACKGROUND_BLEND{ 0.0f };
const float HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_RANGE{ 1000.0 };
const float HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_ALTITUDE{ 200.0f };
void HazePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const {
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_RANGE, Haze, haze, HazeRange, hazeRange);
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_HAZE_COLOR, Haze, haze, HazeColor, hazeColor);
@ -306,6 +293,7 @@ EntityPropertyFlags HazePropertyGroup::getEntityProperties(EncodeBitstreamParams
requestedProperties += PROP_HAZE_ENABLE_GLARE;
requestedProperties += PROP_HAZE_GLARE_ANGLE;
requestedProperties += PROP_HAZE_ALTITUDE_EFFECT;
requestedProperties += PROP_HAZE_CEILING;
requestedProperties += PROP_HAZE_BASE_REF;

View file

@ -27,6 +27,19 @@ class OctreePacketData;
class EntityTreeElementExtraEncodeData;
class ReadBitstreamToTreeParams;
static const float INITIAL_HAZE_RANGE{ 1000.0f };
static const xColor initialHazeGlareColorXcolor{ 255, 229, 179 };
static const xColor initialHazeColorXcolor{ 128, 154, 179 };
static const float INITIAL_HAZE_GLARE_ANGLE{ 20.0f };
static const float INITIAL_HAZE_BASE_REFERENCE{ 0.0f };
static const float INITIAL_HAZE_HEIGHT{ 200.0f };
static const float INITIAL_HAZE_BACKGROUND_BLEND{ 0.0f };
static const float INITIAL_KEY_LIGHT_RANGE{ 1000.0f };
static const float INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f };
class HazePropertyGroup : public PropertyGroup {
public:
// EntityItemProperty related helpers
@ -74,38 +87,25 @@ public:
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
bool& somethingChanged) override;
static const float DEFAULT_HAZE_RANGE;
static const xColor DEFAULT_HAZE_COLOR;
static const xColor DEFAULT_HAZE_GLARE_COLOR;
static const float DEFAULT_HAZE_GLARE_ANGLE;
static const float DEFAULT_HAZE_CEILING;
static const float DEFAULT_HAZE_BASE_REF;
static const float DEFAULT_HAZE_BACKGROUND_BLEND;
static const float DEFAULT_HAZE_KEYLIGHT_RANGE;
static const float DEFAULT_HAZE_KEYLIGHT_ALTITUDE;
// Range only parameters
DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, DEFAULT_HAZE_RANGE);
DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, DEFAULT_HAZE_COLOR);
DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, DEFAULT_HAZE_GLARE_COLOR);
DEFINE_PROPERTY(PROP_HAZE_RANGE, HazeRange, hazeRange, float, INITIAL_HAZE_RANGE);
DEFINE_PROPERTY_REF(PROP_HAZE_COLOR, HazeColor, hazeColor, xColor, initialHazeColorXcolor);
DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_COLOR, HazeGlareColor, hazeGlareColor, xColor, initialHazeGlareColorXcolor);
DEFINE_PROPERTY(PROP_HAZE_ENABLE_GLARE, HazeEnableGlare, hazeEnableGlare, bool, false);
DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, DEFAULT_HAZE_GLARE_ANGLE);
DEFINE_PROPERTY_REF(PROP_HAZE_GLARE_ANGLE, HazeGlareAngle, hazeGlareAngle, float, INITIAL_HAZE_GLARE_ANGLE);
// Altitude parameters
DEFINE_PROPERTY(PROP_HAZE_ALTITUDE_EFFECT, HazeAltitudeEffect, hazeAltitudeEffect, bool, false);
DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, DEFAULT_HAZE_CEILING);
DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, DEFAULT_HAZE_BASE_REF);
DEFINE_PROPERTY_REF(PROP_HAZE_CEILING, HazeCeiling, hazeCeiling, float, INITIAL_HAZE_BASE_REFERENCE + INITIAL_HAZE_HEIGHT);
DEFINE_PROPERTY_REF(PROP_HAZE_BASE_REF, HazeBaseRef, hazeBaseRef, float, INITIAL_HAZE_BASE_REFERENCE);
// Background (skybox) blend value
DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, DEFAULT_HAZE_BACKGROUND_BLEND);
DEFINE_PROPERTY_REF(PROP_HAZE_BACKGROUND_BLEND, HazeBackgroundBlend, hazeBackgroundBlend, float, INITIAL_HAZE_BACKGROUND_BLEND);
// hazeDirectional light attenuation
DEFINE_PROPERTY(PROP_HAZE_ATTENUATE_KEYLIGHT, HazeAttenuateKeyLight, hazeAttenuateKeyLight, bool, false);
DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, DEFAULT_HAZE_KEYLIGHT_RANGE);
DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, DEFAULT_HAZE_KEYLIGHT_ALTITUDE);
DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_RANGE, HazeKeyLightRange, hazeKeyLightRange, float, INITIAL_KEY_LIGHT_RANGE);
DEFINE_PROPERTY_REF(PROP_HAZE_KEYLIGHT_ALTITUDE, HazeKeyLightAltitude, hazeKeyLightAltitude, float, INITIAL_KEY_LIGHT_ALTITUDE);
};
#endif // hifi_HazePropertyGroup_h

View file

@ -51,12 +51,12 @@ namespace entity {
}
}
// shapeCalculator is a hook for external code that knows how to configure a ShapeInfo
// hullShapeCalculator is a hook for external code that knows how to configure a ShapeInfo
// for given entity::Shape and dimensions
ShapeEntityItem::ShapeInfoCalculator shapeCalculator = nullptr;
ShapeEntityItem::ShapeInfoCalculator hullShapeCalculator = nullptr;
void ShapeEntityItem::setShapeInfoCalulator(ShapeEntityItem::ShapeInfoCalculator callback) {
shapeCalculator = callback;
hullShapeCalculator = callback;
}
ShapeEntityItem::Pointer ShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
@ -104,6 +104,14 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) {
case entity::Shape::Sphere:
_type = EntityTypes::Sphere;
break;
case entity::Shape::Circle:
// Circle is implicitly flat so we enforce flat dimensions
setDimensions(getDimensions());
break;
case entity::Shape::Quad:
// Quad is implicitly flat so we enforce flat dimensions
setDimensions(getDimensions());
break;
default:
_type = EntityTypes::Shape;
break;
@ -196,6 +204,18 @@ void ShapeEntityItem::setColor(const QColor& value) {
setAlpha(value.alpha());
}
void ShapeEntityItem::setDimensions(const glm::vec3& value) {
const float MAX_FLAT_DIMENSION = 0.0001f;
if ((_shape == entity::Shape::Circle || _shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) {
// enforce flatness in Y
glm::vec3 newDimensions = value;
newDimensions.y = MAX_FLAT_DIMENSION;
EntityItem::setDimensions(newDimensions);
} else {
EntityItem::setDimensions(value);
}
}
bool ShapeEntityItem::supportsDetailedRayIntersection() const {
return _shape == entity::Sphere;
}
@ -249,19 +269,13 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) {
const glm::vec3 entityDimensions = getDimensions();
switch (_shape){
case entity::Shape::Quad: {
// Not in GeometryCache::buildShapes, unsupported.
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
//TODO WL21389: Add a SHAPE_TYPE_QUAD ShapeType and treat
// as a special box (later if desired support)
}
break;
case entity::Shape::Quad:
// Quads collide like flat Cubes
case entity::Shape::Cube: {
_collisionShapeType = SHAPE_TYPE_BOX;
}
break;
case entity::Shape::Sphere: {
float diameter = entityDimensions.x;
const float MIN_DIAMETER = 0.001f;
const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f;
@ -275,25 +289,28 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) {
}
}
break;
case entity::Shape::Circle: {
_collisionShapeType = SHAPE_TYPE_CIRCLE;
}
break;
case entity::Shape::Circle:
// Circles collide like flat Cylinders
case entity::Shape::Cylinder: {
_collisionShapeType = SHAPE_TYPE_CYLINDER_Y;
// TODO WL21389: determine if rotation is axis-aligned
//const Transform::Quat & rot = _transform.getRotation();
// TODO WL21389: some way to tell apart SHAPE_TYPE_CYLINDER_Y, _X, _Z based on rotation and
// hull ( or dimensions, need circular cross section)
// Should allow for minor variance along axes?
float diameter = entityDimensions.x;
const float MIN_DIAMETER = 0.001f;
const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f;
if (diameter > MIN_DIAMETER
&& fabsf(diameter - entityDimensions.z) / diameter < MIN_RELATIVE_SPHERICAL_ERROR) {
_collisionShapeType = SHAPE_TYPE_SPHERE;
} else if (hullShapeCalculator) {
hullShapeCalculator(this, info);
_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL;
} else {
// woops, someone forgot to hook up the hullShapeCalculator()!
// final fallback is ellipsoid
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
}
}
break;
case entity::Shape::Cone: {
if (shapeCalculator) {
shapeCalculator(this, info);
// shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL)
if (hullShapeCalculator) {
hullShapeCalculator(this, info);
_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL;
} else {
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
@ -304,9 +321,8 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) {
case entity::Shape::Triangle:
case entity::Shape::Hexagon:
case entity::Shape::Octagon: {
if (shapeCalculator) {
shapeCalculator(this, info);
// shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL)
if (hullShapeCalculator) {
hullShapeCalculator(this, info);
_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL;
} else {
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
@ -318,9 +334,8 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) {
case entity::Shape::Octahedron:
case entity::Shape::Dodecahedron:
case entity::Shape::Icosahedron: {
if ( shapeCalculator ) {
shapeCalculator(this, info);
// shapeCalculator only supports convex shapes (e.g. SHAPE_TYPE_HULL)
if ( hullShapeCalculator ) {
hullShapeCalculator(this, info);
_collisionShapeType = SHAPE_TYPE_SIMPLE_HULL;
} else {
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
@ -330,7 +345,7 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) {
case entity::Shape::Torus: {
// Not in GeometryCache::buildShapes, unsupported.
_collisionShapeType = SHAPE_TYPE_ELLIPSOID;
//TODO WL21389: SHAPE_TYPE_SIMPLE_HULL and pointCollection (later if desired support)
//TODO handle this shape more correctly
}
break;
default: {

View file

@ -80,6 +80,8 @@ public:
const rgbColor& getColor() const { return _color; }
void setColor(const rgbColor& value);
void setDimensions(const glm::vec3& value) override;
xColor getXColor() const;
void setColor(const xColor& value);

View file

@ -330,103 +330,3 @@ void ZoneEntityItem::setHazeMode(const uint32_t value) {
uint32_t ZoneEntityItem::getHazeMode() const {
return _hazeMode;
}
void ZoneEntityItem::setHazeRange(const float hazeRange) {
_hazeRange = hazeRange;
_hazePropertiesChanged = true;
}
float ZoneEntityItem::getHazeRange() const {
return _hazeRange;
}
void ZoneEntityItem::setHazeColor(const xColor hazeColor) {
_hazeColor = hazeColor;
_hazePropertiesChanged = true;
}
xColor ZoneEntityItem::getHazeColor() const {
return _hazeColor;
}
void ZoneEntityItem::setHazeGlareColor(const xColor hazeGlareColor) {
_hazeGlareColor = hazeGlareColor;
_hazePropertiesChanged = true;
}
xColor ZoneEntityItem::getHazeGlareColor()const {
return _hazeGlareColor;
}
void ZoneEntityItem::setHazeEnableGlare(const bool hazeEnableGlare) {
_hazeEnableGlare = hazeEnableGlare;
_hazePropertiesChanged = true;
}
bool ZoneEntityItem::getHazeEnableGlare()const {
return _hazeEnableGlare;
}
void ZoneEntityItem::setHazeGlareAngle(const float hazeGlareAngle) {
_hazeGlareAngle = hazeGlareAngle;
_hazePropertiesChanged = true;
}
float ZoneEntityItem::getHazeGlareAngle() const {
return _hazeGlareAngle;
}
void ZoneEntityItem::setHazeCeiling(const float hazeCeiling) {
_hazeCeiling = hazeCeiling;
_hazePropertiesChanged = true;
}
float ZoneEntityItem::getHazeCeiling() const {
return _hazeCeiling;
}
void ZoneEntityItem::setHazeBaseRef(const float hazeBaseRef) {
_hazeBaseRef = hazeBaseRef;
_hazePropertiesChanged = true;
}
float ZoneEntityItem::getHazeBaseRef() const {
return _hazeBaseRef;
}
void ZoneEntityItem::setHazeBackgroundBlend(const float hazeBackgroundBlend) {
_hazeBackgroundBlend = hazeBackgroundBlend;
_hazePropertiesChanged = true;
}
float ZoneEntityItem::getHazeBackgroundBlend() const {
return _hazeBackgroundBlend;
}
void ZoneEntityItem::setHazeAttenuateKeyLight(const bool hazeAttenuateKeyLight) {
_hazeAttenuateKeyLight = hazeAttenuateKeyLight;
_hazePropertiesChanged = true;
}
bool ZoneEntityItem::getHazeAttenuateKeyLight() const {
return _hazeAttenuateKeyLight;
}
void ZoneEntityItem::setHazeKeyLightRange(const float hazeKeyLightRange) {
_hazeKeyLightRange = hazeKeyLightRange;
_hazePropertiesChanged = true;
}
float ZoneEntityItem::getHazeKeyLightRange() const {
return _hazeKeyLightRange;
}
void ZoneEntityItem::setHazeKeyLightAltitude(const float hazeKeyLightAltitude) {
_hazeKeyLightAltitude = hazeKeyLightAltitude;
_hazePropertiesChanged = true;
}
float ZoneEntityItem::getHazeKeyLightAltitude() const {
return _hazeKeyLightAltitude;
}

View file

@ -73,32 +73,6 @@ public:
void setHazeMode(const uint32_t value);
uint32_t getHazeMode() const;
void setHazeRange(const float hazeRange);
float getHazeRange() const;
void setHazeColor(const xColor hazeColor);
xColor getHazeColor() const;
void setHazeGlareColor(const xColor hazeGlareColor);
xColor getHazeGlareColor() const;
void setHazeEnableGlare(const bool hazeEnableGlare);
bool getHazeEnableGlare() const;
void setHazeGlareAngle(const float hazeGlareAngle);
float getHazeGlareAngle() const;
void setHazeCeiling(const float hazeCeiling);
float getHazeCeiling() const;
void setHazeBaseRef(const float hazeBaseRef);
float getHazeBaseRef() const;
void setHazeBackgroundBlend(const float hazeBackgroundBlend);
float getHazeBackgroundBlend() const;
void setHazeAttenuateKeyLight(const bool hazeAttenuateKeyLight);
bool getHazeAttenuateKeyLight() const;
void setHazeKeyLightRange(const float hazeKeyLightRange);
float getHazeKeyLightRange() const;
void setHazeKeyLightAltitude(const float hazeKeyLightAltitude);
float getHazeKeyLightAltitude() const;
SkyboxPropertyGroup getSkyboxProperties() const { return resultWithReadLock<SkyboxPropertyGroup>([&] { return _skyboxProperties; }); }
const HazePropertyGroup& getHazeProperties() const { return _hazeProperties; }
@ -150,21 +124,6 @@ protected:
uint32_t _hazeMode{ DEFAULT_HAZE_MODE };
float _hazeRange{ HazePropertyGroup::DEFAULT_HAZE_RANGE };
xColor _hazeColor{ HazePropertyGroup::DEFAULT_HAZE_COLOR };
xColor _hazeGlareColor{ HazePropertyGroup::DEFAULT_HAZE_GLARE_COLOR };
bool _hazeEnableGlare{ false };
float _hazeGlareAngle{ HazePropertyGroup::DEFAULT_HAZE_GLARE_ANGLE };
float _hazeCeiling{ HazePropertyGroup::DEFAULT_HAZE_CEILING };
float _hazeBaseRef{ HazePropertyGroup::DEFAULT_HAZE_BASE_REF };
float _hazeBackgroundBlend{ HazePropertyGroup::DEFAULT_HAZE_BACKGROUND_BLEND };
bool _hazeAttenuateKeyLight{ false };
float _hazeKeyLightRange{ HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_RANGE };
float _hazeKeyLightAltitude{ HazePropertyGroup::DEFAULT_HAZE_KEYLIGHT_ALTITUDE };
SkyboxPropertyGroup _skyboxProperties;
HazePropertyGroup _hazeProperties;
StagePropertyGroup _stageProperties;

View file

@ -9,12 +9,30 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <memory>
#include <gpu/Resource.h>
#include "Haze.h"
using namespace model;
const float Haze::INITIAL_HAZE_RANGE{ 1000.0f };
const float Haze::INITIAL_HAZE_HEIGHT{ 200.0f };
const float Haze::INITIAL_KEY_LIGHT_RANGE{ 1000.0f };
const float Haze::INITIAL_KEY_LIGHT_ALTITUDE{ 200.0f };
const float Haze::INITIAL_HAZE_BACKGROUND_BLEND{ 0.0f };
const glm::vec3 Haze::INITIAL_HAZE_COLOR{ 0.5f, 0.6f, 0.7f }; // Bluish
const float Haze::INITIAL_HAZE_GLARE_ANGLE{ 20.0f };
const glm::vec3 Haze::INITIAL_HAZE_GLARE_COLOR{ 1.0f, 0.9f, 0.7f };
const float Haze::INITIAL_HAZE_BASE_REFERENCE{ 0.0f };
const float Haze::LOG_P_005{ logf(0.05f)};
const float Haze::LOG_P_05{ logf(0.5f) };
Haze::Haze() {
Parameters parameters;
_hazeParametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) &parameters));
@ -23,7 +41,7 @@ Haze::Haze() {
enum HazeModes {
HAZE_MODE_IS_ACTIVE = 1 << 0,
HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1,
HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED = 1 << 2,
HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2,
HAZE_MODE_IS_MODULATE_COLOR = 1 << 3,
HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4
};
@ -55,25 +73,25 @@ void Haze::setHazeEnableGlare(const bool isHazeEnableGlare) {
}
}
void Haze::setDirectionalLightBlend(const float hazeDirectionalLightBlend) {
void Haze::setHazeGlareBlend(const float hazeGlareBlend) {
auto& params = _hazeParametersBuffer.get<Parameters>();
if (params.directionalLightBlend != hazeDirectionalLightBlend) {
_hazeParametersBuffer.edit<Parameters>().directionalLightBlend = hazeDirectionalLightBlend;
if (params.hazeGlareBlend != hazeGlareBlend) {
_hazeParametersBuffer.edit<Parameters>().hazeGlareBlend = hazeGlareBlend;
}
}
void Haze::setDirectionalLightColor(const glm::vec3 hazeDirectionalLightColor) {
void Haze::setHazeGlareColor(const glm::vec3 hazeGlareColor) {
auto& params = _hazeParametersBuffer.get<Parameters>();
if (params.directionalLightColor.r != hazeDirectionalLightColor.r) {
_hazeParametersBuffer.edit<Parameters>().directionalLightColor.r = hazeDirectionalLightColor.r;
if (params.hazeGlareColor.r != hazeGlareColor.r) {
_hazeParametersBuffer.edit<Parameters>().hazeGlareColor.r = hazeGlareColor.r;
}
if (params.directionalLightColor.g != hazeDirectionalLightColor.g) {
_hazeParametersBuffer.edit<Parameters>().directionalLightColor.g = hazeDirectionalLightColor.g;
if (params.hazeGlareColor.g != hazeGlareColor.g) {
_hazeParametersBuffer.edit<Parameters>().hazeGlareColor.g = hazeGlareColor.g;
}
if (params.directionalLightColor.b != hazeDirectionalLightColor.b) {
_hazeParametersBuffer.edit<Parameters>().directionalLightColor.b = hazeDirectionalLightColor.b;
if (params.hazeGlareColor.b != hazeGlareColor.b) {
_hazeParametersBuffer.edit<Parameters>().hazeGlareColor.b = hazeGlareColor.b;
}
}
void Haze::setHazeActive(const bool isHazeActive) {
@ -99,10 +117,10 @@ void Haze::setAltitudeBased(const bool isAltitudeBased) {
void Haze::setHazeAttenuateKeyLight(const bool isHazeAttenuateKeyLight) {
auto& params = _hazeParametersBuffer.get<Parameters>();
if (((params.hazeMode & HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) == HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED ) && !isHazeAttenuateKeyLight) {
_hazeParametersBuffer.edit<Parameters>().hazeMode &= ~HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED;
} else if (((params.hazeMode & HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) != HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) && isHazeAttenuateKeyLight) {
_hazeParametersBuffer.edit<Parameters>().hazeMode |= HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED;
if (((params.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) && !isHazeAttenuateKeyLight) {
_hazeParametersBuffer.edit<Parameters>().hazeMode &= ~HAZE_MODE_IS_KEYLIGHT_ATTENUATED;
} else if (((params.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) != HAZE_MODE_IS_KEYLIGHT_ATTENUATED) && isHazeAttenuateKeyLight) {
_hazeParametersBuffer.edit<Parameters>().hazeMode |= HAZE_MODE_IS_KEYLIGHT_ATTENUATED;
}
}
@ -124,11 +142,11 @@ void Haze::setHazeRangeFactor(const float hazeRangeFactor) {
}
}
void Haze::setHazeAltitudeFactor(const float hazeAltitudeFactor) {
void Haze::setHazeAltitudeFactor(const float hazeHeightFactor) {
auto& params = _hazeParametersBuffer.get<Parameters>();
if (params.hazeAltitudeFactor != hazeAltitudeFactor) {
_hazeParametersBuffer.edit<Parameters>().hazeAltitudeFactor = hazeAltitudeFactor;
if (params.hazeHeightFactor != hazeHeightFactor) {
_hazeParametersBuffer.edit<Parameters>().hazeHeightFactor = hazeHeightFactor;
}
}
@ -156,11 +174,11 @@ void Haze::setHazeBaseReference(const float hazeBaseReference) {
}
}
void Haze::setHazeBackgroundBlendValue(const float hazeBackgroundBlendValue) {
void Haze::setHazeBackgroundBlend(const float hazeBackgroundBlend) {
auto& params = _hazeParametersBuffer.get<Parameters>();
if (params.hazeBackgroundBlendValue != hazeBackgroundBlendValue) {
_hazeParametersBuffer.edit<Parameters>().hazeBackgroundBlendValue = hazeBackgroundBlendValue;
if (params.hazeBackgroundBlend != hazeBackgroundBlend) {
_hazeParametersBuffer.edit<Parameters>().hazeBackgroundBlend = hazeBackgroundBlend;
}
}

View file

@ -12,71 +12,70 @@
#define hifi_model_Haze_h
#include <glm/glm.hpp>
#include <gpu/Resource.h>
#include "Transform.h"
#include "NumericalConstants.h"
namespace model {
const float LOG_P_005 = (float)log(0.05);
const float LOG_P_05 = (float)log(0.5);
// Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05
// f = exp(-d * b)
// ln(f) = -d * b
// b = -ln(f)/d
inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange_m) {
return glm::vec3(
-LOG_P_005 / hazeRange_m.x,
-LOG_P_005 / hazeRange_m.y,
-LOG_P_005 / hazeRange_m.z);
}
inline float convertHazeRangeToHazeRangeFactor(const float hazeRange_m) { return (-LOG_P_005 / hazeRange_m); }
inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeAltitude_m) {
return -LOG_P_005 / hazeAltitude_m;
}
// Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5
// s = dot(lookAngle, sunAngle) = cos(a)
// m = pow(s, p)
// log(m) = p * log(s)
// p = log(m) / log(s)
inline float convertDirectionalLightAngleToPower(const float directionalLightAngle) {
return LOG_P_05 / (float)log(cos(RADIANS_PER_DEGREE * directionalLightAngle));
}
const glm::vec3 initialHazeColor{ 0.5f, 0.6f, 0.7f };
const float initialDirectionalLightAngle_degs{ 30.0f };
const glm::vec3 initialDirectionalLightColor{ 1.0f, 0.9f, 0.7f };
const float initialHazeBaseReference{ 0.0f };
// Haze range is defined here as the range the visibility is reduced by 95%
// Haze altitude is defined here as the altitude (above 0) that the haze is reduced by 95%
const float initialHazeRange_m{ 150.0f };
const float initialHazeAltitude_m{ 150.0f };
const float initialHazeKeyLightRange_m{ 150.0f };
const float initialHazeKeyLightAltitude_m{ 150.0f };
const float initialHazeBackgroundBlendValue{ 0.0f };
const glm::vec3 initialColorModulationFactor{
convertHazeRangeToHazeRangeFactor(initialHazeRange_m),
convertHazeRangeToHazeRangeFactor(initialHazeRange_m),
convertHazeRangeToHazeRangeFactor(initialHazeRange_m)
};
class Haze {
public:
using UniformBufferView = gpu::BufferView;
// Initial values
static const float INITIAL_HAZE_RANGE;
static const float INITIAL_HAZE_HEIGHT;
static const float INITIAL_KEY_LIGHT_RANGE;
static const float INITIAL_KEY_LIGHT_ALTITUDE;
static const float INITIAL_HAZE_BACKGROUND_BLEND;
static const glm::vec3 INITIAL_HAZE_COLOR;
static const float INITIAL_HAZE_GLARE_ANGLE;
static const glm::vec3 INITIAL_HAZE_GLARE_COLOR;
static const float INITIAL_HAZE_BASE_REFERENCE;
static const float LOG_P_005;
static const float LOG_P_05;
// Derivation (d is distance, b is haze coefficient, f is attenuation, solve for f = 0.05
// f = exp(-d * b)
// ln(f) = -d * b
// b = -ln(f)/d
static inline glm::vec3 convertHazeRangeToHazeRangeFactor(const glm::vec3 hazeRange) {
return glm::vec3(
-LOG_P_005 / hazeRange.x,
-LOG_P_005 / hazeRange.y,
-LOG_P_005 / hazeRange.z);
}
// limit range and altitude to no less than 1.0 metres
static inline float convertHazeRangeToHazeRangeFactor(const float hazeRange) { return -LOG_P_005 / glm::max(hazeRange, 1.0f); }
static inline float convertHazeAltitudeToHazeAltitudeFactor(const float hazeHeight) { return -LOG_P_005 / glm::max(hazeHeight, 1.0f); }
// Derivation (s is the proportion of sun blend, a is the angle at which the blend is 50%, solve for m = 0.5
// s = dot(lookAngle, sunAngle) = cos(a)
// m = pow(s, p)
// log(m) = p * log(s)
// p = log(m) / log(s)
// limit to 0.1 degrees
static inline float convertGlareAngleToPower(const float hazeGlareAngle) {
const float GLARE_ANGLE_LIMIT = 0.1f;
return LOG_P_05 / logf(cosf(RADIANS_PER_DEGREE * glm::max(GLARE_ANGLE_LIMIT, hazeGlareAngle)));
}
Haze();
void setHazeColor(const glm::vec3 hazeColor);
void setDirectionalLightBlend(const float directionalLightBlend);
void setHazeGlareBlend(const float hazeGlareBlend);
void setDirectionalLightColor(const glm::vec3 directionalLightColor);
void setHazeGlareColor(const glm::vec3 hazeGlareColor);
void setHazeBaseReference(const float hazeBaseReference);
void setHazeActive(const bool isHazeActive);
@ -91,23 +90,24 @@ namespace model {
void setHazeKeyLightRangeFactor(const float hazeKeyLightRange);
void setHazeKeyLightAltitudeFactor(const float hazeKeyLightAltitude);
void setHazeBackgroundBlendValue(const float hazeBackgroundBlendValue);
void setHazeBackgroundBlend(const float hazeBackgroundBlend);
void setZoneTransform(const glm::mat4& zoneTransform);
using UniformBufferView = gpu::BufferView;
UniformBufferView getHazeParametersBuffer() const { return _hazeParametersBuffer; }
protected:
class Parameters {
public:
// DO NOT CHANGE ORDER HERE WITHOUT UNDERSTANDING THE std140 LAYOUT
glm::vec3 hazeColor{ initialHazeColor };
float directionalLightBlend{ convertDirectionalLightAngleToPower(initialDirectionalLightAngle_degs) };
glm::vec3 hazeColor{ INITIAL_HAZE_COLOR };
float hazeGlareBlend{ convertGlareAngleToPower(INITIAL_HAZE_GLARE_ANGLE) };
glm::vec3 directionalLightColor{ initialDirectionalLightColor };
float hazeBaseReference{ initialHazeBaseReference };
glm::vec3 hazeGlareColor{ INITIAL_HAZE_GLARE_COLOR };
float hazeBaseReference{ INITIAL_HAZE_BASE_REFERENCE };
glm::vec3 colorModulationFactor{ initialColorModulationFactor };
glm::vec3 colorModulationFactor;
int hazeMode{ 0 }; // bit 0 - set to activate haze attenuation of fragment color
// bit 1 - set to add the effect of altitude to the haze attenuation
// bit 2 - set to activate directional light attenuation mode
@ -116,14 +116,14 @@ namespace model {
glm::mat4 zoneTransform;
// Amount of background (skybox) to display, overriding the haze effect for the background
float hazeBackgroundBlendValue{ initialHazeBackgroundBlendValue };
float hazeBackgroundBlend{ INITIAL_HAZE_BACKGROUND_BLEND };
// The haze attenuation exponents used by both fragment and directional light attenuation
float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeRange_m) };
float hazeAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeAltitude_m) };
float hazeRangeFactor{ convertHazeRangeToHazeRangeFactor(INITIAL_HAZE_RANGE) };
float hazeHeightFactor{ convertHazeAltitudeToHazeAltitudeFactor(INITIAL_HAZE_HEIGHT) };
float hazeKeyLightRangeFactor{ convertHazeRangeToHazeRangeFactor(initialHazeKeyLightRange_m) };
float hazeKeyLightAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(initialHazeKeyLightAltitude_m) };
float hazeKeyLightRangeFactor{ convertHazeRangeToHazeRangeFactor(INITIAL_KEY_LIGHT_RANGE) };
float hazeKeyLightAltitudeFactor{ convertHazeAltitudeToHazeAltitudeFactor(INITIAL_KEY_LIGHT_ALTITUDE) };
Parameters() {}
};

View file

@ -256,10 +256,3 @@ void SunSkyStage::setSkybox(const SkyboxPointer& skybox) {
_skybox = skybox;
invalidate();
}
void SunSkyStage::setHazeMode(uint32_t hazeMode) {
if (hazeMode < COMPONENT_MODE_ITEM_COUNT) {
_hazeMode = hazeMode;
invalidate();
}
}

View file

@ -15,7 +15,6 @@
#include "Light.h"
#include "Skybox.h"
#include "Haze.h"
namespace model {
@ -175,65 +174,8 @@ public:
void setSkybox(const SkyboxPointer& skybox);
const SkyboxPointer& getSkybox() const { valid(); return _skybox; }
// Haze
enum HazeMode {
HAZE_OFF,
HAZE_ON,
NUM_HAZE_MODES
};
void setHazeMode(uint32_t mode);
uint32_t getHazeMode() const { return _hazeMode; }
void setHazeRange(float hazeRange) { _hazeRange = hazeRange; }
float getHazeRange() const { return _hazeRange; }
void setHazeColor(const xColor hazeColor) { _hazeColor = hazeColor; }
xColor getHazeColor() { return _hazeColor; }
void setHazeGlareColor(const xColor hazeGlareColor) { _hazeGlareColor = hazeGlareColor; }
xColor getHazeGlareColor() const { return _hazeGlareColor; }
void setHazeEnableGlare(bool hazeEnableGlare) { _hazeEnableGlare = hazeEnableGlare; }
bool getHazeEnableGlare() const { return _hazeEnableGlare; }
void setHazeGlareAngle(float hazeGlareAngle) { _hazeGlareAngle = hazeGlareAngle; }
float getHazeGlareAngle() const { return _hazeGlareAngle; }
void setHazeAltitudeEffect(bool hazeAltitudeEffect) { _hazeAltitudeEffect = hazeAltitudeEffect; }
bool getHazeAltitudeEffect() const { return _hazeAltitudeEffect; }
void setHazeCeiling(float hazeCeiling) { _hazeCeiling = hazeCeiling; }
float getHazeCeiling() const { return _hazeCeiling; }
void setHazeBaseRef(float hazeBaseRef) { _hazeBaseRef = hazeBaseRef; }
float getHazeBaseRef() const { return _hazeBaseRef; }
void setHazeBackgroundBlend(float hazeBackgroundBlend) { _hazeBackgroundBlend = hazeBackgroundBlend; }
float getHazeBackgroundBlend() const { return _hazeBackgroundBlend; }
void setHazeAttenuateKeyLight(bool hazeAttenuateKeyLight) { _hazeAttenuateKeyLight = hazeAttenuateKeyLight; }
bool getHazeAttenuateKeyLight() const { return _hazeAttenuateKeyLight; }
void setHazeKeyLightRange(float hazeKeyLightRange) { _hazeKeyLightRange = hazeKeyLightRange; }
float getHazeKeyLightRange() const { return _hazeKeyLightRange; }
void setHazeKeyLightAltitude(float hazeKeyLightAltitude) { _hazeKeyLightAltitude = hazeKeyLightAltitude; }
float getHazeKeyLightAltitude() const { return _hazeKeyLightAltitude; }
protected:
BackgroundMode _backgroundMode = SKY_DEFAULT;
uint8_t _hazeMode = (uint8_t)HAZE_OFF;
float _hazeRange;
xColor _hazeColor;
xColor _hazeGlareColor;
bool _hazeEnableGlare;
float _hazeGlareAngle;
bool _hazeAltitudeEffect;
float _hazeCeiling;
float _hazeBaseRef;
float _hazeBackgroundBlend;
bool _hazeAttenuateKeyLight;
float _hazeKeyLightRange;
float _hazeKeyLightAltitude;
LightPointer _sunLight;
mutable SkyboxPointer _skybox;

View file

@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::EntityEdit:
case PacketType::EntityData:
case PacketType::EntityPhysics:
return static_cast<PacketVersion>(EntityVersion::HasDynamicOwnershipTests);
return static_cast<PacketVersion>(EntityVersion::HazeEffect);
case PacketType::EntityQuery:
return static_cast<PacketVersion>(EntityQueryPacketVersion::JSONFilterWithFamilyTree);

View file

@ -196,7 +196,8 @@ QDebug operator<<(QDebug debug, const PacketType& type);
enum class EntityVersion : PacketVersion {
StrokeColorProperty = 77,
HasDynamicOwnershipTests
HasDynamicOwnershipTests,
HazeEffect
};
enum class EntityScriptCallMethodVersion : PacketVersion {

View file

@ -134,7 +134,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
color += directionalSpecular;
// Attenuate the light if haze effect selected
if ((hazeParams.hazeMode & HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) == HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED) {
if ((hazeParams.hazeMode & HAZE_MODE_IS_KEYLIGHT_ATTENUATED) == HAZE_MODE_IS_KEYLIGHT_ATTENUATED) {
// Directional light attenuation is simulated by assuming the light source is at a fixed height above the
// fragment. This height is where the haze density is reduced by 95% from the haze at the fragment's height
//
@ -147,8 +147,8 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
// Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen)
float height_95p = 2000.0;
if (hazeParams.hazeAltitudeFactorKeyLight > 0.0f) {
height_95p = -log(0.05) / hazeParams.hazeAltitudeFactorKeyLight;
if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) {
height_95p = -log(0.05) / hazeParams.hazeKeyLightAltitudeFactor;
}
// Note that the sine will always be positive
@ -168,8 +168,8 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
// Integration is from the fragment towards the light source
// Note that the haze base reference affects only the haze density as function of altitude
float hazeDensityDistribution =
hazeParams.hazeRangeFactorKeyLight *
exp(-hazeParams.hazeAltitudeFactorKeyLight * (worldFragPos.y - hazeParams.hazeBaseReference));
hazeParams.hazeKeyLightRangeFactor *
exp(-hazeParams.hazeKeyLightAltitudeFactor * (worldFragPos.y - hazeParams.hazeBaseReference));
float hazeIntegral = hazeDensityDistribution * distance;

View file

@ -21,32 +21,16 @@
#include "Haze_frag.h"
void HazeConfig::setHazeColorR(const float value) {
hazeColorR = value;
void HazeConfig::setHazeColor(const glm::vec3 value) {
hazeColor = value;
}
void HazeConfig::setHazeColorG(const float value) {
hazeColorG = value;
void HazeConfig::setHazeGlareAngle(const float value) {
hazeGlareAngle = value;
}
void HazeConfig::setHazeColorB(const float value) {
hazeColorB = value;
}
void HazeConfig::setDirectionalLightAngle_degs(const float value) {
hazeDirectionalLightAngle_degs = value;
}
void HazeConfig::setDirectionalLightColorR(const float value) {
hazeDirectionalLightColorR = value;
}
void HazeConfig::setDirectionalLightColorG(const float value) {
hazeDirectionalLightColorG = value;
}
void HazeConfig::setDirectionalLightColorB(const float value) {
hazeDirectionalLightColorB = value;
void HazeConfig::setHazeGlareColor(const glm::vec3 value) {
hazeGlareColor = value;
}
void HazeConfig::setHazeBaseReference(const float value) {
@ -73,24 +57,24 @@ void HazeConfig::setHazeEnableGlare(const bool active) {
isHazeEnableGlare = active;
}
void HazeConfig::setHazeRange_m(const float value) {
hazeRange_m = value;
void HazeConfig::setHazeRange(const float value) {
hazeRange = value;
}
void HazeConfig::setHazeAltitude_m(const float value) {
hazeAltitude_m = value;
void HazeConfig::setHazeAltitude(const float value) {
hazeHeight = value;
}
void HazeConfig::setHazeKeyLightRange_m(const float value) {
hazeKeyLightRange_m = value;
void HazeConfig::setHazeKeyLightRange(const float value) {
hazeKeyLightRange = value;
}
void HazeConfig::setHazeKeyLightAltitude_m(const float value) {
hazeKeyLightAltitude_m = value;
void HazeConfig::setHazeKeyLightAltitude(const float value) {
hazeKeyLightAltitude = value;
}
void HazeConfig::setHazeBackgroundBlendValue(const float value) {
hazeBackgroundBlendValue = value;
void HazeConfig::setHazeBackgroundBlend(const float value) {
hazeBackgroundBlend = value;
}
MakeHaze::MakeHaze() {
@ -98,10 +82,10 @@ MakeHaze::MakeHaze() {
}
void MakeHaze::configure(const Config& config) {
_haze->setHazeColor(glm::vec3(config.hazeColorR, config.hazeColorG, config.hazeColorB));
_haze->setDirectionalLightBlend(model::convertDirectionalLightAngleToPower(config.hazeDirectionalLightAngle_degs));
_haze->setHazeColor(config.hazeColor);
_haze->setHazeGlareBlend(model::Haze::convertGlareAngleToPower(config.hazeGlareAngle));
_haze->setDirectionalLightColor(glm::vec3(config.hazeDirectionalLightColorR, config.hazeDirectionalLightColorG, config.hazeDirectionalLightColorB));
_haze->setHazeGlareColor(config.hazeGlareColor);
_haze->setHazeBaseReference(config.hazeBaseReference);
_haze->setHazeActive(config.isHazeActive);
@ -110,13 +94,13 @@ void MakeHaze::configure(const Config& config) {
_haze->setModulateColorActive(config.isModulateColorActive);
_haze->setHazeEnableGlare(config.isHazeEnableGlare);
_haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange_m));
_haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeAltitude_m));
_haze->setHazeRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(config.hazeRange));
_haze->setHazeAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight));
_haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange_m));
_haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude_m));
_haze->setHazeKeyLightRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange));
_haze->setHazeKeyLightAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude));
_haze->setHazeBackgroundBlendValue(config.hazeBackgroundBlendValue);
_haze->setHazeBackgroundBlend(config.hazeBackgroundBlend);
}
void MakeHaze::run(const render::RenderContextPointer& renderContext, model::HazePointer& haze) {

View file

@ -19,24 +19,19 @@
#include <gpu/Pipeline.h>
#include <render/Forward.h>
#include <render/DrawTask.h>
#include <model/Haze.h>
#include "SurfaceGeometryPass.h"
#include "model/Haze.h"
using LinearDepthFramebufferPointer = std::shared_ptr<LinearDepthFramebuffer>;
class MakeHazeConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(float hazeColorR MEMBER hazeColorR WRITE setHazeColorR NOTIFY dirty);
Q_PROPERTY(float hazeColorG MEMBER hazeColorG WRITE setHazeColorG NOTIFY dirty);
Q_PROPERTY(float hazeColorB MEMBER hazeColorB WRITE setHazeColorB NOTIFY dirty);
Q_PROPERTY(float hazeDirectionalLightAngle_degs MEMBER hazeDirectionalLightAngle_degs WRITE setDirectionalLightAngle_degs NOTIFY dirty);
Q_PROPERTY(glm::vec3 hazeColor MEMBER hazeColor WRITE setHazeColor NOTIFY dirty);
Q_PROPERTY(float hazeGlareAngle MEMBER hazeGlareAngle WRITE setHazeGlareAngle NOTIFY dirty);
Q_PROPERTY(float hazeDirectionalLightColorR MEMBER hazeDirectionalLightColorR WRITE setDirectionalLightColorR NOTIFY dirty);
Q_PROPERTY(float hazeDirectionalLightColorG MEMBER hazeDirectionalLightColorG WRITE setDirectionalLightColorG NOTIFY dirty);
Q_PROPERTY(float hazeDirectionalLightColorB MEMBER hazeDirectionalLightColorB WRITE setDirectionalLightColorB NOTIFY dirty);
Q_PROPERTY(glm::vec3 hazeGlareColor MEMBER hazeGlareColor WRITE setHazeGlareColor NOTIFY dirty);
Q_PROPERTY(float hazeBaseReference MEMBER hazeBaseReference WRITE setHazeBaseReference NOTIFY dirty);
Q_PROPERTY(bool isHazeActive MEMBER isHazeActive WRITE setHazeActive NOTIFY dirty);
@ -45,26 +40,22 @@ class MakeHazeConfig : public render::Job::Config {
Q_PROPERTY(bool isModulateColorActive MEMBER isModulateColorActive WRITE setModulateColorActive NOTIFY dirty);
Q_PROPERTY(bool isHazeEnableGlare MEMBER isHazeEnableGlare WRITE setHazeEnableGlare NOTIFY dirty);
Q_PROPERTY(float hazeRange_m MEMBER hazeRange_m WRITE setHazeRange_m NOTIFY dirty);
Q_PROPERTY(float hazeAltitude_m MEMBER hazeAltitude_m WRITE setHazeAltitude_m NOTIFY dirty);
Q_PROPERTY(float hazeRange MEMBER hazeRange WRITE setHazeRange NOTIFY dirty);
Q_PROPERTY(float hazeHeight MEMBER hazeHeight WRITE setHazeAltitude NOTIFY dirty);
Q_PROPERTY(float hazeKeyLightRange_m MEMBER hazeKeyLightRange_m WRITE setHazeKeyLightRange_m NOTIFY dirty);
Q_PROPERTY(float hazeKeyLightAltitude_m MEMBER hazeKeyLightAltitude_m WRITE setHazeKeyLightAltitude_m NOTIFY dirty);
Q_PROPERTY(float hazeKeyLightRange MEMBER hazeKeyLightRange WRITE setHazeKeyLightRange NOTIFY dirty);
Q_PROPERTY(float hazeKeyLightAltitude MEMBER hazeKeyLightAltitude WRITE setHazeKeyLightAltitude NOTIFY dirty);
Q_PROPERTY(float hazeBackgroundBlendValue MEMBER hazeBackgroundBlendValue WRITE setHazeBackgroundBlendValue NOTIFY dirty);
Q_PROPERTY(float hazeBackgroundBlend MEMBER hazeBackgroundBlend WRITE setHazeBackgroundBlend NOTIFY dirty);
public:
MakeHazeConfig() : render::Job::Config() {}
float hazeColorR{ model::initialHazeColor.r };
float hazeColorG{ model::initialHazeColor.g };
float hazeColorB{ model::initialHazeColor.b };
float hazeDirectionalLightAngle_degs{ model::initialDirectionalLightAngle_degs };
glm::vec3 hazeColor{ model::Haze::INITIAL_HAZE_COLOR };
float hazeGlareAngle{ model::Haze::INITIAL_HAZE_GLARE_ANGLE };
float hazeDirectionalLightColorR{ model::initialDirectionalLightColor.r };
float hazeDirectionalLightColorG{ model::initialDirectionalLightColor.g };
float hazeDirectionalLightColorB{ model::initialDirectionalLightColor.b };
float hazeBaseReference{ model::initialHazeBaseReference };
glm::vec3 hazeGlareColor{ model::Haze::INITIAL_HAZE_GLARE_COLOR };
float hazeBaseReference{ model::Haze::INITIAL_HAZE_BASE_REFERENCE };
bool isHazeActive{ false };
bool isAltitudeBased{ false };
@ -72,23 +63,19 @@ public:
bool isModulateColorActive{ false };
bool isHazeEnableGlare{ false };
float hazeRange_m{ model::initialHazeRange_m };
float hazeAltitude_m{ model::initialHazeAltitude_m };
float hazeRange{ model::Haze::INITIAL_HAZE_RANGE };
float hazeHeight{ model::Haze::INITIAL_HAZE_HEIGHT };
float hazeKeyLightRange_m{ model::initialHazeKeyLightRange_m };
float hazeKeyLightAltitude_m{ model::initialHazeKeyLightAltitude_m };
float hazeKeyLightRange{ model::Haze::INITIAL_KEY_LIGHT_RANGE };
float hazeKeyLightAltitude{ model::Haze::INITIAL_KEY_LIGHT_ALTITUDE };
float hazeBackgroundBlendValue{ model::initialHazeBackgroundBlendValue };
float hazeBackgroundBlend{ model::Haze::INITIAL_HAZE_BACKGROUND_BLEND };
public slots:
void setHazeColorR(const float value) { hazeColorR = value; emit dirty(); }
void setHazeColorG(const float value) { hazeColorG = value; emit dirty(); }
void setHazeColorB(const float value) { hazeColorB = value; emit dirty(); }
void setDirectionalLightAngle_degs(const float value) { hazeDirectionalLightAngle_degs = value; emit dirty(); }
void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); }
void setHazeGlareAngle(const float value) { hazeGlareAngle = value; emit dirty(); }
void setDirectionalLightColorR(const float value) { hazeDirectionalLightColorR = value; emit dirty(); }
void setDirectionalLightColorG(const float value) { hazeDirectionalLightColorG = value; emit dirty(); }
void setDirectionalLightColorB(const float value) { hazeDirectionalLightColorB = value; emit dirty(); }
void setHazeGlareColor(const glm::vec3 value) { hazeGlareColor = value; emit dirty(); }
void setHazeBaseReference(const float value) { hazeBaseReference = value; ; emit dirty(); }
void setHazeActive(const bool active) { isHazeActive = active; emit dirty(); }
@ -97,13 +84,13 @@ public slots:
void setModulateColorActive(const bool active) { isModulateColorActive = active; emit dirty(); }
void setHazeEnableGlare(const bool active) { isHazeEnableGlare = active; emit dirty(); }
void setHazeRange_m(const float value) { hazeRange_m = value; emit dirty(); }
void setHazeAltitude_m(const float value) { hazeAltitude_m = value; emit dirty(); }
void setHazeRange(const float value) { hazeRange = value; emit dirty(); }
void setHazeAltitude(const float value) { hazeHeight = value; emit dirty(); }
void setHazeKeyLightRange_m(const float value) { hazeKeyLightRange_m = value; emit dirty(); }
void setHazeKeyLightAltitude_m(const float value) { hazeKeyLightAltitude_m = value; emit dirty(); }
void setHazeKeyLightRange(const float value) { hazeKeyLightRange = value; emit dirty(); }
void setHazeKeyLightAltitude(const float value) { hazeKeyLightAltitude = value; emit dirty(); }
void setHazeBackgroundBlendValue(const float value) { hazeBackgroundBlendValue = value; ; emit dirty(); }
void setHazeBackgroundBlend(const float value) { hazeBackgroundBlend = value; ; emit dirty(); }
signals:
void dirty();
@ -128,15 +115,11 @@ public:
HazeConfig() : render::Job::Config(true) {}
// attributes
float hazeColorR{ model::initialHazeColor.r };
float hazeColorG{ model::initialHazeColor.g };
float hazeColorB{ model::initialHazeColor.b };
float hazeDirectionalLightAngle_degs{ model::initialDirectionalLightAngle_degs };
glm::vec3 hazeColor{ model::Haze::INITIAL_HAZE_COLOR };
float hazeGlareAngle{ model::Haze::INITIAL_HAZE_GLARE_ANGLE };
float hazeDirectionalLightColorR{ model::initialDirectionalLightColor.r };
float hazeDirectionalLightColorG{ model::initialDirectionalLightColor.g };
float hazeDirectionalLightColorB{ model::initialDirectionalLightColor.b };
float hazeBaseReference{ model::initialHazeBaseReference };
glm::vec3 hazeGlareColor{ model::Haze::INITIAL_HAZE_GLARE_COLOR };
float hazeBaseReference{ model::Haze::INITIAL_HAZE_BASE_REFERENCE };
bool isHazeActive{ false }; // Setting this to true will set haze to on
bool isAltitudeBased{ false };
@ -144,23 +127,19 @@ public:
bool isModulateColorActive{ false };
bool isHazeEnableGlare{ false };
float hazeRange_m{ model::initialHazeRange_m };
float hazeAltitude_m{ model::initialHazeAltitude_m };
float hazeRange{ model::Haze::INITIAL_HAZE_RANGE };
float hazeHeight{ model::Haze::INITIAL_HAZE_HEIGHT };
float hazeKeyLightRange_m{ model::initialHazeKeyLightRange_m };
float hazeKeyLightAltitude_m{ model::initialHazeKeyLightAltitude_m };
float hazeKeyLightRange{ model::Haze::INITIAL_KEY_LIGHT_RANGE };
float hazeKeyLightAltitude{ model::Haze::INITIAL_KEY_LIGHT_ALTITUDE };
float hazeBackgroundBlendValue{ model::initialHazeBackgroundBlendValue };
float hazeBackgroundBlend{ model::Haze::INITIAL_HAZE_BACKGROUND_BLEND };
// methods
void setHazeColorR(const float value);
void setHazeColorG(const float value);
void setHazeColorB(const float value);
void setDirectionalLightAngle_degs(const float value);
void setHazeColor(const glm::vec3 value);
void setHazeGlareAngle(const float value);
void setDirectionalLightColorR(const float value);
void setDirectionalLightColorG(const float value);
void setDirectionalLightColorB(const float value);
void setHazeGlareColor(const glm::vec3 value);
void setHazeBaseReference(const float value);
void setHazeActive(const bool active);
@ -169,13 +148,13 @@ public:
void setModulateColorActive(const bool active);
void setHazeEnableGlare(const bool active);
void setHazeRange_m(const float value);
void setHazeAltitude_m(const float value);
void setHazeRange(const float value);
void setHazeAltitude(const float value);
void setHazeKeyLightRange_m(const float value);
void setHazeKeyLightAltitude_m(const float value);
void setHazeKeyLightRange(const float value);
void setHazeKeyLightAltitude(const float value);
void setHazeBackgroundBlendValue(const float value);
void setHazeBackgroundBlend(const float value);
};
class DrawHaze {

View file

@ -482,8 +482,10 @@ void GeometryCache::buildShapes() {
using namespace geometry;
auto vertexBuffer = std::make_shared<gpu::Buffer>();
auto indexBuffer = std::make_shared<gpu::Buffer>();
// Cube
// Cube
setupFlatShape(_shapes[Cube], geometry::cube(), _shapeVertices, _shapeIndices);
//Quad renders as flat Cube
setupFlatShape(_shapes[Quad], geometry::cube(), _shapeVertices, _shapeIndices);
// Tetrahedron
setupFlatShape(_shapes[Tetrahedron], geometry::tetrahedron(), _shapeVertices, _shapeIndices);
// Icosahedron
@ -524,12 +526,10 @@ void GeometryCache::buildShapes() {
extrudePolygon<64>(_shapes[Cylinder], _shapeVertices, _shapeIndices);
//Cone,
extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true);
//Circle
drawCircle(_shapes[Circle], _shapeVertices, _shapeIndices);
// Circle renders as flat Cylinder
extrudePolygon<64>(_shapes[Circle], _shapeVertices, _shapeIndices);
// Not implemented yet:
//Quad,
//Torus,
//Torus,
}
const GeometryCache::ShapeData * GeometryCache::getShapeData(const Shape shape) const {

View file

@ -60,15 +60,15 @@ void main(void) {
Light light = getLight();
vec3 lightDirection = getLightDirection(light);
float directionalLightComponent = max(0.0, dot(eyeFragDir, -lightDirection));
float power = min(1.0, pow(directionalLightComponent, hazeParams.directionalLightBlend));
float glareComponent = max(0.0, dot(eyeFragDir, -lightDirection));
float power = min(1.0, pow(glareComponent, hazeParams.hazeGlareBlend));
vec4 directionalLightColor = vec4(hazeParams.directionalLightColor, 1.0);
vec4 glareColor = vec4(hazeParams.hazeGlareColor, 1.0);
// Use the haze colour for the belnd-out colour, if blend is not enabled
// Use the haze colour for the glare colour, if blend is not enabled
vec4 blendedHazeColor;
if ((hazeParams.hazeMode & HAZE_MODE_IS_ENABLE_LIGHT_BLEND) == HAZE_MODE_IS_ENABLE_LIGHT_BLEND) {
blendedHazeColor = mix(hazeColor, directionalLightColor, power);
blendedHazeColor = mix(hazeColor, glareColor, power);
} else {
blendedHazeColor = hazeColor;
}
@ -86,14 +86,14 @@ void main(void) {
// Note that the haze base reference affects only the haze density as function of altitude
vec3 hazeDensityDistribution =
hazeParams.colorModulationFactor *
exp(-hazeParams.hazeAltitudeFactor * (worldEyePos.y - hazeParams.hazeBaseReference));
exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference));
vec3 hazeIntegral = hazeDensityDistribution * distance;
const float slopeThreshold = 0.01;
float deltaHeight = worldFragPos.y - worldEyePos.y;
if (abs(deltaHeight) > slopeThreshold) {
float t = hazeParams.hazeAltitudeFactor * deltaHeight;
float t = hazeParams.hazeHeightFactor * deltaHeight;
hazeIntegral *= (1.0 - exp (-t)) / t;
}
@ -117,14 +117,14 @@ void main(void) {
// Note that the haze base reference affects only the haze density as function of altitude
float hazeDensityDistribution =
hazeParams.hazeRangeFactor *
exp(-hazeParams.hazeAltitudeFactor * (worldEyePos.y - hazeParams.hazeBaseReference));
exp(-hazeParams.hazeHeightFactor * (worldEyePos.y - hazeParams.hazeBaseReference));
float hazeIntegral = hazeDensityDistribution * distance;
const float slopeThreshold = 0.01;
float deltaHeight = worldFragPos.y - worldEyePos.y;
if (abs(deltaHeight) > slopeThreshold) {
float t = hazeParams.hazeAltitudeFactor * deltaHeight;
float t = hazeParams.hazeHeightFactor * deltaHeight;
// Protect from wild values
if (abs(t) > 0.0000001) {
hazeIntegral *= (1.0 - exp (-t)) / t;
@ -140,7 +140,7 @@ void main(void) {
// Mix with background at far range
const float BLEND_DISTANCE = 27000.0;
if (distance > BLEND_DISTANCE) {
outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlendValue);
outFragColor = mix(potentialFragColor, fragColor, hazeParams.backgroundBlend);
} else {
outFragColor = potentialFragColor;
}

View file

@ -12,28 +12,28 @@
const int HAZE_MODE_IS_ACTIVE = 1 << 0;
const int HAZE_MODE_IS_ALTITUDE_BASED = 1 << 1;
const int HAZE_MODE_IS_DIRECTIONAL_LIGHT_ATTENUATED = 1 << 2;
const int HAZE_MODE_IS_KEYLIGHT_ATTENUATED = 1 << 2;
const int HAZE_MODE_IS_MODULATE_COLOR = 1 << 3;
const int HAZE_MODE_IS_ENABLE_LIGHT_BLEND = 1 << 4;
struct HazeParams {
vec3 hazeColor;
float directionalLightBlend;
float hazeGlareBlend;
vec3 directionalLightColor;
vec3 hazeGlareColor;
float hazeBaseReference;
vec3 colorModulationFactor;
int hazeMode;
mat4 zoneTransform;
float backgroundBlendValue;
float backgroundBlend;
float hazeRangeFactor;
float hazeAltitudeFactor;
float hazeHeightFactor;
float hazeRangeFactorKeyLight;
float hazeAltitudeFactorKeyLight;
float hazeKeyLightRangeFactor;
float hazeKeyLightAltitudeFactor;
};
layout(std140) uniform hazeBuffer {

View file

@ -20,10 +20,10 @@ FetchHazeStage::FetchHazeStage() {
}
void FetchHazeStage::configure(const Config& config) {
_haze->setHazeColor(glm::vec3(config.hazeColorR, config.hazeColorG, config.hazeColorB));
_haze->setDirectionalLightBlend(model::convertDirectionalLightAngleToPower(config.hazeDirectionalLightAngle_degs));
_haze->setHazeColor(config.hazeColor);
_haze->setHazeGlareBlend(model::Haze::convertGlareAngleToPower(config.hazeGlareAngle));
_haze->setDirectionalLightColor(glm::vec3(config.hazeDirectionalLightColorR, config.hazeDirectionalLightColorG, config.hazeDirectionalLightColorB));
_haze->setHazeGlareColor(config.hazeGlareColor);
_haze->setHazeBaseReference(config.hazeBaseReference);
_haze->setHazeActive(config.isHazeActive);
@ -32,13 +32,13 @@ void FetchHazeStage::configure(const Config& config) {
_haze->setModulateColorActive(config.isModulateColorActive);
_haze->setHazeEnableGlare(config.isHazeEnableGlare);
_haze->setHazeRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeRange_m));
_haze->setHazeAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeAltitude_m));
_haze->setHazeRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(config.hazeRange));
_haze->setHazeAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeHeight));
_haze->setHazeKeyLightRangeFactor(model::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange_m));
_haze->setHazeKeyLightAltitudeFactor(model::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude_m));
_haze->setHazeKeyLightRangeFactor(model::Haze::convertHazeRangeToHazeRangeFactor(config.hazeKeyLightRange));
_haze->setHazeKeyLightAltitudeFactor(model::Haze::convertHazeAltitudeToHazeAltitudeFactor(config.hazeKeyLightAltitude));
_haze->setHazeBackgroundBlendValue(config.hazeBackgroundBlendValue);
_haze->setHazeBackgroundBlend(config.hazeBackgroundBlend);
}
HazeStage::Index HazeStage::findHaze(const HazePointer& haze) const {

View file

@ -19,7 +19,7 @@
#include <render/Forward.h>
#include <render/DrawTask.h>
#include "model/Haze.h"
#include <model/Haze.h>
// Haze stage to set up haze-related rendering tasks
class HazeStage : public render::Stage {
@ -83,14 +83,10 @@ protected:
class FetchHazeConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(float hazeColorR MEMBER hazeColorR WRITE setHazeColorR NOTIFY dirty);
Q_PROPERTY(float hazeColorG MEMBER hazeColorG WRITE setHazeColorG NOTIFY dirty);
Q_PROPERTY(float hazeColorB MEMBER hazeColorB WRITE setHazeColorB NOTIFY dirty);
Q_PROPERTY(float hazeDirectionalLightAngle_degs MEMBER hazeDirectionalLightAngle_degs WRITE setDirectionalLightAngle_degs NOTIFY dirty);
Q_PROPERTY(glm::vec3 hazeColor MEMBER hazeColor WRITE setHazeColor NOTIFY dirty);
Q_PROPERTY(float hazeGlareAngle MEMBER hazeGlareAngle WRITE setHazeGlareAngle NOTIFY dirty);
Q_PROPERTY(float hazeDirectionalLightColorR MEMBER hazeDirectionalLightColorR WRITE setDirectionalLightColorR NOTIFY dirty);
Q_PROPERTY(float hazeDirectionalLightColorG MEMBER hazeDirectionalLightColorG WRITE setDirectionalLightColorG NOTIFY dirty);
Q_PROPERTY(float hazeDirectionalLightColorB MEMBER hazeDirectionalLightColorB WRITE setDirectionalLightColorB NOTIFY dirty);
Q_PROPERTY(glm::vec3 hazeGlareColor MEMBER hazeGlareColor WRITE setHazeGlareColor NOTIFY dirty);
Q_PROPERTY(float hazeBaseReference MEMBER hazeBaseReference WRITE setHazeBaseReference NOTIFY dirty);
Q_PROPERTY(bool isHazeActive MEMBER isHazeActive WRITE setHazeActive NOTIFY dirty);
@ -99,26 +95,22 @@ class FetchHazeConfig : public render::Job::Config {
Q_PROPERTY(bool isModulateColorActive MEMBER isModulateColorActive WRITE setModulateColorActive NOTIFY dirty);
Q_PROPERTY(bool isHazeEnableGlare MEMBER isHazeEnableGlare WRITE setHazeEnableGlare NOTIFY dirty);
Q_PROPERTY(float hazeRange_m MEMBER hazeRange_m WRITE setHazeRange_m NOTIFY dirty);
Q_PROPERTY(float hazeAltitude_m MEMBER hazeAltitude_m WRITE setHazeAltitude_m NOTIFY dirty);
Q_PROPERTY(float hazeRange MEMBER hazeRange WRITE setHazeRange NOTIFY dirty);
Q_PROPERTY(float hazeHeight MEMBER hazeHeight WRITE setHazeAltitude NOTIFY dirty);
Q_PROPERTY(float hazeKeyLightRange_m MEMBER hazeKeyLightRange_m WRITE setHazeKeyLightRange_m NOTIFY dirty);
Q_PROPERTY(float hazeKeyLightAltitude_m MEMBER hazeKeyLightAltitude_m WRITE setHazeKeyLightAltitude_m NOTIFY dirty);
Q_PROPERTY(float hazeKeyLightRange MEMBER hazeKeyLightRange WRITE setHazeKeyLightRange NOTIFY dirty);
Q_PROPERTY(float hazeKeyLightAltitude MEMBER hazeKeyLightAltitude WRITE setHazeKeyLightAltitude NOTIFY dirty);
Q_PROPERTY(float hazeBackgroundBlendValue MEMBER hazeBackgroundBlendValue WRITE setHazeBackgroundBlendValue NOTIFY dirty);
Q_PROPERTY(float hazeBackgroundBlend MEMBER hazeBackgroundBlend WRITE setHazeBackgroundBlend NOTIFY dirty);
public:
FetchHazeConfig() : render::Job::Config() {}
float hazeColorR{ model::initialHazeColor.r };
float hazeColorG{ model::initialHazeColor.g };
float hazeColorB{ model::initialHazeColor.b };
float hazeDirectionalLightAngle_degs{ model::initialDirectionalLightAngle_degs };
glm::vec3 hazeColor{ model::Haze::INITIAL_HAZE_COLOR };
float hazeGlareAngle{ model::Haze::INITIAL_HAZE_GLARE_ANGLE };
float hazeDirectionalLightColorR{ model::initialDirectionalLightColor.r };
float hazeDirectionalLightColorG{ model::initialDirectionalLightColor.g };
float hazeDirectionalLightColorB{ model::initialDirectionalLightColor.b };
float hazeBaseReference{ model::initialHazeBaseReference };
glm::vec3 hazeGlareColor{ model::Haze::INITIAL_HAZE_GLARE_COLOR };
float hazeBaseReference{ model::Haze::INITIAL_HAZE_BASE_REFERENCE };
bool isHazeActive{ false };
bool isAltitudeBased{ false };
@ -126,23 +118,19 @@ public:
bool isModulateColorActive{ false };
bool isHazeEnableGlare{ false };
float hazeRange_m{ model::initialHazeRange_m };
float hazeAltitude_m{ model::initialHazeAltitude_m };
float hazeRange{ model::Haze::INITIAL_HAZE_RANGE };
float hazeHeight{ model::Haze::INITIAL_HAZE_HEIGHT };
float hazeKeyLightRange_m{ model::initialHazeKeyLightRange_m };
float hazeKeyLightAltitude_m{ model::initialHazeKeyLightAltitude_m };
float hazeKeyLightRange{ model::Haze::INITIAL_KEY_LIGHT_RANGE };
float hazeKeyLightAltitude{ model::Haze::INITIAL_KEY_LIGHT_ALTITUDE };
float hazeBackgroundBlendValue{ model::initialHazeBackgroundBlendValue };
float hazeBackgroundBlend{ model::Haze::INITIAL_HAZE_BACKGROUND_BLEND };
public slots:
void setHazeColorR(const float value) { hazeColorR = value; emit dirty(); }
void setHazeColorG(const float value) { hazeColorG = value; emit dirty(); }
void setHazeColorB(const float value) { hazeColorB = value; emit dirty(); }
void setDirectionalLightAngle_degs(const float value) { hazeDirectionalLightAngle_degs = value; emit dirty(); }
void setHazeColor(const glm::vec3 value) { hazeColor = value; emit dirty(); }
void setHazeGlareAngle(const float value) { hazeGlareAngle = value; emit dirty(); }
void setDirectionalLightColorR(const float value) { hazeDirectionalLightColorR = value; emit dirty(); }
void setDirectionalLightColorG(const float value) { hazeDirectionalLightColorG = value; emit dirty(); }
void setDirectionalLightColorB(const float value) { hazeDirectionalLightColorB = value; emit dirty(); }
void setHazeGlareColor(const glm::vec3 value) { hazeGlareColor = value; emit dirty(); }
void setHazeBaseReference(const float value) { hazeBaseReference = value; ; emit dirty(); }
void setHazeActive(const bool active) { isHazeActive = active; emit dirty(); }
@ -151,13 +139,13 @@ public slots:
void setModulateColorActive(const bool active) { isModulateColorActive = active; emit dirty(); }
void setHazeEnableGlare(const bool active) { isHazeEnableGlare = active; emit dirty(); }
void setHazeRange_m(const float value) { hazeRange_m = value; emit dirty(); }
void setHazeAltitude_m(const float value) { hazeAltitude_m = value; emit dirty(); }
void setHazeRange(const float value) { hazeRange = value; emit dirty(); }
void setHazeAltitude(const float value) { hazeHeight = value; emit dirty(); }
void setHazeKeyLightRange_m(const float value) { hazeKeyLightRange_m = value; emit dirty(); }
void setHazeKeyLightAltitude_m(const float value) { hazeKeyLightAltitude_m = value; emit dirty(); }
void setHazeKeyLightRange(const float value) { hazeKeyLightRange = value; emit dirty(); }
void setHazeKeyLightAltitude(const float value) { hazeKeyLightAltitude = value; emit dirty(); }
void setHazeBackgroundBlendValue(const float value) { hazeBackgroundBlendValue = value; ; emit dirty(); }
void setHazeBackgroundBlend(const float value) { hazeBackgroundBlend = value; ; emit dirty(); }
signals:
void dirty();

View file

@ -129,101 +129,6 @@ QString SceneScripting::Stage::getBackgroundMode() const {
};
}
void SceneScripting::Stage::setHazeMode(const QString& mode) {
if (mode == QString("haze off")) {
_skyStage->setHazeMode(model::SunSkyStage::HAZE_OFF);
} else if (mode == QString("haze on")) {
_skyStage->setHazeMode(model::SunSkyStage::HAZE_ON);
}
}
QString SceneScripting::Stage::getHazeMode() const {
switch (_skyStage->getHazeMode()) {
case model::SunSkyStage::HAZE_OFF:
return QString("haze off");
case model::SunSkyStage::HAZE_ON:
return QString("haze on");
default:
return QString("inherit");
};
}
void SceneScripting::Stage::setHazeRange(const float hazeRange) {
_skyStage->setHazeRange(hazeRange);
}
float SceneScripting::Stage::getHazeRange() const {
return _skyStage->getHazeRange();
}
void SceneScripting::Stage::setHazeColor(const xColor hazeColor) {
_skyStage->setHazeColor(hazeColor);
}
xColor SceneScripting::Stage::getHazeColor() const {
return _skyStage->getHazeColor();
}
void SceneScripting::Stage::setHazeGlareColor(const xColor hazeGlareColor) {
_skyStage->setHazeGlareColor(hazeGlareColor);
}
xColor SceneScripting::Stage::getHazeGlareColor() const {
return _skyStage->getHazeGlareColor();
}
void SceneScripting::Stage::setHazeEnableGlare(const bool hazeEnableGlare) {
_skyStage->setHazeEnableGlare(hazeEnableGlare);
}
bool SceneScripting::Stage::getHazeEnableGlare() const {
return _skyStage->getHazeEnableGlare();
}
void SceneScripting::Stage::setHazeGlareAngle(const float hazeGlareAngle) {
_skyStage->setHazeGlareAngle(hazeGlareAngle);
}
float SceneScripting::Stage::getHazeGlareAngle() const {
return _skyStage->getHazeGlareAngle();
}
void SceneScripting::Stage::setHazeAltitudeEffect(const bool hazeAltitudeEffect) {
_skyStage->setHazeAltitudeEffect(hazeAltitudeEffect);
}
bool SceneScripting::Stage::getHazeAltitudeEffect() const {
return _skyStage->getHazeAltitudeEffect();
}
void SceneScripting::Stage::setHazeCeiling(const float hazeCeiling) {
_skyStage->setHazeCeiling(hazeCeiling);
}
float SceneScripting::Stage::getHazeCeiling() const {
return _skyStage->getHazeCeiling();
}
void SceneScripting::Stage::setHazeBaseRef(const float hazeBaseRef) {
_skyStage->setHazeBaseRef(hazeBaseRef);
}
float SceneScripting::Stage::getHazeBaseRef() const {
return _skyStage->getHazeBaseRef();
}
void SceneScripting::Stage::setHazeBackgroundBlend(const float hazeBackgroundBlend) {
_skyStage->setHazeBackgroundBlend(hazeBackgroundBlend);
}
float SceneScripting::Stage::getHazeBackgroundBlend() const {
return _skyStage->getHazeBackgroundBlend();
}
void SceneScripting::Stage::setHazeAttenuateKeyLight(const bool hazeAttenuateKeyLight) {
_skyStage->setHazeAttenuateKeyLight(hazeAttenuateKeyLight);
}
bool SceneScripting::Stage::getHazeAttenuateKeyLight() const {
return _skyStage->getHazeAttenuateKeyLight();
}
void SceneScripting::Stage::setHazeKeyLightRange(const float hazeKeyLightRange) {
_skyStage->setHazeKeyLightRange(hazeKeyLightRange);
}
float SceneScripting::Stage::getHazeKeyLightRange() const {
return _skyStage->getHazeKeyLightRange();
}
void SceneScripting::Stage::setHazeKeyLightAltitude(const float hazeKeyLightAltitude) {
_skyStage->setHazeKeyLightAltitude(hazeKeyLightAltitude);
}
float SceneScripting::Stage::getHazeKeyLightAltitude() const {
return _skyStage->getHazeKeyLightAltitude();
}
SceneScriptingInterface::SceneScriptingInterface() : _stage{ new SceneScripting::Stage{ _skyStage } } {
// Let's make sure the sunSkyStage is using a proceduralSkybox
_skyStage->setSkybox(model::SkyboxPointer(new ProceduralSkybox()));

View file

@ -121,58 +121,6 @@ namespace SceneScripting {
void setBackgroundMode(const QString& mode);
QString getBackgroundMode() const;
Q_PROPERTY(QString hazeMode READ getHazeMode WRITE setHazeMode)
void setHazeMode(const QString& mode);
QString getHazeMode() const;
Q_PROPERTY(float hazeRange READ getHazeRange WRITE setHazeRange)
void setHazeRange(float value);
float getHazeRange() const;
Q_PROPERTY(xColor hazeColor READ getHazeColor WRITE setHazeColor)
void setHazeColor(xColor value);
xColor getHazeColor() const;
Q_PROPERTY(xColor hazeGlareColor READ getHazeGlareColor WRITE setHazeGlareColor)
void setHazeGlareColor(xColor value);
xColor getHazeGlareColor() const;
Q_PROPERTY(bool hazeEnableGlare READ getHazeEnableGlare WRITE setHazeEnableGlare)
void setHazeEnableGlare(bool value);
bool getHazeEnableGlare() const;
Q_PROPERTY(float hazeGlareAngle READ getHazeGlareAngle WRITE setHazeGlareAngle)
void setHazeGlareAngle(float value);
float getHazeGlareAngle() const;
Q_PROPERTY(bool hazeAltitudeEffect READ getHazeAltitudeEffect WRITE setHazeAltitudeEffect)
void setHazeAltitudeEffect(bool value);
bool getHazeAltitudeEffect() const;
Q_PROPERTY(float hazeCeiling READ getHazeCeiling WRITE setHazeCeiling)
void setHazeCeiling(float value);
float getHazeCeiling() const;
Q_PROPERTY(float hazeBaseRef READ getHazeBaseRef WRITE setHazeBaseRef)
void setHazeBaseRef(float value);
float getHazeBaseRef() const;
Q_PROPERTY(float hazeBackgroundBlend READ getHazeBackgroundBlend WRITE setHazeBackgroundBlend)
void setHazeBackgroundBlend(float value);
float getHazeBackgroundBlend() const;
Q_PROPERTY(bool hazeAttenuateKeyLight READ getHazeAttenuateKeyLight WRITE setHazeAttenuateKeyLight)
void setHazeAttenuateKeyLight(bool value);
bool getHazeAttenuateKeyLight() const;
Q_PROPERTY(float hazeKeyLightRange READ getHazeKeyLightRange WRITE setHazeKeyLightRange)
void setHazeKeyLightRange(float value);
float getHazeKeyLightRange() const;
Q_PROPERTY(float hazeKeyLightAltitude READ getHazeKeyLightAltitude WRITE setHazeKeyLightAltitude)
void setHazeKeyLightAltitude(float value);
float getHazeKeyLightAltitude() const;
protected:
model::SunSkyStagePointer _skyStage;
LocationPointer _location;

View file

@ -68,7 +68,7 @@ Item {
label: "Haze Color R"
integral: false
config: root.hazeModel
property: "hazeColorR"
property: "hazeColor.r"
max: 1.0
min: 0.0
width: 280
@ -78,7 +78,7 @@ Item {
label: "Haze Color G"
integral: false
config: root.hazeModel
property: "hazeColorG"
property: "hazeColor.g"
max: 1.0
min: 0.0
width: 280
@ -88,7 +88,7 @@ Item {
label: "Haze Color B"
integral: false
config: root.hazeModel
property: "hazeColorB"
property: "hazeColor.b"
max: 1.0
min: 0.0
width: 280
@ -98,7 +98,7 @@ Item {
label: "Sun R"
integral: false
config: root.hazeModel
property: "hazeDirectionalLightColorR"
property: "hazeGlareColor.r"
max: 1.0
min: 0.0
width: 280
@ -108,7 +108,7 @@ Item {
label: "Sun G"
integral: false
config: root.hazeModel
property: "hazeDirectionalLightColorG"
property: "hazeGlareColor.g"
max: 1.0
min: 0.0
width: 280
@ -118,7 +118,7 @@ Item {
label: "Sun B"
integral: false
config: root.hazeModel
property: "hazeDirectionalLightColorB"
property: "hazeGlareColor.b"
max: 1.0
min: 0.0
width: 280
@ -128,7 +128,7 @@ Item {
label: "Sun glare angle"
integral: false
config: root.hazeModel
property: "hazeDirectionalLightAngle_degs"
property: "hazeGlareAngle_degs"
max: 70.0
min: 0.0
width: 280
@ -148,7 +148,7 @@ Item {
label: "BG Blend"
integral: false
config: root.hazeModel
property: "hazeBackgroundBlendValue"
property: "hazeBackgroundBlend"
max: 1.0
min: 0.0
width: 280
@ -156,9 +156,9 @@ Item {
CheckBox {
text: "Keylight Attenuation"
checked: root.hazeModel["isDirectionaLightAttenuationActive"]
checked: root.hazeModel["isKeyLightAttenuationActive"]
onCheckedChanged: {
root.hazeModel["isDirectionaLightAttenuationActive"] = checked;
root.hazeModel["isKeyLightAttenuationActive"] = checked;
}
}

View file

@ -225,28 +225,41 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
}
function getAttachPointForHotspotFromSettings(hotspot, hand) {
var skeletonModelURL = MyAvatar.skeletonModelURL;
var attachPointSettings = getAttachPointSettings();
var jointName = (hand === RIGHT_HAND) ? "RightHand" : "LeftHand";
var joints = attachPointSettings[hotspot.key];
if (joints) {
return joints[jointName];
} else {
return undefined;
var avatarSettingsData = attachPointSettings[skeletonModelURL];
if (avatarSettingsData) {
var jointName = (hand === RIGHT_HAND) ? "RightHand" : "LeftHand";
var joints = avatarSettingsData[hotspot.key];
if (joints) {
return joints[jointName];
}
}
return undefined;
}
function storeAttachPointForHotspotInSettings(hotspot, hand, offsetPosition, offsetRotation) {
var attachPointSettings = getAttachPointSettings();
var skeletonModelURL = MyAvatar.skeletonModelURL;
var avatarSettingsData = attachPointSettings[skeletonModelURL];
if (!avatarSettingsData) {
avatarSettingsData = {};
attachPointSettings[skeletonModelURL] = avatarSettingsData;
}
var jointName = (hand === RIGHT_HAND) ? "RightHand" : "LeftHand";
var joints = attachPointSettings[hotspot.key];
var joints = avatarSettingsData[hotspot.key];
if (!joints) {
joints = {};
attachPointSettings[hotspot.key] = joints;
avatarSettingsData[hotspot.key] = joints;
}
joints[jointName] = [offsetPosition, offsetRotation];
setAttachPointSettings(attachPointSettings);
}
function clearAttachPoints() {
setAttachPointSettings({});
}
function EquipEntity(hand) {
this.hand = hand;
this.targetEntityID = null;
@ -538,6 +551,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
};
this.endEquipEntity = function () {
this.storeAttachPointInSettings();
Entities.editEntity(this.targetEntityID, {
parentID: Uuid.NULL,
parentJointIndex: -1
@ -684,14 +698,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
if (dropDetected && !this.waitForTriggerRelease && this.triggerSmoothedGrab()) {
this.waitForTriggerRelease = true;
// store the offset attach points into preferences.
if (this.grabbedHotspot && this.targetEntityID) {
var prefprops = Entities.getEntityProperties(this.targetEntityID, ["localPosition", "localRotation"]);
if (prefprops && prefprops.localPosition && prefprops.localRotation) {
storeAttachPointForHotspotInSettings(this.grabbedHotspot, this.hand,
prefprops.localPosition, prefprops.localRotation);
}
}
this.endEquipEntity();
return makeRunningValues(false, [], []);
}
@ -707,6 +713,16 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
return makeRunningValues(true, [this.targetEntityID], []);
};
this.storeAttachPointInSettings = function() {
if (this.grabbedHotspot && this.targetEntityID) {
var prefProps = Entities.getEntityProperties(this.targetEntityID, ["localPosition", "localRotation"]);
if (prefProps && prefProps.localPosition && prefProps.localRotation) {
storeAttachPointForHotspotInSettings(this.grabbedHotspot, this.hand,
prefProps.localPosition, prefProps.localRotation);
}
}
};
this.cleanup = function () {
if (this.targetEntityID) {
this.endEquipEntity();
@ -751,11 +767,12 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
enableDispatcherModule("LeftEquipEntity", leftEquipEntity);
enableDispatcherModule("RightEquipEntity", rightEquipEntity);
this.cleanup = function () {
function cleanup() {
leftEquipEntity.cleanup();
rightEquipEntity.cleanup();
disableDispatcherModule("LeftEquipEntity");
disableDispatcherModule("RightEquipEntity");
clearAttachPoints();
};
Script.scriptEnding.connect(this.cleanup);
Script.scriptEnding.connect(cleanup);
}());

View file

@ -154,6 +154,25 @@ Script.include("/~/system/libraries/controllers.js");
this.showStylus = function() {
if (this.stylus) {
var X_ROT_NEG_90 = { x: -0.70710678, y: 0, z: 0, w: 0.70710678 };
var modelOrientation = Quat.multiply(this.stylusTip.orientation, X_ROT_NEG_90);
var modelOrientationAngles = Quat.safeEulerAngles(modelOrientation);
var rotation = Overlays.getProperty(this.stylus, "rotation");
var rotationAngles = Quat.safeEulerAngles(rotation);
if(!Vec3.withinEpsilon(modelOrientationAngles, rotationAngles, 1)) {
var modelPositionOffset = Vec3.multiplyQbyV(modelOrientation, { x: 0, y: 0, z: MyAvatar.sensorToWorldScale * -WEB_STYLUS_LENGTH / 2 });
var updatedStylusProperties = {
position: Vec3.sum(this.stylusTip.position, modelPositionOffset),
rotation: modelOrientation,
dimensions: Vec3.multiply(MyAvatar.sensorToWorldScale, { x: 0.01, y: 0.01, z: WEB_STYLUS_LENGTH }),
};
Overlays.editOverlay(this.stylus, updatedStylusProperties);
}
return;
}

View file

@ -59,6 +59,7 @@
<option value="Cylinder">Cylinder</option>
<option value="Cone">Cone</option>
<option value="Circle">Circle</option>
<option value="Quad">Quad</option>
</select>
</div>
<div class="property text">
@ -570,14 +571,14 @@
</fieldset>
</fieldset>
<fieldset class="zone-group zone-section haze-section property rgb fstuple">
<div class="color-picker" id="property-zone-haze-blend-in-color"></div>
<div class="color-picker" id="property-zone-haze-color"></div>
<legend>Haze Color</legend>
<div class="tuple">
<div><input type="number" class="red" id="property-zone-haze-blend-in-color-red" min="0" max="255" step="1">
<div><input type="number" class="red" id="property-zone-haze-color-red" min="0" max="255" step="1">
<label for="property-zone-haze-blend-in-color-red">Red:</label></div>
<div><input type="number" class="green" id="property-zone-haze-blend-in-color-green" min="0" max="255" step="1">
<div><input type="number" class="green" id="property-zone-haze-color-green" min="0" max="255" step="1">
<label for="property-zone-haze-blend-in-color-green">Green:</label></div>
<div><input type="number" class="blue" id="property-zone-haze-blend-in-color-blue" min="0" max="255" step="1">
<div><input type="number" class="blue" id="property-zone-haze-color-blue" min="0" max="255" step="1">
<label for="property-zone-haze-blend-in-color-blue">Blue:</label></div>
</div>
</fieldset>
@ -586,14 +587,14 @@
<label for="property-zone-haze-enable-light-blend">Enable Glare</label>
</div>
<fieldset class="zone-group zone-section haze-section property rgb fstuple">
<div class="color-picker" id="property-zone-haze-blend-out-color"></div>
<div class="color-picker" id="property-zone-haze-glare-color"></div>
<legend>Glare Color</legend>
<div class="tuple">
<div><input type="number" class="red" id="property-zone-haze-blend-out-color-red" min="0" max="255" step="1">
<div><input type="number" class="red" id="property-zone-haze-glare-color-red" min="0" max="255" step="1">
<label for="property-zone-haze-blend-out-color-red">Red:</label></div>
<div><input type="number" class="green" id="property-zone-haze-blend-out-color-green" min="0" max="255" step="1">
<div><input type="number" class="green" id="property-zone-haze-glare-color-green" min="0" max="255" step="1">
<label for="property-zone-haze-blend-out-color-green">Green:</label></div>
<div><input type="number" class="blue" id="property-zone-haze-blend-out-color-blue" min="0" max="255" step="1">
<div><input type="number" class="blue" id="property-zone-haze-glare-color-blue" min="0" max="255" step="1">
<label for="property-zone-haze-blend-out-color-blue">Blue:</label></div>
</div>
</fieldset>
@ -602,6 +603,12 @@
<div><label>Glare Angle<span class="unit">deg</span></label><input type="number" id="property-zone-haze-blend-angle" min="0" max="180" step="1"></div>
</div>
</fieldset>
<fieldset class="zone-group zone-section haze-section property gen fstuple">
<div>
<label>Background Blend</label>
<input type="number" id="property-zone-haze-background-blend" min="0.0" max="1.0" step="0.01">
</div>
</fieldset>
<fieldset class="zone-group zone-section haze-section property gen fstuple">
<div class="zone-group zone-section haze-section property checkbox">
<input type="checkbox" id="property-zone-haze-attenuate-keylight">
@ -614,12 +621,6 @@
min="-1000" max="50000" step="10"></div>
</div>
</fieldset>
<fieldset class="zone-group zone-section haze-section property gen fstuple">
<div>
<label>Background Blend</label>
<input type="number" id="property-zone-haze-background-blend" min="0.0" max="1.0" step="0.01">
</div>
</fieldset>
</fieldset>
<fieldset class="minor">
<legend class="sub-section-header zone-group zone-section stage-section">

View file

@ -678,14 +678,14 @@ function loaded() {
var elZoneHazeModeEnabled = document.getElementById("property-zone-haze-mode-enabled");
var elZoneHazeRange = document.getElementById("property-zone-haze-range");
var elZoneHazeColor = document.getElementById("property-zone-haze-blend-in-color");
var elZoneHazeColorRed = document.getElementById("property-zone-haze-blend-in-color-red");
var elZoneHazeColorGreen = document.getElementById("property-zone-haze-blend-in-color-green");
var elZoneHazeColorBlue = document.getElementById("property-zone-haze-blend-in-color-blue");
var elZoneHazeGlareColor = document.getElementById("property-zone-haze-blend-out-color");
var elZoneHazeGlareColorRed = document.getElementById("property-zone-haze-blend-out-color-red");
var elZoneHazeGlareColorGreen = document.getElementById("property-zone-haze-blend-out-color-green");
var elZoneHazeGlareColorBlue = document.getElementById("property-zone-haze-blend-out-color-blue");
var elZoneHazeColor = document.getElementById("property-zone-haze-color");
var elZoneHazeColorRed = document.getElementById("property-zone-haze-color-red");
var elZoneHazeColorGreen = document.getElementById("property-zone-haze-color-green");
var elZoneHazeColorBlue = document.getElementById("property-zone-haze-color-blue");
var elZoneHazeGlareColor = document.getElementById("property-zone-haze-glare-color");
var elZoneHazeGlareColorRed = document.getElementById("property-zone-haze-glare-color-red");
var elZoneHazeGlareColorGreen = document.getElementById("property-zone-haze-glare-color-green");
var elZoneHazeGlareColorBlue = document.getElementById("property-zone-haze-glare-color-blue");
var elZoneHazeEnableGlare = document.getElementById("property-zone-haze-enable-light-blend");
var elZonehazeGlareAngle = document.getElementById("property-zone-haze-blend-angle");
@ -1474,15 +1474,15 @@ function loaded() {
elZoneHazeRange.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeRange'));
colorPickers.push($('#property-zone-haze-blend-in-color').colpick({
colorPickers.push($('#property-zone-haze-color').colpick({
colorScheme: 'dark',
layout: 'hex',
color: '000000',
onShow: function(colpick) {
$('#property-zone-haze-blend-in-color').attr('active', 'true');
$('#property-zone-haze-color').attr('active', 'true');
},
onHide: function(colpick) {
$('#property-zone-haze-blend-in-color').attr('active', 'false');
$('#property-zone-haze-color').attr('active', 'false');
},
onSubmit: function(hsb, hex, rgb, el) {
$(el).css('background-color', '#' + hex);
@ -1499,15 +1499,15 @@ function loaded() {
elZoneHazeColorGreen.addEventListener('change', zoneHazeColorChangeFunction);
elZoneHazeColorBlue.addEventListener('change', zoneHazeColorChangeFunction);
colorPickers.push($('#property-zone-haze-blend-out-color').colpick({
colorPickers.push($('#property-zone-haze-glare-color').colpick({
colorScheme: 'dark',
layout: 'hex',
color: '000000',
onShow: function(colpick) {
$('#property-zone-haze-blend-out-color').attr('active', 'true');
$('#property-zone-haze-glare-color').attr('active', 'true');
},
onHide: function(colpick) {
$('#property-zone-haze-blend-out-color').attr('active', 'false');
$('#property-zone-haze-glare-color').attr('active', 'false');
},
onSubmit: function(hsb, hex, rgb, el) {
$(el).css('background-color', '#' + hex);

View file

@ -124,7 +124,9 @@
print("TABLET in showTabletUI, already rezzed");
}
var tabletProperties = {};
UIWebTablet.calculateTabletAttachmentProperties(activeHand, true, tabletProperties);
if (!HMD.tabletContextualMode) { // contextual mode forces tablet in place -> don't update attachment
UIWebTablet.calculateTabletAttachmentProperties(activeHand, true, tabletProperties);
}
tabletProperties.visible = true;
Overlays.editOverlay(HMD.tabletID, tabletProperties);
Overlays.editOverlay(HMD.homeButtonID, { visible: true });