// // Application.cpp // interface/src // // Created by Andrzej Kapolka on 5/10/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include #include #include #include #include #include #include #include // include this before QGLWidget, which includes an earlier version of OpenGL #include "InterfaceConfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Application.h" #include "InterfaceVersion.h" #include "Menu.h" #include "ModelUploader.h" #include "Util.h" #include "audio/AudioToolBox.h" #include "devices/DdeFaceTracker.h" #include "devices/Faceshift.h" #include "devices/Leapmotion.h" #include "devices/MIDIManager.h" #include "devices/OculusManager.h" #include "devices/TV3DManager.h" #include "devices/Visage.h" #include "renderer/ProgramObject.h" #include "gpu/Batch.h" #include "gpu/GLBackend.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" #include "scripting/ClipboardScriptingInterface.h" #include "scripting/JoystickScriptingInterface.h" #include "scripting/GlobalServicesScriptingInterface.h" #include "scripting/LocationScriptingInterface.h" #include "scripting/MenuScriptingInterface.h" #include "scripting/SettingsScriptingInterface.h" #include "scripting/WindowScriptingInterface.h" #include "scripting/WebWindowClass.h" #include "ui/DataWebDialog.h" #include "ui/InfoView.h" #include "ui/Snapshot.h" #include "ui/Stats.h" #include "ui/TextRenderer.h" using namespace std; // Starfield information static unsigned STARFIELD_NUM_STARS = 50000; static unsigned STARFIELD_SEED = 1; static const int BANDWIDTH_METER_CLICK_MAX_DRAG_LENGTH = 6; // farther dragged clicks are ignored const qint64 MAXIMUM_CACHE_SIZE = 10737418240; // 10GB static QTimer* idleTimer = NULL; const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml"; const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; const QString DEFAULT_SCRIPTS_JS_URL = "http://public.highfidelity.io/scripts/defaultScripts.js"; void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message); if (!logMessage.isEmpty()) { Application::getInstance()->getLogger()->addMessage(qPrintable(logMessage + "\n")); } } QString& Application::resourcesPath() { #ifdef Q_OS_MAC static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/"; #else static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/"; #endif return staticResourcePath; } Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : QApplication(argc, argv), _window(new MainWindow(desktop())), _glWidget(new GLCanvas()), _toolWindow(NULL), _nodeThread(new QThread(this)), _datagramProcessor(), _undoStack(), _undoStackScriptingInterface(&_undoStack), _frameCount(0), _fps(60.0f), _justStarted(true), _voxelImportDialog(NULL), _voxelImporter(), _importSucceded(false), _sharedVoxelSystem(TREE_SCALE, DEFAULT_MAX_VOXELS_PER_SYSTEM, &_clipboard), _entities(true), _entityCollisionSystem(), _entityClipboardRenderer(false), _entityClipboard(), _wantToKillLocalVoxels(false), _viewFrustum(), _lastQueriedViewFrustum(), _lastQueriedTime(usecTimestampNow()), _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), _viewTransform(), _scaleMirror(1.0f), _rotateMirror(0.0f), _raiseMirror(0.0f), _lastMouseMove(usecTimestampNow()), _lastMouseMoveWasSimulated(false), _touchAvgX(0.0f), _touchAvgY(0.0f), _isTouchPressed(false), _mousePressed(false), _enableProcessVoxelsThread(true), _octreeProcessor(), _voxelHideShowThread(&_voxels), _packetsPerSecond(0), _bytesPerSecond(0), _nodeBoundsDisplay(this), _previousScriptLocation(), _applicationOverlay(), _runningScriptsWidget(NULL), _runningScriptsWidgetWasVisible(false), _trayIcon(new QSystemTrayIcon(_window)), _lastNackTime(usecTimestampNow()), _lastSendDownstreamAudioStats(usecTimestampNow()), _isVSyncOn(true), _aboutToQuit(false) { // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); // set the associated application properties applicationInfo.beginGroup("INFO"); setApplicationName(applicationInfo.value("name").toString()); setApplicationVersion(BUILD_VERSION); setOrganizationName(applicationInfo.value("organizationName").toString()); setOrganizationDomain(applicationInfo.value("organizationDomain").toString()); _logger = new FileLogger(this); // After setting organization name in order to get correct directory QSettings::setDefaultFormat(QSettings::IniFormat); _myAvatar = _avatarManager.getMyAvatar(); _applicationStartupTime = startup_time; QFontDatabase::addApplicationFont(Application::resourcesPath() + "styles/Inconsolata.otf"); _window->setWindowTitle("Interface"); qInstallMessageHandler(messageHandler); qDebug() << "[VERSION] Build sequence: " << qPrintable(applicationVersion()); // call Menu getInstance static method to set up the menu _window->setMenuBar(Menu::getInstance()); _runningScriptsWidget = new RunningScriptsWidget(_window); unsigned int listenPort = 0; // bind to an ephemeral port by default const char** constArgv = const_cast(argv); const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); if (portStr) { listenPort = atoi(portStr); } // start the nodeThread so its event loop is running _nodeThread->start(); // make sure the node thread is given highest priority _nodeThread->setPriority(QThread::TimeCriticalPriority); // put the NodeList and datagram processing on the node thread NodeList* nodeList = NodeList::createInstance(NodeType::Agent, listenPort); nodeList->moveToThread(_nodeThread); _datagramProcessor.moveToThread(_nodeThread); // connect the DataProcessor processDatagrams slot to the QUDPSocket readyRead() signal connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), &_datagramProcessor, SLOT(processDatagrams())); // put the audio processing on a separate thread QThread* audioThread = new QThread(this); Audio* audioIO = DependencyManager::get