Merge branch 'master' of https://github.com/highfidelity/hifi into LODUITweaks

This commit is contained in:
ZappoMan 2015-03-25 16:54:37 -07:00
commit 9e34dda7c9
24 changed files with 911 additions and 730 deletions

View file

@ -814,8 +814,9 @@ void DomainServer::requestUserPublicKey(const QString& username) {
qDebug() << "Requesting public key for user" << username; qDebug() << "Requesting public key for user" << username;
AccountManager::getInstance().unauthenticatedRequest(USER_PUBLIC_KEY_PATH.arg(username), AccountManager::getInstance().sendRequest(USER_PUBLIC_KEY_PATH.arg(username),
QNetworkAccessManager::GetOperation, callbackParams); AccountManagerAuth::None,
QNetworkAccessManager::GetOperation, callbackParams);
} }
QUrl DomainServer::oauthRedirectURL() { QUrl DomainServer::oauthRedirectURL() {
@ -1116,8 +1117,10 @@ void DomainServer::sendPendingTransactionsToServer() {
transactionCallbackParams.jsonCallbackMethod = "transactionJSONCallback"; transactionCallbackParams.jsonCallbackMethod = "transactionJSONCallback";
while (i != _pendingAssignmentCredits.end()) { while (i != _pendingAssignmentCredits.end()) {
accountManager.authenticatedRequest("api/v1/transactions", QNetworkAccessManager::PostOperation, accountManager.sendRequest("api/v1/transactions",
transactionCallbackParams, i.value()->postJson().toJson()); AccountManagerAuth::Required,
QNetworkAccessManager::PostOperation,
transactionCallbackParams, i.value()->postJson().toJson());
// set this transaction to finalized so we don't add additional credits to it // set this transaction to finalized so we don't add additional credits to it
i.value()->setIsFinalized(true); i.value()->setIsFinalized(true);
@ -1240,10 +1243,11 @@ void DomainServer::sendHeartbeatToDataServer(const QString& networkAddress) {
QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson())); QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson()));
AccountManager::getInstance().authenticatedRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), AccountManager::getInstance().sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)),
QNetworkAccessManager::PutOperation, AccountManagerAuth::Required,
JSONCallbackParameters(), QNetworkAccessManager::PutOperation,
domainUpdateJSON.toUtf8()); JSONCallbackParameters(),
domainUpdateJSON.toUtf8());
} }
// todo: have data-web respond with ice-server hostname to use // todo: have data-web respond with ice-server hostname to use

View file

