History

Fixup after Merge branch 'master' of https://github.com/highfidelity/hifi into SelectionScriptingInterface

Zach Fox committed 9 years ago

Commit 0cdef282 parents 3c7fadb d675ee9164 files · +9284 −5766Browse files

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

Unified · Split

interface/src/Application.cpp+239−153
@@ -113,7 +113,6 @@ · 112 unmodified lines
113#include <plugins/SteamClientPlugin.h>113#include <plugins/SteamClientPlugin.h>
114#include <plugins/InputConfiguration.h>114#include <plugins/InputConfiguration.h>
115#include <RecordingScriptingInterface.h>115#include <RecordingScriptingInterface.h>
116#include <RenderableWebEntityItem.h>
117#include <UpdateSceneTask.h>116#include <UpdateSceneTask.h>
118#include <RenderViewTask.h>117#include <RenderViewTask.h>
119#include <SecondaryCamera.h>118#include <SecondaryCamera.h>
@@ -139,6 +138,7 @@ · 19 unmodified lines
139#include <display-plugins/CompositorHelper.h>138#include <display-plugins/CompositorHelper.h>
140#include <trackers/EyeTracker.h>139#include <trackers/EyeTracker.h>
141#include <avatars-renderer/ScriptAvatar.h>140#include <avatars-renderer/ScriptAvatar.h>
141#include <RenderableEntityItem.h>
142 142
143#include "AudioClient.h"143#include "AudioClient.h"
144#include "audio/AudioScope.h"144#include "audio/AudioScope.h"
@@ -184,6 +184,7 @@ · 39 unmodified lines
184#include "ui/UpdateDialog.h"184#include "ui/UpdateDialog.h"
185#include "ui/overlays/Overlays.h"185#include "ui/overlays/Overlays.h"
186#include "ui/DomainConnectionModel.h"186#include "ui/DomainConnectionModel.h"
187#include "ui/ImageProvider.h"
187#include "Util.h"188#include "Util.h"
188#include "InterfaceParentFinder.h"189#include "InterfaceParentFinder.h"
189#include "ui/OctreeStatsProvider.h"190#include "ui/OctreeStatsProvider.h"
@@ -212,6 +213,73 @@ extern "C" { · 22 unmodified lines
212}213}
213#endif214#endif
214 215
216enum ApplicationEvent {
217 // Execute a lambda function
218 Lambda = QEvent::User + 1,
219 // Trigger the next render
220 Render,
221 // Trigger the next idle
222 Idle,
223};
224
225
226class RenderEventHandler : public QObject {
227 using Parent = QObject;
228 Q_OBJECT
229public:
230 RenderEventHandler(QOpenGLContext* context) {
231 _renderContext = new OffscreenGLCanvas();
232 _renderContext->setObjectName("RenderContext");
233 _renderContext->create(context);
234 if (!_renderContext->makeCurrent()) {
235 qFatal("Unable to make rendering context current");
236 }
237 _renderContext->doneCurrent();
238
239 // Deleting the object with automatically shutdown the thread
240 connect(qApp, &QCoreApplication::aboutToQuit, this, &QObject::deleteLater);
241
242 // Transfer to a new thread
243 moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) {
244 hifi::qt::addBlockingForbiddenThread("Render", renderThread);
245 _renderContext->moveToThreadWithContext(renderThread);
246 qApp->_lastTimeRendered.start();
247 }, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority);
248 }
249
250private:
251 void initialize() {
252 PROFILE_SET_THREAD_NAME("Render");
253 if (!_renderContext->makeCurrent()) {
254 qFatal("Unable to make rendering context current on render thread");
255 }
256 }
257
258 void render() {
259 if (qApp->shouldPaint()) {
260 qApp->paintGL();
261 }
262 }
263
264 bool event(QEvent* event) override {
265 switch ((int)event->type()) {
266 case ApplicationEvent::Render:
267 render();
268 // Ensure we never back up the render events. Each render should be triggered only in response
269 // to the NEXT render event after the last render occured
270 QCoreApplication::removePostedEvents(this, ApplicationEvent::Render);
271 return true;
272
273 default:
274 break;
275 }
276 return Parent::event(event);
277 }
278
279 OffscreenGLCanvas* _renderContext { nullptr };
280};
281
282
215Q_LOGGING_CATEGORY(trace_app_input_mouse, "trace.app.input.mouse")283Q_LOGGING_CATEGORY(trace_app_input_mouse, "trace.app.input.mouse")
216 284
217using namespace std;285using namespace std;
@@ -427,10 +495,10 @@ class LambdaEvent : public QEvent { · 209 unmodified lines
427 std::function<void()> _fun;495 std::function<void()> _fun;
428public:496public:
429 LambdaEvent(const std::function<void()> & fun) :497 LambdaEvent(const std::function<void()> & fun) :
430 QEvent(static_cast<QEvent::Type>(Application::Lambda)), _fun(fun) {498 QEvent(static_cast<QEvent::Type>(ApplicationEvent::Lambda)), _fun(fun) {
431 }499 }
432 LambdaEvent(std::function<void()> && fun) :500 LambdaEvent(std::function<void()> && fun) :
433 QEvent(static_cast<QEvent::Type>(Application::Lambda)), _fun(fun) {501 QEvent(static_cast<QEvent::Type>(ApplicationEvent::Lambda)), _fun(fun) {
434 }502 }
435 void call() const { _fun(); }503 void call() const { _fun(); }
436};504};
@@ -1368,8 +1436,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 931 unmodified lines
1368 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();1436 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
1369 connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity,1437 connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity,
1370 [this](const EntityItemID& entityItemID, const PointerEvent& event) {1438 [this](const EntityItemID& entityItemID, const PointerEvent& event) {
1371 auto entity = getEntities()->getTree()->findEntityByID(entityItemID);1439 if (getEntities()->wantsKeyboardFocus(entityItemID)) {
1372 if (entity && entity->wantsKeyboardFocus()) {
1373 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);1440 setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
1374 setKeyboardFocusEntity(entityItemID);1441 setKeyboardFocusEntity(entityItemID);
1375 } else {1442 } else {
@@ -1693,7 +1760,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 317 unmodified lines
1693 _defaultSkybox->setCubemap(_defaultSkyboxTexture);1760 _defaultSkybox->setCubemap(_defaultSkyboxTexture);
1694 }1761 }
1695 1762
1696 EntityItem::setEntitiesShouldFadeFunction([this]() {1763 EntityTreeRenderer::setEntitiesShouldFadeFunction([this]() {
1697 SharedNodePointer entityServerNode = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::EntityServer);1764 SharedNodePointer entityServerNode = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::EntityServer);
1698 return entityServerNode && !isPhysicsEnabled();1765 return entityServerNode && !isPhysicsEnabled();
1699 });1766 });
@@ -1737,6 +1804,27 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo · 37 unmodified lines
1737 1804
1738 connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);1805 connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
1739 1806
1807 // Setup the mouse ray pick and related operators
1808 DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(_rayPickManager.createRayPick(
1809 RayPickFilter(DependencyManager::get<RayPickScriptingInterface>()->PICK_ENTITIES() | DependencyManager::get<RayPickScriptingInterface>()->PICK_INCLUDE_NONCOLLIDABLE()),
1810 0.0f, true));
1811 DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([&](QUuid rayPickID) {
1812 RayToEntityIntersectionResult entityResult;
1813 RayPickResult result = _rayPickManager.getPrevRayPickResult(rayPickID);
1814 entityResult.intersects = result.type != DependencyManager::get<RayPickScriptingInterface>()->INTERSECTED_NONE();
1815 if (entityResult.intersects) {
1816 entityResult.intersection = result.intersection;
1817 entityResult.distance = result.distance;
1818 entityResult.surfaceNormal = result.surfaceNormal;
1819 entityResult.entityID = result.objectID;
1820 entityResult.entity = DependencyManager::get<EntityTreeRenderer>()->getTree()->findEntityByID(entityResult.entityID);
1821 }
1822 return entityResult;
1823 });
1824 DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([&](QUuid rayPickID, bool value) {
1825 _rayPickManager.setPrecisionPicking(rayPickID, value);
1826 });
1827
1740 qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());1828 qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
1741}1829}
1742 1830
@@ -2079,6 +2167,13 @@ void Application::initializeGL() { · 336 unmodified lines
2079 _renderEngine->load();2167 _renderEngine->load();
2080 _renderEngine->registerScene(_main3DScene);2168 _renderEngine->registerScene(_main3DScene);
2081 2169
2170 _offscreenContext = new OffscreenGLCanvas();
2171 _offscreenContext->setObjectName("MainThreadContext");
2172 _offscreenContext->create(_glWidget->qglContext());
2173 if (!_offscreenContext->makeCurrent()) {
2174 qFatal("Unable to make offscreen context current");
2175 }
2176
2082 // The UI can't be created until the primary OpenGL2177 // The UI can't be created until the primary OpenGL
2083 // context is created, because it needs to share2178 // context is created, because it needs to share
2084 // texture resources2179 // texture resources
@@ -2102,14 +2197,15 @@ void Application::initializeGL() { · 17 unmodified lines
2102 2197
2103 _idleLoopStdev.reset();2198 _idleLoopStdev.reset();
2104 2199
2105 _offscreenContext = new OffscreenGLCanvas();2200 _renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
2106 _offscreenContext->setObjectName("MainThreadContext");2201
2107 _offscreenContext->create(_glWidget->qglContext());2202 // Restore the primary GL content for the main thread
2108 _offscreenContext->makeCurrent();2203 if (!_offscreenContext->makeCurrent()) {
2204 qFatal("Unable to make offscreen context current");
2205 }
2109 2206
2110 // update before the first render2207 // update before the first render
2111 update(0);2208 update(0);
2112
2113}2209}
2114 2210
2115FrameTimingsScriptingInterface _frameTimingsScriptingInterface;2211FrameTimingsScriptingInterface _frameTimingsScriptingInterface;
@@ -2117,6 +2213,9 @@ FrameTimingsScriptingInterface _frameTimingsScriptingInterface; · 1 unmodified line
2117extern void setupPreferences();2213extern void setupPreferences();
2118 2214
2119void Application::initializeUi() {2215void Application::initializeUi() {
2216 // Make sure all QML surfaces share the main thread GL context
2217 OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext());
2218
2120 AddressBarDialog::registerType();2219 AddressBarDialog::registerType();
2121 ErrorDialog::registerType();2220 ErrorDialog::registerType();
2122 LoginDialog::registerType();2221 LoginDialog::registerType();
@@ -2127,7 +2226,7 @@ void Application::initializeUi() { · 4 unmodified lines
2127 qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");2226 qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
2128 2227
2129 auto offscreenUi = DependencyManager::get<OffscreenUi>();2228 auto offscreenUi = DependencyManager::get<OffscreenUi>();
2130 offscreenUi->create(_glWidget->qglContext());2229 offscreenUi->create();
2131 2230
2132 auto surfaceContext = offscreenUi->getSurfaceContext();2231 auto surfaceContext = offscreenUi->getSurfaceContext();
2133 2232
@@ -2146,6 +2245,9 @@ void Application::initializeUi() { · 12 unmodified lines
2146 qApp->quit();2245 qApp->quit();
2147 });2246 });
2148 2247
2248 // register the pixmap image provider (used only for security image, for now)
2249 engine->addImageProvider(ImageProvider::PROVIDER_NAME, new ImageProvider());
2250
2149 setupPreferences();2251 setupPreferences();
2150 2252
2151 // For some reason there is already an "Application" object in the QML context,2253 // For some reason there is already an "Application" object in the QML context,
@@ -2270,14 +2372,12 @@ void Application::initializeUi() { · 118 unmodified lines
2270 2372
2271void Application::paintGL() {2373void Application::paintGL() {
2272 // Some plugins process message events, allowing paintGL to be called reentrantly.2374 // Some plugins process message events, allowing paintGL to be called reentrantly.
2273 if (_inPaint || _aboutToQuit || _window->isMinimized()) {2375 if (_aboutToQuit || _window->isMinimized()) {
2274 return;2376 return;
2275 }2377 }
2276 2378
2277 _inPaint = true;
2278 Finally clearFlag([this] { _inPaint = false; });
2279
2280 _frameCount++;2379 _frameCount++;
2380 _lastTimeRendered.start();
2281 2381
2282 auto lastPaintBegin = usecTimestampNow();2382 auto lastPaintBegin = usecTimestampNow();
2283 PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_frameCount);2383 PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_frameCount);
@@ -2293,18 +2393,11 @@ void Application::paintGL() { · 9 unmodified lines
2293 displayPlugin = getActiveDisplayPlugin();2393 displayPlugin = getActiveDisplayPlugin();
2294 }2394 }
2295 2395
2296 {
2297 PROFILE_RANGE(render, "/offscreenMakeCurrent");
2298 // FIXME not needed anymore?
2299 _offscreenContext->makeCurrent();
2300 }
2301
2302 {2396 {
2303 PROFILE_RANGE(render, "/pluginBeginFrameRender");2397 PROFILE_RANGE(render, "/pluginBeginFrameRender");
2304 // If a display plugin loses it's underlying support, it2398 // If a display plugin loses it's underlying support, it
2305 // needs to be able to signal us to not use it2399 // needs to be able to signal us to not use it
2306 if (!displayPlugin->beginFrameRender(_frameCount)) {2400 if (!displayPlugin->beginFrameRender(_frameCount)) {
2307 _inPaint = false;
2308 updateDisplayMode();2401 updateDisplayMode();
2309 return;2402 return;
2310 }2403 }
@@ -2372,12 +2465,6 @@ void Application::paintGL() { · 61 unmodified lines
2372 auto myAvatar = getMyAvatar();2465 auto myAvatar = getMyAvatar();
2373 boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;2466 boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD;
2374 2467
2375 if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
2376 Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
2377 Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
2378 cameraMenuChanged();
2379 }
2380
2381 // The render mode is default or mirror if the camera is in mirror mode, assigned further below2468 // The render mode is default or mirror if the camera is in mirror mode, assigned further below
2382 renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;2469 renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE;
2383 2470
@@ -2685,15 +2772,6 @@ void Application::resizeGL() { · 301 unmodified lines
2685 QMutexLocker viewLocker(&_viewMutex);2772 QMutexLocker viewLocker(&_viewMutex);
2686 _myCamera.loadViewFrustum(_viewFrustum);2773 _myCamera.loadViewFrustum(_viewFrustum);
2687 }2774 }
2688
2689 auto offscreenUi = DependencyManager::get<OffscreenUi>();
2690 auto uiSize = displayPlugin->getRecommendedUiSize();
2691 // Bit of a hack since there's no device pixel ratio change event I can find.
2692 if (offscreenUi->size() != fromGlm(uiSize)) {
2693 qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize;
2694 offscreenUi->resize(fromGlm(uiSize), true);
2695 _offscreenContext->makeCurrent();
2696 }
2697}2775}
2698 2776
2699void Application::handleSandboxStatus(QNetworkReply* reply) {2777void Application::handleSandboxStatus(QNetworkReply* reply) {
@@ -2867,56 +2945,26 @@ bool Application::importFromZIP(const QString& filePath) { · 167 unmodified lines
2867}2945}
2868 2946
2869void Application::onPresent(quint32 frameCount) {2947void Application::onPresent(quint32 frameCount) {
2870 if (shouldPaint()) {2948 postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority);
2871 postEvent(this, new QEvent(static_cast<QEvent::Type>(Idle)), Qt::HighEventPriority);2949 if (_renderEventHandler && !isAboutToQuit()) {
2872 postEvent(this, new QEvent(static_cast<QEvent::Type>(Paint)), Qt::HighEventPriority);2950 postEvent(_renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render));
2873 }2951 }
2874}2952}
2875 2953
2876bool _renderRequested { false };2954static inline bool isKeyEvent(QEvent::Type type) {
2877 2955 return type == QEvent::KeyPress || type == QEvent::KeyRelease;
2878bool Application::event(QEvent* event) {2956}
2879 if (!Menu::getInstance()) {
2880 return false;
2881 }
2882
2883 int type = event->type();
2884 switch (type) {
2885 case Event::Lambda:
2886 static_cast<LambdaEvent*>(event)->call();
2887 return true;
2888
2889 // Explicit idle keeps the idle running at a lower interval, but without any rendering
2890 // see (windowMinimizedChanged)
2891 case Event::Idle:
2892 idle();
2893 // Clear the event queue of pending idle calls
2894 removePostedEvents(this, Idle);
2895 return true;
2896
2897 case Event::Paint:
2898 // NOTE: This must be updated as close to painting as possible,
2899 // or AvatarInputs will mysteriously move to the bottom-right
2900 AvatarInputs::getInstance()->update();
2901 paintGL();
2902 // Clear the event queue of pending paint calls
2903 removePostedEvents(this, Paint);
2904 return true;
2905
2906 default:
2907 break;
2908 }
2909 2957
2910 {2958bool Application::handleKeyEventForFocusedEntityOrOverlay(QEvent* event) {
2911 if (!_keyboardFocusedEntity.get().isInvalidID()) {2959 if (!_keyboardFocusedEntity.get().isInvalidID()) {
2912 switch (event->type()) {2960 switch (event->type()) {
2913 case QEvent::KeyPress:2961 case QEvent::KeyPress:
2914 case QEvent::KeyRelease: {2962 case QEvent::KeyRelease:
2915 //auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();2963 {
2916 auto entity = getEntities()->getTree()->findEntityByID(_keyboardFocusedEntity.get());2964 auto eventHandler = getEntities()->getEventHandler(_keyboardFocusedEntity.get());
2917 if (entity && entity->getEventHandler()) {2965 if (eventHandler) {
2918 event->setAccepted(false);2966 event->setAccepted(false);
2919 QCoreApplication::sendEvent(entity->getEventHandler(), event);2967 QCoreApplication::sendEvent(eventHandler, event);
2920 if (event->isAccepted()) {2968 if (event->isAccepted()) {
2921 _lastAcceptedKeyPress = usecTimestampNow();2969 _lastAcceptedKeyPress = usecTimestampNow();
2922 return true;2970 return true;
@@ -2924,20 +2972,17 @@ bool Application::event(QEvent* event) { · 1 unmodified line
2924 }2972 }
2925 break;2973 break;
2926 }2974 }
2927 default:2975 default:
2928 break;2976 break;
2929 }
2930 }2977 }
2931 }2978 }
2932 2979
2933 {2980 if (_keyboardFocusedOverlay.get() != UNKNOWN_OVERLAY_ID) {
2934 if (_keyboardFocusedOverlay.get() != UNKNOWN_OVERLAY_ID) {2981 switch (event->type()) {
2935 switch (event->type()) {2982 case QEvent::KeyPress:
2936 case QEvent::KeyPress:2983 case QEvent::KeyRelease: {
2937 case QEvent::KeyRelease: {
2938 // Only Web overlays can have focus.2984 // Only Web overlays can have focus.
2939 auto overlay =2985 auto overlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(_keyboardFocusedOverlay.get()));
2940 std::dynamic_pointer_cast<Web3DOverlay>(getOverlays().getOverlay(_keyboardFocusedOverlay.get()));
2941 if (overlay && overlay->getEventHandler()) {2986 if (overlay && overlay->getEventHandler()) {
2942 event->setAccepted(false);2987 event->setAccepted(false);
2943 QCoreApplication::sendEvent(overlay->getEventHandler(), event);2988 QCoreApplication::sendEvent(overlay->getEventHandler(), event);
@@ -2946,15 +2991,52 @@ bool Application::event(QEvent* event) { · 2 unmodified lines
2946 return true;2991 return true;
2947 }2992 }
2948 }2993 }
2949 break;
2950 }
2951 default:
2952 break;
2953 }2994 }
2995 break;
2996
2997 default:
2998 break;
2954 }2999 }
2955 }3000 }
2956 3001
2957 switch (event->type()) {3002 return false;
3003}
3004
3005bool Application::handleFileOpenEvent(QFileOpenEvent* fileEvent) {
3006 QUrl url = fileEvent->url();
3007 if (!url.isEmpty()) {
3008 QString urlString = url.toString();
3009 if (canAcceptURL(urlString)) {
3010 return acceptURL(urlString);
3011 }
3012 }
3013 return false;
3014}
3015
3016bool Application::event(QEvent* event) {
3017 if (!Menu::getInstance()) {
3018 return false;
3019 }
3020
3021 // Allow focused Entities and Overlays to handle keyboard input
3022 if (isKeyEvent(event->type()) && handleKeyEventForFocusedEntityOrOverlay(event)) {
3023 return true;
3024 }
3025
3026 int type = event->type();
3027 switch (type) {
3028 case ApplicationEvent::Lambda:
3029 static_cast<LambdaEvent*>(event)->call();
3030 return true;
3031
3032 // Explicit idle keeps the idle running at a lower interval, but without any rendering
3033 // see (windowMinimizedChanged)
3034 case ApplicationEvent::Idle:
3035 idle();
3036 // Don't process extra idle events that arrived in the event queue while we were doing this idle
3037 QCoreApplication::removePostedEvents(this, ApplicationEvent::Idle);
3038 return true;
3039
2958 case QEvent::MouseMove:3040 case QEvent::MouseMove:
2959 mouseMoveEvent(static_cast<QMouseEvent*>(event));3041 mouseMoveEvent(static_cast<QMouseEvent*>(event));
2960 return true;3042 return true;
@@ -2995,26 +3077,15 @@ bool Application::event(QEvent* event) { · 34 unmodified lines
2995 case QEvent::Drop:3077 case QEvent::Drop:
2996 dropEvent(static_cast<QDropEvent*>(event));3078 dropEvent(static_cast<QDropEvent*>(event));
2997 return true;3079 return true;
2998 default:
2999 break;
3000 }
3001 3080
3002 // handle custom URL3081 case QEvent::FileOpen:
3003 if (event->type() == QEvent::FileOpen) {3082 if (handleFileOpenEvent(static_cast<QFileOpenEvent*>(event))) {
3004 3083 return true;
3005 QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event);
3006
3007 QUrl url = fileEvent->url();
3008
3009 if (!url.isEmpty()) {
3010 QString urlString = url.toString();
3011
3012 if (canAcceptURL(urlString)) {
3013
3014 return acceptURL(urlString);
3015 }3084 }
3016 }3085 break;
3017 return false;3086
3087 default:
3088 break;
3018 }3089 }
3019 3090
3020 if (HFActionEvent::types().contains(event->type())) {3091 if (HFActionEvent::types().contains(event->type())) {
@@ -3719,11 +3790,12 @@ bool Application::acceptSnapshot(const QString& urlString) { · 698 unmodified lines
3719 3790
3720static uint32_t _renderedFrameIndex { INVALID_FRAME };3791static uint32_t _renderedFrameIndex { INVALID_FRAME };
3721 3792
3722bool Application::shouldPaint() {3793bool Application::shouldPaint() const {
3723 if (_aboutToQuit) {3794 if (_aboutToQuit) {
3724 return false;3795 return false;
3725 }3796 }
3726 3797
3798
3727 auto displayPlugin = getActiveDisplayPlugin();3799 auto displayPlugin = getActiveDisplayPlugin();
3728 3800
3729#ifdef DEBUG_PAINT_DELAY3801#ifdef DEBUG_PAINT_DELAY
@@ -3739,15 +3811,14 @@ bool Application::shouldPaint() { · 9 unmodified lines
3739 (float)paintDelaySamples / paintDelayUsecs << "us";3811 (float)paintDelaySamples / paintDelayUsecs << "us";
3740 }3812 }
3741#endif3813#endif
3742 3814
3743 // Throttle if requested3815 // Throttle if requested
3744 if (displayPlugin->isThrottled() && (_lastTimeUpdated.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {3816 if (displayPlugin->isThrottled() && (_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) {
3745 return false;3817 return false;
3746 }3818 }
3747 3819
3748 // Sync up the _renderedFrameIndex3820 // Sync up the _renderedFrameIndex
3749 _renderedFrameIndex = displayPlugin->presentCount();3821 _renderedFrameIndex = displayPlugin->presentCount();
3750
3751 return true;3822 return true;
3752}3823}
3753 3824
@@ -3957,7 +4028,6 @@ void setupCpuMonitorThread() { · 203 unmodified lines
3957 4028
3958#endif4029#endif
3959 4030
3960
3961void Application::idle() {4031void Application::idle() {
3962 PerformanceTimer perfTimer("idle");4032 PerformanceTimer perfTimer("idle");
3963 4033
@@ -3988,9 +4058,17 @@ void Application::idle() { · 24 unmodified lines
3988 });4058 });
3989#endif4059#endif
3990 4060
3991
3992
3993 auto displayPlugin = getActiveDisplayPlugin();4061 auto displayPlugin = getActiveDisplayPlugin();
4062 if (displayPlugin) {
4063 auto uiSize = displayPlugin->getRecommendedUiSize();
4064 // Bit of a hack since there's no device pixel ratio change event I can find.
4065 if (offscreenUi->size() != fromGlm(uiSize)) {
4066 qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize;
4067 offscreenUi->resize(fromGlm(uiSize), true);
4068 _offscreenContext->makeCurrent();
4069 }
4070 }
4071
3994 if (displayPlugin) {4072 if (displayPlugin) {
3995 PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate());4073 PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate());
3996 }4074 }
@@ -4038,6 +4116,10 @@ void Application::idle() { · 41 unmodified lines
4038 bool showWarnings = getLogger()->extraDebugging();4116 bool showWarnings = getLogger()->extraDebugging();
4039 PerformanceWarning warn(showWarnings, "idle()");4117 PerformanceWarning warn(showWarnings, "idle()");
4040 4118
4119 if (!_offscreenContext->makeCurrent()) {
4120 qFatal("Unable to make main thread context current");
4121 }
4122
4041 {4123 {
4042 PerformanceTimer perfTimer("update");4124 PerformanceTimer perfTimer("update");
4043 PerformanceWarning warn(showWarnings, "Application::idle()... update()");4125 PerformanceWarning warn(showWarnings, "Application::idle()... update()");
@@ -4100,6 +4182,13 @@ void Application::idle() { · 56 unmodified lines
4100 }4182 }
4101 4183
4102 _overlayConductor.update(secondsSinceLastUpdate);4184 _overlayConductor.update(secondsSinceLastUpdate);
4185
4186 auto myAvatar = getMyAvatar();
4187 if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
4188 Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
4189 Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
4190 cameraMenuChanged();
4191 }
4103}4192}
4104 4193
4105ivec2 Application::getMouse() const {4194ivec2 Application::getMouse() const {
@@ -4354,7 +4443,6 @@ void Application::init() { · 248 unmodified lines
4354 _timerStart.start();4443 _timerStart.start();
4355 _lastTimeUpdated.start();4444 _lastTimeUpdated.start();
4356 4445
4357
4358 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {4446 if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
4359 // when +connect_lobby in command line, join steam lobby4447 // when +connect_lobby in command line, join steam lobby
4360 const QString STEAM_LOBBY_COMMAND_LINE_KEY = "+connect_lobby";4448 const QString STEAM_LOBBY_COMMAND_LINE_KEY = "+connect_lobby";
@@ -4403,14 +4491,7 @@ void Application::init() { · 42 unmodified lines
4403 4491
4404 // Make sure any new sounds are loaded as soon as know about them.4492 // Make sure any new sounds are loaded as soon as know about them.
4405 connect(tree.get(), &EntityTree::newCollisionSoundURL, this, [this](QUrl newURL, EntityItemID id) {4493 connect(tree.get(), &EntityTree::newCollisionSoundURL, this, [this](QUrl newURL, EntityItemID id) {
4406 EntityTreePointer tree = getEntities()->getTree();4494 getEntities()->setCollisionSound(id, DependencyManager::get<SoundCache>()->getSound(newURL));
4407 if (auto entity = tree->findEntityByEntityItemID(id)) {
4408 auto sound = DependencyManager::get<SoundCache>()->getSound(newURL);
4409 auto renderable = entity->getRenderableInterface();
4410 if (renderable) {
4411 renderable->setCollisionSound(sound);
4412 }
4413 }
4414 }, Qt::QueuedConnection);4495 }, Qt::QueuedConnection);
4415 connect(getMyAvatar().get(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) {4496 connect(getMyAvatar().get(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) {
4416 if (auto avatar = getMyAvatar()) {4497 if (auto avatar = getMyAvatar()) {
@@ -4721,9 +4802,12 @@ void Application::setKeyboardFocusEntity(EntityItemID entityItemID) { · 304 unmodified lines
4721 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();4802 auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>();
4722 auto properties = entityScriptingInterface->getEntityProperties(entityItemID);4803 auto properties = entityScriptingInterface->getEntityProperties(entityItemID);
4723 if (!properties.getLocked() && properties.getVisible()) {4804 if (!properties.getLocked() && properties.getVisible()) {
4724 auto entity = getEntities()->getTree()->findEntityByID(entityItemID);4805
4725 if (entity && entity->wantsKeyboardFocus()) {4806 auto entities = getEntities();
4726 entity->setProxyWindow(_window->windowHandle());4807 auto entityId = _keyboardFocusedEntity.get();
4808 if (entities->wantsKeyboardFocus(entityId)) {
4809 entities->setProxyWindow(entityId, _window->windowHandle());
4810 auto entity = getEntities()->getEntity(entityId);
4727 if (_keyboardMouseDevice->isActive()) {4811 if (_keyboardMouseDevice->isActive()) {
4728 _keyboardMouseDevice->pluginFocusOutEvent();4812 _keyboardMouseDevice->pluginFocusOutEvent();
4729 }4813 }
@@ -4999,7 +5083,7 @@ void Application::update(float deltaTime) { · 269 unmodified lines
4999 PerformanceTimer perfTimer("physics");5083 PerformanceTimer perfTimer("physics");
5000 5084
5001 {5085 {
5002 PROFILE_RANGE_EX(simulation_physics, "UpdateStats", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());5086 PROFILE_RANGE_EX(simulation_physics, "UpdateStates", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());
5003 5087
5004 PerformanceTimer perfTimer("updateStates)");5088 PerformanceTimer perfTimer("updateStates)");
5005 static VectorOfMotionStates motionStates;5089 static VectorOfMotionStates motionStates;
@@ -5068,7 +5152,7 @@ void Application::update(float deltaTime) { · 62 unmodified lines
5068 5152
5069 // NOTE: the getEntities()->update() call below will wait for lock5153 // NOTE: the getEntities()->update() call below will wait for lock
5070 // and will simulate entity motion (the EntityTree has been given an EntitySimulation).5154 // and will simulate entity motion (the EntityTree has been given an EntitySimulation).
5071 getEntities()->update(); // update the models...5155 getEntities()->update(true); // update the models...
5072 }5156 }
5073 5157
5074 myAvatar->harvestResultsFromPhysicsSimulation(deltaTime);5158 myAvatar->harvestResultsFromPhysicsSimulation(deltaTime);
@@ -5081,6 +5165,9 @@ void Application::update(float deltaTime) { · 6 unmodified lines
5081 _physicsEngine->dumpStatsIfNecessary();5165 _physicsEngine->dumpStatsIfNecessary();
5082 }5166 }
5083 }5167 }
5168 } else {
5169 // update the rendering without any simulation
5170 getEntities()->update(false);
5084 }5171 }
5085 5172
5086 // AvatarManager update5173 // AvatarManager update
@@ -6256,7 +6343,11 @@ bool Application::askToReplaceDomainContent(const QString& url) { · 1169 unmodified lines
6256 octreeFilePacket->write(urlData);6343 octreeFilePacket->write(urlData);
6257 limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode);6344 limitedNodeList->sendPacket(std::move(octreeFilePacket), *octreeNode);
6258 });6345 });
6259 DependencyManager::get<AddressManager>()->handleLookupString(DOMAIN_SPAWNING_POINT);6346 auto addressManager = DependencyManager::get<AddressManager>();
6347 addressManager->handleLookupString(DOMAIN_SPAWNING_POINT);
6348 QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT;
6349 qCDebug(interfaceapp) << "Setting new home bookmark to: " << newHomeAddress;
6350 DependencyManager::get<LocationBookmarks>()->setHomeLocationToAddress(newHomeAddress);
6260 methodDetails = "SuccessfulRequestToReplaceContent";6351 methodDetails = "SuccessfulRequestToReplaceContent";
6261 } else {6352 } else {
6262 methodDetails = "UserDeclinedToReplaceContent";6353 methodDetails = "UserDeclinedToReplaceContent";
@@ -6269,7 +6360,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { · 6 unmodified lines
6269 OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content",6360 OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content",
6270 QMessageBox::Ok, QMessageBox::Ok);6361 QMessageBox::Ok, QMessageBox::Ok);
6271 }6362 }
6272 QJsonObject messageProperties = { 6363 QJsonObject messageProperties = {
6273 { "status", methodDetails },6364 { "status", methodDetails },
6274 { "content_set_url", url }6365 { "content_set_url", url }
6275 };6366 };
@@ -6352,14 +6443,14 @@ void Application::showAssetServerWidget(QString filePath) { · 76 unmodified lines
6352 6443
6353void Application::addAssetToWorldFromURL(QString url) {6444void Application::addAssetToWorldFromURL(QString url) {
6354 qInfo(interfaceapp) << "Download model and add to world from" << url;6445 qInfo(interfaceapp) << "Download model and add to world from" << url;
6355 6446
6356 QString filename;6447 QString filename;
6357 if (url.contains("filename")) {6448 if (url.contains("filename")) {
6358 filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL.6449 filename = url.section("filename=", 1, 1); // Filename is in "?filename=" parameter at end of URL.
6359 }6450 }
6360 if (url.contains("vr.google.com/downloads")) {6451 if (url.contains("vr.google.com/downloads")) {
6361 filename = url.section('/', -1);6452 filename = url.section('/', -1);
6362 filename.remove(".zip?noDownload=false");6453 filename.remove(".zip");
6363 }6454 }
6364 6455
6365 if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets()) {6456 if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets()) {
@@ -6389,7 +6480,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { · 23 unmodified lines
6389 }6480 }
6390 if (url.contains("vr.google.com/downloads")) {6481 if (url.contains("vr.google.com/downloads")) {
6391 filename = url.section('/', -1);6482 filename = url.section('/', -1);
6392 filename.remove(".zip?noDownload=false");6483 filename.remove(".zip");
6393 isBlocks = true;6484 isBlocks = true;
6394 }6485 }
6395 6486
@@ -6406,6 +6497,7 @@ void Application::addAssetToWorldFromURLRequestFinished() { · 10 unmodified lines
6406 if (tempFile.open(QIODevice::WriteOnly)) {6497 if (tempFile.open(QIODevice::WriteOnly)) {
6407 tempFile.write(request->getData());6498 tempFile.write(request->getData());
6408 addAssetToWorldInfoClear(filename); // Remove message from list; next one added will have a different key.6499 addAssetToWorldInfoClear(filename); // Remove message from list; next one added will have a different key.
6500 tempFile.close();
6409 qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false, isBlocks);6501 qApp->getFileDownloadInterface()->runUnzip(downloadPath, url, true, false, isBlocks);
6410 } else {6502 } else {
6411 QString errorInfo = "Couldn't open temporary file for download";6503 QString errorInfo = "Couldn't open temporary file for download";
@@ -7223,14 +7315,6 @@ void Application::updateDisplayMode() { · 811 unmodified lines
7223 qFatal("Attempted to switch display plugins from a non-main thread");7315 qFatal("Attempted to switch display plugins from a non-main thread");
7224 }7316 }
7225 7317
7226 // Some plugins *cough* Oculus *cough* process message events from inside their
7227 // display function, and we don't want to change the display plugin underneath
7228 // the paintGL call, so we need to guard against that
7229 // The current oculus runtime doesn't do this anymore
7230 if (_inPaint) {
7231 qFatal("Attempted to switch display plugins while in painting");
7232 }
7233
7234 auto menu = Menu::getInstance();7318 auto menu = Menu::getInstance();
7235 auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();7319 auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
7236 7320
@@ -7307,12 +7391,12 @@ void Application::updateDisplayMode() { · 70 unmodified lines
7307 bool wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool();7391 bool wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool();
7308 offscreenUi->getDesktop()->setProperty("repositionLocked", true);7392 offscreenUi->getDesktop()->setProperty("repositionLocked", true);
7309 7393
7310 auto oldDisplayPlugin = _displayPlugin;
7311 if (_displayPlugin) {7394 if (_displayPlugin) {
7312 disconnect(_displayPluginPresentConnection);7395 disconnect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
7313 _displayPlugin->deactivate();7396 _displayPlugin->deactivate();
7314 }7397 }
7315 7398
7399 auto oldDisplayPlugin = _displayPlugin;
7316 bool active = newDisplayPlugin->activate();7400 bool active = newDisplayPlugin->activate();
7317 7401
7318 if (!active) {7402 if (!active) {
@@ -7350,7 +7434,7 @@ void Application::updateDisplayMode() { · 31 unmodified lines
7350 _offscreenContext->makeCurrent();7434 _offscreenContext->makeCurrent();
7351 getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);7435 getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
7352 _displayPlugin = newDisplayPlugin;7436 _displayPlugin = newDisplayPlugin;
7353 _displayPluginPresentConnection = connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);7437 connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
7354 offscreenUi->getDesktop()->setProperty("repositionLocked", wasRepositionLocked);7438 offscreenUi->getDesktop()->setProperty("repositionLocked", wasRepositionLocked);
7355 }7439 }
7356 7440
@@ -7602,3 +7686,5 @@ void Application::setAvatarOverrideUrl(const QUrl& url, bool save) { · 245 unmodified lines
7602 _avatarOverrideUrl = url;7686 _avatarOverrideUrl = url;
7603 _saveAvatarOverrideUrl = save;7687 _saveAvatarOverrideUrl = save;
7604}7688}
7689
7690#include "Application.moc"