History

Merge remote-tracking branch 'samuel/scriptableMaterials' into Leopoly_Phase1_010_graphics-scripting-merge

humbletim committed 8 years ago

Commit 72fca7e2 parents be8d79f 4c6169e498 files · +18323 −41125Browse files

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

Unified · Split

interface/src/Application.cpp+218−98
@@ -319,7 +319,7 @@ static QTimer pingTimer; · 318 unmodified lines
319319 static bool DISABLE_WATCHDOG = true;
320320 #else
321321 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);
323323 #endif
324324
325325 #if defined(USE_GLES)
@@ -336,15 +336,17 @@ static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16; · 10 unmodified lines
336336 // we will never drop below the 'min' value
337337 static const int MIN_PROCESSING_THREAD_POOL_SIZE = 1;
338338
339−static const QString SNAPSHOT_EXTENSION = ".jpg";
340−static const QString SVO_EXTENSION = ".svo";
339+static const QString SNAPSHOT_EXTENSION = ".jpg";
340+static const QString JPG_EXTENSION = ".jpg";
341+static const QString PNG_EXTENSION = ".png";
342+static const QString SVO_EXTENSION = ".svo";
341343 static const QString SVO_JSON_EXTENSION = ".svo.json";
342344 static const QString JSON_GZ_EXTENSION = ".json.gz";
343345 static const QString JSON_EXTENSION = ".json";
344−static const QString JS_EXTENSION = ".js";
345−static const QString FST_EXTENSION = ".fst";
346−static const QString FBX_EXTENSION = ".fbx";
347−static const QString OBJ_EXTENSION = ".obj";
346+static const QString JS_EXTENSION = ".js";
347+static const QString FST_EXTENSION = ".fst";
348+static const QString FBX_EXTENSION = ".fbx";
349+static const QString OBJ_EXTENSION = ".obj";
348350 static const QString AVA_JSON_EXTENSION = ".ava.json";
349351 static const QString WEB_VIEW_TAG = "noDownload=true";
350352 static const QString ZIP_EXTENSION = ".zip";
@@ -383,7 +385,9 @@ const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensi · 32 unmodified lines
383385 { JS_EXTENSION, &Application::askToLoadScript },
384386 { FST_EXTENSION, &Application::askToSetAvatarUrl },
385387 { 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 }
387391 };
388392
389393 class DeadlockWatchdogThread : public QThread {
@@ -416,20 +420,26 @@ public: · 26 unmodified lines
416420 *crashTrigger = 0xDEAD10CC;
417421 }
418422
423+ static void withPause(const std::function<void()>& lambda) {
424+ pause();
425+ lambda();
426+ resume();
427+ }
419428 static void pause() {
420429 _paused = true;
421430 }
422431
423432 static void resume() {
424− _paused = false;
433+ // Update the heartbeat BEFORE resuming the checks
425434 updateHeartbeat();
435+ _paused = false;
426436 }
427437
428438 void run() override {
429439 while (!_quit) {
430440 QThread::sleep(HEARTBEAT_UPDATE_INTERVAL_SECS);
431441 // Don't do heartbeat detection under nsight
432− if (nsightActive() || _paused) {
442+ if (_paused) {
433443 continue;
434444 }
435445 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
863873 OverlayID _keyboardFocusHighlightID{ UNKNOWN_OVERLAY_ID };
864874
865875
876+OffscreenGLCanvas* _qmlShareContext { nullptr };
877+
866878 // FIXME hack access to the internal share context for the Chromium helper
867879 // Normally we'd want to use QWebEngine::initialize(), but we can't because
868880 // 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
11121124 connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &Application::notifyPacketVersionMismatch);
11131125
11141126 // 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()));
11161129
11171130 auto dialogsManager = DependencyManager::get<DialogsManager>();
11181131 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
16461659 }
16471660 });
16481661
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+
16491729 // Keyboard focus handling for Web overlays.
16501730 auto overlays = &(qApp->getOverlays());
16511731 connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) {
@@ -2324,18 +2404,37 @@ void Application::initializeGL() { · 672 unmodified lines
23242404 _isGLInitialized = true;
23252405 }
23262406
2407+ // Build a shared canvas / context for the Chromium processes
23272408 _glWidget->makeCurrent();
23282409
23292410 #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.
23302413 if (!nsightActive()) {
23312414 _chromiumShareContext = new OffscreenGLCanvas();
23322415 _chromiumShareContext->setObjectName("ChromiumShareContext");
23332416 _chromiumShareContext->create(_glWidget->qglContext());
23342417 _chromiumShareContext->makeCurrent();
2418+ if (!_chromiumShareContext->makeCurrent()) {
2419+ qCWarning(interfaceapp, "Unable to make chromium shared context current");
2420+ }
23352421 qt_gl_set_global_share_context(_chromiumShareContext->getContext());
2422+ } else {
2423+ qCWarning(interfaceapp) << "nSIGHT detected, disabling chrome rendering";
23362424 }
23372425 #endif
23382426
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+
23392438 _glWidget->makeCurrent();
23402439 gpu::Context::init<gpu::gl::GLBackend>();
23412440 qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK,
@@ -2348,29 +2447,22 @@ void Application::initializeGL() { · 6 unmodified lines
23482447 initDisplay();
23492448 qCDebug(interfaceapp, "Initialized Display.");
23502449
2351−#ifdef Q_OS_OSX
2352− // FIXME: on mac os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread.
2353− DeadlockWatchdogThread::pause();
2354−#endif
2355−
2356− // Set up the render engine
2357− render::CullFunctor cullFunctor = LODManager::shouldRender;
2358− static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD";
2359− _renderEngine->addJob<UpdateSceneTask>("UpdateScene");
2450+ // FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread.
2451+ DeadlockWatchdogThread::withPause([&] {
2452+ // Set up the render engine
2453+ render::CullFunctor cullFunctor = LODManager::shouldRender;
2454+ static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD";
2455+ _renderEngine->addJob<UpdateSceneTask>("UpdateScene");
23602456 #ifndef Q_OS_ANDROID
2361− _renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !DISABLE_DEFERRED);
2457+ _renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !DISABLE_DEFERRED);
23622458 #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);
23642462
2365−#ifdef Q_OS_OSX
2366− DeadlockWatchdogThread::resume();
2367−#endif
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();
2463+ // Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success.
2464+ DependencyManager::get<GeometryCache>()->initializeShapePipelines();
2465+ });
23742466
23752467 _offscreenContext = new OffscreenGLCanvas();
23762468 _offscreenContext->setObjectName("MainThreadContext");
@@ -2378,20 +2470,24 @@ void Application::initializeGL() { · 1 unmodified line
23782470 if (!_offscreenContext->makeCurrent()) {
23792471 qFatal("Unable to make offscreen context current");
23802472 }
2473+ _offscreenContext->doneCurrent();
2474+ _offscreenContext->setThreadContext();
2475+ _renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
23812476
23822477 // The UI can't be created until the primary OpenGL
23832478 // context is created, because it needs to share
23842479 // texture resources
23852480 // 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+
23862485 initializeUi();
23872486 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());
23942487
2488+ if (!_offscreenContext->makeCurrent()) {
2489+ qFatal("Unable to make offscreen context current");
2490+ }
23952491 init();
23962492 qCDebug(interfaceapp, "init() complete.");
23972493
@@ -2402,7 +2498,6 @@ void Application::initializeGL() { · 4 unmodified lines
24022498
24032499 _idleLoopStdev.reset();
24042500
2405− _renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
24062501
24072502 // Restore the primary GL content for the main thread
24082503 if (!_offscreenContext->makeCurrent()) {
@@ -2468,27 +2563,70 @@ void Application::initializeUi() { · 59 unmodified lines
24682563 auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
24692564 tabletScriptingInterface->getTablet(SYSTEM_TABLET);
24702565 }
2471− auto offscreenUi = DependencyManager::get<OffscreenUi>();
2472− offscreenUi->create();
24732566
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);
24752572
24762573 offscreenUi->setProxyWindow(_window->windowHandle());
24772574 // OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to
24782575 // 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+ });
24802579 // FIXME either expose so that dialogs can set this themselves or
24812580 // do better detection in the offscreen UI of what has focus
24822581 offscreenUi->setNavigationFocused(false);
24832582
2484− auto engine = surfaceContext->engine();
2485− connect(engine, &QQmlEngine::quit, [] {
2486− qApp->quit();
2583+ setupPreferences();
2584+
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();
24872599 });
24882600
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+}
24892626
2490− setupPreferences();
24912627
2628+void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) {
2629+ auto engine = surfaceContext->engine();
24922630 // in Qt 5.10.0 there is already an "Audio" object in the QML context
24932631 // though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface"
24942632 surfaceContext->setContextProperty("AudioScriptingInterface", DependencyManager::get<AudioScriptingInterface>().data());
@@ -2570,48 +2708,12 @@ void Application::initializeUi() { · 75 unmodified lines
25702708 surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
25712709 }
25722710
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− }
26002711 _window->setMenuBar(new Menu());
2712+}
26012713
2602− auto compositorHelper = DependencyManager::get<CompositorHelper>();
2603− connect(compositorHelper.data(), &CompositorHelper::allowMouseCaptureChanged, this, [=] {
2604− if (isHMDMode()) {
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);
2714+void Application::onDesktopRootItemCreated(QQuickItem* rootItem) {
2715+ Stats::show();
2716+ AvatarInputs::show();
26152717 }
26162718
26172719 void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {
@@ -2850,6 +2952,8 @@ void Application::resizeGL() { · 232 unmodified lines
28502952 QMutexLocker viewLocker(&_viewMutex);
28512953 _myCamera.loadViewFrustum(_viewFrustum);
28522954 }
2955+
2956+ DependencyManager::get<OffscreenUi>()->resize(fromGlm(displayPlugin->getRecommendedUiSize()));
28532957 }
28542958
28552959 void Application::handleSandboxStatus(QNetworkReply* reply) {
@@ -2965,6 +3069,14 @@ bool Application::importFromZIP(const QString& filePath) { · 109 unmodified lines
29653069 return true;
29663070 }
29673071
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+
29683080 // thread-safe
29693081 void Application::onPresent(quint32 frameCount) {
29703082 bool expected = false;
@@ -4058,7 +4170,7 @@ void Application::idle() { · 1087 unmodified lines
40584170 // Bit of a hack since there's no device pixel ratio change event I can find.
40594171 if (offscreenUi->size() != fromGlm(uiSize)) {
40604172 qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize;
4061− offscreenUi->resize(fromGlm(uiSize), true);
4173+ offscreenUi->resize(fromGlm(uiSize));
40624174 _offscreenContext->makeCurrent();
40634175 }
40644176 }
@@ -6560,7 +6672,8 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q · 2495 unmodified lines
65606672 addAssetToWorldError(filenameFromPath(filePath), errorInfo);
65616673 } else {
65626674 // 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)) {
65646677 addAssetToWorldAddEntity(filePath, mapping);
65656678 } else {
65666679 qCDebug(interfaceapp) << "Zipped contents are not supported entity files";
@@ -6577,8 +6690,17 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { · 10 unmodified lines
65776690 EntityItemProperties properties;
65786691 properties.setType(EntityTypes::Model);
65796692 properties.setName(mapping.right(mapping.length() - 1));
6580− properties.setModelURL("atp:" + mapping);
6581− properties.setShapeType(SHAPE_TYPE_SIMPLE_COMPOUND);
6693+ if (filePath.endsWith(PNG_EXTENSION) || filePath.endsWith(JPG_EXTENSION)) {
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+ }
65826704 properties.setCollisionless(true); // Temporarily set so that doesn't collide with avatar.
65836705 properties.setVisible(false); // Temporarily set so that don't see at large unresized dimensions.
65846706 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
70027124 DependencyManager::get<HMDScriptingInterface>()->openTablet();
70037125 }
70047126
7005−void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) {
7006− postLambdaEvent([notify, includeAnimated, aspectRatio, this] {
7127+void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio, const QString& filename) {
7128+ postLambdaEvent([notify, includeAnimated, aspectRatio, filename, this] {
70077129 // Get a screenshot and save it
7008− QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio));
7130+ QString path = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getScreenshot(aspectRatio), filename);
70097131 // If we're not doing an animated snapshot as well...
70107132 if (!includeAnimated) {
70117133 // 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
70177139 });
70187140 }
70197141
7020−void Application::takeSecondaryCameraSnapshot() {
7021− postLambdaEvent([this] {
7022− QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot());
7142+void Application::takeSecondaryCameraSnapshot(const QString& filename) {
7143+ postLambdaEvent([filename, this] {
7144+ QString snapshotPath = Snapshot::saveSnapshot(getActiveDisplayPlugin()->getSecondaryCameraScreenshot(), filename);
70237145 emit DependencyManager::get<WindowScriptingInterface>()->stillSnapshotTaken(snapshotPath, true);
70247146 });
70257147 }
@@ -7393,9 +7515,7 @@ void Application::updateDisplayMode() { · 367 unmodified lines
73937515 action->setChecked(true);
73947516 }
73957517
7396− _offscreenContext->makeCurrent();
73977518 offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize()));
7398− _offscreenContext->makeCurrent();
73997519 getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
74007520 _displayPlugin = newDisplayPlugin;
74017521 connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection);