diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json
index 4636c61367..0082bd84ae 100644
--- a/domain-server/resources/describe-settings.json
+++ b/domain-server/resources/describe-settings.json
@@ -6,7 +6,7 @@
{
"name": "access_token",
"label": "Access Token",
- "help": "This is an access token generated on the My Security page of your High Fidelity account. Generate a token with the 'domains' scope and paste it here. This is required to associate this domain-server with a domain in your account."
+ "help": "This is an access token generated on the My Security page of your High Fidelity account. Generate a token with the 'domains' scope and paste it here. This is required to associate this domain-server with a domain in your account."
},
{
"name": "id",
@@ -30,7 +30,7 @@
},
{
"value": "disabled",
- "label": "None: use the network information I have entered for this domain at metaverse.highfidelity.io"
+ "label": "None: use the network information I have entered for this domain at metaverse.highfidelity.com"
}
]
},
diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js
index f62515c863..4fac753959 100644
--- a/domain-server/resources/web/js/settings.js
+++ b/domain-server/resources/web/js/settings.js
@@ -652,7 +652,7 @@ function chooseFromHighFidelityDomains(clickedButton) {
clickedButton.attr('disabled', 'disabled')
// get a list of user domains from data-web
- data_web_domains_url = "https://metaverse.highfidelity.io/api/v1/domains?access_token="
+ data_web_domains_url = "https://metaverse.highfidelity.com/api/v1/domains?access_token="
$.getJSON(data_web_domains_url + Settings.initialValues.metaverse.access_token, function(data){
modal_buttons = {
@@ -682,7 +682,7 @@ function chooseFromHighFidelityDomains(clickedButton) {
modal_buttons["success"] = {
label: 'Create new domain',
callback: function() {
- window.open("https://metaverse.highfidelity.io/user/domains", '_blank');
+ window.open("https://metaverse.highfidelity.com/user/domains", '_blank');
}
}
modal_body = "
You do not have any domains in your High Fidelity account." +
@@ -708,4 +708,4 @@ function chooseFromHighFidelityDomains(clickedButton) {
title: "Access token required"
})
}
-}
\ No newline at end of file
+}
diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp
index 57e133c599..0918b85a63 100644
--- a/domain-server/src/DomainServer.cpp
+++ b/domain-server/src/DomainServer.cpp
@@ -814,8 +814,9 @@ void DomainServer::requestUserPublicKey(const QString& username) {
qDebug() << "Requesting public key for user" << username;
- AccountManager::getInstance().unauthenticatedRequest(USER_PUBLIC_KEY_PATH.arg(username),
- QNetworkAccessManager::GetOperation, callbackParams);
+ AccountManager::getInstance().sendRequest(USER_PUBLIC_KEY_PATH.arg(username),
+ AccountManagerAuth::None,
+ QNetworkAccessManager::GetOperation, callbackParams);
}
QUrl DomainServer::oauthRedirectURL() {
@@ -1116,8 +1117,10 @@ void DomainServer::sendPendingTransactionsToServer() {
transactionCallbackParams.jsonCallbackMethod = "transactionJSONCallback";
while (i != _pendingAssignmentCredits.end()) {
- accountManager.authenticatedRequest("api/v1/transactions", QNetworkAccessManager::PostOperation,
- transactionCallbackParams, i.value()->postJson().toJson());
+ accountManager.sendRequest("api/v1/transactions",
+ AccountManagerAuth::Required,
+ QNetworkAccessManager::PostOperation,
+ transactionCallbackParams, i.value()->postJson().toJson());
// set this transaction to finalized so we don't add additional credits to it
i.value()->setIsFinalized(true);
@@ -1240,10 +1243,11 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) {
QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson()));
- AccountManager::getInstance().authenticatedRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)),
- QNetworkAccessManager::PutOperation,
- JSONCallbackParameters(),
- domainUpdateJSON.toUtf8());
+ AccountManager::getInstance().sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)),
+ AccountManagerAuth::Required,
+ QNetworkAccessManager::PutOperation,
+ JSONCallbackParameters(),
+ domainUpdateJSON.toUtf8());
}
// todo: have data-web respond with ice-server hostname to use
diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js
index f52d6be87e..05ffb0bd3f 100644
--- a/examples/defaultScripts.js
+++ b/examples/defaultScripts.js
@@ -18,4 +18,3 @@ Script.load("lobby.js");
Script.load("notifications.js");
Script.load("look.js");
Script.load("users.js");
-Script.load("utilities/LODWarning.js");
diff --git a/examples/edit.js b/examples/edit.js
index 72938e5ed4..8088b7cd74 100644
--- a/examples/edit.js
+++ b/examples/edit.js
@@ -76,7 +76,6 @@ var DEFAULT_DIMENSIONS = {
var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS);
-var MENU_INSPECT_TOOL_ENABLED = "Inspect Tool";
var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select";
var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode";
@@ -130,7 +129,7 @@ var importingSVOTextOverlay = Overlays.addOverlay("text", {
visible: false,
});
-var MARKETPLACE_URL = "https://metaverse.highfidelity.io/marketplace";
+var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
var marketplaceWindow = new WebWindow('Marketplace', MARKETPLACE_URL, 900, 700, false);
marketplaceWindow.setVisible(false);
@@ -338,7 +337,11 @@ var toolBar = (function () {
return true;
}
if (browseModelsButton === toolBar.clicked(clickedOverlay)) {
+ if (marketplaceWindow.url != MARKETPLACE_URL) {
+ marketplaceWindow.setURL(MARKETPLACE_URL);
+ }
marketplaceWindow.setVisible(true);
+ marketplaceWindow.raise();
return true;
}
@@ -540,7 +543,7 @@ function mousePressEvent(event) {
mouseHasMovedSincePress = false;
mouseCapturedByTool = false;
- if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) {
+ if (propertyMenu.mousePressEvent(event) || toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) {
mouseCapturedByTool = true;
return;
}
@@ -549,18 +552,6 @@ function mousePressEvent(event) {
// Event handled; do nothing.
return;
}
- } else if (Menu.isOptionChecked(MENU_INSPECT_TOOL_ENABLED)) {
- var result = findClickedEntity(event);
- if (event.isRightButton) {
- if (result !== null) {
- var currentProperties = Entities.getEntityProperties(result.entityID);
- cameraManager.enable();
- cameraManager.focus(currentProperties.position, null, Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
- cameraManager.mousePressEvent(event);
- }
- } else {
- cameraManager.mousePressEvent(event);
- }
}
}
@@ -572,6 +563,8 @@ var IDLE_MOUSE_TIMEOUT = 200;
var DEFAULT_ENTITY_DRAG_DROP_DISTANCE = 2.0;
function mouseMoveEvent(event) {
+ mouseHasMovedSincePress = true;
+
if (placingEntityID) {
if (!placingEntityID.isKnownID) {
placingEntityID = Entities.identifyEntity(placingEntityID);
@@ -592,10 +585,8 @@ function mouseMoveEvent(event) {
Script.clearTimeout(idleMouseTimerId);
}
- mouseHasMovedSincePress = true;
-
// allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing
- if (selectionDisplay.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) {
+ if (selectionDisplay.mouseMoveEvent(event) || propertyMenu.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) {
return;
}
@@ -640,7 +631,7 @@ function highlightEntityUnderCursor(position, accurateRay) {
function mouseReleaseEvent(event) {
- if (toolBar.mouseReleaseEvent(event)) {
+ if (propertyMenu.mouseReleaseEvent(event) || toolBar.mouseReleaseEvent(event)) {
return true;
}
if (placingEntityID) {
@@ -664,74 +655,93 @@ function mouseReleaseEvent(event) {
}
function mouseClickEvent(event) {
- if (!event.isLeftButton || !isActive) {
- return;
- }
-
- var result = findClickedEntity(event);
- if (result === null) {
- if (!event.isShifted) {
- selectionManager.clearSelections();
- }
- return;
- }
- toolBar.setActive(true);
- var pickRay = result.pickRay;
- var foundEntity = result.entityID;
-
- var properties = Entities.getEntityProperties(foundEntity);
- if (isLocked(properties)) {
- print("Model locked " + properties.id);
- } else {
- var halfDiagonal = Vec3.length(properties.dimensions) / 2.0;
-
- print("Checking properties: " + properties.id + " " + properties.isKnownID + " - Half Diagonal:" + halfDiagonal);
- // P P - Model
- // /| A - Palm
- // / | d B - unit vector toward tip
- // / | X - base of the perpendicular line
- // A---X----->B d - distance fom axis
- // x x - distance from A
- //
- // |X-A| = (P-A).B
- // X == A + ((P-A).B)B
- // d = |P-X|
-
- var A = pickRay.origin;
- var B = Vec3.normalize(pickRay.direction);
- var P = properties.position;
-
- var x = Vec3.dot(Vec3.subtract(P, A), B);
- var X = Vec3.sum(A, Vec3.multiply(B, x));
- var d = Vec3.length(Vec3.subtract(P, X));
- var halfDiagonal = Vec3.length(properties.dimensions) / 2.0;
-
- var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14;
-
- var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE)
- && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
-
- if (0 < x && sizeOK) {
- entitySelected = true;
- selectedEntityID = foundEntity;
- orientation = MyAvatar.orientation;
- intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation));
-
-
+ if (isActive && event.isLeftButton) {
+ var result = findClickedEntity(event);
+ if (result === null) {
if (!event.isShifted) {
- selectionManager.setSelections([foundEntity]);
+ selectionManager.clearSelections();
+ }
+ return;
+ }
+ toolBar.setActive(true);
+ var pickRay = result.pickRay;
+ var foundEntity = result.entityID;
+
+ var properties = Entities.getEntityProperties(foundEntity);
+ if (isLocked(properties)) {
+ print("Model locked " + properties.id);
+ } else {
+ var halfDiagonal = Vec3.length(properties.dimensions) / 2.0;
+
+ print("Checking properties: " + properties.id + " " + properties.isKnownID + " - Half Diagonal:" + halfDiagonal);
+ // P P - Model
+ // /| A - Palm
+ // / | d B - unit vector toward tip
+ // / | X - base of the perpendicular line
+ // A---X----->B d - distance fom axis
+ // x x - distance from A
+ //
+ // |X-A| = (P-A).B
+ // X == A + ((P-A).B)B
+ // d = |P-X|
+
+ var A = pickRay.origin;
+ var B = Vec3.normalize(pickRay.direction);
+ var P = properties.position;
+
+ var x = Vec3.dot(Vec3.subtract(P, A), B);
+ var X = Vec3.sum(A, Vec3.multiply(B, x));
+ var d = Vec3.length(Vec3.subtract(P, X));
+ var halfDiagonal = Vec3.length(properties.dimensions) / 2.0;
+
+ var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14;
+
+ var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE)
+ && (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
+
+ if (0 < x && sizeOK) {
+ entitySelected = true;
+ selectedEntityID = foundEntity;
+ orientation = MyAvatar.orientation;
+ intersection = rayPlaneIntersection(pickRay, P, Quat.getFront(orientation));
+
+
+ if (!event.isShifted) {
+ selectionManager.setSelections([foundEntity]);
+ } else {
+ selectionManager.addEntity(foundEntity, true);
+ }
+
+ print("Model selected: " + foundEntity.id);
+ selectionDisplay.select(selectedEntityID, event);
+
+ if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) {
+ cameraManager.focus(selectionManager.worldPosition,
+ selectionManager.worldDimensions,
+ Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
+ }
+ }
+ }
+ } else if (event.isRightButton) {
+ var result = findClickedEntity(event);
+ if (result) {
+ var properties = Entities.getEntityProperties(result.entityID);
+ var data = {};
+ try {
+ data = JSON.parse(properties.attribution);
+ } catch (e) {
+ }
+ if (data.marketplaceID) {
+ propertyMenu.marketplaceID = data.marketplaceID;
+ propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace");
} else {
- selectionManager.addEntity(foundEntity, true);
- }
-
- print("Model selected: " + foundEntity.id);
- selectionDisplay.select(selectedEntityID, event);
-
- if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) {
- cameraManager.focus(selectionManager.worldPosition,
- selectionManager.worldDimensions,
- Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
+ propertyMenu.marketplaceID = null;
+ propertyMenu.updateMenuItemText(showMenuItem, "No marketplace info");
}
+ propertyMenu.setPosition(event.x, event.y);
+ propertyMenu.show();
+ } else {
+ propertyMenu.hide();
}
}
}
@@ -776,7 +786,7 @@ function setupModelMenus() {
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Entities", shortcutKey: "CTRL+META+I", afterItem: "Export Entities" });
Menu.addMenuItem({ menuName: "File", menuItemName: "Import Entities from URL", shortcutKey: "CTRL+META+U", afterItem: "Import Entities" });
- Menu.addMenuItem({ menuName: "View", menuItemName: MENU_AUTO_FOCUS_ON_SELECT, afterItem: MENU_INSPECT_TOOL_ENABLED,
+ Menu.addMenuItem({ menuName: "View", menuItemName: MENU_AUTO_FOCUS_ON_SELECT,
isCheckable: true, isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true" });
Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_AUTO_FOCUS_ON_SELECT,
isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" });
@@ -807,7 +817,6 @@ function cleanupModelMenus() {
Menu.removeMenuItem("File", "Import Entities");
Menu.removeMenuItem("File", "Import Entities from URL");
- Menu.removeMenuItem("View", MENU_INSPECT_TOOL_ENABLED);
Menu.removeMenuItem("View", MENU_AUTO_FOCUS_ON_SELECT);
Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS);
Menu.removeMenuItem("View", MENU_SHOW_LIGHTS_IN_EDIT_MODE);
@@ -829,11 +838,21 @@ Script.scriptEnding.connect(function() {
Overlays.deleteOverlay(importingSVOTextOverlay);
});
+var lastOrientation = null;
+var lastPosition = null;
+
// Do some stuff regularly, like check for placement of various overlays
Script.update.connect(function (deltaTime) {
toolBar.move();
progressDialog.move();
selectionDisplay.checkMove();
+ var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1);
+ var dPosition = Vec3.distance(Camera.position, lastPosition);
+ if (dOrientation > 0.001 || dPosition > 0.001) {
+ propertyMenu.hide();
+ lastOrientation = Camera.orientation;
+ lastPosition = Camera.position;
+ }
});
function insideBox(center, dimensions, point) {
@@ -910,8 +929,8 @@ function handeMenuEvent(menuItem) {
if (!selectionManager.hasSelection()) {
Window.alert("No entities have been selected.");
} else {
- var filename = "models__" + Window.location.hostname + "__.svo";
- filename = Window.save("Select where to save", filename, "*.svo")
+ var filename = "entities__" + Window.location.hostname + ".svo.json";
+ filename = Window.save("Select where to save", filename, "*.json")
if (filename) {
var success = Clipboard.exportEntities(filename, selectionManager.selections);
if (!success) {
@@ -923,7 +942,7 @@ function handeMenuEvent(menuItem) {
var importURL;
if (menuItem == "Import Entities") {
- importURL = Window.browse("Select models to import", "", "*.svo");
+ importURL = Window.browse("Select models to import", "", "*.json");
} else {
importURL = Window.prompt("URL of SVO to import", "");
}
@@ -1143,6 +1162,12 @@ PropertiesTool = function(opts) {
}
pushCommandForSelections();
selectionManager._update();
+ } else if (data.type = "showMarketplace") {
+ if (marketplaceWindow.url != data.url) {
+ marketplaceWindow.setURL(data.url);
+ }
+ marketplaceWindow.setVisible(true);
+ marketplaceWindow.raise();
} else if (data.type == "action") {
if (data.action == "moveSelectionToGrid") {
if (selectionManager.hasSelection()) {
@@ -1216,4 +1241,142 @@ PropertiesTool = function(opts) {
return that;
};
+PopupMenu = function() {
+ var self = this;
+
+ var MENU_ITEM_HEIGHT = 21;
+ var MENU_ITEM_SPACING = 1;
+ var TEXT_MARGIN = 7;
+
+ var overlays = [];
+ var overlayInfo = {};
+
+ var upColor = { red: 0, green: 0, blue: 0 };
+ var downColor = { red: 192, green: 192, blue: 192 };
+ var overColor = { red: 128, green: 128, blue: 128 };
+
+ self.onSelectMenuItem = function() { };
+
+ self.addMenuItem = function(name) {
+ var id = Overlays.addOverlay("text", {
+ text: name,
+ backgroundAlpha: 1.0,
+ backgroundColor: upColor,
+ topMargin: TEXT_MARGIN,
+ leftMargin: TEXT_MARGIN,
+ width: 210,
+ height: MENU_ITEM_HEIGHT,
+ font: { size: 12 },
+ visible: false,
+ });
+ overlays.push(id);
+ overlayInfo[id] = { name: name };
+ return id;
+ };
+
+ self.updateMenuItemText = function(id, newText) {
+ Overlays.editOverlay(id, { text: newText });
+ };
+
+ self.setPosition = function(x, y) {
+ for (var key in overlayInfo) {
+ Overlays.editOverlay(key, {
+ x: x,
+ y: y,
+ });
+ y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING;
+ }
+ };
+
+ self.onSelected = function() { };
+
+ var pressingOverlay = null;
+ var hoveringOverlay = null;
+
+ self.mousePressEvent = function(event) {
+ if (event.isLeftButton) {
+ var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
+ if (overlay in overlayInfo) {
+ pressingOverlay = overlay;
+ Overlays.editOverlay(pressingOverlay, { backgroundColor: downColor });
+ } else {
+ self.hide();
+ }
+ return false;
+ }
+ };
+ self.mouseMoveEvent = function(event) {
+ if (visible) {
+ var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
+ if (!pressingOverlay) {
+ if (hoveringOverlay != null && overlay != hoveringOverlay) {
+ Overlays.editOverlay(hoveringOverlay, { backgroundColor: upColor});
+ hoveringOverlay = null;
+ }
+ if (overlay != hoveringOverlay && overlay in overlayInfo) {
+ Overlays.editOverlay(overlay, { backgroundColor: overColor });
+ hoveringOverlay = overlay;
+ }
+ }
+ }
+ return false;
+ };
+ self.mouseReleaseEvent = function(event) {
+ var overlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
+ if (pressingOverlay != null) {
+ if (overlay == pressingOverlay) {
+ self.onSelectMenuItem(overlayInfo[overlay].name);
+ }
+ Overlays.editOverlay(pressingOverlay, { backgroundColor: upColor });
+ pressingOverlay = null;
+ self.hide();
+ }
+ };
+
+ var visible = false;
+
+ self.setVisible = function(newVisible) {
+ if (newVisible != visible) {
+ visible = newVisible;
+ for (var key in overlayInfo) {
+ Overlays.editOverlay(key, { visible: newVisible });
+ }
+ }
+ }
+ self.show = function() {
+ self.setVisible(true);
+ }
+ self.hide = function() {
+ self.setVisible(false);
+ }
+
+ function cleanup() {
+ for (var i = 0; i < overlays.length; i++) {
+ Overlays.deleteOverlay(overlays[i]);
+ }
+ }
+
+ Controller.mousePressEvent.connect(self.mousePressEvent);
+ Controller.mouseMoveEvent.connect(self.mouseMoveEvent);
+ Controller.mouseReleaseEvent.connect(self.mouseReleaseEvent);
+ Script.scriptEnding.connect(cleanup);
+
+ return this;
+};
+
+var propertyMenu = PopupMenu();
+
+propertyMenu.onSelectMenuItem = function(name) {
+ if (propertyMenu.marketplaceID) {
+ var url = "https://metaverse.highfidelity.io/marketplace/items/" + propertyMenu.marketplaceID;
+ if (marketplaceWindow.url != url) {
+ marketplaceWindow.setURL(url);
+ }
+ marketplaceWindow.setVisible(true);
+ marketplaceWindow.raise();
+ }
+};
+
+var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace");
+
propertiesTool = PropertiesTool();
diff --git a/examples/entityScripts/lightController.js b/examples/entityScripts/lightController.js
index 624fc929b3..e6e4998aef 100644
--- a/examples/entityScripts/lightController.js
+++ b/examples/entityScripts/lightController.js
@@ -1,8 +1,32 @@
(function() {
this.entityID = null;
- this.properties = null;
this.lightID = null;
this.sound = null;
+ this.soundURLs = ["https://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/lamp_switch_1.wav",
+ "https://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/lamp_switch_2.wav",
+ "https://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/lamp_switch_3.wav"]
+
+ var DEFAULT_USER_DATA = {
+ creatingLight: false,
+ lightID: null,
+ lightDefaultProperties: {
+ type: "Light",
+ position: { x: 0, y: 0, z: 0 },
+ dimensions: { x: 5, y: 5, z: 5 },
+ isSpotlight: false,
+ color: { red: 255, green: 48, blue: 0 },
+ diffuseColor: { red: 255, green: 255, blue: 255 },
+ ambientColor: { red: 255, green: 255, blue: 255 },
+ specularColor: { red: 0, green: 0, blue: 0 },
+ constantAttenuation: 1,
+ linearAttenuation: 0,
+ quadraticAttenuation: 0,
+ intensity: 10,
+ exponent: 0,
+ cutoff: 180, // in degrees
+ },
+ soundIndex: Math.floor(Math.random() * this.soundURLs.length)
+ };
function copyObject(object) {
return JSON.parse(JSON.stringify(object));
@@ -33,7 +57,8 @@
// Download sound if needed
this.maybeDownloadSound = function() {
if (this.sound === null) {
- this.sound = SoundCache.getSound("http://public.highfidelity.io/sounds/Footsteps/FootstepW3Left-12db.wav");
+ var soundIndex = getUserData(this.entityID).soundIndex;
+ this.sound = SoundCache.getSound(this.soundURLs[soundIndex]);
}
}
// Play switch sound
@@ -47,17 +72,21 @@
print("Warning: Couldn't play sound.");
}
}
-
- // Toggles the associated light entity
- this.toggleLight = function() {
- if (this.lightID) {
- var lightProperties = Entities.getEntityProperties(this.lightID);
- Entities.editEntity(this.lightID, { visible: !lightProperties.visible });
- } else {
- print("Warning: No light to turn on/off");
+
+ // Checks whether the userData is well-formed and updates it if not
+ this.checkUserData = function() {
+ var userData = getUserData(this.entityID);
+ if (!userData) {
+ userData = DEFAULT_USER_DATA;
+ } else if (!userData.lightDefaultProperties) {
+ userData.lightDefaultProperties = DEFAULT_USER_DATA.lightDefaultProperties;
+ } else if (!userData.soundIndex) {
+ userData.soundIndex = DEFAULT_USER_DATA.soundIndex;
}
+ updateUserData(this.entityID, userData);
}
+ // Create a Light entity
this.createLight = function(userData) {
var lightProperties = copyObject(userData.lightDefaultProperties);
if (lightProperties) {
@@ -74,56 +103,48 @@
}
}
+ // Tries to find a valid light, creates one otherwise
this.updateLightID = function() {
- var userData = getUserData(this.entityID);
- if (!userData) {
- userData = {
- lightID: null,
- lightDefaultProperties: {
- type: "Light",
- position: { x: 0, y: 0, z: 0 },
- dimensions: { x: 5, y: 5, z: 5 },
- isSpotlight: false,
- color: { red: 255, green: 48, blue: 0 },
- diffuseColor: { red: 255, green: 255, blue: 255 },
- ambientColor: { red: 255, green: 255, blue: 255 },
- specularColor: { red: 0, green: 0, blue: 0 },
- constantAttenuation: 1,
- linearAttenuation: 0,
- quadraticAttenuation: 0,
- intensity: 10,
- exponent: 0,
- cutoff: 180, // in degrees
- }
- };
- updateUserData(this.entityID, userData);
- }
-
// Find valid light
if (doesEntityExistNow(this.lightID)) {
- if (!didEntityExist(this.lightID)) {
- // Light now has an ID, so update it in userData
- this.lightID = getTrueID(this.lightID);
- userData.lightID = this.lightID;
- updateUserData(this.entityID, userData);
- }
return;
}
+ var userData = getUserData(this.entityID);
if (doesEntityExistNow(userData.lightID)) {
- this.lightID = getTrueID(userData.lightID);
+ this.lightID = userData.lightID;
return;
}
- // No valid light, create one
- this.lightID = this.createLight(userData);
- print("Created new light entity");
-
- // Update user data with new ID
+ if (!userData.creatingLight) {
+ // No valid light, create one
+ userData.creatingLight = true;
+ updateUserData(this.entityID, userData);
+ this.lightID = this.createLight(userData);
+ this.maybeUpdateLightIDInUserData();
+ print("Created new light entity");
+ }
+ }
+
+ this.maybeUpdateLightIDInUserData = function() {
+ if (getTrueID(this.lightID).isKnownID) {
+ this.lightID = getTrueID(this.lightID);
+ this.updateLightIDInUserData();
+ } else {
+ var that = this;
+ Script.setTimeout(function() { that.maybeUpdateLightIDInUserData() }, 500);
+ }
+ }
+
+ // Update user data with new lightID
+ this.updateLightIDInUserData = function() {
+ var userData = getUserData(this.entityID);
userData.lightID = this.lightID;
+ userData.creatingLight = false;
updateUserData(this.entityID, userData);
}
+ // Moves light entity if the lamp entity moved
this.maybeMoveLight = function() {
var entityProperties = Entities.getEntityProperties(this.entityID);
var lightProperties = Entities.getEntityProperties(this.lightID);
@@ -139,8 +160,9 @@
}
}
+ // Stores light entity relative position in the lamp metadata
this.updateRelativeLightPosition = function() {
- if (!doesEntityExistNow(this.entityID) || !doesEntityExistNow(this.lightID)) {
+ if (!doesEntityExistNow(this.lightID)) {
print("Warning: ID invalid, couldn't save relative position.");
return;
}
@@ -168,21 +190,37 @@
updateUserData(this.entityID, userData);
print("Relative properties of light entity saved.");
}
+
+ // This function should be called before any callback is executed
+ this.preOperation = function(entityID) {
+ this.entityID = entityID;
+
+ this.checkUserData();
+ this.maybeDownloadSound();
+ }
+
+ // Toggles the associated light entity
+ this.toggleLight = function() {
+ if (this.lightID) {
+ var lightProperties = Entities.getEntityProperties(this.lightID);
+ Entities.editEntity(this.lightID, { visible: !lightProperties.visible });
+ this.playSound();
+ } else {
+ print("Warning: No light to turn on/off");
+ }
+ }
this.preload = function(entityID) {
- this.entityID = entityID;
- this.maybeDownloadSound();
+ this.preOperation(entityID);
};
this.clickReleaseOnEntity = function(entityID, mouseEvent) {
- this.entityID = entityID;
- this.maybeDownloadSound();
+ this.preOperation(entityID);
if (mouseEvent.isLeftButton) {
this.updateLightID();
this.maybeMoveLight();
this.toggleLight();
- this.playSound();
} else if (mouseEvent.isRightButton) {
this.updateRelativeLightPosition();
}
diff --git a/examples/example/entities/makeHouses.js b/examples/example/entities/makeHouses.js
new file mode 100644
index 0000000000..37bc1d5a8e
--- /dev/null
+++ b/examples/example/entities/makeHouses.js
@@ -0,0 +1,157 @@
+//
+// makeHouses.js
+//
+//
+// Created by Stojce Slavkovski on March 14, 2015
+// Copyright 2015 High Fidelity, Inc.
+//
+// This sample script that creates house entities based on parameters.
+//
+// Distributed under the Apache License, Version 2.0.
+// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
+//
+
+(function () {
+
+ /** options **/
+ var numHouses = 100;
+ var xRange = 300;
+ var yRange = 300;
+
+ var sizeOfTheHouse = {
+ x: 10,
+ y: 15,
+ z: 10
+ };
+
+ var randomizeModels = false;
+ /**/
+
+ var modelUrlPrefix = "http://public.highfidelity.io/load_testing/3-Buildings-2-SanFranciscoHouse-";
+ var modelurlExt = ".fbx";
+ var modelVariations = 100;
+
+ var houses = [];
+
+ function addHouseAt(position, rotation) {
+ // get house model
+ var modelNumber = randomizeModels ?
+ 1 + Math.floor(Math.random() * (modelVariations - 1)) :
+ (houses.length + 1) % modelVariations;
+
+ if (modelNumber == 0) {
+ modelNumber = modelVariations;
+ }
+
+ var modelUrl = modelUrlPrefix + (modelNumber + "") + modelurlExt;
+ print("Model ID:" + modelNumber);
+ print("Model URL:" + modelUrl);
+
+ var properties = {
+ type: "Model",
+ position: position,
+ rotation: rotation,
+ dimensions: sizeOfTheHouse,
+ modelURL: modelUrl
+ };
+
+ return Entities.addEntity(properties);
+ }
+
+ // calculate initial position
+ var posX = MyAvatar.position.x - (xRange / 2);
+ var measures = calculateParcels(numHouses, xRange, yRange);
+ var dd = 0;
+
+ // avatar facing rotation
+ var rotEven = Quat.fromPitchYawRollDegrees(0, 270.0 + MyAvatar.bodyYaw, 0.0);
+
+ // avatar opposite rotation
+ var rotOdd = Quat.fromPitchYawRollDegrees(0, 90.0 + MyAvatar.bodyYaw, 0.0);
+ var housePos = Vec3.sum(MyAvatar.position, Quat.getFront(Camera.getOrientation()));
+
+ for (var j = 0; j < measures.rows; j++) {
+
+ var posX1 = 0 - (xRange / 2);
+ dd += measures.parcelLength;
+
+ for (var i = 0; i < measures.cols; i++) {
+
+ // skip reminder of houses
+ if (houses.length > numHouses) {
+ break;
+ }
+
+ var posShift = {
+ x: posX1,
+ y: 0,
+ z: dd
+ };
+
+ print("House nr.:" + (houses.length + 1));
+ houses.push(
+ addHouseAt(Vec3.sum(housePos, posShift), (j % 2 == 0) ? rotEven : rotOdd)
+ );
+ posX1 += measures.parcelWidth;
+ }
+ }
+
+ // calculate rows and columns in area, and dimension of single parcel
+ function calculateParcels(items, areaWidth, areaLength) {
+
+ var idealSize = Math.min(Math.sqrt(areaWidth * areaLength / items), areaWidth, areaLength);
+
+ var baseWidth = Math.min(Math.floor(areaWidth / idealSize), items);
+ var baseLength = Math.min(Math.floor(areaLength / idealSize), items);
+
+ var sirRows = baseWidth;
+ var sirCols = Math.ceil(items / sirRows);
+ var sirW = areaWidth / sirRows;
+ var sirL = areaLength / sirCols;
+
+ var visCols = baseLength;
+ var visRows = Math.ceil(items / visCols);
+ var visW = areaWidth / visRows;
+ var visL = areaLength / visCols;
+
+ var rows = 0;
+ var cols = 0;
+ var parcelWidth = 0;
+ var parcelLength = 0;
+
+ if (Math.min(sirW, sirL) > Math.min(visW, visL)) {
+ rows = sirRows;
+ cols = sirCols;
+ parcelWidth = sirW;
+ parcelLength = sirL;
+ } else {
+ rows = visRows;
+ cols = visCols;
+ parcelWidth = visW;
+ parcelLength = visL;
+ }
+
+ print("rows:" + rows);
+ print("cols:" + cols);
+ print("parcelWidth:" + parcelWidth);
+ print("parcelLength:" + parcelLength);
+
+ return {
+ rows: rows,
+ cols: cols,
+ parcelWidth: parcelWidth,
+ parcelLength: parcelLength
+ };
+ }
+
+ function cleanup() {
+ while (houses.length > 0) {
+ if (!houses[0].isKnownID) {
+ houses[0] = Entities.identifyEntity(houses[0]);
+ }
+ Entities.deleteEntity(houses.shift());
+ }
+ }
+
+ Script.scriptEnding.connect(cleanup);
+})();
diff --git a/examples/hmdDefaults.js b/examples/hmdDefaults.js
index 1e96d41713..0096b11777 100644
--- a/examples/hmdDefaults.js
+++ b/examples/hmdDefaults.js
@@ -13,5 +13,4 @@ Script.load("progress.js");
Script.load("lobby.js");
Script.load("notifications.js");
Script.load("controllers/oculus/goTo.js");
-Script.load("utilities/LODWarning.js");
//Script.load("scripts.js"); // Not created yet
diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js
index c261e0d8a6..b6c536f063 100644
--- a/examples/libraries/entitySelectionTool.js
+++ b/examples/libraries/entitySelectionTool.js
@@ -1263,11 +1263,13 @@ SelectionDisplay = (function () {
duplicatedEntityIDs = [];
for (var otherEntityID in SelectionManager.savedProperties) {
var properties = SelectionManager.savedProperties[otherEntityID];
- var entityID = Entities.addEntity(properties);
- duplicatedEntityIDs.push({
- entityID: entityID,
- properties: properties,
- });
+ if (!properties.locked) {
+ var entityID = Entities.addEntity(properties);
+ duplicatedEntityIDs.push({
+ entityID: entityID,
+ properties: properties,
+ });
+ }
}
} else {
duplicatedEntityIDs = null;
@@ -1361,11 +1363,13 @@ SelectionDisplay = (function () {
duplicatedEntityIDs = [];
for (var otherEntityID in SelectionManager.savedProperties) {
var properties = SelectionManager.savedProperties[otherEntityID];
- var entityID = Entities.addEntity(properties);
- duplicatedEntityIDs.push({
- entityID: entityID,
- properties: properties,
- });
+ if (!properties.locked) {
+ var entityID = Entities.addEntity(properties);
+ duplicatedEntityIDs.push({
+ entityID: entityID,
+ properties: properties,
+ });
+ }
}
} else {
duplicatedEntityIDs = null;
diff --git a/examples/libraries/modelUploader.js b/examples/libraries/modelUploader.js
index fcc96854ab..64a9e91203 100644
--- a/examples/libraries/modelUploader.js
+++ b/examples/libraries/modelUploader.js
@@ -21,8 +21,8 @@ modelUploader = (function () {
//svoBuffer,
mapping,
geometry,
- API_URL = "https://metaverse.highfidelity.io/api/v1/models",
- MODEL_URL = "http://public.highfidelity.io/models/content",
+ API_URL = "https://metaverse.highfidelity.com/api/v1/models",
+ MODEL_URL = "http://public.highfidelity.com/models/content",
NAME_FIELD = "name",
SCALE_FIELD = "scale",
FILENAME_FIELD = "filename",
@@ -690,4 +690,4 @@ modelUploader = (function () {
};
return that;
-}());
\ No newline at end of file
+}());
diff --git a/examples/lobby.js b/examples/lobby.js
index 5d687dc07a..381107d65a 100644
--- a/examples/lobby.js
+++ b/examples/lobby.js
@@ -158,7 +158,7 @@ var places = {};
function changeLobbyTextures() {
var req = new XMLHttpRequest();
- req.open("GET", "https://metaverse.highfidelity.io/api/v1/places?limit=21", false);
+ req.open("GET", "https://metaverse.highfidelity.com/api/v1/places?limit=21", false);
req.send();
places = JSON.parse(req.responseText).data.places;
diff --git a/examples/look.js b/examples/look.js
index bcdfcf9e44..6bba57e3ad 100644
--- a/examples/look.js
+++ b/examples/look.js
@@ -80,7 +80,6 @@ function touchBeginEvent(event) {
yawFromTouch = 0;
pitchFromTouch = 0;
startedTouching = true;
- print("TOUCH BEGIN");
}
function touchEndEvent(event) {
@@ -88,7 +87,6 @@ function touchEndEvent(event) {
print("touchEndEvent event.x,y=" + event.x + ", " + event.y);
}
startedTouching = false;
- print("TOUCH END");
}
function touchUpdateEvent(event) {
diff --git a/examples/notifications.js b/examples/notifications.js
index 0c2a06c878..7e56c1b50d 100644
--- a/examples/notifications.js
+++ b/examples/notifications.js
@@ -43,7 +43,6 @@
// after that we will send it to createNotification(text).
// If the message is 42 chars or less you should bypass wordWrap() and call createNotification() directly.
-
// To add a keypress driven notification:
//
// 1. Add a key to the keyPressEvent(key).
@@ -85,16 +84,19 @@ var PLAY_NOTIFICATION_SOUNDS_MENU_ITEM = "Play Notification Sounds";
var NOTIFICATION_MENU_ITEM_POST = " Notifications";
var PLAY_NOTIFICATION_SOUNDS_SETTING = "play_notification_sounds";
var PLAY_NOTIFICATION_SOUNDS_TYPE_SETTING_PRE = "play_notification_sounds_type_";
+var lodTextID = false;
var NotificationType = {
UNKNOWN: 0,
MUTE_TOGGLE: 1,
SNAPSHOT: 2,
WINDOW_RESIZE: 3,
+ LOD_WARNING: 4,
properties: [
{ text: "Mute Toggle" },
{ text: "Snapshot" },
- { text: "Window Resize" }
+ { text: "Window Resize" },
+ { text: "Level of Detail" }
],
getTypeFromMenuItem: function(menuItemName) {
if (menuItemName.substr(menuItemName.length - NOTIFICATION_MENU_ITEM_POST.length) !== NOTIFICATION_MENU_ITEM_POST) {
@@ -143,6 +145,10 @@ function createArrays(notice, button, createTime, height, myAlpha) {
// This handles the final dismissal of a notification after fading
function dismiss(firstNoteOut, firstButOut, firstOut) {
+ if (firstNoteOut == lodTextID) {
+ lodTextID = false;
+ }
+
Overlays.deleteOverlay(firstNoteOut);
Overlays.deleteOverlay(firstButOut);
notifications.splice(firstOut, 1);
@@ -261,7 +267,8 @@ function notify(notice, button, height) {
height: noticeHeight
});
} else {
- notifications.push((Overlays.addOverlay("text", notice)));
+ var notificationText = Overlays.addOverlay("text", notice);
+ notifications.push((notificationText));
buttons.push((Overlays.addOverlay("image", button)));
}
@@ -272,6 +279,7 @@ function notify(notice, button, height) {
last = notifications.length - 1;
createArrays(notifications[last], buttons[last], times[last], heights[last], myAlpha[last]);
fadeIn(notifications[last], buttons[last]);
+ return notificationText;
}
// This function creates and sizes the overlays
@@ -331,11 +339,15 @@ function createNotification(text, notificationType) {
randomSounds.playRandom();
}
- notify(noticeProperties, buttonProperties, height);
+ return notify(noticeProperties, buttonProperties, height);
}
function deleteNotification(index) {
- Overlays.deleteOverlay(notifications[index]);
+ var notificationTextID = notifications[index];
+ if (notificationTextID == lodTextID) {
+ lodTextID = false;
+ }
+ Overlays.deleteOverlay(notificationTextID);
Overlays.deleteOverlay(buttons[index]);
notifications.splice(index, 1);
buttons.splice(index, 1);
@@ -575,6 +587,20 @@ function menuItemEvent(menuItem) {
}
}
+LODManager.LODDecreased.connect(function() {
+ var warningText = "\n"
+ + "Due to the complexity of the content, the \n"
+ + "level of detail has been decreased."
+ + "You can now see: \n"
+ + LODManager.getLODFeedbackText();
+
+ if (lodTextID == false) {
+ lodTextID = createNotification(warningText, NotificationType.LOD_WARNING);
+ } else {
+ Overlays.editOverlay(lodTextID, { text: warningText });
+ }
+});
+
AudioDevice.muteToggled.connect(onMuteStateChanged);
Controller.keyPressEvent.connect(keyPressEvent);
Controller.mousePressEvent.connect(mousePressEvent);
diff --git a/examples/users.js b/examples/users.js
index dec141127e..22fe89389f 100644
--- a/examples/users.js
+++ b/examples/users.js
@@ -34,7 +34,7 @@ var usersWindow = (function () {
usersOnline, // Raw users data
linesOfUsers = [], // Array of indexes pointing into usersOnline
- API_URL = "https://metaverse.highfidelity.io/api/v1/users?status=online",
+ API_URL = "https://metaverse.highfidelity.com/api/v1/users?status=online",
HTTP_GET_TIMEOUT = 60000, // ms = 1 minute
usersRequest,
processUsers,
diff --git a/examples/utilities/LODWarning.js b/examples/utilities/LODWarning.js
deleted file mode 100644
index 644d98ebf4..0000000000
--- a/examples/utilities/LODWarning.js
+++ /dev/null
@@ -1,115 +0,0 @@
-// LODWarning.js
-// examples
-//
-// Created by Brad Hefta-Gaub on 3/17/15.
-// Copyright 2015 High Fidelity, Inc.
-//
-// This script will display a warning when the LOD is adjusted to do scene complexity.
-//
-// Distributed under the Apache License, Version 2.0.
-// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-//
-
-var DISPLAY_WARNING_FOR = 3; // in seconds
-var DISTANCE_FROM_CAMERA = 2;
-var SHOW_LOD_UP_MESSAGE = false; // By default we only display the LOD message when reducing LOD
-
-
-var warningIsVisible = false; // initially the warning is hidden
-var warningShownAt = 0;
-var billboardPosition = Vec3.sum(Camera.getPosition(),
- Vec3.multiply(DISTANCE_FROM_CAMERA, Quat.getFront(Camera.getOrientation())));
-
-var warningOverlay = Overlays.addOverlay("text3d", {
- position: billboardPosition,
- dimensions: { x: 2, y: 1.25 },
- width: 2,
- height: 1.25,
- backgroundColor: { red: 0, green: 0, blue: 0 },
- color: { red: 255, green: 255, blue: 255},
- topMargin: 0.1,
- leftMargin: 0.1,
- lineHeight: 0.07,
- text: "",
- alpha: 0.5,
- backgroundAlpha: 0.7,
- isFacingAvatar: true,
- visible: warningIsVisible,
- });
-
-// Handle moving the billboard to remain in front of the camera
-var billboardNeedsMoving = false;
-Script.update.connect(function() {
-
- if (warningIsVisible) {
- var bestBillboardPosition = Vec3.sum(Camera.getPosition(),
- Vec3.multiply(DISTANCE_FROM_CAMERA, Quat.getFront(Camera.getOrientation())));
-
- var MAX_DISTANCE = 0.5;
- var CLOSE_ENOUGH = 0.01;
- if (!billboardNeedsMoving && Vec3.distance(bestBillboardPosition, billboardPosition) > MAX_DISTANCE) {
- billboardNeedsMoving = true;
- }
-
- if (billboardNeedsMoving && Vec3.distance(bestBillboardPosition, billboardPosition) <= CLOSE_ENOUGH) {
- billboardNeedsMoving = false;
- }
-
- if (billboardNeedsMoving) {
- // slurp the billboard to the best location
- moveVector = Vec3.multiply(0.05, Vec3.subtract(bestBillboardPosition, billboardPosition));
- billboardPosition = Vec3.sum(billboardPosition, moveVector);
- Overlays.editOverlay(warningOverlay, { position: billboardPosition });
- }
-
- var now = new Date();
- var sinceWarningShown = now - warningShownAt;
- if (sinceWarningShown > 1000 * DISPLAY_WARNING_FOR) {
- warningIsVisible = false;
- Overlays.editOverlay(warningOverlay, { visible: warningIsVisible });
- }
- }
-});
-
-LODManager.LODIncreased.connect(function() {
- if (SHOW_LOD_UP_MESSAGE) {
- // if the warning wasn't visible, then move it before showing it.
- if (!warningIsVisible) {
- billboardPosition = Vec3.sum(Camera.getPosition(),
- Vec3.multiply(DISTANCE_FROM_CAMERA, Quat.getFront(Camera.getOrientation())));
- Overlays.editOverlay(warningOverlay, { position: billboardPosition });
- }
-
- warningShownAt = new Date();
- warningIsVisible = true;
- warningText = "Level of detail has been increased. \n"
- + "You can now see: \n"
- + LODManager.getLODFeedbackText();
-
- Overlays.editOverlay(warningOverlay, { visible: warningIsVisible, text: warningText });
- }
-});
-
-LODManager.LODDecreased.connect(function() {
- // if the warning wasn't visible, then move it before showing it.
- if (!warningIsVisible) {
- billboardPosition = Vec3.sum(Camera.getPosition(),
- Vec3.multiply(DISTANCE_FROM_CAMERA, Quat.getFront(Camera.getOrientation())));
- Overlays.editOverlay(warningOverlay, { position: billboardPosition });
- }
-
- warningShownAt = new Date();
- warningIsVisible = true;
- warningText = "\n"
- + "Due to the complexity of the content, the \n"
- + "level of detail has been decreased. \n"
- + "You can now see: \n"
- + LODManager.getLODFeedbackText();
-
- Overlays.editOverlay(warningOverlay, { visible: warningIsVisible, text: warningText });
-});
-
-
-Script.scriptEnding.connect(function() {
- Overlays.deleteOverlay(warningOverlay);
-});
\ No newline at end of file
diff --git a/interface/resources/html/edit-commands.html b/interface/resources/html/edit-commands.html
new file mode 100644
index 0000000000..65b985fb6a
--- /dev/null
+++ b/interface/resources/html/edit-commands.html
@@ -0,0 +1,2058 @@
+
+