diff --git a/CMakeLists.txt b/CMakeLists.txt index 296a566fa4..fdeb6dfd0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets") project(hifi) add_definitions(-DGLM_FORCE_RADIANS) +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") if (WIN32) add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index ed1f293c06..098460ecac 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -45,7 +45,7 @@ Agent::Agent(const QByteArray& packet) : DependencyManager::get()->setPacketSender(&_entityEditSender); - DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); } diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 1280b55b12..d591087acd 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -180,7 +180,7 @@ void AssignmentClientMonitor::readPendingDatagrams() { senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) { if (!packetUUID.isNull()) { matchingNode = DependencyManager::get()->addOrUpdateNode - (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false); + (packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false, false); AssignmentClientChildData *childData = new AssignmentClientChildData("unknown"); matchingNode->setLinkedData(childData); } else { diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 7cca9d3ef5..266183745f 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "../AssignmentClient.h" @@ -252,7 +253,7 @@ OctreeServer::OctreeServer(const QByteArray& packet) : // make sure the AccountManager has an Auth URL for payment redemptions - AccountManager::getInstance().setAuthURL(DEFAULT_NODE_AUTH_URL); + AccountManager::getInstance().setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); } OctreeServer::~OctreeServer() { diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index e3610997d1..2d98b2e147 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -19,7 +19,7 @@ if (WIN32) ${EXTERNAL_NAME} URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip URL_MD5 f5e8914fc9064ad32e0d62d19d33d977 - CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 + CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 -DUSE_DX11=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 diff --git a/cmake/externals/tbb/CMakeLists.txt b/cmake/externals/tbb/CMakeLists.txt index ad46196b95..b9b2b65010 100644 --- a/cmake/externals/tbb/CMakeLists.txt +++ b/cmake/externals/tbb/CMakeLists.txt @@ -13,16 +13,28 @@ if (ANDROID) BUILD_COMMAND ${NDK_BUILD_COMMAND} --directory=jni target=android tbb tbbmalloc arch=arm BUILD_IN_SOURCE 1 CONFIGURE_COMMAND "" - INSTALL_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/AndroidTBBLibCopy.cmake + INSTALL_COMMAND ${CMAKE_COMMAND} -DTBB_LIBS_SUFFIX=so -P ${CMAKE_CURRENT_SOURCE_DIR}/TBBLibCopy.cmake + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + ) +elseif (APPLE) + find_program(MAKE_COMMAND NAMES make DOC "Path to the make command") + + ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_src.tgz + URL_MD5 bf090eaa86cf89ea014b7b462786a440 + BUILD_COMMAND ${MAKE_COMMAND} tbb_os=macos + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "" + INSTALL_COMMAND ${CMAKE_COMMAND} -DTBB_LIBS_SUFFIX=dylib -P ${CMAKE_CURRENT_SOURCE_DIR}/TBBLibCopy.cmake LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 ) else () - if (APPLE) - set(DOWNLOAD_URL http://hifi-public.s3.amazonaws.com/dependencies/tbb43_20150316oss_osx.tgz) - set(DOWNLOAD_MD5 25a36ebff070ff801760ec658079f6aa) - elseif (WIN32) + if (WIN32) set(DOWNLOAD_URL http://s3.amazonaws.com/hifi-public/dependencies/tbb43_20150316oss_win.zip) set(DOWNLOAD_MD5 d250d40bb93b255f75bcbb19e976a440) else () @@ -46,7 +58,7 @@ ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) if (APPLE) - set(_TBB_LIB_DIR "${SOURCE_DIR}/lib/libc++") + set(_TBB_LIB_DIR "${SOURCE_DIR}/lib") set(_LIB_PREFIX "lib") set(_LIB_EXT "dylib") @@ -95,14 +107,8 @@ elseif (UNIX) endif () if (DEFINED _TBB_LIB_DIR) - if (NOT APPLE) - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb_debug.${_LIB_EXT} CACHE FILEPATH "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc_debug.${_LIB_EXT} CACHE FILEPATH "TBB malloc debug library location") - else () - set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "TBB debug library location") - set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG "" CACHE FILEPATH "TBB malloc debug library location") - endif () - + set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb_debug.${_LIB_EXT} CACHE FILEPATH "TBB debug library location") + set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_DEBUG ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc_debug.${_LIB_EXT} CACHE FILEPATH "TBB malloc debug library location") set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbb.${_LIB_EXT} CACHE FILEPATH "TBB release library location") set(${EXTERNAL_NAME_UPPER}_MALLOC_LIBRARY_RELEASE ${_TBB_LIB_DIR}/${_LIB_PREFIX}tbbmalloc.${_LIB_EXT} CACHE FILEPATH "TBB malloc release library location") endif () diff --git a/cmake/externals/tbb/OSXTBBInstallNameChange.cmake b/cmake/externals/tbb/OSXTBBInstallNameChange.cmake index c263ed7d2e..cc4df46812 100644 --- a/cmake/externals/tbb/OSXTBBInstallNameChange.cmake +++ b/cmake/externals/tbb/OSXTBBInstallNameChange.cmake @@ -10,9 +10,11 @@ # # first find the so files in the source dir -set(_TBB_LIBRARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib/libc++) +set(_TBB_LIBRARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib) file(GLOB_RECURSE _TBB_LIBRARIES "${_TBB_LIBRARY_DIR}/*.dylib") +message(${_TBB_LIBRARIES}) + # raise an error if we found none if (NOT _TBB_LIBRARIES) message(FATAL_ERROR "Did not find any TBB libraries") @@ -28,20 +30,6 @@ find_program(LIPO_COMMAND NAMES lipo DOC "Path to the lipo command") foreach(_TBB_LIBRARY ${_TBB_LIBRARIES}) get_filename_component(_TBB_LIBRARY_FILENAME ${_TBB_LIBRARY} NAME) - set(_LIPO_ARGS -remove i386 ${_TBB_LIBRARY_FILENAME} -output ${_TBB_LIBRARY_FILENAME}) - message(STATUS "${LIPO_COMMAND} ${_LIPO_ARGS}") - - # first we use lipo to remove i386 from each dylib - execute_process( - COMMAND ${LIPO_COMMAND} ${_LIPO_ARGS} - WORKING_DIRECTORY ${_TBB_LIBRARY_DIR} - ERROR_VARIABLE _LIPO_ERROR - ) - - if (_LIPO_ERROR) - message(FATAL_ERROR "There was an error removing i386 for ${_TBB_LIBRARY_FILENAME} - ${_LIPO_ERROR}") - endif () - set(_INSTALL_NAME_ARGS ${INSTALL_NAME_TOOL_COMMAND} -id ${_TBB_LIBRARY} ${_TBB_LIBRARY_FILENAME}) message(STATUS "${INSTALL_NAME_COMMAND} ${_INSTALL_NAME_ARGS}") diff --git a/cmake/externals/tbb/AndroidTBBLibCopy.cmake b/cmake/externals/tbb/TBBLibCopy.cmake similarity index 94% rename from cmake/externals/tbb/AndroidTBBLibCopy.cmake rename to cmake/externals/tbb/TBBLibCopy.cmake index 1c7697ab54..8f5423750b 100644 --- a/cmake/externals/tbb/AndroidTBBLibCopy.cmake +++ b/cmake/externals/tbb/TBBLibCopy.cmake @@ -1,5 +1,5 @@ # -# AndroidTBBLibCopy.cmake +# TBBLibCopy.cmake # cmake/externals/tbb # # Copyright 2015 High Fidelity, Inc. @@ -10,7 +10,7 @@ # # first find the so files in the source dir -file(GLOB_RECURSE _TBB_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/build/*.so") +file(GLOB_RECURSE _TBB_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/build/*.${TBB_LIBS_SUFFIX}") # raise an error if we found none if (NOT _TBB_LIBRARIES) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 0082bd84ae..e694afa1da 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -95,6 +95,13 @@ "can_set": true } ] + }, + { + "name": "editors_are_rezzers", + "type": "checkbox", + "label": "Only editors can create new entities", + "help": "When checked, only those who can edit the domain can create new entites.", + "default": false } ] }, diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 0918b85a63..9ce15b7507 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.io"; const QString ALLOWED_USERS_SETTINGS_KEYPATH = "security.allowed_users"; const QString MAXIMUM_USER_CAPACITY = "security.maximum_user_capacity"; const QString ALLOWED_EDITORS_SETTINGS_KEYPATH = "security.allowed_editors"; +const QString EDITORS_ARE_REZZERS_KEYPATH = "security.editors_are_rezzers"; DomainServer::DomainServer(int argc, char* argv[]) : @@ -181,7 +183,7 @@ bool DomainServer::optionallySetupOAuth() { // if we don't have an oauth provider URL then we default to the default node auth url if (_oauthProviderURL.isEmpty()) { - _oauthProviderURL = DEFAULT_NODE_AUTH_URL; + _oauthProviderURL = NetworkingConstants::METAVERSE_SERVER_URL; } AccountManager& accountManager = AccountManager::getInstance(); @@ -645,9 +647,23 @@ void DomainServer::handleConnectRequest(const QByteArray& packet, const HifiSock QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); bool canAdjustLocks = allowedEditors.isEmpty() || allowedEditors.contains(username); + const QVariant* editorsAreRezzersVariant = + valueForKeyPath(_settingsManager.getSettingsMap(), EDITORS_ARE_REZZERS_KEYPATH); + + bool onlyEditorsAreRezzers = false; + if (editorsAreRezzersVariant) { + onlyEditorsAreRezzers = editorsAreRezzersVariant->toBool(); + } + + bool canRez = true; + if (onlyEditorsAreRezzers) { + canRez = canAdjustLocks; + } + SharedNodePointer newNode = DependencyManager::get()->addOrUpdateNode(nodeUUID, nodeType, - publicSockAddr, localSockAddr, canAdjustLocks); + publicSockAddr, localSockAddr, + canAdjustLocks, canRez); // when the newNode is created the linked data is also created // if this was a static assignment set the UUID, set the sendingSockAddr DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); @@ -902,6 +918,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); broadcastDataStream << node->getUUID(); broadcastDataStream << node->getCanAdjustLocks(); + broadcastDataStream << node->getCanRez(); int numBroadcastPacketLeadBytes = broadcastDataStream.device()->pos(); diff --git a/examples/blocks.js b/examples/blocks.js index 30c2126096..7bc52824db 100644 --- a/examples/blocks.js +++ b/examples/blocks.js @@ -43,8 +43,8 @@ var floor = Entities.addEntity( var edge1 = Entities.addEntity( { type: "Box", position: Vec3.sum(center, { x: FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), - dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE }, - color: { red: 128, green: 128, blue: 128 }, + dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE + EDGE_THICKESS }, + color: { red: 100, green: 100, blue: 100 }, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, visible: true, @@ -54,8 +54,8 @@ var edge1 = Entities.addEntity( var edge2 = Entities.addEntity( { type: "Box", position: Vec3.sum(center, { x: -FLOOR_SIZE / 2.0, y: FLOOR_THICKNESS / 2.0, z: 0 }), - dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE }, - color: { red: 128, green: 128, blue: 128 }, + dimensions: { x: EDGE_THICKESS, y: EDGE_THICKESS, z: FLOOR_SIZE + EDGE_THICKESS }, + color: { red: 100, green: 100, blue: 100 }, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, visible: true, @@ -65,8 +65,8 @@ var edge2 = Entities.addEntity( var edge3 = Entities.addEntity( { type: "Box", position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: -FLOOR_SIZE / 2.0 }), - dimensions: { x: FLOOR_SIZE, y: EDGE_THICKESS, z: EDGE_THICKESS }, - color: { red: 128, green: 128, blue: 128 }, + dimensions: { x: FLOOR_SIZE + EDGE_THICKESS, y: EDGE_THICKESS, z: EDGE_THICKESS }, + color: { red: 100, green: 100, blue: 100 }, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, visible: true, @@ -76,8 +76,8 @@ var edge3 = Entities.addEntity( var edge4 = Entities.addEntity( { type: "Box", position: Vec3.sum(center, { x: 0, y: FLOOR_THICKNESS / 2.0, z: FLOOR_SIZE / 2.0 }), - dimensions: { x: FLOOR_SIZE, y: EDGE_THICKESS, z: EDGE_THICKESS }, - color: { red: 128, green: 128, blue: 128 }, + dimensions: { x: FLOOR_SIZE + EDGE_THICKESS, y: EDGE_THICKESS, z: EDGE_THICKESS }, + color: { red: 100, green: 100, blue: 100 }, gravity: { x: 0, y: 0, z: 0 }, ignoreCollisions: false, visible: true, @@ -97,6 +97,7 @@ for (var i = 0; i < NUM_BLOCKS; i++) { dimensions: { x: type.x * SCALE, y: type.y * SCALE, z: type.z * SCALE }, color: { red: type.red, green: type.green, blue: type.blue }, gravity: { x: 0, y: GRAVITY, z: 0 }, + velocity: { x: 0, y: 0.05, z: 0 }, ignoreCollisions: false, damping: DAMPING, lifetime: LIFETIME, @@ -104,6 +105,11 @@ for (var i = 0; i < NUM_BLOCKS; i++) { } function scriptEnding() { + Entities.editEntity(edge1, { locked: false }); + Entities.editEntity(edge2, { locked: false }); + Entities.editEntity(edge3, { locked: false }); + Entities.editEntity(edge4, { locked: false }); + Entities.editEntity(floor, { locked: false }); Entities.deleteEntity(edge1); Entities.deleteEntity(edge2); Entities.deleteEntity(edge3); diff --git a/examples/dice.js b/examples/dice.js index 2aefcf90fe..6943c926ae 100644 --- a/examples/dice.js +++ b/examples/dice.js @@ -23,6 +23,8 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; var rollSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/dice/diceRoll.wav"); +var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to create new objects." + var screenSize = Controller.getViewportDimensions(); var offButton = Overlays.addOverlay("image", { x: screenSize.x - 48, @@ -49,20 +51,26 @@ var LIFETIME = 300; var MAX_ANGULAR_SPEED = Math.PI; function shootDice(position, velocity) { - for (var i = 0; i < NUMBER_OF_DICE; i++) { - dice.push(Entities.addEntity( - { type: "Model", - modelURL: HIFI_PUBLIC_BUCKET + "models/props/Dice/goldDie.fbx", - position: position, - velocity: velocity, - rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), - angularVelocity: { x: Math.random() * MAX_ANGULAR_SPEED, y: Math.random() * MAX_ANGULAR_SPEED, z: Math.random() * MAX_ANGULAR_SPEED }, - lifetime: LIFETIME, - gravity: { x: 0, y: GRAVITY, z: 0 }, - shapeType: "box", - collisionsWillMove: true - })); - position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation())))); + if (!Entities.canRez()) { + Window.alert(INSUFFICIENT_PERMISSIONS_ERROR_MSG); + } else { + for (var i = 0; i < NUMBER_OF_DICE; i++) { + dice.push(Entities.addEntity( + { type: "Model", + modelURL: HIFI_PUBLIC_BUCKET + "models/props/Dice/goldDie.fbx", + position: position, + velocity: velocity, + rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), + angularVelocity: { x: Math.random() * MAX_ANGULAR_SPEED, + y: Math.random() * MAX_ANGULAR_SPEED, + z: Math.random() * MAX_ANGULAR_SPEED }, + lifetime: LIFETIME, + gravity: { x: 0, y: GRAVITY, z: 0 }, + shapeType: "box", + collisionsWillMove: true + })); + position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation())))); + } } } diff --git a/examples/entityScripts/lightController.js b/examples/entityScripts/lightController.js index e6e4998aef..31e07c4602 100644 --- a/examples/entityScripts/lightController.js +++ b/examples/entityScripts/lightController.js @@ -132,7 +132,7 @@ this.updateLightIDInUserData(); } else { var that = this; - Script.setTimeout(function() { that.maybeUpdateLightIDInUserData() }, 500); + Script.setTimeout(function() { that.maybeUpdateLightIDInUserData() }, 500); } } @@ -213,6 +213,10 @@ this.preload = function(entityID) { this.preOperation(entityID); }; + this.unload = function(){ + Entities.deleteEntity(this.lightID); + } + this.clickReleaseOnEntity = function(entityID, mouseEvent) { this.preOperation(entityID); diff --git a/examples/users.js b/examples/users.js index ebd59886aa..2bc69d1638 100644 --- a/examples/users.js +++ b/examples/users.js @@ -11,8 +11,11 @@ var usersWindow = (function () { - var WINDOW_WIDTH_2D = 160, + var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/", + + WINDOW_WIDTH_2D = 160, WINDOW_MARGIN_2D = 12, + WINDOW_BASE_MARGIN_2D = 6, // A little less is needed in order look correct WINDOW_FONT_2D = { size: 12 }, WINDOW_FOREGROUND_COLOR_2D = { red: 240, green: 240, blue: 240 }, WINDOW_FOREGROUND_ALPHA_2D = 0.9, @@ -22,6 +25,14 @@ var usersWindow = (function () { WINDOW_BACKGROUND_ALPHA_2D = 0.7, windowPane2D, windowHeading2D, + MINIMIZE_BUTTON_SVG = HIFI_PUBLIC_BUCKET + "images/tools/min-max-toggle.svg", + MINIMIZE_BUTTON_SVG_WIDTH = 17.1, + MINIMIZE_BUTTON_SVG_HEIGHT = 32.5, + MINIMIZE_BUTTON_WIDTH_2D = 14, + MINIMIZE_BUTTON_HEIGHT_2D = MINIMIZE_BUTTON_WIDTH_2D, + MINIMIZE_BUTTON_COLOR_2D = { red: 255, green: 255, blue: 255 }, + MINIMIZE_BUTTON_ALPHA_2D = 0.9, + minimizeButton2D, SCROLLBAR_BACKGROUND_WIDTH_2D = 12, SCROLLBAR_BACKGROUND_COLOR_2D = { red: 80, green: 80, blue: 80 }, SCROLLBAR_BACKGROUND_ALPHA_2D = 0.8, @@ -65,6 +76,7 @@ var usersWindow = (function () { MENU_ITEM_AFTER = "Chat...", isVisible = true, + isMinimized = false, viewportHeight, isMirrorDisplay = false, @@ -77,7 +89,6 @@ var usersWindow = (function () { scrollbarBarClickedAt, // 0.0 .. 1.0 scrollbarValue = 0.0, // 0.0 .. 1.0 - HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/", RADIO_BUTTON_SVG = HIFI_PUBLIC_BUCKET + "images/radio-button.svg", RADIO_BUTTON_SVG_DIAMETER = 14, RADIO_BUTTON_DISPLAY_SCALE = 0.7, // 1.0 = windowTextHeight @@ -89,9 +100,15 @@ var usersWindow = (function () { nonUsersHeight, maxWindowHeight; + if (isMinimized) { + windowHeight = windowTextHeight + WINDOW_MARGIN_2D + WINDOW_BASE_MARGIN_2D; + return; + } + // Reserve 5 lines for window heading plus visibility heading and controls // Subtract windowLineSpacing for both end of user list and end of controls - nonUsersHeight = 5 * windowLineHeight - 2 * windowLineSpacing + VISIBILITY_SPACER_2D + 2 * WINDOW_MARGIN_2D; + nonUsersHeight = 5 * windowLineHeight - 2 * windowLineSpacing + VISIBILITY_SPACER_2D + WINDOW_MARGIN_2D + + WINDOW_BASE_MARGIN_2D; // Limit window to height of viewport minus VU meter and mirror if displayed windowHeight = linesOfUsers.length * windowLineHeight + nonUsersHeight; @@ -102,7 +119,7 @@ var usersWindow = (function () { windowHeight = Math.max(Math.min(windowHeight, maxWindowHeight), nonUsersHeight); // Corresponding number of users to actually display - numUsersToDisplay = Math.max(Math.round((windowHeight - nonUsersHeight) / windowLineHeight), 0); + numUsersToDisplay = Math.max(Math.floor((windowHeight - nonUsersHeight) / windowLineHeight), 0); isUsingScrollbars = 0 < numUsersToDisplay && numUsersToDisplay < linesOfUsers.length; if (isUsingScrollbars) { firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay)); @@ -123,6 +140,10 @@ var usersWindow = (function () { y: viewportHeight - windowHeight + WINDOW_MARGIN_2D }); + Overlays.editOverlay(minimizeButton2D, { + y: viewportHeight - windowHeight + WINDOW_MARGIN_2D / 2 + }); + scrollbarBackgroundPosition.y = viewportHeight - windowHeight + WINDOW_MARGIN_2D + windowTextHeight; Overlays.editOverlay(scrollbarBackground2D, { y: scrollbarBackgroundPosition.y @@ -133,10 +154,10 @@ var usersWindow = (function () { y: scrollbarBarPosition.y }); Overlays.editOverlay(visibilityHeading2D, { - y: viewportHeight - 4 * windowLineHeight + windowLineSpacing - WINDOW_MARGIN_2D + y: viewportHeight - 4 * windowLineHeight + windowLineSpacing - WINDOW_BASE_MARGIN_2D }); for (i = 0; i < visibilityControls2D.length; i += 1) { - y = viewportHeight - (3 - i) * windowLineHeight + windowLineSpacing - WINDOW_MARGIN_2D; + y = viewportHeight - (3 - i) * windowLineHeight + windowLineSpacing - WINDOW_BASE_MARGIN_2D; Overlays.editOverlay(visibilityControls2D[i].radioOverlay, { y: y }); Overlays.editOverlay(visibilityControls2D[i].textOverlay, { y: y }); } @@ -166,29 +187,43 @@ var usersWindow = (function () { reducedTextWidth, i; - maxTextWidth = WINDOW_WIDTH_2D - (isUsingScrollbars ? SCROLLBAR_BACKGROUND_WIDTH_2D : 0) - 2 * WINDOW_MARGIN_2D; - ellipsisWidth = Overlays.textSize(windowPane2D, "...").width; - reducedTextWidth = maxTextWidth - ellipsisWidth; + if (!isMinimized) { + maxTextWidth = WINDOW_WIDTH_2D - (isUsingScrollbars ? SCROLLBAR_BACKGROUND_WIDTH_2D : 0) - 2 * WINDOW_MARGIN_2D; + ellipsisWidth = Overlays.textSize(windowPane2D, "...").width; + reducedTextWidth = maxTextWidth - ellipsisWidth; - for (i = 0; i < numUsersToDisplay; i += 1) { - user = usersOnline[linesOfUsers[firstUserToDisplay + i]]; - userText = user.text; - textWidth = user.textWidth; + for (i = 0; i < numUsersToDisplay; i += 1) { + user = usersOnline[linesOfUsers[firstUserToDisplay + i]]; + userText = user.text; + textWidth = user.textWidth; - if (textWidth > maxTextWidth) { - // Trim and append "..." to fit window width - maxTextWidth = maxTextWidth - Overlays.textSize(windowPane2D, "...").width; - while (textWidth > reducedTextWidth) { - userText = userText.slice(0, -1); - textWidth = Overlays.textSize(windowPane2D, userText).width; + if (textWidth > maxTextWidth) { + // Trim and append "..." to fit window width + maxTextWidth = maxTextWidth - Overlays.textSize(windowPane2D, "...").width; + while (textWidth > reducedTextWidth) { + userText = userText.slice(0, -1); + textWidth = Overlays.textSize(windowPane2D, userText).width; + } + userText += "..."; } - userText += "..."; + + displayText += "\n" + userText; } - displayText += "\n" + userText; - } + displayText = displayText.slice(1); // Remove leading "\n". - displayText = displayText.slice(1); // Remove leading "\n". + scrollbarBackgroundHeight = numUsersToDisplay * windowLineHeight - windowLineSpacing / 2; + Overlays.editOverlay(scrollbarBackground2D, { + height: scrollbarBackgroundHeight, + visible: isUsingScrollbars + }); + scrollbarBarHeight = Math.max(numUsersToDisplay / linesOfUsers.length * scrollbarBackgroundHeight, + SCROLLBAR_BAR_MIN_HEIGHT); + Overlays.editOverlay(scrollbarBar2D, { + height: scrollbarBarHeight, + visible: isUsingScrollbars + }); + } Overlays.editOverlay(windowPane2D, { height: windowHeight, @@ -198,20 +233,6 @@ var usersWindow = (function () { Overlays.editOverlay(windowHeading2D, { text: linesOfUsers.length > 0 ? "Users online" : "No users online" }); - - scrollbarBackgroundHeight = numUsersToDisplay * windowLineHeight - windowLineSpacing / 2; - Overlays.editOverlay(scrollbarBackground2D, { - height: scrollbarBackgroundHeight, - visible: isUsingScrollbars - }); - scrollbarBarHeight = Math.max(numUsersToDisplay / linesOfUsers.length * scrollbarBackgroundHeight, - SCROLLBAR_BAR_MIN_HEIGHT); - Overlays.editOverlay(scrollbarBar2D, { - height: scrollbarBarHeight, - visible: isUsingScrollbars - }); - - updateOverlayPositions(); } function pollUsers() { @@ -264,6 +285,7 @@ var usersWindow = (function () { calculateWindowHeight(); updateUsersDisplay(); + updateOverlayPositions(); } else { print("Error: Request for users status returned " + usersRequest.status + " " + usersRequest.statusText); @@ -289,9 +311,22 @@ var usersWindow = (function () { } } - function setVisible(visible) { + function updateOverlayVisibility() { var i; + Overlays.editOverlay(windowPane2D, { visible: isVisible }); + Overlays.editOverlay(windowHeading2D, { visible: isVisible }); + Overlays.editOverlay(minimizeButton2D, { visible: isVisible }); + Overlays.editOverlay(scrollbarBackground2D, { visible: isVisible && isUsingScrollbars && !isMinimized }); + Overlays.editOverlay(scrollbarBar2D, { visible: isVisible && isUsingScrollbars && !isMinimized }); + Overlays.editOverlay(visibilityHeading2D, { visible: isVisible && !isMinimized }); + for (i = 0; i < visibilityControls2D.length; i += 1) { + Overlays.editOverlay(visibilityControls2D[i].radioOverlay, { visible: isVisible && !isMinimized }); + Overlays.editOverlay(visibilityControls2D[i].textOverlay, { visible: isVisible && !isMinimized }); + } + } + + function setVisible(visible) { isVisible = visible; if (isVisible) { @@ -303,15 +338,15 @@ var usersWindow = (function () { usersTimer = null; } - Overlays.editOverlay(windowPane2D, { visible: isVisible }); - Overlays.editOverlay(windowHeading2D, { visible: isVisible }); - Overlays.editOverlay(scrollbarBackground2D, { visible: isVisible && isUsingScrollbars }); - Overlays.editOverlay(scrollbarBar2D, { visible: isVisible && isUsingScrollbars }); - Overlays.editOverlay(visibilityHeading2D, { visible: isVisible }); - for (i = 0; i < visibilityControls2D.length; i += 1) { - Overlays.editOverlay(visibilityControls2D[i].radioOverlay, { visible: isVisible }); - Overlays.editOverlay(visibilityControls2D[i].textOverlay, { visible: isVisible }); - } + updateOverlayVisibility(); + } + + function setMinimized(minimized) { + isMinimized = minimized; + Overlays.editOverlay(minimizeButton2D, { + subImage: { y: isMinimized ? MINIMIZE_BUTTON_SVG_HEIGHT / 2 : 0 } + }); + updateOverlayVisibility(); } function onMenuItemEvent(event) { @@ -360,6 +395,8 @@ var usersWindow = (function () { //print("Go to " + usersOnline[linesOfUsers[userClicked]].username); location.goToUser(usersOnline[linesOfUsers[userClicked]].username); } + + return; } visibilityChanged = false; @@ -376,6 +413,15 @@ var usersWindow = (function () { visibilityControls2D[i].selected = clickedOverlay === visibilityControls2D[i].textOverlay; } updateVisibilityControls(); + return; + } + + if (clickedOverlay === minimizeButton2D) { + setMinimized(!isMinimized); + calculateWindowHeight(); + updateOverlayPositions(); + updateUsersDisplay(); + return; } if (clickedOverlay === scrollbarBar2D) { @@ -384,6 +430,7 @@ var usersWindow = (function () { backgroundAlpha: SCROLLBAR_BAR_SELECTED_ALPHA_2D }); isMovingScrollbar = true; + return; } if (clickedOverlay === scrollbarBackground2D) { @@ -398,6 +445,7 @@ var usersWindow = (function () { firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay)); updateOverlayPositions(); updateUsersDisplay(); + return; } } @@ -492,7 +540,19 @@ var usersWindow = (function () { backgroundAlpha: 0.0, text: "No users online", font: WINDOW_FONT_2D, - visible: isVisible + visible: isVisible && !isMinimized + }); + + minimizeButton2D = Overlays.addOverlay("image", { + x: WINDOW_WIDTH_2D - WINDOW_MARGIN_2D / 2 - MINIMIZE_BUTTON_WIDTH_2D, + y: viewportHeight, + width: MINIMIZE_BUTTON_WIDTH_2D, + height: MINIMIZE_BUTTON_HEIGHT_2D, + imageURL: MINIMIZE_BUTTON_SVG, + subImage: { x: 0, y: 0, width: MINIMIZE_BUTTON_SVG_WIDTH, height: MINIMIZE_BUTTON_SVG_HEIGHT / 2 }, + color: MINIMIZE_BUTTON_COLOR_2D, + alpha: MINIMIZE_BUTTON_ALPHA_2D, + visible: isVisible && !isMinimized }); scrollbarBackgroundPosition = { @@ -507,7 +567,7 @@ var usersWindow = (function () { backgroundColor: SCROLLBAR_BACKGROUND_COLOR_2D, backgroundAlpha: SCROLLBAR_BACKGROUND_ALPHA_2D, text: "", - visible: isVisible && isUsingScrollbars + visible: isVisible && isUsingScrollbars && !isMinimized }); scrollbarBarPosition = { @@ -522,7 +582,7 @@ var usersWindow = (function () { backgroundColor: SCROLLBAR_BAR_COLOR_2D, backgroundAlpha: SCROLLBAR_BAR_ALPHA_2D, text: "", - visible: isVisible && isUsingScrollbars + visible: isVisible && isUsingScrollbars && !isMinimized }); visibilityHeading2D = Overlays.addOverlay("text", { @@ -537,7 +597,7 @@ var usersWindow = (function () { backgroundAlpha: 0.0, text: "I am visible to:", font: WINDOW_FONT_2D, - visible: isVisible + visible: isVisible && !isMinimized }); myVisibility = GlobalServices.findableBy; @@ -561,7 +621,8 @@ var usersWindow = (function () { height: RADIO_BUTTON_SVG_DIAMETER }, color: WINDOW_HEADING_COLOR_2D, - alpha: WINDOW_FOREGROUND_ALPHA_2D + alpha: WINDOW_FOREGROUND_ALPHA_2D, + visible: isVisible && !isMinimized }), textOverlay: Overlays.addOverlay("text", { x: WINDOW_MARGIN_2D, @@ -575,7 +636,7 @@ var usersWindow = (function () { backgroundAlpha: 0.0, text: optionText, font: WINDOW_FONT_2D, - visible: isVisible + visible: isVisible && !isMinimized }), selected: myVisibility === VISIBILITY_VALUES[0] }]; @@ -634,6 +695,7 @@ var usersWindow = (function () { Script.clearTimeout(usersTimer); Overlays.deleteOverlay(windowPane2D); Overlays.deleteOverlay(windowHeading2D); + Overlays.deleteOverlay(minimizeButton2D); Overlays.deleteOverlay(scrollbarBackground2D); Overlays.deleteOverlay(scrollbarBar2D); Overlays.deleteOverlay(visibilityHeading2D); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eb427737e1..e1f66e1e89 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -136,6 +137,13 @@ #include "ui/StandAloneJSConsole.h" #include "ui/Stats.h" +// ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU +#if defined(Q_OS_WIN) +extern "C" { + _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; +} +#endif + using namespace std; // Starfield information @@ -241,7 +249,7 @@ bool setupEssentials(int& argc, char** argv) { auto jsConsole = DependencyManager::set(); auto dialogsManager = DependencyManager::set(); auto bandwidthRecorder = DependencyManager::set(); - auto resouceCacheSharedItems = DependencyManager::set(); + auto resourceCacheSharedItems = DependencyManager::set(); auto entityScriptingInterface = DependencyManager::set(); auto windowScriptingInterface = DependencyManager::set(); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -418,7 +426,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle); // set the account manager's root URL and trigger a login request if we don't have the access token - accountManager.setAuthURL(DEFAULT_NODE_AUTH_URL); + accountManager.setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL); UserActivityLogger::getInstance().launch(applicationVersion()); // once the event loop has started, check and signal for an access token @@ -646,6 +654,11 @@ void Application::initializeGL() { } #endif + qDebug() << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); + qDebug() << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); + qDebug() << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR)); + qDebug() << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER)); + #ifdef WIN32 GLenum err = glewInit(); if (GLEW_OK != err) { diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 3a61f69dee..dc5427ab48 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -685,6 +685,10 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) { * joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform; } + // Each joint contributes its point to the bounding box + glm::vec3 jointPosition = extractTranslation(transforms[i]); + totalExtents.addPoint(jointPosition); + Shape* shape = _shapes[i]; if (!shape) { continue; @@ -694,8 +698,6 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) { // that contains the sphere centered at the end of the joint with radius of the bone. // TODO: skip hand and arm shapes for bounding box calculation - glm::vec3 jointPosition = extractTranslation(transforms[i]); - int type = shape->getType(); if (type == CAPSULE_SHAPE) { // add the two furthest surface points of the capsule diff --git a/interface/src/ui/DataWebDialog.cpp b/interface/src/ui/DataWebDialog.cpp index e28dcf8df7..f405ef50c5 100644 --- a/interface/src/ui/DataWebDialog.cpp +++ b/interface/src/ui/DataWebDialog.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include "Application.h" #include "DataWebPage.h" @@ -39,7 +39,7 @@ DataWebDialog* DataWebDialog::dialogForPath(const QString& path, connect(dialogWebView->page()->mainFrame(), &QWebFrame::javaScriptWindowObjectCleared, dialogWebView, &DataWebDialog::addJavascriptObjectsToWindow); - QUrl dataWebUrl(DEFAULT_NODE_AUTH_URL); + QUrl dataWebUrl(NetworkingConstants::METAVERSE_SERVER_URL); dataWebUrl.setPath(path); qDebug() << "Opening a data web dialog for" << dataWebUrl.toString(); diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 4e7a4a7dc9..690489fdb2 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include "Application.h" @@ -23,7 +24,7 @@ #include "LoginDialog.h" #include "UIUtil.h" -const QString FORGOT_PASSWORD_URL = "https://metaverse.highfidelity.com/users/password/new"; +const QString FORGOT_PASSWORD_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/users/password/new"; LoginDialog::LoginDialog(QWidget* parent) : FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP), diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 058e02b507..95ca30a90f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -101,7 +101,7 @@ void EntityTreeRenderer::init() { _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE); connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity); - connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::checkAndCallPreload); + connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity); connect(entityTree, &EntityTree::entityScriptChanging, this, &EntityTreeRenderer::entitySciptChanging); connect(entityTree, &EntityTree::changingEntityID, this, &EntityTreeRenderer::changingEntityID); } @@ -193,7 +193,7 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity, bool isPre // can accomplish all we need to here with just the script "text" and the ID. EntityItemID entityID = entity->getEntityItemID(); QString entityScript = entity->getScript(); - + if (_entityScripts.contains(entityID)) { EntityScriptDetails details = _entityScripts[entityID]; @@ -217,7 +217,6 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity, bool isPre if (isPending && isPreload && isURL) { _waitingOnPreload.insert(url, entityID); - } auto scriptCache = DependencyManager::get(); @@ -941,6 +940,10 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { _entityScripts.remove(entityID); } +void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) { + checkAndCallPreload(entityID); +} + void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) { if (_tree && !_shuttingDown) { checkAndCallUnload(entityID); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 12d5f6e166..e8d70c9df9 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -105,6 +105,7 @@ signals: void leaveEntity(const EntityItemID& entityItemID); public slots: + void addingEntity(const EntityItemID& entityID); void deletingEntity(const EntityItemID& entityID); void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID); void entitySciptChanging(const EntityItemID& entityID); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 2b65081185..2353a20e7d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -61,7 +61,7 @@ void RenderableModelEntityItem::remapTextures() { } if (!_model->isLoadedWithTextures()) { - return; // nothing to do if the model has not yet loaded it's default textures + return; // nothing to do if the model has not yet loaded its default textures } if (!_originalTexturesRead && _model->isLoadedWithTextures()) { @@ -220,7 +220,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { // if we have a URL, then we will want to end up returning a model... if (!getModelURL().isEmpty()) { - // if we have a previously allocated model, but it's URL doesn't match + // if we have a previously allocated model, but its URL doesn't match // then we need to let our renderer update our model for us. if (_model && QUrl(getModelURL()) != _model->getURL()) { result = _model = _myRenderer->updateModel(_model, getModelURL(), getCollisionModelURL()); @@ -293,7 +293,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { } if (_model->getCollisionURL().isEmpty()) { - // no model url, so we're ready to compute a shape. + // no collision-model url, so we're ready to compute a shape (of type None). return true; } @@ -312,35 +312,30 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { info.setParams(getShapeType(), 0.5f * getDimensions()); } else { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); - const FBXGeometry& fbxGeometry = collisionNetworkGeometry->getFBXGeometry(); + const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); + + const QSharedPointer renderNetworkGeometry = _model->getGeometry(); + const FBXGeometry& renderGeometry = renderNetworkGeometry->getFBXGeometry(); - AABox aaBox; _points.clear(); unsigned int i = 0; // the way OBJ files get read, each section under a "g" line is its own meshPart. We only expect // to find one actual "mesh" (with one or more meshParts in it), but we loop over the meshes, just in case. - foreach (const FBXMesh& mesh, fbxGeometry.meshes) { + foreach (const FBXMesh& mesh, collisionGeometry.meshes) { // each meshPart is a convex hull foreach (const FBXMeshPart &meshPart, mesh.parts) { QVector pointsInPart; // run through all the triangles and (uniquely) add each point to the hull unsigned int triangleCount = meshPart.triangleIndices.size() / 3; - assert((unsigned int)meshPart.triangleIndices.size() == triangleCount*3); for (unsigned int j = 0; j < triangleCount; j++) { unsigned int p0Index = meshPart.triangleIndices[j*3]; unsigned int p1Index = meshPart.triangleIndices[j*3+1]; unsigned int p2Index = meshPart.triangleIndices[j*3+2]; - assert(p0Index < (unsigned int)mesh.vertices.size()); - assert(p1Index < (unsigned int)mesh.vertices.size()); - assert(p2Index < (unsigned int)mesh.vertices.size()); glm::vec3 p0 = mesh.vertices[p0Index]; glm::vec3 p1 = mesh.vertices[p1Index]; glm::vec3 p2 = mesh.vertices[p2Index]; - aaBox += p0; - aaBox += p1; - aaBox += p2; if (!pointsInPart.contains(p0)) { pointsInPart << p0; } @@ -360,18 +355,10 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { unsigned int p1Index = meshPart.quadIndices[j*4+1]; unsigned int p2Index = meshPart.quadIndices[j*4+2]; unsigned int p3Index = meshPart.quadIndices[j*4+3]; - assert(p0Index < (unsigned int)mesh.vertices.size()); - assert(p1Index < (unsigned int)mesh.vertices.size()); - assert(p2Index < (unsigned int)mesh.vertices.size()); - assert(p3Index < (unsigned int)mesh.vertices.size()); glm::vec3 p0 = mesh.vertices[p0Index]; glm::vec3 p1 = mesh.vertices[p1Index]; glm::vec3 p2 = mesh.vertices[p2Index]; glm::vec3 p3 = mesh.vertices[p3Index]; - aaBox += p0; - aaBox += p1; - aaBox += p2; - aaBox += p3; if (!pointsInPart.contains(p0)) { pointsInPart << p0; } @@ -386,6 +373,11 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } } + if (pointsInPart.size() == 0) { + qDebug() << "Warning -- meshPart has no faces"; + continue; + } + // add next convex hull QVector newMeshPoints; _points << newMeshPoints; @@ -394,11 +386,14 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { } } - // make sure we aren't about to divide by zero - glm::vec3 aaBoxDim = aaBox.getDimensions(); - aaBoxDim = glm::clamp(aaBoxDim, glm::vec3(FLT_EPSILON), aaBoxDim); + // We expect that the collision model will have the same units and will be displaced + // from its origin in the same way the visual model is. The visual model has + // been centered and probably scaled. We take the scaling and offset which were applied + // to the visual model and apply them to the collision model (without regard for the + // collision model's extents). + + glm::vec3 scale = _dimensions / renderGeometry.getUnscaledMeshExtents().size(); - glm::vec3 scale = _dimensions / aaBoxDim; // multiply each point by scale before handing the point-set off to the physics engine for (int i = 0; i < _points.size(); i++) { for (int j = 0; j < _points[i].size(); j++) { diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 5624e0765b..c41b9a5c41 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -23,6 +23,7 @@ EntityScriptingInterface::EntityScriptingInterface() : { auto nodeList = DependencyManager::get(); connect(nodeList.data(), &NodeList::canAdjustLocksChanged, this, &EntityScriptingInterface::canAdjustLocksChanged); + connect(nodeList.data(), &NodeList::canRezChanged, this, &EntityScriptingInterface::canRezChanged); } void EntityScriptingInterface::queueEntityMessage(PacketType packetType, @@ -30,12 +31,15 @@ void EntityScriptingInterface::queueEntityMessage(PacketType packetType, getEntityPacketSender()->queueEditEntityMessage(packetType, entityID, properties); } - bool EntityScriptingInterface::canAdjustLocks() { auto nodeList = DependencyManager::get(); return nodeList->getThisNodeCanAdjustLocks(); } +bool EntityScriptingInterface::canRez() { + auto nodeList = DependencyManager::get(); + return nodeList->getThisNodeCanRez(); +} void EntityScriptingInterface::setEntityTree(EntityTree* modelTree) { if (_entityTree) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 5e75e2ae0d..075f5a712b 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -66,6 +66,9 @@ public slots: // returns true if the DomainServer will allow this Node/Avatar to make changes Q_INVOKABLE bool canAdjustLocks(); + // returns true if the DomainServer will allow this Node/Avatar to rez new entities + Q_INVOKABLE bool canRez(); + /// adds a model with the specific properties Q_INVOKABLE EntityItemID addEntity(const EntityItemProperties& properties); @@ -117,6 +120,7 @@ signals: void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void canAdjustLocksChanged(bool canAdjustLocks); + void canRezChanged(bool canRez); void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 266aa2bdce..c4b12f2059 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -404,7 +404,8 @@ void EntityTree::handleAddEntityResponse(const QByteArray& packet) { EntityItem* foundEntity = NULL; EntityItemID creatorTokenVersion = searchEntityID.convertToCreatorTokenVersion(); EntityItemID knownIDVersion = searchEntityID.convertToKnownIDVersion(); - + + _changedEntityIDs[creatorTokenVersion] = knownIDVersion; // First look for and find the "viewed version" of this entity... it's possible we got // the known ID version sent to us between us creating our local version, and getting this @@ -592,6 +593,9 @@ EntityItem* EntityTree::findEntityByEntityItemID(const EntityItemID& entityID) / EntityTreeElement* containingElement = getContainingElement(entityID); if (containingElement) { foundEntity = containingElement->getEntityWithEntityItemID(entityID); + if (!foundEntity && _changedEntityIDs.contains(entityID)) { + foundEntity = containingElement->getEntityWithEntityItemID(_changedEntityIDs[entityID]); + } } return foundEntity; } @@ -655,12 +659,14 @@ int EntityTree::processEditPacketData(PacketType packetType, const unsigned char qDebug() << "User attempted to edit an unknown entity. ID:" << entityItemID; } } else { - // this is a new entity... assign a new entityID - entityItemID = assignEntityID(entityItemID); - EntityItem* newEntity = addEntity(entityItemID, properties); - if (newEntity) { - newEntity->markAsChangedOnServer(); - notifyNewlyCreatedEntity(*newEntity, senderNode); + if (senderNode->getCanRez()) { + // this is a new entity... assign a new entityID + entityItemID = assignEntityID(entityItemID); + EntityItem* newEntity = addEntity(entityItemID, properties); + if (newEntity) { + newEntity->markAsChangedOnServer(); + notifyNewlyCreatedEntity(*newEntity, senderNode); + } } } } @@ -958,6 +964,12 @@ EntityTreeElement* EntityTree::getContainingElement(const EntityItemID& entityIt creatorTokenOnly.isKnownID = false; element = _entityToElementMap.value(creatorTokenOnly); } + + // If we still didn't find the entity, but the ID was in our changed entityIDs, search for the new ID version + if (!element && _changedEntityIDs.contains(entityItemID)) { + element = getContainingElement(_changedEntityIDs[entityItemID]); + } + return element; } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 29fecc88b4..c49cfb2600 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -195,6 +195,7 @@ private: EntityItemFBXService* _fbxService; QHash _entityToElementMap; + QHash _changedEntityIDs; EntitySimulation* _simulation; diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index db2733f27b..c87a942baa 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -27,7 +27,8 @@ public: enum SpecialToken { NO_TOKEN = -1, NO_PUSHBACKED_TOKEN = -1, - DATUM_TOKEN = 0x100 + DATUM_TOKEN = 0x100, + COMMENT_TOKEN = 0x101 }; int nextToken(); const QByteArray& getDatum() const { return _datum; } @@ -35,11 +36,13 @@ public: void skipLine() { _device->readLine(); } void pushBackToken(int token) { _pushedBackToken = token; } void ungetChar(char ch) { _device->ungetChar(ch); } + const QString getComment() const { return _comment; } private: QIODevice* _device; QByteArray _datum; int _pushedBackToken; + QString _comment; }; @@ -56,9 +59,11 @@ int OBJTokenizer::nextToken() { continue; // skip whitespace } switch (ch) { - case '#': - _device->readLine(); // skip the comment - break; + case '#': { + _comment = _device->readLine(); // skip the comment + qDebug() << "COMMENT:" << _comment; + return COMMENT_TOKEN; + } case '\"': _datum = ""; @@ -104,7 +109,8 @@ bool OBJTokenizer::isNextTokenFloat() { } bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, - FBXGeometry &geometry, QVector& faceNormals, QVector& faceNormalIndexes) { + FBXGeometry &geometry, QVector& faceNormals, QVector& faceNormalIndexes, + float& scaleGuess) { FBXMesh &mesh = geometry.meshes[0]; mesh.parts.append(FBXMeshPart()); FBXMeshPart &meshPart = mesh.parts.last(); @@ -128,7 +134,17 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0)); while (true) { - if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { + int tokenType = tokenizer.nextToken(); + if (tokenType == OBJTokenizer::COMMENT_TOKEN) { + if (tokenizer.getComment().contains("This file uses centimeters as units")) { + scaleGuess = 1.0f / 100.0f; + } + if (tokenizer.getComment().contains("This file uses millimeters as units")) { + scaleGuess = 1.0f / 1000.0f; + } + continue; + } + if (tokenType != OBJTokenizer::DATUM_TOKEN) { result = false; break; } @@ -192,6 +208,7 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, while (true) { if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { if (indices.count() == 0) { + // nonsense, bail out. goto done; } break; @@ -266,22 +283,22 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, } } else { // something we don't (yet) care about - qDebug() << "OBJ parser is skipping a line with" << token; + // qDebug() << "OBJ parser is skipping a line with" << token; tokenizer.skipLine(); } } done: + + if (meshPart.triangleIndices.size() == 0 && meshPart.quadIndices.size() == 0) { + // empty mesh? + mesh.parts.pop_back(); + } + return result; } -FBXGeometry extractOBJGeometry(const FBXNode& node, const QVariantHash& mapping) { - FBXGeometry geometry; - return geometry; -} - - FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping) { QBuffer buffer(const_cast(&model)); buffer.open(QIODevice::ReadOnly); @@ -294,24 +311,30 @@ FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping) { OBJTokenizer tokenizer(device); QVector faceNormalIndexes; QVector faceNormals; + float scaleGuess = 1.0f; faceNormalIndexes.clear(); geometry.meshExtents.reset(); geometry.meshes.append(FBXMesh()); - - try { // call parseOBJGroup as long as it's returning true. Each successful call will // add a new meshPart to the geometry's single mesh. bool success = true; while (success) { - success = parseOBJGroup(tokenizer, mapping, geometry, faceNormals, faceNormalIndexes); + success = parseOBJGroup(tokenizer, mapping, geometry, faceNormals, faceNormalIndexes, scaleGuess); } FBXMesh &mesh = geometry.meshes[0]; + // if we got a hint about units, scale all the points + if (scaleGuess != 1.0f) { + for (int i = 0; i < mesh.vertices.size(); i++) { + mesh.vertices[i] *= scaleGuess; + } + } + mesh.meshExtents.reset(); foreach (const glm::vec3& vertex, mesh.vertices) { mesh.meshExtents.addPoint(vertex); diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 3c27c4644c..f8b297c025 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -33,8 +33,7 @@ AddressManager::AddressManager() : _rootPlaceName(), _rootPlaceID(), _positionGetter(NULL), - _orientationGetter(NULL), - _localDSPortSharedMem(NULL) + _orientationGetter(NULL) { connect(qApp, &QCoreApplication::aboutToQuit, this, &AddressManager::storeCurrentAddress); } @@ -331,13 +330,6 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) { quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; - if (domainHostname == "localhost") { - auto nodeList = DependencyManager::get(); - nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, - _localDSPortSharedMem, - domainPort); - } - if (!hostnameRegex.cap(2).isEmpty()) { domainPort = (qint16) hostnameRegex.cap(2).toInt(); } diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index a2522afcbc..db1cd6a3c8 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -95,8 +95,6 @@ private: QUuid _rootPlaceID; PositionGetter _positionGetter; OrientationGetter _orientationGetter; - - QSharedMemory* _localDSPortSharedMem; // memory shared with domain server }; #endif // hifi_AddressManager_h diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 0877f657e1..35ef7d8e2c 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -47,6 +47,7 @@ public: void setSockAddr(const HifiSockAddr& sockAddr, const QString& hostname); unsigned short getPort() const { return _sockAddr.getPort(); } + void setPort(quint16 port) { _sockAddr.setPort(port); } const QUuid& getAssignmentUUID() const { return _assignmentUUID; } void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; } diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index ebd10b67a6..42a20aac03 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -36,8 +36,6 @@ const char SOLO_NODE_TYPES[2] = { NodeType::AudioMixer }; -const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://metaverse.highfidelity.com"); - LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort) : linkedDataCreateCallback(NULL), _sessionUUID(), @@ -49,7 +47,8 @@ LimitedNodeList::LimitedNodeList(unsigned short socketListenPort, unsigned short _publicSockAddr(), _stunSockAddr(STUN_SERVER_HOSTNAME, STUN_SERVER_PORT), _packetStatTimer(), - _thisNodeCanAdjustLocks(false) + _thisNodeCanAdjustLocks(false), + _thisNodeCanRez(true) { static bool firstCall = true; if (firstCall) { @@ -108,6 +107,13 @@ void LimitedNodeList::setThisNodeCanAdjustLocks(bool canAdjustLocks) { } } +void LimitedNodeList::setThisNodeCanRez(bool canRez) { + if (_thisNodeCanRez != canRez) { + _thisNodeCanRez = canRez; + emit canRezChanged(canRez); + } +} + QUdpSocket& LimitedNodeList::getDTLSSocket() { if (!_dtlsSocket) { // DTLS socket getter called but no DTLS socket exists, create it now @@ -392,8 +398,9 @@ void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { _nodeMutex.unlock(); - QWriteLocker writeLocker(&_nodeMutex); + _nodeMutex.lockForWrite(); _nodeHash.unsafe_erase(it); + _nodeMutex.unlock(); handleNodeKill(matchingNode); } else { @@ -416,7 +423,7 @@ void LimitedNodeList::handleNodeKill(const SharedNodePointer& node) { SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, - bool canAdjustLocks) { + bool canAdjustLocks, bool canRez) { NodeHash::const_iterator it = _nodeHash.find(uuid); if (it != _nodeHash.end()) { @@ -425,11 +432,12 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t matchingNode->setPublicSocket(publicSocket); matchingNode->setLocalSocket(localSocket); matchingNode->setCanAdjustLocks(canAdjustLocks); + matchingNode->setCanRez(canRez); return matchingNode; } else { // we didn't have this node, so add them - Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, canAdjustLocks); + Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, canAdjustLocks, canRez); SharedNodePointer newNodePointer(newNode); _nodeHash.insert(UUIDNodePair(newNode->getUUID(), newNodePointer)); diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 532e8ffcf4..80ceccc407 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -42,8 +42,6 @@ const quint64 NODE_SILENCE_THRESHOLD_MSECS = 2 * 1000; extern const char SOLO_NODE_TYPES[2]; -extern const QUrl DEFAULT_NODE_AUTH_URL; - const char DEFAULT_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost"; const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; @@ -86,6 +84,9 @@ public: bool getThisNodeCanAdjustLocks() const { return _thisNodeCanAdjustLocks; } void setThisNodeCanAdjustLocks(bool canAdjustLocks); + + bool getThisNodeCanRez() const { return _thisNodeCanRez; } + void setThisNodeCanRez(bool canRez); void rebindNodeSocket(); QUdpSocket& getNodeSocket() { return _nodeSocket; } @@ -116,7 +117,8 @@ public: SharedNodePointer sendingNodeForPacket(const QByteArray& packet); SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, - const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, bool canAdjustLocks); + const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, + bool canAdjustLocks, bool canRez); const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; } const HifiSockAddr& getSTUNSockAddr() const { return _stunSockAddr; } @@ -208,6 +210,7 @@ signals: void publicSockAddrChanged(const HifiSockAddr& publicSockAddr); void canAdjustLocksChanged(bool canAdjustLocks); + void canRezChanged(bool canRez); void dataSent(const quint8 channel_type, const int bytes); void dataReceived(const quint8 channel_type, const int bytes); @@ -243,6 +246,7 @@ protected: QElapsedTimer _packetStatTimer; bool _thisNodeCanAdjustLocks; + bool _thisNodeCanRez; template void eachNodeHashIterator(IteratorLambda functor) { diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h new file mode 100644 index 0000000000..a1940611bc --- /dev/null +++ b/libraries/networking/src/NetworkingConstants.h @@ -0,0 +1,21 @@ +// +// NetworkingConstants.h +// libraries/networking/src +// +// Created by Stephen Birarda on 2015-03-31. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_NetworkingConstants_h +#define hifi_NetworkingConstants_h + +#include + +namespace NetworkingConstants { + const QUrl METAVERSE_SERVER_URL = QUrl("https://metaverse.highfidelity.com"); +} + +#endif // hifi_NetworkingConstants_h \ No newline at end of file diff --git a/libraries/networking/src/Node.cpp b/libraries/networking/src/Node.cpp index 0304defb55..defcd0035b 100644 --- a/libraries/networking/src/Node.cpp +++ b/libraries/networking/src/Node.cpp @@ -41,7 +41,7 @@ const QString& NodeType::getNodeTypeName(NodeType_t nodeType) { } Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, - const HifiSockAddr& localSocket, bool canAdjustLocks) : + const HifiSockAddr& localSocket, bool canAdjustLocks, bool canRez) : NetworkPeer(uuid, publicSocket, localSocket), _type(type), _activeSocket(NULL), @@ -53,7 +53,8 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket, _clockSkewUsec(0), _mutex(), _clockSkewMovingPercentile(30, 0.8f), // moving 80th percentile of 30 samples - _canAdjustLocks(canAdjustLocks) + _canAdjustLocks(canAdjustLocks), + _canRez(canRez) { } @@ -133,6 +134,7 @@ QDataStream& operator<<(QDataStream& out, const Node& node) { out << node._publicSocket; out << node._localSocket; out << node._canAdjustLocks; + out << node._canRez; return out; } @@ -143,6 +145,7 @@ QDataStream& operator>>(QDataStream& in, Node& node) { in >> node._publicSocket; in >> node._localSocket; in >> node._canAdjustLocks; + in >> node._canRez; return in; } diff --git a/libraries/networking/src/Node.h b/libraries/networking/src/Node.h index fa77540c96..420c52b423 100644 --- a/libraries/networking/src/Node.h +++ b/libraries/networking/src/Node.h @@ -45,7 +45,7 @@ class Node : public NetworkPeer { Q_OBJECT public: Node(const QUuid& uuid, NodeType_t type, - const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, bool canAdjustLocks); + const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, bool canAdjustLocks, bool canRez); ~Node(); bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; } @@ -79,6 +79,9 @@ public: void setCanAdjustLocks(bool canAdjustLocks) { _canAdjustLocks = canAdjustLocks; } bool getCanAdjustLocks() { return _canAdjustLocks; } + + void setCanRez(bool canRez) { _canRez = canRez; } + bool getCanRez() { return _canRez; } void activatePublicSocket(); void activateLocalSocket(); @@ -105,6 +108,7 @@ private: QMutex _mutex; MovingPercentile _clockSkewMovingPercentile; bool _canAdjustLocks; + bool _canRez; }; QDebug operator<<(QDebug debug, const Node &message); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index e63f230f6e..307ba93c88 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -277,6 +277,23 @@ void NodeList::sendDomainServerCheckIn() { if (!_domainHandler.isConnected()) { qDebug() << "Sending connect request to domain-server at" << _domainHandler.getHostname(); + + // is this our localhost domain-server? + // if so we need to make sure we have an up-to-date local port in case it restarted + + if (_domainHandler.getSockAddr().getAddress() == QHostAddress::LocalHost + || _domainHandler.getHostname() == "localhost") { + + static QSharedMemory* localDSPortSharedMem = NULL; + + quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; + getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, + localDSPortSharedMem, + domainPort); + qDebug() << "Local domain-server port read from shared memory (or default) is" << domainPort; + _domainHandler.setPort(domainPort); + } + } // construct the DS check in packet @@ -386,6 +403,10 @@ int NodeList::processDomainServerList(const QByteArray& packet) { bool thisNodeCanAdjustLocks; packetStream >> thisNodeCanAdjustLocks; setThisNodeCanAdjustLocks(thisNodeCanAdjustLocks); + + bool thisNodeCanRez; + packetStream >> thisNodeCanRez; + setThisNodeCanRez(thisNodeCanRez); // pull each node in the packet while(packetStream.device()->pos() < packet.size()) { @@ -394,8 +415,9 @@ int NodeList::processDomainServerList(const QByteArray& packet) { QUuid nodeUUID, connectionUUID; HifiSockAddr nodePublicSocket, nodeLocalSocket; bool canAdjustLocks; + bool canRez; - packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> canAdjustLocks; + packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> canAdjustLocks >> canRez; // if the public socket address is 0 then it's reachable at the same IP // as the domain server @@ -403,7 +425,8 @@ int NodeList::processDomainServerList(const QByteArray& packet) { nodePublicSocket.setAddress(_domainHandler.getIP()); } - SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket, canAdjustLocks); + SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, + nodeLocalSocket, canAdjustLocks, canRez); packetStream >> connectionUUID; node->setConnectionSecret(connectionUUID); diff --git a/libraries/networking/src/OAuthNetworkAccessManager.cpp b/libraries/networking/src/OAuthNetworkAccessManager.cpp index 89a73d5984..fa6f3b8340 100644 --- a/libraries/networking/src/OAuthNetworkAccessManager.cpp +++ b/libraries/networking/src/OAuthNetworkAccessManager.cpp @@ -15,6 +15,7 @@ #include "AccountManager.h" #include "LimitedNodeList.h" +#include "NetworkingConstants.h" #include "SharedUtil.h" #include "OAuthNetworkAccessManager.h" @@ -33,7 +34,8 @@ QNetworkReply* OAuthNetworkAccessManager::createRequest(QNetworkAccessManager::O QIODevice* outgoingData) { AccountManager& accountManager = AccountManager::getInstance(); - if (accountManager.hasValidAccessToken() && req.url().host() == DEFAULT_NODE_AUTH_URL.host()) { + if (accountManager.hasValidAccessToken() + && req.url().host() == NetworkingConstants::METAVERSE_SERVER_URL.host()) { QNetworkRequest authenticatedRequest(req); authenticatedRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); authenticatedRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 78a27af686..af6308d72f 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -64,7 +64,7 @@ PacketVersion versionForPacketType(PacketType type) { return 2; case PacketTypeDomainList: case PacketTypeDomainListRequest: - return 4; + return 5; case PacketTypeCreateAssignment: case PacketTypeRequestAssignment: return 2; diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 739e587f5f..9cf0d53244 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -70,6 +70,7 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& bool delayLoad, void* extra) { QSharedPointer resource = _resources.value(url); if (!resource.isNull()) { + removeUnusedResource(resource); return resource; } @@ -83,16 +84,14 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& return getResource(fallback, QUrl(), delayLoad); } - if (resource.isNull()) { - resource = createResource(url, fallback.isValid() ? - getResource(fallback, QUrl(), true) : QSharedPointer(), delayLoad, extra); - resource->setSelf(resource); - resource->setCache(this); - _resources.insert(url, resource); - - } else { - removeUnusedResource(resource); - } + resource = createResource(url, fallback.isValid() ? + getResource(fallback, QUrl(), true) : QSharedPointer(), delayLoad, extra); + resource->setSelf(resource); + resource->setCache(this); + _resources.insert(url, resource); + removeUnusedResource(resource); + resource->ensureLoading(); + return resource; } @@ -134,7 +133,7 @@ void ResourceCache::reserveUnusedResource(qint64 resourceSize) { } void ResourceCache::attemptRequest(Resource* resource) { - auto sharedItems = DependencyManager::get(); + auto sharedItems = DependencyManager::get(); if (_requestLimit <= 0) { // wait until a slot becomes available sharedItems->_pendingRequests.append(resource); @@ -147,7 +146,7 @@ void ResourceCache::attemptRequest(Resource* resource) { void ResourceCache::requestCompleted(Resource* resource) { - auto sharedItems = DependencyManager::get(); + auto sharedItems = DependencyManager::get(); sharedItems->_loadingRequests.removeOne(resource); _requestLimit++; diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index c7aceb2e1a..ebe2c6e684 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -48,14 +48,14 @@ static const qint64 MAX_UNUSED_MAX_SIZE = 10 * BYTES_PER_GIGABYTES; // ResourceCache derived classes. Since we can't count on the ordering of // static members destruction, we need to use this Dependency manager implemented // object instead -class ResouceCacheSharedItems : public Dependency { +class ResourceCacheSharedItems : public Dependency { SINGLETON_DEPENDENCY public: QList > _pendingRequests; QList _loadingRequests; private: - ResouceCacheSharedItems() { } - virtual ~ResouceCacheSharedItems() { } + ResourceCacheSharedItems() { } + virtual ~ResourceCacheSharedItems() { } }; @@ -71,10 +71,10 @@ public: qint64 getUnusedResourceCacheSize() const { return _unusedResourcesMaxSize; } static const QList& getLoadingRequests() - { return DependencyManager::get()->_loadingRequests; } + { return DependencyManager::get()->_loadingRequests; } static int getPendingRequestCount() - { return DependencyManager::get()->_pendingRequests.size(); } + { return DependencyManager::get()->_pendingRequests.size(); } ResourceCache(QObject* parent = NULL); virtual ~ResourceCache(); diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 65feaa7ea3..d714194b2e 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -864,7 +864,7 @@ void CharacterController::updateShapeIfNecessary() { void CharacterController::preSimulation(btScalar timeStep) { if (_enabled && _dynamicsWorld) { glm::quat rotation = _avatarData->getOrientation(); - btVector3 _currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS); + _currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS); glm::vec3 position = _avatarData->getPosition() + rotation * _shapeLocalOffset; btVector3 walkVelocity = glmToBullet(_avatarData->getVelocity()); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index ffa84adbdf..f46bd689d4 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -535,10 +535,13 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit } void DeferredLightingEffect::setAmbientLightMode(int preset) { - if ((preset >= -1) && (preset < model::SphericalHarmonics::NUM_PRESET)) { + if ((preset >= 0) && (preset < model::SphericalHarmonics::NUM_PRESET)) { _ambientLightMode = preset; auto light = _allocatedLights.front(); light->setAmbientSpherePreset(model::SphericalHarmonics::Preset(preset % model::SphericalHarmonics::NUM_PRESET)); + } else { + // force to preset 0 + setAmbientLightMode(0); } } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index c74f714e8d..98843cc87f 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1775,10 +1775,10 @@ QSharedPointer GeometryCache::getGeometry(const QUrl& url, cons return getResource(url, fallback, delayLoad, NULL).staticCast(); } -QSharedPointer GeometryCache::createResource(const QUrl& url, - const QSharedPointer& fallback, bool delayLoad, const void* extra) { +QSharedPointer GeometryCache::createResource(const QUrl& url, const QSharedPointer& fallback, + bool delayLoad, const void* extra) { QSharedPointer geometry(new NetworkGeometry(url, fallback.staticCast(), delayLoad), - &Resource::allReferencesCleared); + &Resource::allReferencesCleared); geometry->setLODParent(geometry); return geometry.staticCast(); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 81c9f9448c..e9cfdaf345 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -2372,7 +2372,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - bool forceRenderSomeMeshes) { + bool forceRenderMeshes) { PROFILE_RANGE(__FUNCTION__); int meshPartsRendered = 0; @@ -2395,7 +2395,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, - args, locations, skinLocations, forceRenderSomeMeshes); + args, locations, skinLocations, forceRenderMeshes); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2403,7 +2403,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - Locations* locations, SkinLocations* skinLocations, bool forceRenderSomeMeshes) { + Locations* locations, SkinLocations* skinLocations, bool forceRenderMeshes) { PROFILE_RANGE(__FUNCTION__); auto textureCache = DependencyManager::get(); @@ -2439,21 +2439,14 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod // if we got here, then check to see if this mesh is in view if (args) { bool shouldRender = true; - bool forceRender = false; args->_meshesConsidered++; if (args->_viewFrustum) { - // NOTE: This is a hack to address the fact that for avatar meshes, the _calculatedMeshBoxes can be wrong - // for some meshes. Those meshes where the mesh's modelTransform is the identity matrix, and will have - // incorrectly calculated mesh boxes. In this case, we will ignore the box and assume it's visible. - if (forceRenderSomeMeshes && (geometry.meshes.at(i).modelTransform == glm::mat4())) { - forceRender = true; - } - - shouldRender = forceRender || args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE; + shouldRender = forceRenderMeshes || + args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE; - if (shouldRender && !forceRender) { + if (shouldRender && !forceRenderMeshes) { float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter()); shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), distance); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 3b4cbdd450..299853ec9d 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -460,14 +460,14 @@ private: bool renderCore(float alpha, RenderMode mode, RenderArgs* args); int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL, - bool forceRenderSomeMeshes = false); + bool forceRenderMeshes = false); void setupBatchTransform(gpu::Batch& batch); QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned); int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, Locations* locations, SkinLocations* skinLocations, - bool forceRenderSomeMeshes = false); + bool forceRenderMeshes = false); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, diff --git a/libraries/script-engine/src/XMLHttpRequestClass.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp index 3054472a3c..ae0486dd0c 100644 --- a/libraries/script-engine/src/XMLHttpRequestClass.cpp +++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp @@ -17,12 +17,13 @@ #include #include +#include #include #include "XMLHttpRequestClass.h" #include "ScriptEngine.h" -const QString METAVERSE_API_URL = "https://metaverse.highfidelity.com/api/"; +const QString METAVERSE_API_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/api/"; Q_DECLARE_METATYPE(QByteArray*) diff --git a/libraries/shared/src/Extents.h b/libraries/shared/src/Extents.h index 66b33114f7..024d72013a 100644 --- a/libraries/shared/src/Extents.h +++ b/libraries/shared/src/Extents.h @@ -48,7 +48,7 @@ public: void rotate(const glm::quat& rotation); glm::vec3 size() const { return maximum - minimum; } - float largestDimension () const {glm::vec3 s = size(); return glm::max(s[0], s[1], s[2]); } + float largestDimension() const {glm::vec3 s = size(); return glm::max(s[0], s[1], s[2]); } /// \return new Extents which is original rotated around orign by rotation Extents getRotated(const glm::quat& rotation) const { diff --git a/libraries/shared/src/SettingInterface.cpp b/libraries/shared/src/SettingInterface.cpp index 0ef22e3fcb..217a8f00b2 100644 --- a/libraries/shared/src/SettingInterface.cpp +++ b/libraries/shared/src/SettingInterface.cpp @@ -1,6 +1,6 @@ // // SettingInterface.cpp -// +// libraries/shared/src // // Created by Clement on 2/2/15. // Copyright 2015 High Fidelity, Inc. @@ -9,7 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - #include #include #include @@ -23,8 +22,16 @@ namespace Setting { // cleans up the settings private instance. Should only be run once at closing down. void cleanupPrivateInstance() { - delete privateInstance; - privateInstance = nullptr; + // grab the thread before we nuke the instance + QThread* settingsManagerThread = privateInstance->thread(); + + // tell the private instance to clean itself up on its thread + privateInstance->deleteLater(); + privateInstance = NULL; + + // quit the settings manager thread and wait on it to make sure it's gone + settingsManagerThread->quit(); + settingsManagerThread->wait(); } // Sets up the settings private instance. Should only be run once at startup diff --git a/libraries/shared/src/StreamUtils.cpp b/libraries/shared/src/StreamUtils.cpp index f58115d288..b2ea5d95a4 100644 --- a/libraries/shared/src/StreamUtils.cpp +++ b/libraries/shared/src/StreamUtils.cpp @@ -66,7 +66,9 @@ QDataStream& operator>>(QDataStream& in, glm::quat& quaternion) { } // less common utils can be enabled with DEBUG -#ifdef DEBUG +// FIXME, remove the second defined clause once these compile, or remove the +// functions. +#if defined(DEBUG) && defined(FIXED_STREAMS) std::ostream& operator<<(std::ostream& s, const CollisionInfo& c) { s << "{penetration=" << c._penetration