Showing the changes to interface/src/Application.cpp (1 of 498 files). Show all
Unified · Split
| @@ -319,7 +319,7 @@ static QTimer pingTimer; · 318 unmodified lines | |||
| 319 | static bool DISABLE_WATCHDOG = true; | 319 | static bool DISABLE_WATCHDOG = true; |
| 320 | #else | 320 | #else |
| 321 | static const QString DISABLE_WATCHDOG_FLAG{ "HIFI_DISABLE_WATCHDOG" }; | 321 | static const QString DISABLE_WATCHDOG_FLAG{ "HIFI_DISABLE_WATCHDOG" }; |
| 322 | static bool DISABLE_WATCHDOG = QProcessEnvironment::systemEnvironment().contains(DISABLE_WATCHDOG_FLAG); | 322 | static bool DISABLE_WATCHDOG = nsightActive() || QProcessEnvironment::systemEnvironment().contains(DISABLE_WATCHDOG_FLAG); |
| 323 | #endif | 323 | #endif |
| 324 | 324 | ||
| 325 | #if defined(USE_GLES) | 325 | #if defined(USE_GLES) |
| @@ -336,15 +336,17 @@ static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16; · 10 unmodified lines | |||
| 336 | // we will never drop below the 'min' value | 336 | // we will never drop below the 'min' value |
| 337 | static const int MIN_PROCESSING_THREAD_POOL_SIZE = 1; | 337 | static const int MIN_PROCESSING_THREAD_POOL_SIZE = 1; |
| 338 | 338 | ||
| 339 | static const QString SNAPSHOT_EXTENSION = ".jpg"; | 339 | static const QString SNAPSHOT_EXTENSION = ".jpg"; |
| 340 | static const QString SVO_EXTENSION = ".svo"; | 340 | static const QString JPG_EXTENSION = ".jpg"; |
| 341 | static const QString PNG_EXTENSION = ".png"; | ||
| 342 | static const QString SVO_EXTENSION = ".svo"; | ||
| 341 | static const QString SVO_JSON_EXTENSION = ".svo.json"; | 343 | static const QString SVO_JSON_EXTENSION = ".svo.json"; |
| 342 | static const QString JSON_GZ_EXTENSION = ".json.gz"; | 344 | static const QString JSON_GZ_EXTENSION = ".json.gz"; |
| 343 | static const QString JSON_EXTENSION = ".json"; | 345 | static const QString JSON_EXTENSION = ".json"; |
| 344 | static const QString JS_EXTENSION = ".js"; | 346 | static const QString JS_EXTENSION = ".js"; |
| 345 | static const QString FST_EXTENSION = ".fst"; | 347 | static const QString FST_EXTENSION = ".fst"; |
| 346 | static const QString FBX_EXTENSION = ".fbx"; | 348 | static const QString FBX_EXTENSION = ".fbx"; |
| 347 | static const QString OBJ_EXTENSION = ".obj"; | 349 | static const QString OBJ_EXTENSION = ".obj"; |
| 348 | static const QString AVA_JSON_EXTENSION = ".ava.json"; | 350 | static const QString AVA_JSON_EXTENSION = ".ava.json"; |
| 349 | static const QString WEB_VIEW_TAG = "noDownload=true"; | 351 | static const QString WEB_VIEW_TAG = "noDownload=true"; |
| 350 | static const QString ZIP_EXTENSION = ".zip"; | 352 | static const QString ZIP_EXTENSION = ".zip"; |
| @@ -383,7 +385,9 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi · 32 unmodified lines | |||
| 383 | { JS_EXTENSION, &Application::askToLoadScript }, | 385 | { JS_EXTENSION, &Application::askToLoadScript }, |
| 384 | { FST_EXTENSION, &Application::askToSetAvatarUrl }, | 386 | { FST_EXTENSION, &Application::askToSetAvatarUrl }, |
| 385 | { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent }, | 387 | { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent }, |
| 386 | { ZIP_EXTENSION, &Application::importFromZIP } | 388 | { ZIP_EXTENSION, &Application::importFromZIP }, |
| 389 | { JPG_EXTENSION, &Application::importImage }, | ||
| 390 | { PNG_EXTENSION, &Application::importImage } | ||
| 387 | }; | 391 | }; |
| 388 | 392 | ||
| 389 | class DeadlockWatchdogThread : public QThread { | 393 | class DeadlockWatchdogThread : public QThread { |
| @@ -416,20 +420,26 @@ public: · 26 unmodified lines | |||
| 416 | *crashTrigger = 0xDEAD10CC; | 420 | *crashTrigger = 0xDEAD10CC; |
| 417 | } | 421 | } |
| 418 | 422 | ||
| 423 | static void withPause(const std::function<void()>& lambda) { | ||
| 424 | pause(); | ||
| 425 | lambda(); | ||
| 426 | resume(); | ||
| 427 | } | ||
| 419 | static void pause() { | 428 | static void pause() { |
| 420 | _paused = true; | 429 | _paused = true; |
| 421 | } | 430 | } |
| 422 | 431 | ||
| 423 | static void resume() { | 432 | static void resume() { |
| 424 | _paused = false; | 433 | // Update the heartbeat BEFORE resuming the checks |
| 425 | updateHeartbeat(); | 434 | updateHeartbeat(); |
| 435 | _paused = false; | ||
| 426 | } | 436 | } |
| 427 | 437 | ||
| 428 | void run() override { | 438 | void run() override { |
| 429 | while (!_quit) { | 439 | while (!_quit) { |
| 430 | QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS); | 440 | QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS); |
| 431 | // Don't do heartbeat detection under nsight | 441 | // Don't do heartbeat detection under nsight |
| 432 | if (nsightActive() || _paused) { | 442 | if (_paused) { |
| 433 | continue; | 443 | continue; |
| 434 | } | 444 | } |
| 435 | uint64_t lastHeartbeat = _heartbeat; // sample atomic _heartbeat, because we could context switch away and have it updated on us | 445 | uint64_t lastHeartbeat = _heartbeat; // sample atomic _heartbeat, because we could context switch away and have it updated on us |
| @@ -863,6 +873,8 @@ std::shared_ptr<Cube3DOverlay> _keyboardFocusHighlight{ nullptr }; · 427 unmodified lines | |||
| 863 | OverlayID _keyboardFocusHighlightID{ UNKNOWN_OVERLAY_ID }; | 873 | OverlayID _keyboardFocusHighlightID{ UNKNOWN_OVERLAY_ID }; |
| 864 | 874 | ||
| 865 | 875 | ||
| 876 | OffscreenGLCanvas* _qmlShareContext { nullptr }; | ||
| 877 | |||
| 866 | // FIXME hack access to the internal share context for the Chromium helper | 878 | // FIXME hack access to the internal share context for the Chromium helper |
| 867 | // Normally we'd want to use QWebEngine::initialize(), but we can't because | 879 | // Normally we'd want to use QWebEngine::initialize(), but we can't because |
| 868 | // our primary context is a QGLWidget, which can't easily be initialized to share | 880 | // our primary context is a QGLWidget, which can't easily be initialized to share |
| @@ -1112,7 +1124,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 243 unmodified lines | |||
| 1112 | connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &Application::notifyPacketVersionMismatch); | 1124 | connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &Application::notifyPacketVersionMismatch); |
| 1113 | 1125 | ||
| 1114 | // you might think we could just do this in NodeList but we only want this connection for Interface | 1126 | // you might think we could just do this in NodeList but we only want this connection for Interface |
| 1115 | connect(nodeList.data(), &NodeList::limitOfSilentDomainCheckInsReached, nodeList.data(), &NodeList::reset); | 1127 | connect(&nodeList->getDomainHandler(), SIGNAL(limitOfSilentDomainCheckInsReached()), |
| 1128 | nodeList.data(), SLOT(reset())); | ||
| 1116 | 1129 | ||
| 1117 | auto dialogsManager = DependencyManager::get<DialogsManager>(); | 1130 | auto dialogsManager = DependencyManager::get<DialogsManager>(); |
| 1118 | connect(accountManager.data(), &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog); | 1131 | connect(accountManager.data(), &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog); |
| @@ -1646,6 +1659,73 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 527 unmodified lines | |||
| 1646 | } | 1659 | } |
| 1647 | }); | 1660 | }); |
| 1648 | 1661 | ||
| 1662 | EntityTree::setAddMaterialToEntityOperator([&](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) { | ||
| 1663 | // try to find the renderable | ||
| 1664 | auto renderable = getEntities()->renderableForEntityId(entityID); | ||
| 1665 | if (renderable) { | ||
| 1666 | renderable->addMaterial(material, parentMaterialName); | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | // even if we don't find it, try to find the entity | ||
| 1670 | auto entity = getEntities()->getEntity(entityID); | ||
| 1671 | if (entity) { | ||
| 1672 | entity->addMaterial(material, parentMaterialName); | ||
| 1673 | return true; | ||
| 1674 | } | ||
| 1675 | return false; | ||
| 1676 | }); | ||
| 1677 | EntityTree::setRemoveMaterialFromEntityOperator([&](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) { | ||
| 1678 | // try to find the renderable | ||
| 1679 | auto renderable = getEntities()->renderableForEntityId(entityID); | ||
| 1680 | if (renderable) { | ||
| 1681 | renderable->removeMaterial(material, parentMaterialName); | ||
| 1682 | } | ||
| 1683 | |||
| 1684 | // even if we don't find it, try to find the entity | ||
| 1685 | auto entity = getEntities()->getEntity(entityID); | ||
| 1686 | if (entity) { | ||
| 1687 | entity->removeMaterial(material, parentMaterialName); | ||
| 1688 | return true; | ||
| 1689 | } | ||
| 1690 | return false; | ||
| 1691 | }); | ||
| 1692 | |||
| 1693 | EntityTree::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName) { | ||
| 1694 | auto avatarManager = DependencyManager::get<AvatarManager>(); | ||
| 1695 | auto avatar = avatarManager->getAvatarBySessionID(avatarID); | ||
| 1696 | if (avatar) { | ||
| 1697 | avatar->addMaterial(material, parentMaterialName); | ||
| 1698 | return true; | ||
| 1699 | } | ||
| 1700 | return false; | ||
| 1701 | }); | ||
| 1702 | EntityTree::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName) { | ||
| 1703 | auto avatarManager = DependencyManager::get<AvatarManager>(); | ||
| 1704 | auto avatar = avatarManager->getAvatarBySessionID(avatarID); | ||
| 1705 | if (avatar) { | ||
| 1706 | avatar->removeMaterial(material, parentMaterialName); | ||
| 1707 | return true; | ||
| 1708 | } | ||
| 1709 | return false; | ||
| 1710 | }); | ||
| 1711 | |||
| 1712 | EntityTree::setAddMaterialToOverlayOperator([&](const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) { | ||
| 1713 | auto overlay = _overlays.getOverlay(overlayID); | ||
| 1714 | if (overlay) { | ||
| 1715 | overlay->addMaterial(material, parentMaterialName); | ||
| 1716 | return true; | ||
| 1717 | } | ||
| 1718 | return false; | ||
| 1719 | }); | ||
| 1720 | EntityTree::setRemoveMaterialFromOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName) { | ||
| 1721 | auto overlay = _overlays.getOverlay(overlayID); | ||
| 1722 | if (overlay) { | ||
| 1723 | overlay->removeMaterial(material, parentMaterialName); | ||
| 1724 | return true; | ||
| 1725 | } | ||
| 1726 | return false; | ||
| 1727 | }); | ||
| 1728 | |||
| 1649 | // Keyboard focus handling for Web overlays. | 1729 | // Keyboard focus handling for Web overlays. |
| 1650 | auto overlays = &(qApp->getOverlays()); | 1730 | auto overlays = &(qApp->getOverlays()); |
| 1651 | connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) { | 1731 | connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) { |
| @@ -2324,18 +2404,37 @@ void Application::initializeGL() { · 672 unmodified lines | |||
| 2324 | _isGLInitialized = true; | 2404 | _isGLInitialized = true; |
| 2325 | } | 2405 | } |
| 2326 | 2406 | ||
| 2407 | // Build a shared canvas / context for the Chromium processes | ||
| 2327 | _glWidget->makeCurrent(); | 2408 | _glWidget->makeCurrent(); |
| 2328 | 2409 | ||
| 2329 | #if !defined(DISABLE_QML) | 2410 | #if !defined(DISABLE_QML) |
| 2411 | // Chromium rendering uses some GL functions that prevent nSight from capturing | ||
| 2412 | // frames, so we only create the shared context if nsight is NOT active. | ||
| 2330 | if (!nsightActive()) { | 2413 | if (!nsightActive()) { |
| 2331 | _chromiumShareContext = new OffscreenGLCanvas(); | 2414 | _chromiumShareContext = new OffscreenGLCanvas(); |
| 2332 | _chromiumShareContext->setObjectName("ChromiumShareContext"); | 2415 | _chromiumShareContext->setObjectName("ChromiumShareContext"); |
| 2333 | _chromiumShareContext->create(_glWidget->qglContext()); | 2416 | _chromiumShareContext->create(_glWidget->qglContext()); |
| 2334 | _chromiumShareContext->makeCurrent(); | 2417 | _chromiumShareContext->makeCurrent(); |
| 2418 | if (!_chromiumShareContext->makeCurrent()) { | ||
| 2419 | qCWarning(interfaceapp, "Unable to make chromium shared context current"); | ||
| 2420 | } | ||
| 2335 | qt_gl_set_global_share_context(_chromiumShareContext->getContext()); | 2421 | qt_gl_set_global_share_context(_chromiumShareContext->getContext()); |
| 2422 | } else { | ||
| 2423 | qCWarning(interfaceapp) << "nSIGHT detected, disabling chrome rendering"; | ||
| 2336 | } | 2424 | } |
| 2337 | #endif | 2425 | #endif |
| 2338 | 2426 | ||
| 2427 | // Build a shared canvas / context for the QML rendering | ||
| 2428 | _glWidget->makeCurrent(); | ||
| 2429 | _qmlShareContext = new OffscreenGLCanvas(); | ||
| 2430 | _qmlShareContext->setObjectName("QmlShareContext"); | ||
| 2431 | _qmlShareContext->create(_glWidget->qglContext()); | ||
| 2432 | if (!_qmlShareContext->makeCurrent()) { | ||
| 2433 | qCWarning(interfaceapp, "Unable to make QML shared context current"); | ||
| 2434 | } | ||
| 2435 | OffscreenQmlSurface::setSharedContext(_qmlShareContext->getContext()); | ||
| 2436 | _qmlShareContext->doneCurrent(); | ||
| 2437 | |||
| 2339 | _glWidget->makeCurrent(); | 2438 | _glWidget->makeCurrent(); |
| 2340 | gpu::Context::init<gpu::gl::GLBackend>(); | 2439 | gpu::Context::init<gpu::gl::GLBackend>(); |
| 2341 | qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK, | 2440 | qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK, |
| @@ -2348,29 +2447,22 @@ void Application::initializeGL() { · 6 unmodified lines | |||
| 2348 | initDisplay(); | 2447 | initDisplay(); |
| 2349 | qCDebug(interfaceapp, "Initialized Display."); | 2448 | qCDebug(interfaceapp, "Initialized Display."); |
| 2350 | 2449 | ||
| 2351 | #ifdef Q_OS_OSX | 2450 | // FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread. |
| 2352 | // FIXME: on mac os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread. | 2451 | DeadlockWatchdogThread::withPause([&] { |
| 2353 | DeadlockWatchdogThread::pause(); | 2452 | // Set up the render engine |
| 2354 | #endif | 2453 | render::CullFunctor cullFunctor = LODManager::shouldRender; |
| 2355 | 2454 | static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD"; | |
| 2356 | // Set up the render engine | 2455 | _renderEngine->addJob<UpdateSceneTask>("UpdateScene"); |
| 2357 | render::CullFunctor cullFunctor = LODManager::shouldRender; | ||
| 2358 | static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD"; | ||
| 2359 | _renderEngine->addJob<UpdateSceneTask>("UpdateScene"); | ||
| 2360 | #ifndef Q_OS_ANDROID | 2456 | #ifndef Q_OS_ANDROID |
| 2361 | _renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !DISABLE_DEFERRED); | 2457 | _renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !DISABLE_DEFERRED); |
| 2362 | #endif | 2458 | #endif |
| 2363 | _renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, !DISABLE_DEFERRED); | 2459 | _renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, !DISABLE_DEFERRED, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0); |
| 2460 | _renderEngine->load(); | ||
| 2461 | _renderEngine->registerScene(_main3DScene); | ||
| 2364 | 2462 | ||
| 2365 | #ifdef Q_OS_OSX | 2463 | // Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success. |
| 2366 | DeadlockWatchdogThread::resume(); | 2464 | DependencyManager::get<GeometryCache>()->initializeShapePipelines(); |
| 2367 | #endif | 2465 | }); |
| 2368 | |||
| 2369 | _renderEngine->load(); | ||
| 2370 | _renderEngine->registerScene(_main3DScene); | ||
| 2371 | |||
| 2372 | // Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success. | ||
| 2373 | DependencyManager::get<GeometryCache>()->initializeShapePipelines(); | ||
| 2374 | 2466 | ||
| 2375 | _offscreenContext = new OffscreenGLCanvas(); | 2467 | _offscreenContext = new OffscreenGLCanvas(); |
| 2376 | _offscreenContext->setObjectName("MainThreadContext"); | 2468 | _offscreenContext->setObjectName("MainThreadContext"); |
| @@ -2378,20 +2470,24 @@ void Application::initializeGL() { · 1 unmodified line | |||
| 2378 | if (!_offscreenContext->makeCurrent()) { | 2470 | if (!_offscreenContext->makeCurrent()) { |
| 2379 | qFatal("Unable to make offscreen context current"); | 2471 | qFatal("Unable to make offscreen context current"); |
| 2380 | } | 2472 | } |
| 2473 | _offscreenContext->doneCurrent(); | ||
| 2474 | _offscreenContext->setThreadContext(); | ||
| 2475 | _renderEventHandler = new RenderEventHandler(_glWidget->qglContext()); | ||
| 2381 | 2476 | ||
| 2382 | // The UI can't be created until the primary OpenGL | 2477 | // The UI can't be created until the primary OpenGL |
| 2383 | // context is created, because it needs to share | 2478 | // context is created, because it needs to share |
| 2384 | // texture resources | 2479 | // texture resources |
| 2385 | // Needs to happen AFTER the render engine initialization to access its configuration | 2480 | // Needs to happen AFTER the render engine initialization to access its configuration |
| 2481 | if (!_offscreenContext->makeCurrent()) { | ||
| 2482 | qFatal("Unable to make offscreen context current"); | ||
| 2483 | } | ||
| 2484 | |||
| 2386 | initializeUi(); | 2485 | initializeUi(); |
| 2387 | qCDebug(interfaceapp, "Initialized Offscreen UI."); | 2486 | qCDebug(interfaceapp, "Initialized Offscreen UI."); |
| 2388 | _glWidget->makeCurrent(); | ||
| 2389 | |||
| 2390 | |||
| 2391 | // call Menu getInstance static method to set up the menu | ||
| 2392 | // Needs to happen AFTER the QML UI initialization | ||
| 2393 | _window->setMenuBar(Menu::getInstance()); | ||
| 2394 | 2487 | ||
| 2488 | if (!_offscreenContext->makeCurrent()) { | ||
| 2489 | qFatal("Unable to make offscreen context current"); | ||
| 2490 | } | ||
| 2395 | init(); | 2491 | init(); |
| 2396 | qCDebug(interfaceapp, "init() complete."); | 2492 | qCDebug(interfaceapp, "init() complete."); |
| 2397 | 2493 | ||
| @@ -2402,7 +2498,6 @@ void Application::initializeGL() { · 4 unmodified lines | |||
| 2402 | 2498 | ||
| 2403 | _idleLoopStdev.reset(); | 2499 | _idleLoopStdev.reset(); |
| 2404 | 2500 | ||
| 2405 | _renderEventHandler = new RenderEventHandler(_glWidget->qglContext()); | ||
| 2406 | 2501 | ||
| 2407 | // Restore the primary GL content for the main thread | 2502 | // Restore the primary GL content for the main thread |
| 2408 | if (!_offscreenContext->makeCurrent()) { | 2503 | if (!_offscreenContext->makeCurrent()) { |
| @@ -2468,27 +2563,70 @@ void Application::initializeUi() { · 59 unmodified lines | |||
| 2468 | auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); | 2563 | auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); |
| 2469 | tabletScriptingInterface->getTablet(SYSTEM_TABLET); | 2564 | tabletScriptingInterface->getTablet(SYSTEM_TABLET); |
| 2470 | } | 2565 | } |
| 2471 | auto offscreenUi = DependencyManager::get<OffscreenUi>(); | ||
| 2472 | offscreenUi->create(); | ||
| 2473 | 2566 | ||
| 2474 | auto surfaceContext = offscreenUi->getSurfaceContext(); | 2567 | auto offscreenUi = DependencyManager::get<OffscreenUi>(); |
| 2568 | connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootContextCreated, | ||
| 2569 | this, &Application::onDesktopRootContextCreated); | ||
| 2570 | connect(offscreenUi.data(), &hifi::qml::OffscreenSurface::rootItemCreated, | ||
| 2571 | this, &Application::onDesktopRootItemCreated); | ||
| 2475 | 2572 | ||
| 2476 | offscreenUi->setProxyWindow(_window->windowHandle()); | 2573 | offscreenUi->setProxyWindow(_window->windowHandle()); |
| 2477 | // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to | 2574 | // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to |
| 2478 | // support the window management and scripting proxies for VR use | 2575 | // support the window management and scripting proxies for VR use |
| 2479 | offscreenUi->createDesktop(PathUtils::qmlUrl("hifi/Desktop.qml")); | 2576 | DeadlockWatchdogThread::withPause([&] { |
| 2577 | offscreenUi->createDesktop(PathUtils::qmlUrl("hifi/Desktop.qml")); | ||
| 2578 | }); | ||
| 2480 | // FIXME either expose so that dialogs can set this themselves or | 2579 | // FIXME either expose so that dialogs can set this themselves or |
| 2481 | // do better detection in the offscreen UI of what has focus | 2580 | // do better detection in the offscreen UI of what has focus |
| 2482 | offscreenUi->setNavigationFocused(false); | 2581 | offscreenUi->setNavigationFocused(false); |
| 2483 | 2582 | ||
| 2484 | auto engine = surfaceContext->engine(); | 2583 | setupPreferences(); |
| 2485 | connect(engine, &QQmlEngine::quit, [] { | 2584 | |
| 2486 | qApp->quit(); | 2585 | _glWidget->installEventFilter(offscreenUi.data()); |
| 2586 | offscreenUi->setMouseTranslator([=](const QPointF& pt) { | ||
| 2587 | QPointF result = pt; | ||
| 2588 | auto displayPlugin = getActiveDisplayPlugin(); | ||
| 2589 | if (displayPlugin->isHmd()) { | ||
| 2590 | getApplicationCompositor().handleRealMouseMoveEvent(false); | ||
| 2591 | auto resultVec = getApplicationCompositor().getReticlePosition(); | ||
| 2592 | result = QPointF(resultVec.x, resultVec.y); | ||
| 2593 | } | ||
| 2594 | return result.toPoint(); | ||
| 2595 | }); | ||
| 2596 | offscreenUi->resume(); | ||
| 2597 | connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r){ | ||
| 2598 | resizeGL(); | ||
| 2487 | }); | 2599 | }); |
| 2488 | 2600 | ||
| 2601 | // This will set up the input plugins UI | ||
| 2602 | _activeInputPlugins.clear(); | ||
| 2603 | foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { | ||
| 2604 | if (KeyboardMouseDevice::NAME == inputPlugin->getName()) { | ||
| 2605 | _keyboardMouseDevice = std::dynamic_pointer_cast<KeyboardMouseDevice>(inputPlugin); | ||
| 2606 | } | ||
| 2607 | if (TouchscreenDevice::NAME == inputPlugin->getName()) { | ||
| 2608 | _touchscreenDevice = std::dynamic_pointer_cast<TouchscreenDevice>(inputPlugin); | ||
| 2609 | } | ||
| 2610 | } | ||
| 2611 | |||
| 2612 | auto compositorHelper = DependencyManager::get<CompositorHelper>(); | ||
| 2613 | connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, this, [=] { | ||
| 2614 | if (isHMDMode()) { | ||
| 2615 | showCursor(compositorHelper->getAllowMouseCapture() ? | ||
| 2616 | Cursor::Manager::lookupIcon(_preferredCursor.get()) : | ||
| 2617 | Cursor::Icon::SYSTEM); | ||
| 2618 | } | ||
| 2619 | }); | ||
| 2620 | |||
| 2621 | // Pre-create a couple of Web3D overlays to speed up tablet UI | ||
| 2622 | auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>(); | ||
| 2623 | offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1); | ||
| 2624 | offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2); | ||
| 2625 | } | ||
| 2489 | 2626 | ||
| 2490 | setupPreferences(); | ||
| 2491 | 2627 | ||
| 2628 | void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { | ||
| 2629 | auto engine = surfaceContext->engine(); | ||
| 2492 | // in Qt 5.10.0 there is already an "Audio" object in the QML context | 2630 | // in Qt 5.10.0 there is already an "Audio" object in the QML context |
| 2493 | // though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface" | 2631 | // though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface" |
| 2494 | surfaceContext->setContextProperty("AudioScriptingInterface", DependencyManager::get<AudioScriptingInterface>().data()); | 2632 | surfaceContext->setContextProperty("AudioScriptingInterface", DependencyManager::get<AudioScriptingInterface>().data()); |
| @@ -2570,48 +2708,12 @@ void Application::initializeUi() { · 75 unmodified lines | |||
| 2570 | surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); | 2708 | surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); |
| 2571 | } | 2709 | } |
| 2572 | 2710 | ||
| 2573 | |||
| 2574 | _glWidget->installEventFilter(offscreenUi.data()); | ||
| 2575 | offscreenUi->setMouseTranslator([=](const QPointF& pt) { | ||
| 2576 | QPointF result = pt; | ||
| 2577 | auto displayPlugin = getActiveDisplayPlugin(); | ||
| 2578 | if (displayPlugin->isHmd()) { | ||
| 2579 | getApplicationCompositor().handleRealMouseMoveEvent(false); | ||
| 2580 | auto resultVec = getApplicationCompositor().getReticlePosition(); | ||
| 2581 | result = QPointF(resultVec.x, resultVec.y); | ||
| 2582 | } | ||
| 2583 | return result.toPoint(); | ||
| 2584 | }); | ||
| 2585 | offscreenUi->resume(); | ||
| 2586 | connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect& r){ | ||
| 2587 | resizeGL(); | ||
| 2588 | }); | ||
| 2589 | |||
| 2590 | // This will set up the input plugins UI | ||
| 2591 | _activeInputPlugins.clear(); | ||
| 2592 | foreach(auto inputPlugin, PluginManager::getInstance()->getInputPlugins()) { | ||
| 2593 | if (KeyboardMouseDevice::NAME == inputPlugin->getName()) { | ||
| 2594 | _keyboardMouseDevice = std::dynamic_pointer_cast<KeyboardMouseDevice>(inputPlugin); | ||
| 2595 | } | ||
| 2596 | if (TouchscreenDevice::NAME == inputPlugin->getName()) { | ||
| 2597 | _touchscreenDevice = std::dynamic_pointer_cast<TouchscreenDevice>(inputPlugin); | ||
| 2598 | } | ||
| 2599 | } | ||
| 2600 | _window->setMenuBar(new Menu()); | 2711 | _window->setMenuBar(new Menu()); |
| 2712 | } | ||
| 2601 | 2713 | ||
| 2602 | auto compositorHelper = DependencyManager::get<CompositorHelper>(); | 2714 | void Application::onDesktopRootItemCreated(QQuickItem* rootItem) { |
| 2603 | connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, this, [=] { | 2715 | Stats::show(); |
| 2604 | if (isHMDMode()) { | 2716 | AvatarInputs::show(); |
| 2605 | showCursor(compositorHelper->getAllowMouseCapture() ? | ||
| 2606 | Cursor::Manager::lookupIcon(_preferredCursor.get()) : | ||
| 2607 | Cursor::Icon::SYSTEM); | ||
| 2608 | } | ||
| 2609 | }); | ||
| 2610 | |||
| 2611 | // Pre-create a couple of Web3D overlays to speed up tablet UI | ||
| 2612 | auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>(); | ||
| 2613 | offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1); | ||
| 2614 | offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2); | ||
| 2615 | } | 2717 | } |
| 2616 | 2718 | ||
| 2617 | void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { | 2719 | void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) { |
| @@ -2850,6 +2952,8 @@ void Application::resizeGL() { · 232 unmodified lines | |||
| 2850 | QMutexLocker viewLocker(&_viewMutex); | 2952 | QMutexLocker viewLocker(&_viewMutex); |
| 2851 | _myCamera.loadViewFrustum(_viewFrustum); | 2953 | _myCamera.loadViewFrustum(_viewFrustum); |
| 2852 | } | 2954 | } |
| 2955 | |||
| 2956 | DependencyManager::get<OffscreenUi>()->resize(fromGlm(displayPlugin->getRecommendedUiSize())); | ||
| 2853 | } | 2957 | } |
| 2854 | 2958 | ||
| 2855 | void Application::handleSandboxStatus(QNetworkReply* reply) { | 2959 | void Application::handleSandboxStatus(QNetworkReply* reply) { |
| @@ -2965,6 +3069,14 @@ bool Application::importFromZIP(const QString& filePath) { · 109 unmodified lines | |||
| 2965 | return true; | 3069 | return true; |
| 2966 | } | 3070 | } |
| 2967 | 3071 | ||
| 3072 | bool Application::importImage(const QString& urlString) { | ||
| 3073 | qCDebug(interfaceapp) << "An image file has been dropped in"; | ||
| 3074 | QString filepath(urlString); | ||
| 3075 | filepath.remove("file:///"); | ||
| 3076 | addAssetToWorld(filepath, "", false, false); | ||
| 3077 | return true; | ||
| 3078 | } | ||
| 3079 | |||
| 2968 | // thread-safe | 3080 | // thread-safe |
| 2969 | void Application::onPresent(quint32 frameCount) { | 3081 | void Application::onPresent(quint32 frameCount) { |
| 2970 | bool expected = false; | 3082 | bool expected = false; |
| @@ -4058,7 +4170,7 @@ void Application::idle() { · 1087 unmodified lines | |||
| 4058 | // Bit of a hack since there's no device pixel ratio change event I can find. | 4170 | // Bit of a hack since there's no device pixel ratio change event I can find. |
| 4059 | if (offscreenUi->size() != fromGlm(uiSize)) { | 4171 | if (offscreenUi->size() != fromGlm(uiSize)) { |
| 4060 | qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize; | 4172 | qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize; |
| 4061 | offscreenUi->resize(fromGlm(uiSize), true); | 4173 | offscreenUi->resize(fromGlm(uiSize)); |
| 4062 | _offscreenContext->makeCurrent(); | 4174 | _offscreenContext->makeCurrent(); |
| 4063 | } | 4175 | } |
| 4064 | } | 4176 | } |
| @@ -6560,7 +6672,8 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q · 2495 unmodified lines | |||
| 6560 | addAssetToWorldError(filenameFromPath(filePath), errorInfo); | 6672 | addAssetToWorldError(filenameFromPath(filePath), errorInfo); |
| 6561 | } else { | 6673 | } else { |
| 6562 | // to prevent files that aren't models from being loaded into world automatically | 6674 | // to prevent files that aren't models from being loaded into world automatically |
| 6563 | if (filePath.endsWith(".obj") || filePath.endsWith(".fbx")) { | 6675 | if (filePath.endsWith(OBJ_EXTENSION) || filePath.endsWith(FBX_EXTENSION) || |
| 6676 | filePath.endsWith(JPG_EXTENSION) || filePath.endsWith(PNG_EXTENSION)) { | ||
| 6564 | addAssetToWorldAddEntity(filePath, mapping); | 6677 | addAssetToWorldAddEntity(filePath, mapping); |
| 6565 | } else { | 6678 | } else { |
| 6566 | qCDebug(interfaceapp) << "Zipped contents are not supported entity files"; | 6679 | qCDebug(interfaceapp) << "Zipped contents are not supported entity files"; |
| @@ -6577,8 +6690,17 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { · 10 unmodified lines | |||
| 6577 | EntityItemProperties properties; | 6690 | EntityItemProperties properties; |
| 6578 | properties.setType(EntityTypes::Model); | 6691 | properties.setType(EntityTypes::Model); |
| 6579 | properties.setName(mapping.right(mapping.length() - 1)); | 6692 | properties.setName(mapping.right(mapping.length() - 1)); |
| 6580 | properties.setModelURL("atp:" + mapping); | 6693 | if (filePath.endsWith(PNG_EXTENSION) || filePath.endsWith(JPG_EXTENSION)) { |
| 6581 | properties.setShapeType(SHAPE_TYPE_SIMPLE_COMPOUND); | 6694 | QJsonObject textures { |
| 6695 | {"tex.picture", QString("atp:" + mapping) } | ||
| 6696 | }; | ||
| 6697 | properties.setModelURL("https://hifi-content.s3.amazonaws.com/DomainContent/production/default-image-model.fbx"); | ||
| 6698 | properties.setTextures(QJsonDocument(textures).toJson(QJsonDocument::Compact)); | ||
| 6699 | properties.setShapeType(SHAPE_TYPE_BOX); | ||
| 6700 | } else { | ||
| 6701 | properties.setModelURL("atp:" + mapping); | ||
| 6702 | properties.setShapeType(SHAPE_TYPE_SIMPLE_COMPOUND); | ||
| 6703 | } | ||
| 6582 | properties.setCollisionless(true); // Temporarily set so that doesn't collide with avatar. | 6704 | properties.setCollisionless(true); // Temporarily set so that doesn't collide with avatar. |
| 6583 | properties.setVisible(false); // Temporarily set so that don't see at large unresized dimensions. | 6705 | properties.setVisible(false); // Temporarily set so that don't see at large unresized dimensions. |
| 6584 | glm::vec3 positionOffset = getMyAvatar()->getWorldOrientation() * (getMyAvatar()->getSensorToWorldScale() * glm::vec3(0.0f, 0.0f, -2.0f)); | 6706 | glm::vec3 positionOffset = getMyAvatar()->getWorldOrientation() * (getMyAvatar()->getSensorToWorldScale() * glm::vec3(0.0f, 0.0f, -2.0f)); |
| @@ -7002,10 +7124,10 @@ void Application::loadAvatarBrowser() const { · 417 unmodified lines | |||
| 7002 | DependencyManager::get<HMDScriptingInterface>()->openTablet(); | 7124 | DependencyManager::get<HMDScriptingInterface>()->openTablet(); |
| 7003 | } | 7125 | } |
| 7004 | 7126 | ||
| 7005 | void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) { | 7127 | void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) { |
| 7006 | postLambdaEvent([notify, includeAnimated, aspectRatio, this] { | 7128 | postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] { |
| 7007 | // Get a screenshot and save it | 7129 | // Get a screenshot and save it |
| 7008 | QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio)); | 7130 | QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename); |
| 7009 | // If we're not doing an animated snapshot as well... | 7131 | // If we're not doing an animated snapshot as well... |
| 7010 | if (!includeAnimated) { | 7132 | if (!includeAnimated) { |
| 7011 | // Tell the dependency manager that the capture of the still snapshot has taken place. | 7133 | // Tell the dependency manager that the capture of the still snapshot has taken place. |
| @@ -7017,9 +7139,9 @@ void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRa · 5 unmodified lines | |||
| 7017 | }); | 7139 | }); |
| 7018 | } | 7140 | } |
| 7019 | 7141 | ||
| 7020 | void Application::takeSecondaryCameraSnapshot() { | 7142 | void Application::takeSecondaryCameraSnapshot(const QString& filename) { |
| 7021 | postLambdaEvent([this] { | 7143 | postLambdaEvent([filename, this] { |
| 7022 | QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot()); | 7144 | QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename); |
| 7023 | emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(snapshotPath, true); | 7145 | emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(snapshotPath, true); |
| 7024 | }); | 7146 | }); |
| 7025 | } | 7147 | } |
| @@ -7393,9 +7515,7 @@ void Application::updateDisplayMode() { · 367 unmodified lines | |||
| 7393 | action->setChecked(true); | 7515 | action->setChecked(true); |
| 7394 | } | 7516 | } |
| 7395 | 7517 | ||
| 7396 | _offscreenContext->makeCurrent(); | ||
| 7397 | offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); | 7518 | offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); |
| 7398 | _offscreenContext->makeCurrent(); | ||
| 7399 | getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); | 7519 | getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); |
| 7400 | _displayPlugin = newDisplayPlugin; | 7520 | _displayPlugin = newDisplayPlugin; |
| 7401 | connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection); | 7521 | connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection); |