Showing the changes to interface/src/Application.cpp (1 of 184 files). Show all
Unified · Split
| @@ -61,6 +61,7 @@ · 60 unmodified lines | ||
| 61 | 61 | #include <AssetClient.h> |
| 62 | 62 | #include <AssetUpload.h> |
| 63 | 63 | #include <AutoUpdater.h> |
| 64 | +#include <Midi.h> | |
| 64 | 65 | #include <AudioInjectorManager.h> |
| 65 | 66 | #include <AvatarBookmarks.h> |
| 66 | 67 | #include <CursorManager.h> |
| @@ -69,7 +70,7 @@ · 2 unmodified lines | ||
| 69 | 70 | #include <EntityScriptClient.h> |
| 70 | 71 | #include <EntityScriptServerLogClient.h> |
| 71 | 72 | #include <EntityScriptingInterface.h> |
| 72 | −#include <HoverOverlayInterface.h> | |
| 73 | +#include "ui/overlays/ContextOverlayInterface.h" | |
| 73 | 74 | #include <ErrorDialog.h> |
| 74 | 75 | #include <FileScriptingInterface.h> |
| 75 | 76 | #include <Finally.h> |
| @@ -230,6 +231,7 @@ static const QString FBX_EXTENSION = ".fbx"; · 154 unmodified lines | ||
| 230 | 231 | static const QString OBJ_EXTENSION = ".obj"; |
| 231 | 232 | static const QString AVA_JSON_EXTENSION = ".ava.json"; |
| 232 | 233 | static const QString WEB_VIEW_TAG = "noDownload=true"; |
| 234 | +static const QString ZIP_EXTENSION = ".zip"; | |
| 233 | 235 | |
| 234 | 236 | static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; |
| 235 | 237 | |
| @@ -264,7 +266,8 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi · 28 unmodified lines | ||
| 264 | 266 | { JSON_EXTENSION, &Application::importJSONFromURL }, |
| 265 | 267 | { JS_EXTENSION, &Application::askToLoadScript }, |
| 266 | 268 | { FST_EXTENSION, &Application::askToSetAvatarUrl }, |
| 267 | − { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent } | |
| 269 | + { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent }, | |
| 270 | + { ZIP_EXTENSION, &Application::importFromZIP } | |
| 268 | 271 | }; |
| 269 | 272 | |
| 270 | 273 | class DeadlockWatchdogThread : public QThread { |
| @@ -403,6 +406,10 @@ public: · 132 unmodified lines | ||
| 403 | 406 | return true; |
| 404 | 407 | } |
| 405 | 408 | } |
| 409 | + | |
| 410 | + if (message->message == WM_DEVICECHANGE) { | |
| 411 | + Midi::USBchanged(); // re-scan the MIDI bus | |
| 412 | + } | |
| 406 | 413 | } |
| 407 | 414 | return false; |
| 408 | 415 | } |
| @@ -573,6 +580,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 164 unmodified lines | ||
| 573 | 580 | DependencyManager::set<SceneScriptingInterface>(); |
| 574 | 581 | DependencyManager::set<OffscreenUi>(); |
| 575 | 582 | DependencyManager::set<AutoUpdater>(); |
| 583 | + DependencyManager::set<Midi>(); | |
| 576 | 584 | DependencyManager::set<PathUtils>(); |
| 577 | 585 | DependencyManager::set<InterfaceDynamicFactory>(); |
| 578 | 586 | DependencyManager::set<AudioInjectorManager>(); |
| @@ -595,7 +603,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { · 16 unmodified lines | ||
| 595 | 603 | DependencyManager::set<Snapshot>(); |
| 596 | 604 | DependencyManager::set<CloseEventSender>(); |
| 597 | 605 | DependencyManager::set<ResourceManager>(); |
| 598 | − DependencyManager::set<HoverOverlayInterface>(); | |
| 606 | + DependencyManager::set<ContextOverlayInterface>(); | |
| 599 | 607 | |
| 600 | 608 | return previousSessionCrashed; |
| 601 | 609 | } |
| @@ -624,6 +632,7 @@ const float DEFAULT_DESKTOP_TABLET_SCALE_PERCENT = 75.0f; · 22 unmodified lines | ||
| 624 | 632 | const bool DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR = true; |
| 625 | 633 | const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false; |
| 626 | 634 | const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false; |
| 635 | +const QString DEFAULT_CURSOR_NAME = "DEFAULT"; | |
| 627 | 636 | |
| 628 | 637 | Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bool runningMarkerExisted) : |
| 629 | 638 | QApplication(argc, argv), |
| @@ -643,6 +652,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 13 unmodified lines | ||
| 643 | 652 | _hmdTabletBecomesToolbarSetting("hmdTabletBecomesToolbar", DEFAULT_HMD_TABLET_BECOMES_TOOLBAR), |
| 644 | 653 | _preferAvatarFingerOverStylusSetting("preferAvatarFingerOverStylus", DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS), |
| 645 | 654 | _constrainToolbarPosition("toolbar/constrainToolbarToCenterX", true), |
| 655 | + _preferredCursor("preferredCursor", DEFAULT_CURSOR_NAME), | |
| 646 | 656 | _scaleMirror(1.0f), |
| 647 | 657 | _rotateMirror(0.0f), |
| 648 | 658 | _raiseMirror(0.0f), |
| @@ -938,14 +948,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 289 unmodified lines | ||
| 938 | 948 | _glWidget->setFocusPolicy(Qt::StrongFocus); |
| 939 | 949 | _glWidget->setFocus(); |
| 940 | 950 | |
| 941 | −#ifdef Q_OS_MAC | |
| 942 | − auto cursorTarget = _window; // OSX doesn't seem to provide for hiding the cursor only on the GL widget | |
| 943 | −#else | |
| 944 | − // On windows and linux, hiding the top level cursor also means it's invisible when hovering over the | |
| 945 | − // window menu, which is a pain, so only hide it for the GL surface | |
| 946 | − auto cursorTarget = _glWidget; | |
| 947 | −#endif | |
| 948 | − cursorTarget->setCursor(Qt::BlankCursor); | |
| 951 | + showCursor(Cursor::Manager::lookupIcon(_preferredCursor.get())); | |
| 949 | 952 | |
| 950 | 953 | // enable mouse tracking; otherwise, we only get drag events |
| 951 | 954 | _glWidget->setMouseTracking(true); |
| @@ -1329,12 +1332,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 377 unmodified lines | ||
| 1329 | 1332 | // Keyboard focus handling for Web overlays. |
| 1330 | 1333 | auto overlays = &(qApp->getOverlays()); |
| 1331 | 1334 | |
| 1332 | − connect(overlays, &Overlays::mousePressOnOverlay, [=](OverlayID overlayID, const PointerEvent& event) { | |
| 1333 | − setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); | |
| 1334 | − setKeyboardFocusOverlay(overlayID); | |
| 1335 | + connect(overlays, &Overlays::mousePressOnOverlay, [=](const OverlayID& overlayID, const PointerEvent& event) { | |
| 1336 | + auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(overlays->getOverlay(overlayID)); | |
| 1337 | + // Only Web overlays can have keyboard focus. | |
| 1338 | + if (thisOverlay) { | |
| 1339 | + setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); | |
| 1340 | + setKeyboardFocusOverlay(overlayID); | |
| 1341 | + } | |
| 1335 | 1342 | }); |
| 1336 | 1343 | |
| 1337 | − connect(overlays, &Overlays::overlayDeleted, [=](OverlayID overlayID) { | |
| 1344 | + connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) { | |
| 1338 | 1345 | if (overlayID == _keyboardFocusedOverlay.get()) { |
| 1339 | 1346 | setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); |
| 1340 | 1347 | } |
| @@ -1349,6 +1356,21 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 8 unmodified lines | ||
| 1349 | 1356 | setKeyboardFocusEntity(UNKNOWN_ENTITY_ID); |
| 1350 | 1357 | }); |
| 1351 | 1358 | |
| 1359 | + connect(overlays, | |
| 1360 | + SIGNAL(mousePressOnOverlay(const OverlayID&, const PointerEvent&)), | |
| 1361 | + DependencyManager::get<ContextOverlayInterface>().data(), | |
| 1362 | + SLOT(contextOverlays_mousePressOnOverlay(const OverlayID&, const PointerEvent&))); | |
| 1363 | + | |
| 1364 | + connect(overlays, | |
| 1365 | + SIGNAL(hoverEnterOverlay(const OverlayID&, const PointerEvent&)), | |
| 1366 | + DependencyManager::get<ContextOverlayInterface>().data(), | |
| 1367 | + SLOT(contextOverlays_hoverEnterOverlay(const OverlayID&, const PointerEvent&))); | |
| 1368 | + | |
| 1369 | + connect(overlays, | |
| 1370 | + SIGNAL(hoverLeaveOverlay(const OverlayID&, const PointerEvent&)), | |
| 1371 | + DependencyManager::get<ContextOverlayInterface>().data(), | |
| 1372 | + SLOT(contextOverlays_hoverLeaveOverlay(const OverlayID&, const PointerEvent&))); | |
| 1373 | + | |
| 1352 | 1374 | // Add periodic checks to send user activity data |
| 1353 | 1375 | static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000; |
| 1354 | 1376 | static int NEARBY_AVATAR_RADIUS_METERS = 10; |
| @@ -1475,7 +1497,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 120 unmodified lines | ||
| 1475 | 1497 | properties["atp_mapping_requests"] = atpMappingRequests; |
| 1476 | 1498 | |
| 1477 | 1499 | properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false; |
| 1478 | − | |
| 1500 | + | |
| 1479 | 1501 | QJsonObject bytesDownloaded; |
| 1480 | 1502 | bytesDownloaded["atp"] = statTracker->getStat(STAT_ATP_RESOURCE_TOTAL_BYTES).toInt(); |
| 1481 | 1503 | bytesDownloaded["http"] = statTracker->getStat(STAT_HTTP_RESOURCE_TOTAL_BYTES).toInt(); |
| @@ -1743,9 +1765,16 @@ void Application::checkChangeCursor() { · 261 unmodified lines | ||
| 1743 | 1765 | } |
| 1744 | 1766 | } |
| 1745 | 1767 | |
| 1746 | −void Application::showCursor(const QCursor& cursor) { | |
| 1768 | +void Application::showCursor(const Cursor::Icon& cursor) { | |
| 1747 | 1769 | QMutexLocker locker(&_changeCursorLock); |
| 1748 | − _desiredCursor = cursor; | |
| 1770 | + | |
| 1771 | + auto managedCursor = Cursor::Manager::instance().getCursor(); | |
| 1772 | + auto curIcon = managedCursor->getIcon(); | |
| 1773 | + if (curIcon != cursor) { | |
| 1774 | + managedCursor->setIcon(cursor); | |
| 1775 | + curIcon = cursor; | |
| 1776 | + } | |
| 1777 | + _desiredCursor = cursor == Cursor::Icon::SYSTEM ? Qt::ArrowCursor : Qt::BlankCursor; | |
| 1749 | 1778 | _cursorNeedsChanging = true; |
| 1750 | 1779 | } |
| 1751 | 1780 | |
| @@ -2120,7 +2149,6 @@ void Application::initializeUi() { · 368 unmodified lines | ||
| 2120 | 2149 | surfaceContext->setContextProperty("AvatarManager", DependencyManager::get<AvatarManager>().data()); |
| 2121 | 2150 | surfaceContext->setContextProperty("UndoStack", &_undoStackScriptingInterface); |
| 2122 | 2151 | surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data()); |
| 2123 | − surfaceContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data()); | |
| 2124 | 2152 | surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data()); |
| 2125 | 2153 | surfaceContext->setContextProperty("Scene", DependencyManager::get<SceneScriptingInterface>().data()); |
| 2126 | 2154 | surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); |
| @@ -2131,7 +2159,7 @@ void Application::initializeUi() { · 4 unmodified lines | ||
| 2131 | 2159 | surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); |
| 2132 | 2160 | |
| 2133 | 2161 | surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); |
| 2134 | − surfaceContext->setContextProperty("HoverOverlay", DependencyManager::get<HoverOverlayInterface>().data()); | |
| 2162 | + surfaceContext->setContextProperty("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data()); | |
| 2135 | 2163 | |
| 2136 | 2164 | if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { |
| 2137 | 2165 | surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); |
| @@ -2167,9 +2195,11 @@ void Application::initializeUi() { · 29 unmodified lines | ||
| 2167 | 2195 | _window->setMenuBar(new Menu()); |
| 2168 | 2196 | |
| 2169 | 2197 | auto compositorHelper = DependencyManager::get<CompositorHelper>(); |
| 2170 | − connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, [=] { | |
| 2198 | + connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, this, [=] { | |
| 2171 | 2199 | if (isHMDMode()) { |
| 2172 | − showCursor(compositorHelper->getAllowMouseCapture() ? Qt::BlankCursor : Qt::ArrowCursor); | |
| 2200 | + showCursor(compositorHelper->getAllowMouseCapture() ? | |
| 2201 | + Cursor::Manager::lookupIcon(_preferredCursor.get()) : | |
| 2202 | + Cursor::Icon::SYSTEM); | |
| 2173 | 2203 | } |
| 2174 | 2204 | }); |
| 2175 | 2205 | |
| @@ -2235,7 +2265,7 @@ void Application::paintGL() { · 59 unmodified lines | ||
| 2235 | 2265 | QMutexLocker viewLocker(&_viewMutex); |
| 2236 | 2266 | _viewFrustum.calculate(); |
| 2237 | 2267 | } |
| 2238 | − renderArgs = RenderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(), | |
| 2268 | + renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(), | |
| 2239 | 2269 | lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, |
| 2240 | 2270 | RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); |
| 2241 | 2271 | { |
| @@ -2321,7 +2351,7 @@ void Application::paintGL() { · 79 unmodified lines | ||
| 2321 | 2351 | } |
| 2322 | 2352 | } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { |
| 2323 | 2353 | if (isHMDMode()) { |
| 2324 | − auto mirrorBodyOrientation = myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)); | |
| 2354 | + auto mirrorBodyOrientation = myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)); | |
| 2325 | 2355 | |
| 2326 | 2356 | glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix()); |
| 2327 | 2357 | // Mirror HMD yaw and roll |
| @@ -2343,7 +2373,7 @@ void Application::paintGL() { · 15 unmodified lines | ||
| 2343 | 2373 | + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror |
| 2344 | 2374 | + mirrorBodyOrientation * hmdOffset); |
| 2345 | 2375 | } else { |
| 2346 | − _myCamera.setOrientation(myAvatar->getWorldAlignedOrientation() | |
| 2376 | + _myCamera.setOrientation(myAvatar->getOrientation() | |
| 2347 | 2377 | * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); |
| 2348 | 2378 | _myCamera.setPosition(myAvatar->getDefaultEyePosition() |
| 2349 | 2379 | + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) |
| @@ -2511,6 +2541,12 @@ void Application::setPreferAvatarFingerOverStylus(bool value) { · 161 unmodified lines | ||
| 2511 | 2541 | _preferAvatarFingerOverStylusSetting.set(value); |
| 2512 | 2542 | } |
| 2513 | 2543 | |
| 2544 | +void Application::setPreferredCursor(const QString& cursorName) { | |
| 2545 | + qCDebug(interfaceapp) << "setPreferredCursor" << cursorName; | |
| 2546 | + _preferredCursor.set(cursorName.isEmpty() ? DEFAULT_CURSOR_NAME : cursorName); | |
| 2547 | + showCursor(Cursor::Manager::lookupIcon(_preferredCursor.get())); | |
| 2548 | +} | |
| 2549 | + | |
| 2514 | 2550 | void Application::setSettingConstrainToolbarPosition(bool setting) { |
| 2515 | 2551 | _constrainToolbarPosition.set(setting); |
| 2516 | 2552 | DependencyManager::get<OffscreenUi>()->setConstrainToolbarToCenterX(setting); |
| @@ -2744,6 +2780,20 @@ bool Application::importSVOFromURL(const QString& urlString) { · 227 unmodified lines | ||
| 2744 | 2780 | return true; |
| 2745 | 2781 | } |
| 2746 | 2782 | |
| 2783 | +void Application::onPresent(quint32 frameCount) { | |
| 2784 | + if (shouldPaint()) { | |
| 2785 | + postEvent(this, new QEvent(static_cast<QEvent::Type>(Idle)), Qt::HighEventPriority); | |
| 2786 | + postEvent(this, new QEvent(static_cast<QEvent::Type>(Paint)), Qt::HighEventPriority); | |
| 2787 | + } | |
| 2788 | +} | |
| 2789 | + | |
| 2790 | +bool Application::importFromZIP(const QString& filePath) { | |
| 2791 | + qDebug() << "A zip file has been dropped in: " << filePath; | |
| 2792 | + QUrl empty; | |
| 2793 | + qApp->getFileDownloadInterface()->runUnzip(filePath, empty, true, true); | |
| 2794 | + return true; | |
| 2795 | +} | |
| 2796 | + | |
| 2747 | 2797 | bool _renderRequested { false }; |
| 2748 | 2798 | |
| 2749 | 2799 | bool Application::event(QEvent* event) { |
| @@ -2760,23 +2810,9 @@ bool Application::event(QEvent* event) { · 10 unmodified lines | ||
| 2760 | 2810 | // Explicit idle keeps the idle running at a lower interval, but without any rendering |
| 2761 | 2811 | // see (windowMinimizedChanged) |
| 2762 | 2812 | case Event::Idle: |
| 2763 | − { | |
| 2764 | − float nsecsElapsed = (float)_lastTimeUpdated.nsecsElapsed(); | |
| 2765 | − _lastTimeUpdated.start(); | |
| 2766 | − idle(nsecsElapsed); | |
| 2767 | − } | |
| 2768 | − return true; | |
| 2769 | − | |
| 2770 | − case Event::Present: | |
| 2771 | − if (!_renderRequested) { | |
| 2772 | − float nsecsElapsed = (float)_lastTimeUpdated.nsecsElapsed(); | |
| 2773 | − if (shouldPaint(nsecsElapsed)) { | |
| 2774 | − _renderRequested = true; | |
| 2775 | − _lastTimeUpdated.start(); | |
| 2776 | − idle(nsecsElapsed); | |
| 2777 | − postEvent(this, new QEvent(static_cast<QEvent::Type>(Paint)), Qt::HighEventPriority); | |
| 2778 | − } | |
| 2779 | − } | |
| 2813 | + idle(); | |
| 2814 | + // Clear the event queue of pending idle calls | |
| 2815 | + removePostedEvents(this, Idle); | |
| 2780 | 2816 | return true; |
| 2781 | 2817 | |
| 2782 | 2818 | case Event::Paint: |
| @@ -2784,9 +2820,8 @@ bool Application::event(QEvent* event) { · 1 unmodified line | ||
| 2784 | 2820 | // or AvatarInputs will mysteriously move to the bottom-right |
| 2785 | 2821 | AvatarInputs::getInstance()->update(); |
| 2786 | 2822 | paintGL(); |
| 2787 | − // wait for the next present event before starting idle / paint again | |
| 2788 | − removePostedEvents(this, Present); | |
| 2789 | − _renderRequested = false; | |
| 2823 | + // Clear the event queue of pending paint calls | |
| 2824 | + removePostedEvents(this, Paint); | |
| 2790 | 2825 | return true; |
| 2791 | 2826 | |
| 2792 | 2827 | default: |
| @@ -3026,7 +3061,9 @@ void Application::keyPressEvent(QKeyEvent* event) { · 233 unmodified lines | ||
| 3026 | 3061 | break; |
| 3027 | 3062 | |
| 3028 | 3063 | case Qt::Key_F: { |
| 3029 | − _physicsEngine->dumpNextStats(); | |
| 3064 | + if (isOption) { | |
| 3065 | + _physicsEngine->dumpNextStats(); | |
| 3066 | + } | |
| 3030 | 3067 | break; |
| 3031 | 3068 | } |
| 3032 | 3069 | |
| @@ -3070,9 +3107,13 @@ void Application::keyPressEvent(QKeyEvent* event) { · 37 unmodified lines | ||
| 3070 | 3107 | auto cursor = Cursor::Manager::instance().getCursor(); |
| 3071 | 3108 | auto curIcon = cursor->getIcon(); |
| 3072 | 3109 | if (curIcon == Cursor::Icon::DEFAULT) { |
| 3073 | − cursor->setIcon(Cursor::Icon::LINK); | |
| 3110 | + showCursor(Cursor::Icon::RETICLE); | |
| 3111 | + } else if (curIcon == Cursor::Icon::RETICLE) { | |
| 3112 | + showCursor(Cursor::Icon::SYSTEM); | |
| 3113 | + } else if (curIcon == Cursor::Icon::SYSTEM) { | |
| 3114 | + showCursor(Cursor::Icon::LINK); | |
| 3074 | 3115 | } else { |
| 3075 | − cursor->setIcon(Cursor::Icon::DEFAULT); | |
| 3116 | + showCursor(Cursor::Icon::DEFAULT); | |
| 3076 | 3117 | } |
| 3077 | 3118 | } else { |
| 3078 | 3119 | resetSensors(true); |
| @@ -3599,7 +3640,7 @@ bool Application::acceptSnapshot(const QString& urlString) { · 520 unmodified lines | ||
| 3599 | 3640 | |
| 3600 | 3641 | static uint32_t _renderedFrameIndex { INVALID_FRAME }; |
| 3601 | 3642 | |
| 3602 | −bool Application::shouldPaint(float nsecsElapsed) { | |
| 3643 | +bool Application::shouldPaint() { | |
| 3603 | 3644 | if (_aboutToQuit) { |
| 3604 | 3645 | return false; |
| 3605 | 3646 | } |
| @@ -3619,11 +3660,9 @@ bool Application::shouldPaint(float nsecsElapsed) { · 13 unmodified lines | ||
| 3619 | 3660 | (float)paintDelaySamples / paintDelayUsecs << "us"; |
| 3620 | 3661 | } |
| 3621 | 3662 | #endif |
| 3622 | − | |
| 3623 | − float msecondsSinceLastUpdate = nsecsElapsed / NSECS_PER_USEC / USECS_PER_MSEC; | |
| 3624 | − | |
| 3663 | + | |
| 3625 | 3664 | // Throttle if requested |
| 3626 | − if (displayPlugin->isThrottled() && (msecondsSinceLastUpdate < THROTTLED_SIM_FRAME_PERIOD_MS)) { | |
| 3665 | + if (displayPlugin->isThrottled() && (_lastTimeUpdated.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { | |
| 3627 | 3666 | return false; |
| 3628 | 3667 | } |
| 3629 | 3668 | |
| @@ -3840,7 +3879,7 @@ void setupCpuMonitorThread() { · 210 unmodified lines | ||
| 3840 | 3879 | #endif |
| 3841 | 3880 | |
| 3842 | 3881 | |
| 3843 | −void Application::idle(float nsecsElapsed) { | |
| 3882 | +void Application::idle() { | |
| 3844 | 3883 | PerformanceTimer perfTimer("idle"); |
| 3845 | 3884 | |
| 3846 | 3885 | // Update the deadlock watchdog |
| @@ -3897,7 +3936,8 @@ void Application::idle(float nsecsElapsed) { · 50 unmodified lines | ||
| 3897 | 3936 | steamClient->runCallbacks(); |
| 3898 | 3937 | } |
| 3899 | 3938 | |
| 3900 | − float secondsSinceLastUpdate = nsecsElapsed / NSECS_PER_MSEC / MSECS_PER_SECOND; | |
| 3939 | + float secondsSinceLastUpdate = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_MSEC / MSECS_PER_SECOND; | |
| 3940 | + _lastTimeUpdated.start(); | |
| 3901 | 3941 | |
| 3902 | 3942 | // If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus. |
| 3903 | 3943 | if (_keyboardDeviceHasFocus && offscreenUi && offscreenUi->getWindow()->activeFocusItem() != offscreenUi->getRootItem()) { |
| @@ -4131,6 +4171,7 @@ void Application::loadSettings() { · 227 unmodified lines | ||
| 4131 | 4171 | //DependencyManager::get<LODManager>()->setAutomaticLODAdjust(false); |
| 4132 | 4172 | |
| 4133 | 4173 | Menu::getInstance()->loadSettings(); |
| 4174 | + | |
| 4134 | 4175 | // If there is a preferred plugin, we probably messed it up with the menu settings, so fix it. |
| 4135 | 4176 | auto pluginManager = PluginManager::getInstance(); |
| 4136 | 4177 | auto plugins = pluginManager->getPreferredDisplayPlugins(); |
| @@ -4144,24 +4185,44 @@ void Application::loadSettings() { · 7 unmodified lines | ||
| 4144 | 4185 | break; |
| 4145 | 4186 | } |
| 4146 | 4187 | } |
| 4147 | − } else { | |
| 4188 | + } | |
| 4189 | + | |
| 4190 | + Setting::Handle<bool> firstRun { Settings::firstRun, true }; | |
| 4191 | + bool isFirstPerson = false; | |
| 4192 | + if (firstRun.get()) { | |
| 4148 | 4193 | // If this is our first run, and no preferred devices were set, default to |
| 4149 | 4194 | // an HMD device if available. |
| 4150 | − Setting::Handle<bool> firstRun { Settings::firstRun, true }; | |
| 4151 | − if (firstRun.get()) { | |
| 4152 | − auto displayPlugins = pluginManager->getDisplayPlugins(); | |
| 4153 | − for (auto& plugin : displayPlugins) { | |
| 4154 | − if (plugin->isHmd()) { | |
| 4155 | − if (auto action = menu->getActionForOption(plugin->getName())) { | |
| 4156 | − action->setChecked(true); | |
| 4157 | − action->trigger(); | |
| 4158 | − break; | |
| 4159 | − } | |
| 4195 | + auto displayPlugins = pluginManager->getDisplayPlugins(); | |
| 4196 | + for (auto& plugin : displayPlugins) { | |
| 4197 | + if (plugin->isHmd()) { | |
| 4198 | + if (auto action = menu->getActionForOption(plugin->getName())) { | |
| 4199 | + action->setChecked(true); | |
| 4200 | + action->trigger(); | |
| 4201 | + break; | |
| 4160 | 4202 | } |
| 4161 | 4203 | } |
| 4162 | 4204 | } |
| 4205 | + | |
| 4206 | + isFirstPerson = (qApp->isHMDMode()); | |
| 4207 | + } else { | |
| 4208 | + // if this is not the first run, the camera will be initialized differently depending on user settings | |
| 4209 | + | |
| 4210 | + if (qApp->isHMDMode()) { | |
| 4211 | + // if the HMD is active, use first-person camera, unless the appropriate setting is checked | |
| 4212 | + isFirstPerson = menu->isOptionChecked(MenuOption::FirstPersonHMD); | |
| 4213 | + } else { | |
| 4214 | + // if HMD is not active, only use first person if the menu option is checked | |
| 4215 | + isFirstPerson = menu->isOptionChecked(MenuOption::FirstPerson); | |
| 4216 | + } | |
| 4163 | 4217 | } |
| 4164 | 4218 | |
| 4219 | + // finish initializing the camera, based on everything we checked above. Third person camera will be used if no settings | |
| 4220 | + // dictated that we should be in first person | |
| 4221 | + Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, isFirstPerson); | |
| 4222 | + Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !isFirstPerson); | |
| 4223 | + _myCamera.setMode((isFirstPerson) ? CAMERA_MODE_FIRST_PERSON : CAMERA_MODE_THIRD_PERSON); | |
| 4224 | + cameraMenuChanged(); | |
| 4225 | + | |
| 4165 | 4226 | auto inputs = pluginManager->getInputPlugins(); |
| 4166 | 4227 | for (auto plugin : inputs) { |
| 4167 | 4228 | if (!plugin->isActive()) { |
| @@ -4210,7 +4271,6 @@ void Application::init() { · 42 unmodified lines | ||
| 4210 | 4271 | DependencyManager::get<DeferredLightingEffect>()->init(); |
| 4211 | 4272 | |
| 4212 | 4273 | DependencyManager::get<AvatarManager>()->init(); |
| 4213 | − _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); | |
| 4214 | 4274 | |
| 4215 | 4275 | _timerStart.start(); |
| 4216 | 4276 | _lastTimeUpdated.start(); |
| @@ -4466,27 +4526,29 @@ void Application::cameraModeChanged() { · 249 unmodified lines | ||
| 4466 | 4526 | |
| 4467 | 4527 | |
| 4468 | 4528 | void Application::cameraMenuChanged() { |
| 4469 | − if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { | |
| 4529 | + auto menu = Menu::getInstance(); | |
| 4530 | + if (menu->isOptionChecked(MenuOption::FullscreenMirror)) { | |
| 4470 | 4531 | if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { |
| 4471 | 4532 | _myCamera.setMode(CAMERA_MODE_MIRROR); |
| 4533 | + getMyAvatar()->reset(false, false, false); // to reset any active MyAvatar::FollowHelpers | |
| 4472 | 4534 | } |
| 4473 | − } else if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) { | |
| 4535 | + } else if (menu->isOptionChecked(MenuOption::FirstPerson)) { | |
| 4474 | 4536 | if (_myCamera.getMode() != CAMERA_MODE_FIRST_PERSON) { |
| 4475 | 4537 | _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); |
| 4476 | 4538 | getMyAvatar()->setBoomLength(MyAvatar::ZOOM_MIN); |
| 4477 | 4539 | } |
| 4478 | − } else if (Menu::getInstance()->isOptionChecked(MenuOption::ThirdPerson)) { | |
| 4540 | + } else if (menu->isOptionChecked(MenuOption::ThirdPerson)) { | |
| 4479 | 4541 | if (_myCamera.getMode() != CAMERA_MODE_THIRD_PERSON) { |
| 4480 | 4542 | _myCamera.setMode(CAMERA_MODE_THIRD_PERSON); |
| 4481 | 4543 | if (getMyAvatar()->getBoomLength() == MyAvatar::ZOOM_MIN) { |
| 4482 | 4544 | getMyAvatar()->setBoomLength(MyAvatar::ZOOM_DEFAULT); |
| 4483 | 4545 | } |
| 4484 | 4546 | } |
| 4485 | − } else if (Menu::getInstance()->isOptionChecked(MenuOption::IndependentMode)) { | |
| 4547 | + } else if (menu->isOptionChecked(MenuOption::IndependentMode)) { | |
| 4486 | 4548 | if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT) { |
| 4487 | 4549 | _myCamera.setMode(CAMERA_MODE_INDEPENDENT); |
| 4488 | 4550 | } |
| 4489 | − } else if (Menu::getInstance()->isOptionChecked(MenuOption::CameraEntityMode)) { | |
| 4551 | + } else if (menu->isOptionChecked(MenuOption::CameraEntityMode)) { | |
| 4490 | 4552 | if (_myCamera.getMode() != CAMERA_MODE_ENTITY) { |
| 4491 | 4553 | _myCamera.setMode(CAMERA_MODE_ENTITY); |
| 4492 | 4554 | } |
| @@ -5380,6 +5442,17 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se · 887 unmodified lines | ||
| 5380 | 5442 | } |
| 5381 | 5443 | renderArgs->_debugFlags = renderDebugFlags; |
| 5382 | 5444 | //ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, transaction); |
| 5445 | + | |
| 5446 | + RenderArgs::OutlineFlags renderOutlineFlags = RenderArgs::RENDER_OUTLINE_NONE; | |
| 5447 | + auto contextOverlayInterface = DependencyManager::get<ContextOverlayInterface>(); | |
| 5448 | + if (contextOverlayInterface->getEnabled()) { | |
| 5449 | + if (DependencyManager::get<ContextOverlayInterface>()->getIsInMarketplaceInspectionMode()) { | |
| 5450 | + renderOutlineFlags = RenderArgs::RENDER_OUTLINE_MARKETPLACE_MODE; | |
| 5451 | + } else { | |
| 5452 | + renderOutlineFlags = RenderArgs::RENDER_OUTLINE_WIREFRAMES; | |
| 5453 | + } | |
| 5454 | + } | |
| 5455 | + renderArgs->_outlineFlags = renderOutlineFlags; | |
| 5383 | 5456 | } |
| 5384 | 5457 | } |
| 5385 | 5458 | |
| @@ -5844,7 +5917,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri · 458 unmodified lines | ||
| 5844 | 5917 | auto entityScriptServerLog = DependencyManager::get<EntityScriptServerLogClient>(); |
| 5845 | 5918 | scriptEngine->registerGlobalObject("EntityScriptServerLog", entityScriptServerLog.data()); |
| 5846 | 5919 | scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance()); |
| 5847 | − scriptEngine->registerGlobalObject("HoverOverlay", DependencyManager::get<HoverOverlayInterface>().data()); | |
| 5920 | + scriptEngine->registerGlobalObject("ContextOverlay", DependencyManager::get<ContextOverlayInterface>().data()); | |
| 5848 | 5921 | |
| 5849 | 5922 | qScriptRegisterMetaType(scriptEngine, OverlayIDtoScriptValue, OverlayIDfromScriptValue); |
| 5850 | 5923 | |
| @@ -6199,7 +6272,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { · 348 unmodified lines | ||
| 6199 | 6272 | if (tempFile.open(QIODevice::WriteOnly)) { |
| 6200 | 6273 | tempFile.write(request->getData()); |
| 6201 | 6274 | addAssetToWorldInfoClear(filename); // Remove message from list; next one added will have a different key. |
| 6202 | − qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true); | |
| 6275 | + qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false); | |
| 6203 | 6276 | } else { |
| 6204 | 6277 | QString errorInfo = "Couldn't open temporary file for download"; |
| 6205 | 6278 | qWarning(interfaceapp) << errorInfo; |
| @@ -6229,12 +6302,18 @@ void Application::addAssetToWorldUnzipFailure(QString filePath) { · 23 unmodified lines | ||
| 6229 | 6302 | addAssetToWorldError(filename, "Couldn't unzip file " + filename + "."); |
| 6230 | 6303 | } |
| 6231 | 6304 | |
| 6232 | −void Application::addAssetToWorld(QString filePath) { | |
| 6305 | +void Application::addAssetToWorld(QString filePath, QString zipFile, bool isZip) { | |
| 6233 | 6306 | // Automatically upload and add asset to world as an alternative manual process initiated by showAssetServerWidget(). |
| 6234 | − | |
| 6235 | − QString path = QUrl(filePath).toLocalFile(); | |
| 6307 | + QString mapping; | |
| 6308 | + QString path = filePath; | |
| 6236 | 6309 | QString filename = filenameFromPath(path); |
| 6237 | − QString mapping = "/" + filename; | |
| 6310 | + if (isZip) { | |
| 6311 | + QString assetFolder = zipFile.section("/", -1); | |
| 6312 | + assetFolder.remove(".zip"); | |
| 6313 | + mapping = "/" + assetFolder + "/" + filename; | |
| 6314 | + } else { | |
| 6315 | + mapping = "/" + filename; | |
| 6316 | + } | |
| 6238 | 6317 | |
| 6239 | 6318 | // Test repeated because possibly different code paths. |
| 6240 | 6319 | if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets()) { |
| @@ -6315,7 +6394,13 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q · 74 unmodified lines | ||
| 6315 | 6394 | qWarning(interfaceapp) << "Error downloading model: " + errorInfo; |
| 6316 | 6395 | addAssetToWorldError(filenameFromPath(filePath), errorInfo); |
| 6317 | 6396 | } else { |
| 6318 | − addAssetToWorldAddEntity(filePath, mapping); | |
| 6397 | + // to prevent files that aren't models from being loaded into world automatically | |
| 6398 | + if (filePath.endsWith(".obj") || filePath.endsWith(".fbx")) { | |
| 6399 | + addAssetToWorldAddEntity(filePath, mapping); | |
| 6400 | + } else { | |
| 6401 | + qCDebug(interfaceapp) << "Zipped contents are not supported entity files"; | |
| 6402 | + addAssetToWorldInfoDone(filenameFromPath(filePath)); | |
| 6403 | + } | |
| 6319 | 6404 | } |
| 6320 | 6405 | request->deleteLater(); |
| 6321 | 6406 | }); |
| @@ -6605,15 +6690,18 @@ void Application::onAssetToWorldMessageBoxClosed() { · 283 unmodified lines | ||
| 6605 | 6690 | } |
| 6606 | 6691 | |
| 6607 | 6692 | |
| 6608 | −void Application::handleUnzip(QString zipFile, QString unzipFile, bool autoAdd) { | |
| 6693 | +void Application::handleUnzip(QString zipFile, QStringList unzipFile, bool autoAdd, bool isZip) { | |
| 6609 | 6694 | if (autoAdd) { |
| 6610 | 6695 | if (!unzipFile.isEmpty()) { |
| 6611 | − addAssetToWorld(unzipFile); | |
| 6696 | + for (int i = 0; i < unzipFile.length(); i++) { | |
| 6697 | + qCDebug(interfaceapp) << "Preparing file for asset server: " << unzipFile.at(i); | |
| 6698 | + addAssetToWorld(unzipFile.at(i), zipFile, isZip); | |
| 6699 | + } | |
| 6612 | 6700 | } else { |
| 6613 | 6701 | addAssetToWorldUnzipFailure(zipFile); |
| 6614 | 6702 | } |
| 6615 | 6703 | } else { |
| 6616 | − showAssetServerWidget(unzipFile); | |
| 6704 | + showAssetServerWidget(unzipFile.first()); | |
| 6617 | 6705 | } |
| 6618 | 6706 | } |
| 6619 | 6707 | |
| @@ -7076,6 +7164,7 @@ void Application::updateDisplayMode() { · 456 unmodified lines | ||
| 7076 | 7164 | |
| 7077 | 7165 | auto oldDisplayPlugin = _displayPlugin; |
| 7078 | 7166 | if (_displayPlugin) { |
| 7167 | + disconnect(_displayPluginPresentConnection); | |
| 7079 | 7168 | _displayPlugin->deactivate(); |
| 7080 | 7169 | } |
| 7081 | 7170 | |
| @@ -7116,6 +7205,7 @@ void Application::updateDisplayMode() { · 34 unmodified lines | ||
| 7116 | 7205 | _offscreenContext->makeCurrent(); |
| 7117 | 7206 | getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); |
| 7118 | 7207 | _displayPlugin = newDisplayPlugin; |
| 7208 | + _displayPluginPresentConnection = connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent); | |
| 7119 | 7209 | offscreenUi->getDesktop()->setProperty("repositionLocked", wasRepositionLocked); |
| 7120 | 7210 | } |
| 7121 | 7211 | |