@ -76,7 +76,6 @@ var DEFAULT_DIMENSIONS = {
var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, 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_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select";
var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus";
var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode"; var MENU_SHOW_LIGHTS_IN_EDIT_MODE = "Show Lights in Edit Mode";
@ -338,7 +337,11 @@ var toolBar = (function () {
return true; return true;
} }
if (browseModelsButton === toolBar.clicked(clickedOverlay)) { if (browseModelsButton === toolBar.clicked(clickedOverlay)) {
if (marketplaceWindow.url != MARKETPLACE_URL) {
marketplaceWindow.setURL(MARKETPLACE_URL);
}
marketplaceWindow.setVisible(true); marketplaceWindow.setVisible(true);
marketplaceWindow.raise();
return true; return true;
} }
@ -540,7 +543,7 @@ function mousePressEvent(event) {
mouseHasMovedSincePress = false; mouseHasMovedSincePress = false;
mouseCapturedByTool = false; mouseCapturedByTool = false;
if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { if (propertyMenu.mousePressEvent(event) || toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)) {
mouseCapturedByTool = true; mouseCapturedByTool = true;
return; return;
} }
@ -549,18 +552,6 @@ function mousePressEvent(event) {
// Event handled; do nothing. // Event handled; do nothing.
return; 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; var DEFAULT_ENTITY_DRAG_DROP_DISTANCE = 2.0;
function mouseMoveEvent(event) { function mouseMoveEvent(event) {
mouseHasMovedSincePress = true;
if (placingEntityID) { if (placingEntityID) {
if (!placingEntityID.isKnownID) { if (!placingEntityID.isKnownID) {
placingEntityID = Entities.identifyEntity(placingEntityID); placingEntityID = Entities.identifyEntity(placingEntityID);
@ -592,10 +585,8 @@ function mouseMoveEvent(event) {
Script.clearTimeout(idleMouseTimerId); 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 // 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; return;
} }
@ -640,7 +631,7 @@ function highlightEntityUnderCursor(position, accurateRay) {
function mouseReleaseEvent(event) { function mouseReleaseEvent(event) {
if (toolBar.mouseReleaseEvent(event)) { if (propertyMenu.mouseReleaseEvent(event) || toolBar.mouseReleaseEvent(event)) {
return true; return true;
} }
if (placingEntityID) { if (placingEntityID) {
@ -664,74 +655,93 @@ function mouseReleaseEvent(event) {
} }
function mouseClickEvent(event) { function mouseClickEvent(event) {
if (!event.isLeftButton || !isActive) { if (isActive && event.isLeftButton) {
return; var result = findClickedEntity(event);
} if (result === null) {
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 (!event.isShifted) { 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 { } else {
selectionManager.addEntity(foundEntity, true); propertyMenu.marketplaceID = null;
} propertyMenu.updateMenuItemText(showMenuItem, "No marketplace info");
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.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", 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: "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" }); 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, 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" }); 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");
Menu.removeMenuItem("File", "Import Entities from URL"); 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_AUTO_FOCUS_ON_SELECT);
Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS); Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS);
Menu.removeMenuItem("View", MENU_SHOW_LIGHTS_IN_EDIT_MODE); Menu.removeMenuItem("View", MENU_SHOW_LIGHTS_IN_EDIT_MODE);
@ -829,11 +838,21 @@ Script.scriptEnding.connect(function() {
Overlays.deleteOverlay(importingSVOTextOverlay); Overlays.deleteOverlay(importingSVOTextOverlay);
}); });
var lastOrientation = null;
var lastPosition = null;
// Do some stuff regularly, like check for placement of various overlays // Do some stuff regularly, like check for placement of various overlays
Script.update.connect(function (deltaTime) { Script.update.connect(function (deltaTime) {
toolBar.move(); toolBar.move();
progressDialog.move(); progressDialog.move();
selectionDisplay.checkMove(); 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) { function insideBox(center, dimensions, point) {
@ -910,8 +929,8 @@ function handeMenuEvent(menuItem) {
if (!selectionManager.hasSelection()) { if (!selectionManager.hasSelection()) {
Window.alert("No entities have been selected."); Window.alert("No entities have been selected.");
} else { } else {
var filename = "models__" + Window.location.hostname + "__.svo"; var filename = "entities__" + Window.location.hostname + ".svo.json";
filename = Window.save("Select where to save", filename, "*.svo") filename = Window.save("Select where to save", filename, "*.json")
if (filename) { if (filename) {
var success = Clipboard.exportEntities(filename, selectionManager.selections); var success = Clipboard.exportEntities(filename, selectionManager.selections);
if (!success) { if (!success) {
@ -923,7 +942,7 @@ function handeMenuEvent(menuItem) {
var importURL; var importURL;
if (menuItem == "Import Entities") { if (menuItem == "Import Entities") {
importURL = Window.browse("Select models to import", "", "*.svo"); importURL = Window.browse("Select models to import", "", "*.json");
} else { } else {
importURL = Window.prompt("URL of SVO to import", ""); importURL = Window.prompt("URL of SVO to import", "");
} }
@ -1143,6 +1162,12 @@ PropertiesTool = function(opts) {
} }
pushCommandForSelections(); pushCommandForSelections();
selectionManager._update(); 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") { } else if (data.type == "action") {
if (data.action == "moveSelectionToGrid") { if (data.action == "moveSelectionToGrid") {
if (selectionManager.hasSelection()) { if (selectionManager.hasSelection()) {
@ -1216,4 +1241,142 @@ PropertiesTool = function(opts) {
return that; 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(); propertiesTool = PropertiesTool();

View file

@ -1,8 +1,32 @@
(function() { (function() {
this.entityID = null; this.entityID = null;
this.properties = null;
this.lightID = null; this.lightID = null;
this.sound = 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) { function copyObject(object) {
return JSON.parse(JSON.stringify(object)); return JSON.parse(JSON.stringify(object));
@ -33,7 +57,8 @@
// Download sound if needed // Download sound if needed
this.maybeDownloadSound = function() { this.maybeDownloadSound = function() {
if (this.sound === null) { 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 // Play switch sound
@ -47,17 +72,21 @@
print("Warning: Couldn't play sound."); print("Warning: Couldn't play sound.");
} }
} }
// Toggles the associated light entity // Checks whether the userData is well-formed and updates it if not
this.toggleLight = function() { this.checkUserData = function() {
if (this.lightID) { var userData = getUserData(this.entityID);
var lightProperties = Entities.getEntityProperties(this.lightID); if (!userData) {
Entities.editEntity(this.lightID, { visible: !lightProperties.visible }); userData = DEFAULT_USER_DATA;
} else { } else if (!userData.lightDefaultProperties) {
print("Warning: No light to turn on/off"); 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) { this.createLight = function(userData) {
var lightProperties = copyObject(userData.lightDefaultProperties); var lightProperties = copyObject(userData.lightDefaultProperties);
if (lightProperties) { if (lightProperties) {
@ -74,56 +103,48 @@
} }
} }
// Tries to find a valid light, creates one otherwise
this.updateLightID = function() { 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 // Find valid light
if (doesEntityExistNow(this.lightID)) { 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; return;
} }
var userData = getUserData(this.entityID);
if (doesEntityExistNow(userData.lightID)) { if (doesEntityExistNow(userData.lightID)) {
this.lightID = getTrueID(userData.lightID); this.lightID = userData.lightID;
return; return;
} }
// No valid light, create one if (!userData.creatingLight) {
this.lightID = this.createLight(userData); // No valid light, create one
print("Created new light entity"); userData.creatingLight = true;
updateUserData(this.entityID, userData);
// Update user data with new ID 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.lightID = this.lightID;
userData.creatingLight = false;
updateUserData(this.entityID, userData); updateUserData(this.entityID, userData);
} }
// Moves light entity if the lamp entity moved
this.maybeMoveLight = function() { this.maybeMoveLight = function() {
var entityProperties = Entities.getEntityProperties(this.entityID); var entityProperties = Entities.getEntityProperties(this.entityID);
var lightProperties = Entities.getEntityProperties(this.lightID); var lightProperties = Entities.getEntityProperties(this.lightID);
@ -139,8 +160,9 @@
} }
} }
// Stores light entity relative position in the lamp metadata
this.updateRelativeLightPosition = function() { this.updateRelativeLightPosition = function() {
if (!doesEntityExistNow(this.entityID) || !doesEntityExistNow(this.lightID)) { if (!doesEntityExistNow(this.lightID)) {
print("Warning: ID invalid, couldn't save relative position."); print("Warning: ID invalid, couldn't save relative position.");
return; return;
} }
@ -168,21 +190,37 @@
updateUserData(this.entityID, userData); updateUserData(this.entityID, userData);
print("Relative properties of light entity saved."); 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.preload = function(entityID) {
this.entityID = entityID; this.preOperation(entityID);
this.maybeDownloadSound();
}; };
this.clickReleaseOnEntity = function(entityID, mouseEvent) { this.clickReleaseOnEntity = function(entityID, mouseEvent) {
this.entityID = entityID; this.preOperation(entityID);
this.maybeDownloadSound();
if (mouseEvent.isLeftButton) { if (mouseEvent.isLeftButton) {
this.updateLightID(); this.updateLightID();
this.maybeMoveLight(); this.maybeMoveLight();
this.toggleLight(); this.toggleLight();
this.playSound();
} else if (mouseEvent.isRightButton) { } else if (mouseEvent.isRightButton) {
this.updateRelativeLightPosition(); this.updateRelativeLightPosition();
} }

View file

@ -1263,11 +1263,13 @@ SelectionDisplay = (function () {
duplicatedEntityIDs = []; duplicatedEntityIDs = [];
for (var otherEntityID in SelectionManager.savedProperties) { for (var otherEntityID in SelectionManager.savedProperties) {
var properties = SelectionManager.savedProperties[otherEntityID]; var properties = SelectionManager.savedProperties[otherEntityID];
var entityID = Entities.addEntity(properties); if (!properties.locked) {
duplicatedEntityIDs.push({ var entityID = Entities.addEntity(properties);
entityID: entityID, duplicatedEntityIDs.push({
properties: properties, entityID: entityID,
}); properties: properties,
});
}
} }
} else { } else {
duplicatedEntityIDs = null; duplicatedEntityIDs = null;
@ -1361,11 +1363,13 @@ SelectionDisplay = (function () {
duplicatedEntityIDs = []; duplicatedEntityIDs = [];
for (var otherEntityID in SelectionManager.savedProperties) { for (var otherEntityID in SelectionManager.savedProperties) {
var properties = SelectionManager.savedProperties[otherEntityID]; var properties = SelectionManager.savedProperties[otherEntityID];
var entityID = Entities.addEntity(properties); if (!properties.locked) {
duplicatedEntityIDs.push({ var entityID = Entities.addEntity(properties);
entityID: entityID, duplicatedEntityIDs.push({
properties: properties, entityID: entityID,
}); properties: properties,
});
}
} }
} else { } else {
duplicatedEntityIDs = null; duplicatedEntityIDs = null;

View file

@ -80,7 +80,6 @@ function touchBeginEvent(event) {
yawFromTouch = 0; yawFromTouch = 0;
pitchFromTouch = 0; pitchFromTouch = 0;
startedTouching = true; startedTouching = true;
print("TOUCH BEGIN");
} }
function touchEndEvent(event) { function touchEndEvent(event) {
@ -88,7 +87,6 @@ function touchEndEvent(event) {
print("touchEndEvent event.x,y=" + event.x + ", " + event.y); print("touchEndEvent event.x,y=" + event.x + ", " + event.y);
} }
startedTouching = false; startedTouching = false;
print("TOUCH END");
} }
function touchUpdateEvent(event) { function touchUpdateEvent(event) {

View file

@ -1755,7 +1755,7 @@ bool Application::exportEntities(const QString& filename, const QVector<EntityIt
exportTree.addEntity(entityItem->getEntityItemID(), properties); exportTree.addEntity(entityItem->getEntityItemID(), properties);
} }
exportTree.writeToSVOFile(filename.toLocal8Bit().constData()); exportTree.writeToJSONFile(filename.toLocal8Bit().constData());
// restore the main window's active state // restore the main window's active state
_window->activateWindow(); _window->activateWindow();
@ -1909,8 +1909,6 @@ void Application::init() {
_physicsEngine.init(&_entityEditSender); _physicsEngine.init(&_entityEditSender);
_physicsEngine.setAvatarData(_myAvatar);
auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
connect(&_physicsEngine, &EntitySimulation::entityCollisionWithEntity, connect(&_physicsEngine, &EntitySimulation::entityCollisionWithEntity,
@ -2197,6 +2195,7 @@ void Application::update(float deltaTime) {
{ {
PerformanceTimer perfTimer("physics"); PerformanceTimer perfTimer("physics");
_myAvatar->preSimulation();
_physicsEngine.stepSimulation(); _physicsEngine.stepSimulation();
} }
@ -3600,6 +3599,7 @@ void Application::initializeAcceptedFiles() {
if (_acceptedExtensions.size() == 0) { if (_acceptedExtensions.size() == 0) {
_acceptedExtensions[SNAPSHOT_EXTENSION] = &Application::acceptSnapshot; _acceptedExtensions[SNAPSHOT_EXTENSION] = &Application::acceptSnapshot;
_acceptedExtensions[SVO_EXTENSION] = &Application::importSVOFromURL; _acceptedExtensions[SVO_EXTENSION] = &Application::importSVOFromURL;
_acceptedExtensions[SVO_JSON_EXTENSION] = &Application::importSVOFromURL;
_acceptedExtensions[JS_EXTENSION] = &Application::askToLoadScript; _acceptedExtensions[JS_EXTENSION] = &Application::askToLoadScript;
_acceptedExtensions[FST_EXTENSION] = &Application::askToSetAvatarUrl; _acceptedExtensions[FST_EXTENSION] = &Application::askToSetAvatarUrl;
} }
@ -4208,7 +4208,7 @@ void Application::checkSkeleton() {
_myAvatar->setSkeletonModelURL(DEFAULT_BODY_MODEL_URL); _myAvatar->setSkeletonModelURL(DEFAULT_BODY_MODEL_URL);
_myAvatar->sendIdentityPacket(); _myAvatar->sendIdentityPacket();
} else { } else {
_myAvatar->updateLocalAABox(); _myAvatar->updateCharacterController();
_physicsEngine.setAvatarData(_myAvatar); _physicsEngine.setCharacterController(_myAvatar->getCharacterController());
} }
} }

View file

@ -95,6 +95,7 @@ static const float NODE_KILLED_BLUE = 0.0f;
static const QString SNAPSHOT_EXTENSION = ".jpg"; static const QString SNAPSHOT_EXTENSION = ".jpg";
static const QString SVO_EXTENSION = ".svo"; static const QString SVO_EXTENSION = ".svo";
static const QString SVO_JSON_EXTENSION = ".svo.json";
static const QString JS_EXTENSION = ".js"; static const QString JS_EXTENSION = ".js";
static const QString FST_EXTENSION = ".fst"; static const QString FST_EXTENSION = ".fst";

View file

@ -61,17 +61,21 @@ void DiscoverabilityManager::updateLocation() {
uuidStringWithoutCurlyBraces(domainHandler.getUUID())); uuidStringWithoutCurlyBraces(domainHandler.getUUID()));
} }
const QString FRIENDS_ONLY_KEY_IN_LOCATION = "friends_only";
locationObject.insert(FRIENDS_ONLY_KEY_IN_LOCATION, (_mode.get() == Discoverability::Friends));
rootObject.insert(LOCATION_KEY_IN_ROOT, locationObject); rootObject.insert(LOCATION_KEY_IN_ROOT, locationObject);
accountManager.authenticatedRequest(API_USER_LOCATION_PATH, QNetworkAccessManager::PutOperation, accountManager.sendRequest(API_USER_LOCATION_PATH, AccountManagerAuth::Required,
JSONCallbackParameters(), QJsonDocument(rootObject).toJson()); QNetworkAccessManager::PutOperation,
JSONCallbackParameters(), QJsonDocument(rootObject).toJson());
} }
} }
} }
void DiscoverabilityManager::removeLocation() { void DiscoverabilityManager::removeLocation() {
AccountManager& accountManager = AccountManager::getInstance(); AccountManager& accountManager = AccountManager::getInstance();
accountManager.authenticatedRequest(API_USER_LOCATION_PATH, QNetworkAccessManager::DeleteOperation); accountManager.sendRequest(API_USER_LOCATION_PATH, AccountManagerAuth::Required, QNetworkAccessManager::DeleteOperation);
} }
void DiscoverabilityManager::setDiscoverabilityMode(Discoverability::Mode discoverabilityMode) { void DiscoverabilityManager::setDiscoverabilityMode(Discoverability::Mode discoverabilityMode) {

View file

@ -70,7 +70,6 @@ MyAvatar::MyAvatar() :
Avatar(), Avatar(),
_turningKeyPressTime(0.0f), _turningKeyPressTime(0.0f),
_gravity(0.0f, 0.0f, 0.0f), _gravity(0.0f, 0.0f, 0.0f),
_shouldJump(false),
_wasPushing(false), _wasPushing(false),
_isPushing(false), _isPushing(false),
_isBraking(false), _isBraking(false),
@ -82,6 +81,8 @@ MyAvatar::MyAvatar() :
_scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE), _scriptedMotorTimescale(DEFAULT_SCRIPTED_MOTOR_TIMESCALE),
_scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME), _scriptedMotorFrame(SCRIPTED_MOTOR_CAMERA_FRAME),
_motionBehaviors(AVATAR_MOTION_DEFAULTS), _motionBehaviors(AVATAR_MOTION_DEFAULTS),
_enablePhysics(false),
_characterController(this),
_lookAtTargetAvatar(), _lookAtTargetAvatar(),
_shouldRender(true), _shouldRender(true),
_billboardValid(false), _billboardValid(false),
@ -954,15 +955,15 @@ glm::vec3 MyAvatar::getSkeletonPosition() const {
return Avatar::getPosition(); return Avatar::getPosition();
} }
void MyAvatar::updateLocalAABox() { void MyAvatar::updateCharacterController() {
// compute localAABox
const CapsuleShape& capsule = _skeletonModel.getBoundingShape(); const CapsuleShape& capsule = _skeletonModel.getBoundingShape();
float radius = capsule.getRadius(); float radius = capsule.getRadius();
float height = 2.0f * (capsule.getHalfHeight() + radius); float height = 2.0f * (capsule.getHalfHeight() + radius);
glm::vec3 offset = _skeletonModel.getBoundingShapeOffset();
glm::vec3 corner(-radius, -0.5f * height, -radius); glm::vec3 corner(-radius, -0.5f * height, -radius);
corner += offset; corner += _skeletonModel.getBoundingShapeOffset();
glm::vec3 scale(2.0f * radius, height, 2.0f * radius); glm::vec3 scale(2.0f * radius, height, 2.0f * radius);
_localAABox.setBox(corner, scale); _characterController.setLocalBoundingBox(corner, scale);
} }
QString MyAvatar::getScriptedMotorFrame() const { QString MyAvatar::getScriptedMotorFrame() const {
@ -1580,6 +1581,10 @@ glm::vec3 MyAvatar::getLaserPointerTipPosition(const PalmData* palm) {
return palm->getPosition(); return palm->getPosition();
} }
void MyAvatar::preSimulation() {
_characterController.setEnabled(_enablePhysics);
}
void MyAvatar::clearDriveKeys() { void MyAvatar::clearDriveKeys() {
for (int i = 0; i < MAX_DRIVE_KEYS; ++i) { for (int i = 0; i < MAX_DRIVE_KEYS; ++i) {
_driveKeys[i] = 0.0f; _driveKeys[i] = 0.0f;

View file

@ -13,6 +13,7 @@
#define hifi_MyAvatar_h #define hifi_MyAvatar_h
#include <SettingHandle.h> #include <SettingHandle.h>
#include <CharacterController.h>
#include "Avatar.h" #include "Avatar.h"
@ -88,7 +89,7 @@ public:
void clearDriveKeys(); void clearDriveKeys();
void setDriveKeys(int key, float val) { _driveKeys[key] = val; }; void setDriveKeys(int key, float val) { _driveKeys[key] = val; };
bool getDriveKeys(int key) { return _driveKeys[key] != 0.0f; }; bool getDriveKeys(int key) { return _driveKeys[key] != 0.0f; };
void jump() { _shouldJump = true; }; void jump() { _characterController.jump(); }
bool isMyAvatar() { return true; } bool isMyAvatar() { return true; }
@ -122,6 +123,8 @@ public:
virtual glm::vec3 getSkeletonPosition() const; virtual glm::vec3 getSkeletonPosition() const;
void updateLocalAABox(); void updateLocalAABox();
CharacterController* getCharacterController() { return &_characterController; }
void updateCharacterController();
void clearJointAnimationPriorities(); void clearJointAnimationPriorities();
@ -145,6 +148,11 @@ public:
const RecorderPointer getRecorder() const { return _recorder; } const RecorderPointer getRecorder() const { return _recorder; }
const PlayerPointer getPlayer() const { return _player; } const PlayerPointer getPlayer() const { return _player; }
void togglePhysicsEnabled() { _enablePhysics = !_enablePhysics; }
bool isPhysicsEnabled() { return _enablePhysics; }
void setPhysicsEnabled(bool enablePhysics) { _enablePhysics = enablePhysics; }
void preSimulation();
public slots: public slots:
void increaseSize(); void increaseSize();
@ -186,7 +194,6 @@ private:
float _turningKeyPressTime; float _turningKeyPressTime;
glm::vec3 _gravity; glm::vec3 _gravity;
bool _shouldJump;
float _driveKeys[MAX_DRIVE_KEYS]; float _driveKeys[MAX_DRIVE_KEYS];
bool _wasPushing; bool _wasPushing;
bool _isPushing; bool _isPushing;
@ -202,6 +209,9 @@ private:
int _scriptedMotorFrame; int _scriptedMotorFrame;
quint32 _motionBehaviors; quint32 _motionBehaviors;
bool _enablePhysics;
CharacterController _characterController;
QWeakPointer<AvatarData> _lookAtTargetAvatar; QWeakPointer<AvatarData> _lookAtTargetAvatar;
glm::vec3 _targetAvatarPosition; glm::vec3 _targetAvatarPosition;
bool _shouldRender; bool _shouldRender;

View file

@ -223,7 +223,7 @@ void SixenseManager::update(float deltaTime) {
palm->setJoystick(data->joystick_x, data->joystick_y); palm->setJoystick(data->joystick_x, data->joystick_y);
// Emulate the mouse so we can use scripts // Emulate the mouse so we can use scripts
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput) && !_controllersAtBase) {
emulateMouse(palm, numActiveControllers - 1); emulateMouse(palm, numActiveControllers - 1);
} }

View file

@ -55,6 +55,7 @@ WebWindowClass::WebWindowClass(const QString& title, const QString& url, int wid
_windowWidget = dockWidget; _windowWidget = dockWidget;
} else { } else {
_windowWidget = new QWidget(Application::getInstance()->getWindow(), Qt::Window); _windowWidget = new QWidget(Application::getInstance()->getWindow(), Qt::Window);
_windowWidget->setWindowTitle(title);
_windowWidget->setMinimumSize(width, height); _windowWidget->setMinimumSize(width, height);
auto layout = new QVBoxLayout(_windowWidget); auto layout = new QVBoxLayout(_windowWidget);
@ -96,6 +97,18 @@ void WebWindowClass::setVisible(bool visible) {
QMetaObject::invokeMethod(_windowWidget, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible)); QMetaObject::invokeMethod(_windowWidget, "setVisible", Qt::BlockingQueuedConnection, Q_ARG(bool, visible));
} }
void WebWindowClass::setURL(const QString& url) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setURL", Qt::BlockingQueuedConnection, Q_ARG(QString, url));
return;
}
_webView->setUrl(url);
}
void WebWindowClass::raise() {
QMetaObject::invokeMethod(_windowWidget, "raise", Qt::BlockingQueuedConnection);
}
QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) { QScriptValue WebWindowClass::constructor(QScriptContext* context, QScriptEngine* engine) {
WebWindowClass* retVal; WebWindowClass* retVal;
QString file = context->argument(0).toString(); QString file = context->argument(0).toString();

View file

@ -34,6 +34,7 @@ signals:
class WebWindowClass : public QObject { class WebWindowClass : public QObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QObject* eventBridge READ getEventBridge) Q_PROPERTY(QObject* eventBridge READ getEventBridge)
Q_PROPERTY(QString url READ getURL)
public: public:
WebWindowClass(const QString& title, const QString& url, int width, int height, bool isToolWindow = false); WebWindowClass(const QString& title, const QString& url, int width, int height, bool isToolWindow = false);
~WebWindowClass(); ~WebWindowClass();
@ -42,6 +43,9 @@ public:
public slots: public slots:
void setVisible(bool visible); void setVisible(bool visible);
QString getURL() const { return _webView->url().url(); }
void setURL(const QString& url);
void raise();
ScriptEventBridge* getEventBridge() const { return _eventBridge; } ScriptEventBridge* getEventBridge() const { return _eventBridge; }
void addEventBridgeToWindowObject(); void addEventBridgeToWindowObject();

View file

@ -300,16 +300,6 @@ public:
const AABox& getLocalAABox() const { return _localAABox; } const AABox& getLocalAABox() const { return _localAABox; }
const Referential* getReferential() const { return _referential; } const Referential* getReferential() const { return _referential; }
void togglePhysicsEnabled() { _enablePhysics = !_enablePhysics; }
bool isPhysicsEnabled() { return _enablePhysics; }
void setPhysicsEnabled(bool enablePhysics) { _enablePhysics = enablePhysics; }
void lockForRead() { _lock.lockForRead(); }
bool tryLockForRead() { return _lock.tryLockForRead(); }
void lockForWrite() { _lock.lockForWrite(); }
bool tryLockForWrite() { return _lock.tryLockForWrite(); }
void unlock() { _lock.unlock(); }
void setVelocity(const glm::vec3 velocity) { _velocity = velocity; } void setVelocity(const glm::vec3 velocity) { _velocity = velocity; }
Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; } Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; }
@ -409,9 +399,6 @@ private:
// privatize the copy constructor and assignment operator so they cannot be called // privatize the copy constructor and assignment operator so they cannot be called
AvatarData(const AvatarData&); AvatarData(const AvatarData&);
AvatarData& operator= (const AvatarData&); AvatarData& operator= (const AvatarData&);
QReadWriteLock _lock;
bool _enablePhysics = false;
}; };
Q_DECLARE_METATYPE(AvatarData*) Q_DECLARE_METATYPE(AvatarData*)

View file

@ -25,7 +25,7 @@ EntityItemID::EntityItemID() :
creatorTokenID(UNKNOWN_ENTITY_TOKEN), creatorTokenID(UNKNOWN_ENTITY_TOKEN),
isKnownID(false) isKnownID(false)
{ {
}; }
EntityItemID::EntityItemID(const EntityItemID& other) : EntityItemID::EntityItemID(const EntityItemID& other) :
id(other.id), id(other.id),

View file

@ -115,7 +115,7 @@ void AccountManager::updateBalance() {
callbackParameters.jsonCallbackReceiver = &_accountInfo; callbackParameters.jsonCallbackReceiver = &_accountInfo;
callbackParameters.jsonCallbackMethod = "setBalanceFromJSON"; callbackParameters.jsonCallbackMethod = "setBalanceFromJSON";
authenticatedRequest("/api/v1/wallets/mine", QNetworkAccessManager::GetOperation, callbackParameters); sendRequest("/api/v1/wallets/mine", AccountManagerAuth::Required, QNetworkAccessManager::GetOperation, callbackParameters);
} }
} }
@ -159,50 +159,30 @@ void AccountManager::setAuthURL(const QUrl& authURL) {
} }
} }
void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation, void AccountManager::sendRequest(const QString& path,
const JSONCallbackParameters& callbackParams, AccountManagerAuth::Type authType,
const QByteArray& dataByteArray, QNetworkAccessManager::Operation operation,
QHttpMultiPart* dataMultiPart, const JSONCallbackParameters& callbackParams,
const QVariantMap& propertyMap) { const QByteArray& dataByteArray,
QHttpMultiPart* dataMultiPart,
const QVariantMap& propertyMap) {
QMetaObject::invokeMethod(this, "invokedRequest", if (thread() != QThread::currentThread()) {
Q_ARG(const QString&, path), QMetaObject::invokeMethod(this, "sendRequest",
Q_ARG(bool, true), Q_ARG(const QString&, path),
Q_ARG(QNetworkAccessManager::Operation, operation), Q_ARG(AccountManagerAuth::Type, AccountManagerAuth::Required),
Q_ARG(const JSONCallbackParameters&, callbackParams), Q_ARG(QNetworkAccessManager::Operation, operation),
Q_ARG(const QByteArray&, dataByteArray), Q_ARG(const JSONCallbackParameters&, callbackParams),
Q_ARG(QHttpMultiPart*, dataMultiPart), Q_ARG(const QByteArray&, dataByteArray),
Q_ARG(QVariantMap, propertyMap)); Q_ARG(QHttpMultiPart*, dataMultiPart),
} Q_ARG(QVariantMap, propertyMap));
}
void AccountManager::unauthenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray,
QHttpMultiPart* dataMultiPart,
const QVariantMap& propertyMap) {
QMetaObject::invokeMethod(this, "invokedRequest",
Q_ARG(const QString&, path),
Q_ARG(bool, false),
Q_ARG(QNetworkAccessManager::Operation, operation),
Q_ARG(const JSONCallbackParameters&, callbackParams),
Q_ARG(const QByteArray&, dataByteArray),
Q_ARG(QHttpMultiPart*, dataMultiPart),
Q_ARG(QVariantMap, propertyMap));
}
void AccountManager::invokedRequest(const QString& path,
bool requiresAuthentication,
QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart,
const QVariantMap& propertyMap) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest; QNetworkRequest networkRequest;
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
QUrl requestURL = _authURL; QUrl requestURL = _authURL;
if (path.startsWith("/")) { if (path.startsWith("/")) {
@ -211,13 +191,17 @@ void AccountManager::invokedRequest(const QString& path,
requestURL.setPath("/" + path); requestURL.setPath("/" + path);
} }
if (requiresAuthentication) { if (authType != AccountManagerAuth::None ) {
if (hasValidAccessToken()) { if (hasValidAccessToken()) {
networkRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, networkRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER,
_accountInfo.getAccessToken().authorizationHeaderValue()); _accountInfo.getAccessToken().authorizationHeaderValue());
} else { } else {
qDebug() << "No valid access token present. Bailing on authenticated invoked request."; if (authType == AccountManagerAuth::Required) {
return; qDebug() << "No valid access token present. Bailing on invoked request to"
<< path << "that requires authentication";
return;
}
} }
} }
@ -540,8 +524,8 @@ void AccountManager::processGeneratedKeypair(const QByteArray& publicKey, const
requestMultiPart->append(keyPart); requestMultiPart->append(keyPart);
authenticatedRequest(PUBLIC_KEY_UPDATE_PATH, QNetworkAccessManager::PutOperation, sendRequest(PUBLIC_KEY_UPDATE_PATH, AccountManagerAuth::Required, QNetworkAccessManager::PutOperation,
JSONCallbackParameters(), QByteArray(), requestMultiPart); JSONCallbackParameters(), QByteArray(), requestMultiPart);
// get rid of the keypair generator now that we don't need it anymore // get rid of the keypair generator now that we don't need it anymore
sender()->deleteLater(); sender()->deleteLater();

View file

@ -37,6 +37,16 @@ public:
QString updateSlot; QString updateSlot;
}; };
namespace AccountManagerAuth {
enum Type {
None,
Required,
Optional
};
}
Q_DECLARE_METATYPE(AccountManagerAuth::Type);
const QByteArray ACCESS_TOKEN_AUTHORIZATION_HEADER = "Authorization"; const QByteArray ACCESS_TOKEN_AUTHORIZATION_HEADER = "Authorization";
class AccountManager : public QObject { class AccountManager : public QObject {
@ -44,19 +54,13 @@ class AccountManager : public QObject {
public: public:
static AccountManager& getInstance(bool forceReset = false); static AccountManager& getInstance(bool forceReset = false);
void authenticatedRequest(const QString& path, Q_INVOKABLE void sendRequest(const QString& path,
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, AccountManagerAuth::Type authType,
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(), QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
const QByteArray& dataByteArray = QByteArray(), const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
QHttpMultiPart* dataMultiPart = NULL, const QByteArray& dataByteArray = QByteArray(),
const QVariantMap& propertyMap = QVariantMap()); QHttpMultiPart* dataMultiPart = NULL,
const QVariantMap& propertyMap = QVariantMap());
void unauthenticatedRequest(const QString& path,
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
const QByteArray& dataByteArray = QByteArray(),
QHttpMultiPart* dataMultiPart = NULL,
const QVariantMap& propertyMap = QVariantMap()) ;
const QUrl& getAuthURL() const { return _authURL; } const QUrl& getAuthURL() const { return _authURL; }
void setAuthURL(const QUrl& authURL); void setAuthURL(const QUrl& authURL);
@ -107,14 +111,6 @@ private:
void passSuccessToCallback(QNetworkReply* reply); void passSuccessToCallback(QNetworkReply* reply);
void passErrorToCallback(QNetworkReply* reply); void passErrorToCallback(QNetworkReply* reply);
Q_INVOKABLE void invokedRequest(const QString& path,
bool requiresAuthentication,
QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray,
QHttpMultiPart* dataMultiPart,
const QVariantMap& propertyMap);
QUrl _authURL; QUrl _authURL;
QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap; QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;

View file

@ -294,12 +294,11 @@ void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const Q
requestParams.insert(OVERRIDE_PATH_KEY, overridePath); requestParams.insert(OVERRIDE_PATH_KEY, overridePath);
} }
AccountManager::getInstance().unauthenticatedRequest(GET_PLACE.arg(placeName), AccountManager::getInstance().sendRequest(GET_PLACE.arg(placeName),
QNetworkAccessManager::GetOperation, AccountManagerAuth::None,
apiCallbackParameters(), QNetworkAccessManager::GetOperation,
QByteArray(), apiCallbackParameters(),
NULL, QByteArray(), NULL, requestParams);
requestParams);
} }
bool AddressManager::handleNetworkAddress(const QString& lookupString) { bool AddressManager::handleNetworkAddress(const QString& lookupString) {
@ -439,9 +438,10 @@ void AddressManager::setDomainInfo(const QString& hostname, quint16 port) {
void AddressManager::goToUser(const QString& username) { void AddressManager::goToUser(const QString& username) {
QString formattedUsername = QUrl::toPercentEncoding(username); QString formattedUsername = QUrl::toPercentEncoding(username);
// this is a username - pull the captured name and lookup that user's location // this is a username - pull the captured name and lookup that user's location
AccountManager::getInstance().unauthenticatedRequest(GET_USER_LOCATION.arg(formattedUsername), AccountManager::getInstance().sendRequest(GET_USER_LOCATION.arg(formattedUsername),
QNetworkAccessManager::GetOperation, AccountManagerAuth::Optional,
apiCallbackParameters()); QNetworkAccessManager::GetOperation,
apiCallbackParameters());
} }
void AddressManager::copyAddress() { void AddressManager::copyAddress() {

View file

@ -23,7 +23,7 @@
#include "AccountManager.h" #include "AccountManager.h"
const QString HIFI_URL_SCHEME = "hifi"; const QString HIFI_URL_SCHEME = "hifi";
const QString DEFAULT_HIFI_ADDRESS = "hifi://sandbox"; const QString DEFAULT_HIFI_ADDRESS = "hifi://entry";
typedef const glm::vec3& (*PositionGetter)(); typedef const glm::vec3& (*PositionGetter)();
typedef glm::quat (*OrientationGetter)(); typedef glm::quat (*OrientationGetter)();

View file

@ -62,11 +62,10 @@ void UserActivityLogger::logAction(QString action, QJsonObject details, JSONCall
params.errorCallbackMethod = "requestError"; params.errorCallbackMethod = "requestError";
} }
accountManager.authenticatedRequest(USER_ACTIVITY_URL, accountManager.sendRequest(USER_ACTIVITY_URL,
QNetworkAccessManager::PostOperation, AccountManagerAuth::Required,
params, QNetworkAccessManager::PostOperation,
NULL, params, NULL, multipart);
multipart);
} }
void UserActivityLogger::requestFinished(QNetworkReply& requestReply) { void UserActivityLogger::requestFinished(QNetworkReply& requestReply) {

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
/* /*
Bullet Continuous Collision Detection and Physics Library Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
2015.03.25 -- modified by Andrew Meadows andrew@highfidelity.io
This software is provided 'as-is', without any express or implied warranty. This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software. In no event will the authors be held liable for any damages arising from the use of this software.
@ -37,59 +38,57 @@ class btPairCachingGhostObject;
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. ///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user. ///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
ATTRIBUTE_ALIGNED16(class) CharacterController : public btCharacterControllerInterface ATTRIBUTE_ALIGNED16(class) CharacterController : public btCharacterControllerInterface
{ {
protected: protected:
AvatarData* m_avatarData = NULL; AvatarData* _avatarData = NULL;
btPairCachingGhostObject* m_ghostObject; btPairCachingGhostObject* _ghostObject;
glm::vec3 m_shapeLocalOffset;
btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast btConvexShape* _convexShape;//is also in _ghostObject, but it needs to be convex, so we store it here to avoid upcast
btScalar m_radius; btScalar _radius;
btScalar m_halfHeight; btScalar _halfHeight;
btScalar m_verticalVelocity; btScalar _verticalVelocity;
btScalar m_verticalOffset; // fall distance from velocity this frame btScalar _verticalOffset; // fall distance from velocity this frame
btScalar m_maxFallSpeed; btScalar _maxFallSpeed;
btScalar m_jumpSpeed; btScalar _jumpSpeed;
btScalar m_maxJumpHeight; btScalar _maxJumpHeight;
btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value) btScalar _maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization) btScalar _maxSlopeCosine; // Cosine equivalent of _maxSlopeRadians (calculated once when set, for optimization)
btScalar m_gravity; btScalar _gravity;
btScalar m_turnAngle; btScalar _stepHeight; // height of stepUp prior to stepForward
btScalar m_stepHeight; // height of stepUp prior to stepForward btScalar _addedMargin;//@todo: remove this and fix the code
btScalar m_addedMargin;//@todo: remove this and fix the code
///this is the desired walk direction, set by the user ///this is the desired walk direction, set by the user
btVector3 m_walkDirection; btVector3 _walkDirection;
btVector3 m_normalizedDirection; btVector3 _normalizedDirection;
//some internal variables //some internal variables
btVector3 m_currentPosition; btVector3 _currentPosition;
btVector3 m_targetPosition; btQuaternion _currentRotation;
btScalar m_lastStepUp; btVector3 _targetPosition;
btScalar _lastStepUp;
///keep track of the contact manifolds ///keep track of the contact manifolds
btManifoldArray m_manifoldArray; btManifoldArray _manifoldArray;
bool m_touchingContact; bool _touchingContact;
btVector3 m_floorNormal; // points from object to character btVector3 _floorNormal; // points from object to character
bool m_enabled; bool _enabled;
bool m_wasOnGround; bool _wasOnGround;
bool m_wasJumping; bool _wasJumping;
bool m_useWalkDirection; btScalar _velocityTimeInterval;
btScalar m_velocityTimeInterval; uint32_t _pendingFlags;
int m_upAxis;
static btVector3* getUpAxisDirections(); glm::vec3 _shapeLocalOffset;
bool m_interpolateUp; glm::vec3 _boxScale; // used to compute capsule shape
bool full_drop;
bool bounce_fix; btDynamicsWorld* _dynamicsWorld = NULL;
btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal); btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal);
btVector3 parallelComponent(const btVector3& direction, const btVector3& normal); btVector3 parallelComponent(const btVector3& direction, const btVector3& normal);
@ -118,14 +117,6 @@ public:
///btActionInterface interface ///btActionInterface interface
void debugDraw(btIDebugDraw* debugDrawer); void debugDraw(btIDebugDraw* debugDrawer);
void setUpAxis(int axis) {
if (axis < 0)
axis = 0;
if (axis > 2)
axis = 2;
m_upAxis = axis;
}
/// This should probably be called setPositionIncrementPerSimulatorStep. /// This should probably be called setPositionIncrementPerSimulatorStep.
/// This is neither a direction nor a velocity, but the amount to /// This is neither a direction nor a velocity, but the amount to
/// increment the position each simulation iteration, regardless /// increment the position each simulation iteration, regardless
@ -141,18 +132,19 @@ public:
virtual void setVelocityForTimeInterval(const btVector3& velocity, virtual void setVelocityForTimeInterval(const btVector3& velocity,
btScalar timeInterval); btScalar timeInterval);
void reset(btCollisionWorld* collisionWorld ); virtual void reset(btCollisionWorld* collisionWorld );
void warp(const btVector3& origin); virtual void warp(const btVector3& origin);
void preStep(btCollisionWorld* collisionWorld); virtual void preStep(btCollisionWorld* collisionWorld);
void playerStep(btCollisionWorld* collisionWorld, btScalar dt); virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt);
virtual bool canJump() const;
virtual void jump();
virtual bool onGround() const;
void setMaxFallSpeed(btScalar speed); void setMaxFallSpeed(btScalar speed);
void setJumpSpeed(btScalar jumpSpeed); void setJumpSpeed(btScalar jumpSpeed);
void setMaxJumpHeight(btScalar maxJumpHeight); void setMaxJumpHeight(btScalar maxJumpHeight);
bool canJump() const;
void jump();
void setGravity(btScalar gravity); void setGravity(btScalar gravity);
btScalar getGravity() const; btScalar getGravity() const;
@ -164,11 +156,16 @@ public:
btPairCachingGhostObject* getGhostObject(); btPairCachingGhostObject* getGhostObject();
bool onGround() const;
void setUpInterpolate(bool value); void setUpInterpolate(bool value);
bool needsShapeUpdate(); bool needsRemoval() const;
void updateShape(); bool needsAddition() const;
void setEnabled(bool enabled);
void setDynamicsWorld(btDynamicsWorld* world);
void setLocalBoundingBox(const glm::vec3& corner, const glm::vec3& scale);
bool needsShapeUpdate() const;
void updateShapeIfNecessary();
void preSimulation(btScalar timeStep); void preSimulation(btScalar timeStep);
void postSimulation(); void postSimulation();

View file

@ -280,12 +280,12 @@ void PhysicsEngine::init(EntityEditPacketSender* packetSender) {
void PhysicsEngine::stepSimulation() { void PhysicsEngine::stepSimulation() {
lock(); lock();
// NOTE: the grand order of operations is: // NOTE: the grand order of operations is:
// (1) relay incoming changes // (1) pull incoming changes
// (2) step simulation // (2) step simulation
// (3) synchronize outgoing motion states // (3) synchronize outgoing motion states
// (4) send outgoing packets // (4) send outgoing packets
// This is step (1). // This is step (1) pull incoming changes
relayIncomingChangesToSimulation(); relayIncomingChangesToSimulation();
const int MAX_NUM_SUBSTEPS = 4; const int MAX_NUM_SUBSTEPS = 4;
@ -294,16 +294,25 @@ void PhysicsEngine::stepSimulation() {
_clock.reset(); _clock.reset();
float timeStep = btMin(dt, MAX_TIMESTEP); float timeStep = btMin(dt, MAX_TIMESTEP);
// This is step (2). // TODO: move character->preSimulation() into relayIncomingChanges
if (_characterController) { if (_characterController) {
if (_characterController->needsRemoval()) {
_characterController->setDynamicsWorld(NULL);
}
_characterController->updateShapeIfNecessary();
if (_characterController->needsAddition()) {
_characterController->setDynamicsWorld(_dynamicsWorld);
}
_characterController->preSimulation(timeStep); _characterController->preSimulation(timeStep);
} }
// This is step (2) step simulation
int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP); int numSubsteps = _dynamicsWorld->stepSimulation(timeStep, MAX_NUM_SUBSTEPS, PHYSICS_ENGINE_FIXED_SUBSTEP);
_numSubsteps += (uint32_t)numSubsteps; _numSubsteps += (uint32_t)numSubsteps;
stepNonPhysicalKinematics(usecTimestampNow()); stepNonPhysicalKinematics(usecTimestampNow());
unlock(); unlock();
// TODO: make all of this harvest stuff into one function: relayOutgoingChanges()
if (numSubsteps > 0) { if (numSubsteps > 0) {
// This is step (3) which is done outside of stepSimulation() so we can lock _entityTree. // This is step (3) which is done outside of stepSimulation() so we can lock _entityTree.
// //
@ -598,34 +607,10 @@ bool PhysicsEngine::updateObjectHard(btRigidBody* body, ObjectMotionState* motio
return true; return true;
} }
void PhysicsEngine::setAvatarData(AvatarData *avatarData) { void PhysicsEngine::setCharacterController(CharacterController* character) {
if (_characterController) { if (!_characterController) {
bool needsShapeUpdate = _characterController->needsShapeUpdate();
if (needsShapeUpdate) {
lock();
// remove old info
_dynamicsWorld->removeCollisionObject(_characterController->getGhostObject());
_dynamicsWorld->removeAction(_characterController);
// update shape
_characterController->updateShape();
// insert new info
_dynamicsWorld->addCollisionObject(_characterController->getGhostObject(),
btBroadphaseProxy::CharacterFilter,
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
_dynamicsWorld->addAction(_characterController);
_characterController->reset(_dynamicsWorld);
unlock();
}
} else {
// initialize _characterController
assert(avatarData); // don't pass NULL argument
lock(); lock();
_characterController = new CharacterController(avatarData); _characterController = character;
_dynamicsWorld->addCollisionObject(_characterController->getGhostObject(),
btBroadphaseProxy::CharacterFilter,
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
_dynamicsWorld->addAction(_characterController);
_characterController->reset(_dynamicsWorld);
unlock(); unlock();
} }
} }

View file

@ -17,9 +17,7 @@
#include <QSet> #include <QSet>
#include <btBulletDynamicsCommon.h> #include <btBulletDynamicsCommon.h>
#include <BulletCollision/CollisionDispatch/btGhostObject.h> #include <BulletCollision/CollisionDispatch/btGhostObject.h>
//#include <BulletCollision/CollisionShapes/btCapsuleShape.h>
#include <AvatarData.h>
#include <EntityItem.h> #include <EntityItem.h>
#include <EntitySimulation.h> #include <EntitySimulation.h>
@ -86,7 +84,7 @@ public:
/// process queue of changed from external sources /// process queue of changed from external sources
void relayIncomingChangesToSimulation(); void relayIncomingChangesToSimulation();
void setAvatarData(AvatarData *avatarData); void setCharacterController(CharacterController* character);
private: private:
/// \param motionState pointer to Object's MotionState /// \param motionState pointer to Object's MotionState