History

Merge branch 'master' into mergeAccountGlobalServices

David Back committed 8 years ago

Commit 3873a8f2 parents c8a0f97 4c96fc2603 files · +20840 −11446Browse files

Showing the changes to interface/src/Application.cpp (1 of 603 files). Show all

Unified · Split

interface/src/Application.cpp+202−207
@@ -120,6 +120,7 @@ · 119 unmodified lines
120120 #include <SceneScriptingInterface.h>
121121 #include <ScriptEngines.h>
122122 #include <ScriptCache.h>
123+#include <ShapeEntityItem.h>
123124 #include <SoundCache.h>
124125 #include <ui/TabletScriptingInterface.h>
125126 #include <ui/ToolbarScriptingInterface.h>
@@ -192,8 +193,13 @@ · 66 unmodified lines
192193 #include <EntityScriptClient.h>
193194 #include <ModelScriptingInterface.h>
194195
196+#include <PickManager.h>
197+#include <PointerManager.h>
195198 #include <raypick/RayPickScriptingInterface.h>
196199 #include <raypick/LaserPointerScriptingInterface.h>
200+#include <raypick/PickScriptingInterface.h>
201+#include <raypick/PointerScriptingInterface.h>
202+#include <raypick/MouseRayPick.h>
197203
198204 #include <FadeEffect.h>
199205
@@ -201,6 +207,8 @@ · 1 unmodified line
201207 #include "commerce/Wallet.h"
202208 #include "commerce/QmlCommerce.h"
203209
210+#include "webbrowser/WebBrowserSuggestionsEngine.h"
211+
204212 // On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
205213 // FIXME seems to be broken.
206214 #if defined(Q_OS_WIN)
@@ -616,6 +624,12 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 409 unmodified lines
616624 DependencyManager::registerInheritance<SpatialParentFinder, InterfaceParentFinder>();
617625
618626 // Set dependencies
627+ DependencyManager::set<PickManager>();
628+ DependencyManager::set<PointerManager>();
629+ DependencyManager::set<LaserPointerScriptingInterface>();
630+ DependencyManager::set<RayPickScriptingInterface>();
631+ DependencyManager::set<PointerScriptingInterface>();
632+ DependencyManager::set<PickScriptingInterface>();
619633 DependencyManager::set<Cursor::Manager>();
620634 DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
621635 DependencyManager::set<StatTracker>();
@@ -690,16 +704,12 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 68 unmodified lines
690704 DependencyManager::set<CloseEventSender>();
691705 DependencyManager::set<ResourceManager>();
692706 DependencyManager::set<SelectionScriptingInterface>();
693− DependencyManager::set<ContextOverlayInterface>();
694707 DependencyManager::set<Ledger>();
695708 DependencyManager::set<Wallet>();
696709 DependencyManager::set<WalletScriptingInterface>();
697710
698711 DependencyManager::set<FadeEffect>();
699712
700− DependencyManager::set<LaserPointerScriptingInterface>();
701− DependencyManager::set<RayPickScriptingInterface>();
702−
703713 return previousSessionCrashed;
704714 }
705715
@@ -758,7 +768,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 52 unmodified lines
758768 _notifiedPacketVersionMismatchThisDomain(false),
759769 _maxOctreePPS(maxOctreePacketsPerSecond.get()),
760770 _lastFaceTrackerUpdate(0),
761− _snapshotSound(nullptr)
771+ _snapshotSound(nullptr),
772+ _sampleSound(nullptr)
773+
762774 {
763775 auto steamClient = PluginManager::getInstance()->getSteamClientPlugin();
764776 setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning()));
@@ -803,7 +815,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 38 unmodified lines
803815 installNativeEventFilter(&MyNativeEventFilter::getInstance());
804816 #endif
805817
806−
807818 _logger = new FileLogger(this);
808819 qInstallMessageHandler(messageHandler);
809820
@@ -891,7 +902,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 81 unmodified lines
891902 connect(audioIO.data(), &AudioClient::muteEnvironmentRequested, [](glm::vec3 position, float radius) {
892903 auto audioClient = DependencyManager::get<AudioClient>();
893904 auto audioScriptingInterface = DependencyManager::get<AudioScriptingInterface>();
894− auto myAvatarPosition = DependencyManager::get<AvatarManager>()->getMyAvatar()->getPosition();
905+ auto myAvatarPosition = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldPosition();
895906 float distance = glm::distance(myAvatarPosition, position);
896907 bool shouldMute = !audioClient->isMuted() && (distance < radius);
897908
@@ -964,8 +975,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 66 unmodified lines
964975 auto addressManager = DependencyManager::get<AddressManager>();
965976
966977 // use our MyAvatar position and quat for address manager path
967− addressManager->setPositionGetter([this]{ return getMyAvatar()->getPosition(); });
968− addressManager->setOrientationGetter([this]{ return getMyAvatar()->getOrientation(); });
978+ addressManager->setPositionGetter([this]{ return getMyAvatar()->getWorldPosition(); });
979+ addressManager->setOrientationGetter([this]{ return getMyAvatar()->getWorldOrientation(); });
969980
970981 connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
971982 connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress);
@@ -980,6 +991,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 8 unmodified lines
980991 connect(myAvatar.get(), &MyAvatar::positionGoneTo,
981992 DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress);
982993
994+ // Inititalize sample before registering
995+ QFileInfo infSample = QFileInfo(PathUtils::resourcesPath() + "sounds/sample.wav");
996+ _sampleSound = DependencyManager::get<SoundCache>()->getSound(QUrl::fromLocalFile(infSample.absoluteFilePath()));
997+
983998 auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
984999 scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine){
9851000 registerScriptEngineWithApplicationServices(engine);
@@ -1012,6 +1027,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 26 unmodified lines
10121027
10131028 // connect to the packet sent signal of the _entityEditSender
10141029 connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent);
1030+ connect(&_entityEditSender, &EntityEditPacketSender::addingEntityWithCertificate, this, &Application::addingEntityWithCertificate);
10151031
10161032 const char** constArgv = const_cast<const char**>(argv);
10171033 QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads");
@@ -1176,12 +1192,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 158 unmodified lines
11761192 _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
11771193 _entityEditSender.setMyAvatar(myAvatar.get());
11781194
1195+ // The entity octree will have to know about MyAvatar for the parentJointName import
1196+ getEntities()->getTree()->setMyAvatar(myAvatar);
1197+ _entityClipboard->setMyAvatar(myAvatar);
1198+
11791199 // For now we're going to set the PPS for outbound packets to be super high, this is
11801200 // probably not the right long term solution. But for now, we're going to do this to
11811201 // allow you to move an entity around in your hand
11821202 _entityEditSender.setPacketsPerSecond(3000); // super high!!
11831203
1204+ // Overlays need to exist before we set the ContextOverlayInterface dependency
11841205 _overlays.init(); // do this before scripts load
1206+ DependencyManager::set<ContextOverlayInterface>();
1207+
11851208 // Make sure we don't time out during slow operations at startup
11861209 updateHeartbeat();
11871210
@@ -1382,7 +1405,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 194 unmodified lines
13821405 // Make sure we don't time out during slow operations at startup
13831406 updateHeartbeat();
13841407
1385−
13861408 QTimer* settingsTimer = new QTimer();
13871409 moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{
13881410 connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer]{
@@ -1455,13 +1477,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 66 unmodified lines
14551477
14561478 // If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it
14571479 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
1458− connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity,
1480+ connect(entityScriptingInterface.data(), &EntityScriptingInterface::mousePressOnEntity,
14591481 [this](const EntityItemID& entityItemID, const PointerEvent& event) {
1460− if (getEntities()->wantsKeyboardFocus(entityItemID)) {
1461− setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
1462− setKeyboardFocusEntity(entityItemID);
1463− } else {
1464− setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
1482+ if (event.shouldFocus()) {
1483+ if (getEntities()->wantsKeyboardFocus(entityItemID)) {
1484+ setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
1485+ setKeyboardFocusEntity(entityItemID);
1486+ } else {
1487+ setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
1488+ }
14651489 }
14661490 });
14671491
@@ -1471,53 +1495,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 3 unmodified lines
14711495 }
14721496 });
14731497
1474− // If the user clicks somewhere where there is NO entity at all, we will release focus
1475− connect(getEntities().data(), &EntityTreeRenderer::mousePressOffEntity, [=]() {
1476− setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
1477− });
1478−
14791498 // Keyboard focus handling for Web overlays.
14801499 auto overlays = &(qApp->getOverlays());
1481−
1482− connect(overlays, &Overlays::mousePressOnOverlay, [=](const OverlayID& overlayID, const PointerEvent& event) {
1483− auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays->getOverlay(overlayID));
1484− // Only Web overlays can have keyboard focus.
1485− if (thisOverlay) {
1486− setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
1487− setKeyboardFocusOverlay(overlayID);
1488− }
1489− });
1490−
14911500 connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) {
14921501 if (overlayID == _keyboardFocusedOverlay.get()) {
14931502 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
14941503 }
14951504 });
14961505
1497− connect(overlays, &Overlays::mousePressOffOverlay, [=]() {
1498− setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
1499− });
1500−
15011506 connect(this, &Application::aboutToQuit, [=]() {
15021507 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
15031508 setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
15041509 });
15051510
1506− connect(overlays,
1507− SIGNAL(mousePressOnOverlay(const OverlayID&, const PointerEvent&)),
1508− DependencyManager::get<ContextOverlayInterface>().data(),
1509− SLOT(contextOverlays_mousePressOnOverlay(const OverlayID&, const PointerEvent&)));
1510−
1511− connect(overlays,
1512− SIGNAL(hoverEnterOverlay(const OverlayID&, const PointerEvent&)),
1513− DependencyManager::get<ContextOverlayInterface>().data(),
1514− SLOT(contextOverlays_hoverEnterOverlay(const OverlayID&, const PointerEvent&)));
1515−
1516− connect(overlays,
1517− SIGNAL(hoverLeaveOverlay(const OverlayID&, const PointerEvent&)),
1518− DependencyManager::get<ContextOverlayInterface>().data(),
1519− SLOT(contextOverlays_hoverLeaveOverlay(const OverlayID&, const PointerEvent&)));
1520−
15211511 // Add periodic checks to send user activity data
15221512 static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000;
15231513 static int NEARBY_AVATAR_RADIUS_METERS = 10;
@@ -1526,7 +1516,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 2 unmodified lines
15261516 static const QString FAST_STATS_ARG = "--fast-heartbeat";
15271517 static int SEND_STATS_INTERVAL_MS = arguments().indexOf(FAST_STATS_ARG) != -1 ? 1000 : 10000;
15281518
1529− static glm::vec3 lastAvatarPosition = myAvatar->getPosition();
1519+ static glm::vec3 lastAvatarPosition = myAvatar->getWorldPosition();
15301520 static glm::mat4 lastHMDHeadPose = getHMDSensorPose();
15311521 static controller::Pose lastLeftHandPose = myAvatar->getLeftHandPose();
15321522 static controller::Pose lastRightHandPose = myAvatar->getRightHandPose();
@@ -1654,7 +1644,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 121 unmodified lines
16541644 properties["bytes_downloaded"] = bytesDownloaded;
16551645
16561646 auto myAvatar = getMyAvatar();
1657− glm::vec3 avatarPosition = myAvatar->getPosition();
1647+ glm::vec3 avatarPosition = myAvatar->getWorldPosition();
16581648 properties["avatar_has_moved"] = lastAvatarPosition != avatarPosition;
16591649 lastAvatarPosition = avatarPosition;
16601650
@@ -1724,8 +1714,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 63 unmodified lines
17241714 lastLeftHandPose = leftHandPose;
17251715 lastRightHandPose = rightHandPose;
17261716
1727− properties["local_socket_changes"] = DependencyManager::get<StatTracker>()->getStat(LOCAL_SOCKET_CHANGE_STAT).toInt();
1728−
17291717 UserActivityLogger::getInstance().logAction("stats", properties);
17301718 });
17311719 sendStatsTimer->start();
@@ -1736,7 +1724,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 4 unmodified lines
17361724 checkNearbyAvatarsTimer->setInterval(CHECK_NEARBY_AVATARS_INTERVAL_MS); // 10 seconds, Qt::CoarseTimer ok
17371725 connect(checkNearbyAvatarsTimer, &QTimer::timeout, this, [this]() {
17381726 auto avatarManager = DependencyManager::get<AvatarManager>();
1739− int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(),
1727+ int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getWorldPosition(),
17401728 NEARBY_AVATAR_RADIUS_METERS) - 1;
17411729 if (nearbyAvatars != lastCountOfNearbyAvatars) {
17421730 lastCountOfNearbyAvatars = nearbyAvatars;
@@ -1786,9 +1774,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 43 unmodified lines
17861774 return entityServerNode && !isPhysicsEnabled();
17871775 });
17881776
1789− QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav");
1790− _snapshotSound = DependencyManager::get<SoundCache>()->getSound(QUrl::fromLocalFile(inf.absoluteFilePath()));
1791−
1777+ QFileInfo infSnap = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav");
1778+ _snapshotSound = DependencyManager::get<SoundCache>()->getSound(QUrl::fromLocalFile(infSnap.absoluteFilePath()));
1779+
17921780 QVariant testProperty = property(hifi::properties::TEST);
17931781 qDebug() << testProperty;
17941782 if (testProperty.isValid()) {
@@ -1825,30 +1813,43 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 30 unmodified lines
18251813
18261814 connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
18271815
1816+ DependencyManager::get<PickManager>()->setShouldPickHUDOperator([&]() { return DependencyManager::get<HMDScriptingInterface>()->isHMDMode(); });
1817+ DependencyManager::get<PickManager>()->setCalculatePos2DFromHUDOperator([&](const glm::vec3& intersection) {
1818+ const glm::vec2 MARGIN(25.0f);
1819+ glm::vec2 maxPos = _controllerScriptingInterface->getViewportDimensions() - MARGIN;
1820+ glm::vec2 pos2D = DependencyManager::get<HMDScriptingInterface>()->overlayFromWorldPoint(intersection);
1821+ return glm::max(MARGIN, glm::min(pos2D, maxPos));
1822+ });
1823+
18281824 // Setup the mouse ray pick and related operators
1829− DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(_rayPickManager.createRayPick(
1830− RayPickFilter(DependencyManager::get<RayPickScriptingInterface>()->PICK_ENTITIES() | DependencyManager::get<RayPickScriptingInterface>()->PICK_INCLUDE_NONCOLLIDABLE()),
1831− 0.0f, true));
1832− DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([&](QUuid rayPickID) {
1825+ DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<MouseRayPick>(
1826+ PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true)));
1827+ DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([&](unsigned int rayPickID) {
18331828 RayToEntityIntersectionResult entityResult;
1834− RayPickResult result = _rayPickManager.getPrevRayPickResult(rayPickID);
1835− entityResult.intersects = result.type != DependencyManager::get<RayPickScriptingInterface>()->INTERSECTED_NONE();
1836− if (entityResult.intersects) {
1837− entityResult.intersection = result.intersection;
1838− entityResult.distance = result.distance;
1839− entityResult.surfaceNormal = result.surfaceNormal;
1840− entityResult.entityID = result.objectID;
1841− entityResult.entity = DependencyManager::get<EntityTreeRenderer>()->getTree()->findEntityByID(entityResult.entityID);
1829+ entityResult.intersects = false;
1830+ auto pickResult = DependencyManager::get<PickManager>()->getPrevPickResultTyped<RayPickResult>(rayPickID);
1831+ if (pickResult) {
1832+ entityResult.intersects = pickResult->type != IntersectionType::NONE;
1833+ if (entityResult.intersects) {
1834+ entityResult.intersection = pickResult->intersection;
1835+ entityResult.distance = pickResult->distance;
1836+ entityResult.surfaceNormal = pickResult->surfaceNormal;
1837+ entityResult.entityID = pickResult->objectID;
1838+ entityResult.entity = DependencyManager::get<EntityTreeRenderer>()->getTree()->findEntityByID(entityResult.entityID);
1839+ }
18421840 }
18431841 return entityResult;
18441842 });
1845− DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([&](QUuid rayPickID, bool value) {
1846− _rayPickManager.setPrecisionPicking(rayPickID, value);
1843+ DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([&](unsigned int rayPickID, bool value) {
1844+ DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value);
18471845 });
18481846
18491847 // Preload Tablet sounds
18501848 DependencyManager::get<TabletScriptingInterface>()->preloadSounds();
18511849
1850+ _pendingIdleEvent = false;
1851+ _pendingRenderEvent = false;
1852+
18521853 qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
18531854 }
18541855
@@ -2247,6 +2248,7 @@ void Application::initializeUi() { · 392 unmodified lines
22472248 QmlCommerce::registerType();
22482249 qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
22492250 qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
2251+ qmlRegisterType<WebBrowserSuggestionsEngine>("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine");
22502252
22512253 auto offscreenUi = DependencyManager::get<OffscreenUi>();
22522254 offscreenUi->create();
@@ -2425,7 +2427,7 @@ void Application::updateCamera(RenderArgs& renderArgs) { · 172 unmodified lines
24252427 auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
24262428 _myCamera.setOrientation(glm::normalize(glmExtractRotation(hmdWorldMat)));
24272429 _myCamera.setPosition(extractTranslation(hmdWorldMat) +
2428− myAvatar->getOrientation() * boomOffset);
2430+ myAvatar->getWorldOrientation() * boomOffset);
24292431 }
24302432 else {
24312433 _myCamera.setOrientation(myAvatar->getHead()->getOrientation());
@@ -2435,13 +2437,13 @@ void Application::updateCamera(RenderArgs& renderArgs) { · 3 unmodified lines
24352437 }
24362438 else {
24372439 _myCamera.setPosition(myAvatar->getDefaultEyePosition()
2438− + myAvatar->getOrientation() * boomOffset);
2440+ + myAvatar->getWorldOrientation() * boomOffset);
24392441 }
24402442 }
24412443 }
24422444 else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
24432445 if (isHMDMode()) {
2444− auto mirrorBodyOrientation = myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));
2446+ auto mirrorBodyOrientation = myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f));
24452447
24462448 glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
24472449 // Mirror HMD yaw and roll
@@ -2464,11 +2466,11 @@ void Application::updateCamera(RenderArgs& renderArgs) { · 16 unmodified lines
24642466 + mirrorBodyOrientation * hmdOffset);
24652467 }
24662468 else {
2467− _myCamera.setOrientation(myAvatar->getOrientation()
2469+ _myCamera.setOrientation(myAvatar->getWorldOrientation()
24682470 * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
24692471 _myCamera.setPosition(myAvatar->getDefaultEyePosition()
24702472 + glm::vec3(0, _raiseMirror * myAvatar->getModelScale(), 0)
2471− + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
2473+ + (myAvatar->getWorldOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) *
24722474 glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
24732475 }
24742476 renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE;
@@ -2478,13 +2480,13 @@ void Application::updateCamera(RenderArgs& renderArgs) { · 3 unmodified lines
24782480 if (cameraEntity != nullptr) {
24792481 if (isHMDMode()) {
24802482 glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix());
2481− _myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation);
2483+ _myCamera.setOrientation(cameraEntity->getWorldOrientation() * hmdRotation);
24822484 glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix());
2483− _myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset));
2485+ _myCamera.setPosition(cameraEntity->getWorldPosition() + (hmdRotation * hmdOffset));
24842486 }
24852487 else {
2486− _myCamera.setOrientation(cameraEntity->getRotation());
2487− _myCamera.setPosition(cameraEntity->getPosition());
2488+ _myCamera.setOrientation(cameraEntity->getWorldOrientation());
2489+ _myCamera.setPosition(cameraEntity->getWorldPosition());
24882490 }
24892491 }
24902492 }
@@ -2717,7 +2719,7 @@ bool Application::importFromZIP(const QString& filePath) { · 226 unmodified lines
27172719 qDebug() << "A zip file has been dropped in: " << filePath;
27182720 QUrl empty;
27192721 // handle Blocks download from Marketplace
2720− if (filePath.contains("vr.google.com/downloads")) {
2722+ if (filePath.contains("poly.google.com/downloads")) {
27212723 addAssetToWorldFromURL(filePath);
27222724 } else {
27232725 qApp->getFileDownloadInterface()->runUnzip(filePath, empty, true, true, false);
@@ -3300,7 +3302,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { · 576 unmodified lines
33003302
33013303 auto offscreenUi = DependencyManager::get<OffscreenUi>();
33023304 auto eventPosition = compositor.getMouseEventPosition(event);
3303− QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget);
3305+ QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition);
33043306 auto button = event->button();
33053307 auto buttons = event->buttons();
33063308 // Determine if the ReticleClick Action is 1 and if so, fake include the LeftMouseButton
@@ -3346,7 +3348,7 @@ void Application::mousePressEvent(QMouseEvent* event) { · 39 unmodified lines
33463348 offscreenUi->unfocusWindows();
33473349
33483350 auto eventPosition = getApplicationCompositor().getMouseEventPosition(event);
3349− QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget);
3351+ QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition);
33503352 QMouseEvent mappedEvent(event->type(),
33513353 transformedPos,
33523354 event->screenPos(), event->button(),
@@ -3376,7 +3378,7 @@ void Application::mousePressEvent(QMouseEvent* event) { · 23 unmodified lines
33763378 void Application::mouseDoublePressEvent(QMouseEvent* event) {
33773379 auto offscreenUi = DependencyManager::get<OffscreenUi>();
33783380 auto eventPosition = getApplicationCompositor().getMouseEventPosition(event);
3379− QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget);
3381+ QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition);
33803382 QMouseEvent mappedEvent(event->type(),
33813383 transformedPos,
33823384 event->screenPos(), event->button(),
@@ -3402,7 +3404,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { · 19 unmodified lines
34023404
34033405 auto offscreenUi = DependencyManager::get<OffscreenUi>();
34043406 auto eventPosition = getApplicationCompositor().getMouseEventPosition(event);
3405− QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget);
3407+ QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition);
34063408 QMouseEvent mappedEvent(event->type(),
34073409 transformedPos,
34083410 event->screenPos(), event->button(),
@@ -3895,16 +3897,16 @@ void Application::idle() { · 486 unmodified lines
38953897 if (!_keyboardFocusedEntity.get().isInvalidID()) {
38963898 auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get());
38973899 if (entity && _keyboardFocusHighlight) {
3898− _keyboardFocusHighlight->setRotation(entity->getRotation());
3899− _keyboardFocusHighlight->setPosition(entity->getPosition());
3900+ _keyboardFocusHighlight->setWorldOrientation(entity->getWorldOrientation());
3901+ _keyboardFocusHighlight->setWorldPosition(entity->getWorldPosition());
39003902 }
39013903 } else {
39023904 // Only Web overlays can have focus.
39033905 auto overlay =
39043906 std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(_keyboardFocusedOverlay.get()));
39053907 if (overlay && _keyboardFocusHighlight) {
3906− _keyboardFocusHighlight->setRotation(overlay->getRotation());
3907− _keyboardFocusHighlight->setPosition(overlay->getPosition());
3908+ _keyboardFocusHighlight->setWorldOrientation(overlay->getWorldOrientation());
3909+ _keyboardFocusHighlight->setWorldPosition(overlay->getWorldPosition());
39083910 }
39093911 }
39103912 }
@@ -4020,6 +4022,7 @@ bool Application::exportEntities(const QString& filename, · 109 unmodified lines
40204022
40214023 auto entityTree = getEntities()->getTree();
40224024 auto exportTree = std::make_shared<EntityTree>();
4025+ exportTree->setMyAvatar(getMyAvatar());
40234026 exportTree->createRootElement();
40244027 glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE);
40254028 bool success = true;
@@ -4038,7 +4041,7 @@ bool Application::exportEntities(const QString& filename, · 12 unmodified lines
40384041 !entityIDs.contains(parentID) ||
40394042 !entityTree->findEntityByEntityItemID(parentID))) {
40404043 // If parent wasn't selected, we want absolute position, which isn't in properties.
4041− auto position = entityItem->getPosition();
4044+ auto position = entityItem->getWorldPosition();
40424045 root.x = glm::min(root.x, position.x);
40434046 root.y = glm::min(root.y, position.y);
40444047 root.z = glm::min(root.z, position.z);
@@ -4201,6 +4204,7 @@ void Application::initDisplay() { · 156 unmodified lines
42014204 }
42024205
42034206 void Application::init() {
4207+
42044208 // Make sure Login state is up to date
42054209 DependencyManager::get<DialogsManager>()->toggleLoginDialog();
42064210
@@ -4227,6 +4231,10 @@ void Application::init() { · 20 unmodified lines
42274231 // fire off an immediate domain-server check in now that settings are loaded
42284232 DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
42294233
4234+ // This allows collision to be set up properly for shape entities supported by GeometryCache.
4235+ // This is before entity setup to ensure that it's ready for whenever instance collision is initialized.
4236+ ShapeEntityItem::setShapeInfoCalulator(ShapeEntityItem::ShapeInfoCalculator(&shapeInfoCalculator));
4237+
42304238 getEntities()->init();
42314239 getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) {
42324240 auto dims = item.getDimensions();
@@ -4236,7 +4244,7 @@ void Application::init() { · 3 unmodified lines
42364244 return 0.0f;
42374245 }
42384246
4239− auto distance = glm::distance(getMyAvatar()->getPosition(), item.getPosition());
4247+ auto distance = glm::distance(getMyAvatar()->getWorldPosition(), item.getWorldPosition());
42404248 return atan2(maxSize, distance);
42414249 });
42424250
@@ -4313,7 +4321,7 @@ void Application::updateMyAvatarLookAtPosition() { · 70 unmodified lines
43134321 // TODO -- this code is probably wrong, getHeadPose() returns something in sensor frame, not avatar
43144322 glm::mat4 headPose = getActiveDisplayPlugin()->getHeadPose();
43154323 glm::quat hmdRotation = glm::quat_cast(headPose);
4316− lookAtSpot = _myCamera.getPosition() + myAvatar->getOrientation() * (hmdRotation * lookAtPosition);
4324+ lookAtSpot = _myCamera.getPosition() + myAvatar->getWorldOrientation() * (hmdRotation * lookAtPosition);
43174325 } else {
43184326 lookAtSpot = myAvatar->getHead()->getEyePosition()
43194327 + (myAvatar->getHead()->getFinalOrientationInWorldFrame() * lookAtPosition);
@@ -4460,7 +4468,7 @@ void Application::cameraModeChanged() { · 140 unmodified lines
44604468 void Application::cameraMenuChanged() {
44614469 auto menu = Menu::getInstance();
44624470 if (menu->isOptionChecked(MenuOption::FullscreenMirror)) {
4463− if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
4471+ if (!isHMDMode() && _myCamera.getMode() != CAMERA_MODE_MIRROR) {
44644472 _myCamera.setMode(CAMERA_MODE_MIRROR);
44654473 getMyAvatar()->reset(false, false, false); // to reset any active MyAvatar::FollowHelpers
44664474 }
@@ -4500,8 +4508,11 @@ void Application::resetPhysicsReadyInformation() { · 33 unmodified lines
45004508
45014509 void Application::reloadResourceCaches() {
45024510 resetPhysicsReadyInformation();
4511+
45034512 // Query the octree to refresh everything in view
45044513 _lastQueriedTime = 0;
4514+ _octreeQuery.incrementConnectionID();
4515+
45054516 queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions);
45064517
45074518 DependencyManager::get<AssetClient>()->clearCache();
@@ -4539,8 +4550,8 @@ void Application::setKeyboardFocusHighlight(const glm::vec3& position, const glm · 31 unmodified lines
45394550 }
45404551
45414552 // Position focus
4542− _keyboardFocusHighlight->setRotation(rotation);
4543− _keyboardFocusHighlight->setPosition(position);
4553+ _keyboardFocusHighlight->setWorldOrientation(rotation);
4554+ _keyboardFocusHighlight->setWorldPosition(position);
45444555 _keyboardFocusHighlight->setDimensions(dimensions);
45454556 _keyboardFocusHighlight->setVisible(true);
45464557 }
@@ -4549,14 +4560,9 @@ QUuid Application::getKeyboardFocusEntity() const { · 2 unmodified lines
45494560 return _keyboardFocusedEntity.get();
45504561 }
45514562
4552−void Application::setKeyboardFocusEntity(QUuid id) {
4553− EntityItemID entityItemID(id);
4554− setKeyboardFocusEntity(entityItemID);
4555−}
4556−
45574563 static const float FOCUS_HIGHLIGHT_EXPANSION_FACTOR = 1.05f;
45584564
4559−void Application::setKeyboardFocusEntity(EntityItemID entityItemID) {
4565+void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) {
45604566 if (_keyboardFocusedEntity.get() != entityItemID) {
45614567 _keyboardFocusedEntity.set(entityItemID);
45624568
@@ -4582,7 +4588,7 @@ void Application::setKeyboardFocusEntity(EntityItemID entityItemID) { · 19 unmodified lines
45824588 }
45834589 _lastAcceptedKeyPress = usecTimestampNow();
45844590
4585− setKeyboardFocusHighlight(entity->getPosition(), entity->getRotation(),
4591+ setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(),
45864592 entity->getDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR);
45874593 }
45884594 }
@@ -4593,7 +4599,7 @@ OverlayID Application::getKeyboardFocusOverlay() { · 4 unmodified lines
45934599 return _keyboardFocusedOverlay.get();
45944600 }
45954601
4596−void Application::setKeyboardFocusOverlay(OverlayID overlayID) {
4602+void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) {
45974603 if (overlayID != _keyboardFocusedOverlay.get()) {
45984604 _keyboardFocusedOverlay.set(overlayID);
45994605
@@ -4619,7 +4625,7 @@ void Application::setKeyboardFocusOverlay(OverlayID overlayID) { · 19 unmodified lines
46194625 if (overlay->getProperty("showKeyboardFocusHighlight").toBool()) {
46204626 auto size = overlay->getSize() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR;
46214627 const float OVERLAY_DEPTH = 0.0105f;
4622− setKeyboardFocusHighlight(overlay->getPosition(), overlay->getRotation(), glm::vec3(size.x, size.y, OVERLAY_DEPTH));
4628+ setKeyboardFocusHighlight(overlay->getWorldPosition(), overlay->getWorldOrientation(), glm::vec3(size.x, size.y, OVERLAY_DEPTH));
46234629 } else if (_keyboardFocusHighlight) {
46244630 _keyboardFocusHighlight->setVisible(false);
46254631 }
@@ -4711,7 +4717,7 @@ void Application::update(float deltaTime) { · 85 unmodified lines
47114717
47124718 controller::InputCalibrationData calibrationData = {
47134719 myAvatar->getSensorToWorldMatrix(),
4714− createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition()),
4720+ createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition()),
47154721 myAvatar->getHMDSensorMatrix(),
47164722 myAvatar->getCenterEyeCalibrationMat(),
47174723 myAvatar->getHeadCalibrationMat(),
@@ -4821,7 +4827,7 @@ void Application::update(float deltaTime) { · 103 unmodified lines
48214827 };
48224828
48234829 // copy controller poses from userInputMapper to myAvatar.
4824− glm::mat4 myAvatarMatrix = createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition());
4830+ glm::mat4 myAvatarMatrix = createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition());
48254831 glm::mat4 worldToSensorMatrix = glm::inverse(myAvatar->getSensorToWorldMatrix());
48264832 glm::mat4 avatarToSensorMatrix = worldToSensorMatrix * myAvatarMatrix;
48274833 for (auto& action : avatarControllerActions) {
@@ -4961,13 +4967,13 @@ void Application::update(float deltaTime) { · 133 unmodified lines
49614967
49624968 // TODO: break these out into distinct perfTimers when they prove interesting
49634969 {
4964− PROFILE_RANGE(app, "RayPickManager");
4965− _rayPickManager.update();
4970+ PROFILE_RANGE(app, "PickManager");
4971+ DependencyManager::get<PickManager>()->update();
49664972 }
49674973
49684974 {
4969− PROFILE_RANGE(app, "LaserPointerManager");
4970− _laserPointerManager.update();
4975+ PROFILE_RANGE(app, "PointerManager");
4976+ DependencyManager::get<PointerManager>()->update();
49714977 }
49724978
49734979 {
@@ -5089,6 +5095,7 @@ void Application::update(float deltaTime) { · 115 unmodified lines
50895095 }
50905096
50915097 this->updateCamera(appRenderArgs._renderArgs);
5098+ appRenderArgs._eyeToWorld = _myCamera.getTransform();
50925099 appRenderArgs._isStereo = false;
50935100
50945101 {
@@ -5436,7 +5443,7 @@ std::shared_ptr<MyAvatar> Application::getMyAvatar() const { · 341 unmodified lines
54365443 }
54375444
54385445 glm::vec3 Application::getAvatarPosition() const {
5439− return getMyAvatar()->getPosition();
5446+ return getMyAvatar()->getWorldPosition();
54405447 }
54415448
54425449 void Application::copyViewFrustum(ViewFrustum& viewOut) const {
@@ -5520,6 +5527,8 @@ void Application::clearDomainOctreeDetails() { · 77 unmodified lines
55205527 DependencyManager::get<ModelCache>()->clearUnusedResources();
55215528 DependencyManager::get<SoundCache>()->clearUnusedResources();
55225529 DependencyManager::get<TextureCache>()->clearUnusedResources();
5530+
5531+ getMyAvatar()->setAvatarEntityDataChanged(true);
55235532 }
55245533
55255534 void Application::clearDomainAvatars() {
@@ -5566,6 +5575,7 @@ void Application::nodeActivated(SharedNodePointer node) { · 40 unmodified lines
55665575 // so we will do a proper query during update
55675576 if (node->getType() == NodeType::EntityServer) {
55685577 _lastQueriedTime = 0;
5578+ _octreeQuery.incrementConnectionID();
55695579 }
55705580
55715581 if (node->getType() == NodeType::AudioMixer) {
@@ -5648,7 +5658,7 @@ bool Application::nearbyEntitiesAreReadyForPhysics() { · 76 unmodified lines
56485658 // whose bounding boxes cannot be computed (it is too loose for our purposes here). Instead we manufacture
56495659 // custom filters and use the general-purpose EntityTree::findEntities(filter, ...)
56505660 QVector<EntityItemPointer> entities;
5651− AABox avatarBox(getMyAvatar()->getPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE));
5661+ AABox avatarBox(getMyAvatar()->getWorldPosition() - glm::vec3(PHYSICS_READY_RANGE), glm::vec3(2 * PHYSICS_READY_RANGE));
56525662 // create two functions that use avatarBox (entityScan and elementScan), the second calls the first
56535663 std::function<bool (EntityItemPointer&)> entityScan = [=](EntityItemPointer& entity) {
56545664 if (entity->shouldBePhysical()) {
@@ -5763,6 +5773,11 @@ int Application::processOctreeStats(ReceivedMessage& message, SharedNodePointer · 108 unmodified lines
57635773 void Application::packetSent(quint64 length) {
57645774 }
57655775
5776+void Application::addingEntityWithCertificate(const QString& certificateID, const QString& placeName) {
5777+ auto ledger = DependencyManager::get<Ledger>();
5778+ ledger->updateLocation(certificateID, placeName);
5779+}
5780+
57665781 void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointer scriptEngine) {
57675782
57685783 scriptEngine->setEmitScriptUpdatesFunction([this]() {
@@ -5845,6 +5860,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 76 unmodified lines
58455860
58465861 scriptEngine->registerGlobalObject("RayPick", DependencyManager::get<RayPickScriptingInterface>().data());
58475862 scriptEngine->registerGlobalObject("LaserPointers", DependencyManager::get<LaserPointerScriptingInterface>().data());
5863+ scriptEngine->registerGlobalObject("Picks", DependencyManager::get<PickScriptingInterface>().data());
5864+ scriptEngine->registerGlobalObject("Pointers", DependencyManager::get<PointerScriptingInterface>().data());
58485865
58495866 // Caches
58505867 scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data());
@@ -5902,6 +5919,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe · 51 unmodified lines
59025919
59035920 qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
59045921
5922+ DependencyManager::get<PickScriptingInterface>()->registerMetaTypes(scriptEngine.data());
5923+
59055924 // connect this script engines printedMessage signal to the global ScriptEngines these various messages
59065925 connect(scriptEngine.data(), &ScriptEngine::printedMessage,
59075926 DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onPrintedMessage);
@@ -6143,46 +6162,60 @@ bool Application::askToReplaceDomainContent(const QString& url) { · 235 unmodified lines
61436162 "and restoring content, visit the documentation page at: ", MAX_CHARACTERS_PER_LINE) +
61446163 "\nhttps://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content";
61456164
6146− bool agreeToReplaceContent = false; // assume false
6147− agreeToReplaceContent = QMessageBox::Yes == OffscreenUi::question("Are you sure you want to replace this domain's content set?",
6148− infoText, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
6149−
6150− if (agreeToReplaceContent) {
6151− // Given confirmation, send request to domain server to replace content
6152− qCDebug(interfaceapp) << "Attempting to replace domain content: " << url;
6153− QByteArray urlData(url.toUtf8());
6154− auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
6155− limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) {
6156− return node->getType() == NodeType::EntityServer && node->getActiveSocket();
6157− }, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) {
6158− auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true);
6159− octreeFilePacket->write(urlData);
6160− limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode);
6161− });
6162− auto addressManager = DependencyManager::get<AddressManager>();
6163− addressManager->handleLookupString(DOMAIN_SPAWNING_POINT);
6164− QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT;
6165− qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress;
6166− DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(newHomeAddress);
6167− methodDetails = "SuccessfulRequestToReplaceContent";
6168− } else {
6169− methodDetails = "UserDeclinedToReplaceContent";
6170− }
6165+ ModalDialogListener* dig = OffscreenUi::asyncQuestion("Are you sure you want to replace this domain's content set?",
6166+ infoText, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
6167+
6168+ QObject::connect(dig, &ModalDialogListener::response, this, [=] (QVariant answer) {
6169+ QString details;
6170+ if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) {
6171+ // Given confirmation, send request to domain server to replace content
6172+ qCDebug(interfaceapp) << "Attempting to replace domain content: " << url;
6173+ QByteArray urlData(url.toUtf8());
6174+ auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
6175+ limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) {
6176+ return node->getType() == NodeType::EntityServer && node->getActiveSocket();
6177+ }, [&urlData, limitedNodeList](const SharedNodePointer& octreeNode) {
6178+ auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true);
6179+ octreeFilePacket->write(urlData);
6180+ limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode);
6181+ });
6182+ auto addressManager = DependencyManager::get<AddressManager>();
6183+ addressManager->handleLookupString(DOMAIN_SPAWNING_POINT);
6184+ QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT;
6185+ qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress;
6186+ DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(newHomeAddress);
6187+ details = "SuccessfulRequestToReplaceContent";
6188+ } else {
6189+ details = "UserDeclinedToReplaceContent";
6190+ }
6191+ QJsonObject messageProperties = {
6192+ { "status", details },
6193+ { "content_set_url", url }
6194+ };
6195+ UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties);
6196+ QObject::disconnect(dig, &ModalDialogListener::response, this, nullptr);
6197+ });
61716198 } else {
61726199 methodDetails = "ContentSetDidNotOriginateFromMarketplace";
6200+ QJsonObject messageProperties = {
6201+ { "status", methodDetails },
6202+ { "content_set_url", url }
6203+ };
6204+ UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties);
61736205 }
61746206 } else {
61756207 methodDetails = "UserDoesNotHavePermissionToReplaceContent";
61766208 static const QString warningMessage = simpleWordWrap("The domain owner must enable 'Replace Content' "
61776209 "permissions for you in this domain's server settings before you can continue.", MAX_CHARACTERS_PER_LINE);
6178− OffscreenUi::warning("You do not have permissions to replace domain content", warningMessage,
6210+ OffscreenUi::asyncWarning("You do not have permissions to replace domain content", warningMessage,
61796211 QMessageBox::Ok, QMessageBox::Ok);
6212+
6213+ QJsonObject messageProperties = {
6214+ { "status", methodDetails },
6215+ { "content_set_url", url }
6216+ };
6217+ UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties);
61806218 }
6181− QJsonObject messageProperties = {
6182− { "status", methodDetails },
6183− { "content_set_url", url }
6184− };
6185− UserActivityLogger::getInstance().logAction("replace_domain_content", messageProperties);
61866219 return true;
61876220 }
61886221
@@ -6253,7 +6286,7 @@ void Application::addAssetToWorldFromURL(QString url) { · 64 unmodified lines
62536286 if (url.contains("filename")) {
62546287 filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL.
62556288 }
6256− if (url.contains("vr.google.com/downloads")) {
6289+ if (url.contains("poly.google.com/downloads")) {
62576290 filename = url.section('/', -1);
62586291 if (url.contains("noDownload")) {
62596292 filename.remove(".zip?noDownload=false");
@@ -6288,7 +6321,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { · 28 unmodified lines
62886321 if (url.contains("filename")) {
62896322 filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL.
62906323 }
6291− if (url.contains("vr.google.com/downloads")) {
6324+ if (url.contains("poly.google.com/downloads")) {
62926325 filename = url.section('/', -1);
62936326 if (url.contains("noDownload")) {
62946327 filename.remove(".zip?noDownload=false");
@@ -6342,20 +6375,14 @@ void Application::addAssetToWorldUnzipFailure(QString filePath) { · 47 unmodified lines
63426375 addAssetToWorldError(filename, "Couldn't unzip file " + filename + ".");
63436376 }
63446377
6345−void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip, bool isBlocks) {
6378+void Application::addAssetToWorld(QString path, QString zipFile, bool isZip, bool isBlocks) {
63466379 // Automatically upload and add asset to world as an alternative manual process initiated by showAssetServerWidget().
63476380 QString mapping;
6348− QString path = filePath;
63496381 QString filename = filenameFromPath(path);
6350− if (isZip) {
6351− QString assetFolder = zipFile.section("/", -1);
6352− assetFolder.remove(".zip");
6353− mapping = "/" + assetFolder + "/" + filename;
6354− } else if (isBlocks) {
6355− qCDebug(interfaceapp) << "Path to asset folder: " << zipFile;
6356− QString assetFolder = zipFile.section('/', -1);
6357− assetFolder.remove(".zip?noDownload=false");
6358− mapping = "/" + assetFolder + "/" + filename;
6382+ if (isZip || isBlocks) {
6383+ QString assetName = zipFile.section("/", -1).remove(QRegExp("[.]zip(.*)$"));
6384+ QString assetFolder = path.section("model_repo/", -1);
6385+ mapping = "/" + assetName + "/" + assetFolder;
63596386 } else {
63606387 mapping = "/" + filename;
63616388 }
@@ -6461,9 +6488,9 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { · 99 unmodified lines
64616488 properties.setShapeType(SHAPE_TYPE_SIMPLE_COMPOUND);
64626489 properties.setCollisionless(true); // Temporarily set so that doesn't collide with avatar.
64636490 properties.setVisible(false); // Temporarily set so that don't see at large unresized dimensions.
6464− glm::vec3 positionOffset = getMyAvatar()->getOrientation() * (getMyAvatar()->getSensorToWorldScale() * glm::vec3(0.0f, 0.0f, -2.0f));
6465− properties.setPosition(getMyAvatar()->getPosition() + positionOffset);
6466− properties.setRotation(getMyAvatar()->getOrientation());
6491+ glm::vec3 positionOffset = getMyAvatar()->getWorldOrientation() * (getMyAvatar()->getSensorToWorldScale() * glm::vec3(0.0f, 0.0f, -2.0f));
6492+ properties.setPosition(getMyAvatar()->getWorldPosition() + positionOffset);
6493+ properties.setRotation(getMyAvatar()->getWorldOrientation());
64676494 properties.setGravity(glm::vec3(0.0f, 0.0f, 0.0f));
64686495 auto entityID = DependencyManager::get<EntityScriptingInterface>()->addEntity(properties);
64696496
@@ -6741,8 +6768,10 @@ void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoA · 271 unmodified lines
67416768 if (autoAdd) {
67426769 if (!unzipFile.isEmpty()) {
67436770 for (int i = 0; i < unzipFile.length(); i++) {
6744− qCDebug(interfaceapp) << "Preparing file for asset server: " << unzipFile.at(i);
6745− addAssetToWorld(unzipFile.at(i), zipFile, isZip, isBlocks);
6771+ if (QFileInfo(unzipFile.at(i)).isFile()) {
6772+ qCDebug(interfaceapp) << "Preparing file for asset server: " << unzipFile.at(i);
6773+ addAssetToWorld(unzipFile.at(i), zipFile, isZip, isBlocks);
6774+ }
67466775 }
67476776 } else {
67486777 addAssetToWorldUnzipFailure(zipFile);
@@ -6804,6 +6833,10 @@ void Application::loadScriptURLDialog() const { · 55 unmodified lines
68046833 });
68056834 }
68066835
6836+SharedSoundPointer Application::getSampleSound() const {
6837+ return _sampleSound;
6838+}
6839+
68076840 void Application::loadLODToolsDialog() {
68086841 auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
68096842 auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet(SYSTEM_TABLET));
@@ -7096,6 +7129,7 @@ DisplayPluginPointer Application::getActiveDisplayPlugin() const { · 286 unmodified lines
70967129 return _displayPlugin;
70977130 }
70987131
7132+static const char* EXCLUSION_GROUP_KEY = "exclusionGroup";
70997133
71007134 static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) {
71017135 auto menu = Menu::getInstance();
@@ -7131,6 +7165,8 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti · 29 unmodified lines
71317165 action->setCheckable(true);
71327166 action->setChecked(active);
71337167 displayPluginGroup->addAction(action);
7168+
7169+ action->setProperty(EXCLUSION_GROUP_KEY, QVariant::fromValue(displayPluginGroup));
71347170 Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name));
71357171 }
71367172
@@ -7285,6 +7321,10 @@ void Application::updateDisplayMode() { · 148 unmodified lines
72857321 menu->setIsOptionChecked(MenuOption::FirstPerson, true);
72867322 cameraMenuChanged();
72877323 }
7324+
7325+ // Remove the mirror camera option from menu if in HMD mode
7326+ auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror);
7327+ mirrorAction->setVisible(!isHmd);
72887328
72897329 Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
72907330 }
@@ -7426,51 +7466,6 @@ bool Application::isForeground() const { · 135 unmodified lines
74267466 return _isForeground && !_window->isMinimized();
74277467 }
74287468
7429−void Application::sendMousePressOnEntity(QUuid id, PointerEvent event) {
7430− EntityItemID entityItemID(id);
7431− emit getEntities()->mousePressOnEntity(entityItemID, event);
7432−}
7433−
7434−void Application::sendMouseMoveOnEntity(QUuid id, PointerEvent event) {
7435− EntityItemID entityItemID(id);
7436− emit getEntities()->mouseMoveOnEntity(entityItemID, event);
7437−}
7438−
7439−void Application::sendMouseReleaseOnEntity(QUuid id, PointerEvent event) {
7440− EntityItemID entityItemID(id);
7441− emit getEntities()->mouseReleaseOnEntity(entityItemID, event);
7442−}
7443−
7444−void Application::sendClickDownOnEntity(QUuid id, PointerEvent event) {
7445− EntityItemID entityItemID(id);
7446− emit getEntities()->clickDownOnEntity(entityItemID, event);
7447−}
7448−
7449−void Application::sendHoldingClickOnEntity(QUuid id, PointerEvent event) {
7450− EntityItemID entityItemID(id);
7451− emit getEntities()->holdingClickOnEntity(entityItemID, event);
7452−}
7453−
7454−void Application::sendClickReleaseOnEntity(QUuid id, PointerEvent event) {
7455− EntityItemID entityItemID(id);
7456− emit getEntities()->clickReleaseOnEntity(entityItemID, event);
7457−}
7458−
7459−void Application::sendHoverEnterEntity(QUuid id, PointerEvent event) {
7460− EntityItemID entityItemID(id);
7461− emit getEntities()->hoverEnterEntity(entityItemID, event);
7462−}
7463−
7464−void Application::sendHoverOverEntity(QUuid id, PointerEvent event) {
7465− EntityItemID entityItemID(id);
7466− emit getEntities()->hoverOverEntity(entityItemID, event);
7467−}
7468−
7469−void Application::sendHoverLeaveEntity(QUuid id, PointerEvent event) {
7470− EntityItemID entityItemID(id);
7471− emit getEntities()->hoverLeaveEntity(entityItemID, event);
7472−}
7473−
74747469 // FIXME? perhaps two, one for the main thread and one for the offscreen UI rendering thread?
74757470 static const int UI_RESERVED_THREADS = 1;
74767471 // Windows won't let you have all the cores