Showing the changes to interface/src/Application.cpp (1 of 76 files). Show all
Unified · Split
| @@ -49,7 +49,7 @@ · 48 unmodified lines | |||
| 49 | #include <QXmlStreamReader> | 49 | #include <QXmlStreamReader> |
| 50 | #include <QXmlStreamAttributes> | 50 | #include <QXmlStreamAttributes> |
| 51 | #include <QMediaPlayer> | 51 | #include <QMediaPlayer> |
| 52 | #include <QMimeData> | 52 | #include <QMimeData> |
| 53 | #include <QMessageBox> | 53 | #include <QMessageBox> |
| 54 | 54 | ||
| 55 | #include <AccountManager.h> | 55 | #include <AccountManager.h> |
| @@ -63,7 +63,7 @@ · 7 unmodified lines | |||
| 63 | #include <UUID.h> | 63 | #include <UUID.h> |
| 64 | #include <OctreeSceneStats.h> | 64 | #include <OctreeSceneStats.h> |
| 65 | #include <LocalVoxelsList.h> | 65 | #include <LocalVoxelsList.h> |
| 66 | #include <FstReader.h> | 66 | #include <ModelUploader.h> |
| 67 | 67 | ||
| 68 | #include "Application.h" | 68 | #include "Application.h" |
| 69 | #include "InterfaceVersion.h" | 69 | #include "InterfaceVersion.h" |
| @@ -81,6 +81,7 @@ · 11 unmodified lines | |||
| 81 | #include "ui/InfoView.h" | 81 | #include "ui/InfoView.h" |
| 82 | #include "ui/Snapshot.h" | 82 | #include "ui/Snapshot.h" |
| 83 | #include "ui/TextRenderer.h" | 83 | #include "ui/TextRenderer.h" |
| 84 | #include "ui/Stats.h" | ||
| 84 | 85 | ||
| 85 | using namespace std; | 86 | using namespace std; |
| 86 | 87 | ||
| @@ -110,15 +111,11 @@ const float MIRROR_FIELD_OF_VIEW = 30.0f; · 23 unmodified lines | |||
| 110 | const QString CHECK_VERSION_URL = "http://highfidelity.io/latestVersion.xml"; | 111 | const QString CHECK_VERSION_URL = "http://highfidelity.io/latestVersion.xml"; |
| 111 | const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; | 112 | const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; |
| 112 | 113 | ||
| 113 | const int STATS_PELS_PER_LINE = 20; | ||
| 114 | |||
| 115 | const QString CUSTOM_URL_SCHEME = "hifi:"; | ||
| 116 | |||
| 117 | void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { | 114 | void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { |
| 118 | if (message.size() > 0) { | 115 | if (message.size() > 0) { |
| 119 | QString dateString = QDateTime::currentDateTime().toTimeSpec(Qt::LocalTime).toString(Qt::ISODate); | 116 | QString dateString = QDateTime::currentDateTime().toTimeSpec(Qt::LocalTime).toString(Qt::ISODate); |
| 120 | QString formattedMessage = QString("[%1] %2\n").arg(dateString).arg(message); | 117 | QString formattedMessage = QString("[%1] %2\n").arg(dateString).arg(message); |
| 121 | 118 | ||
| 122 | fprintf(stdout, "%s", qPrintable(formattedMessage)); | 119 | fprintf(stdout, "%s", qPrintable(formattedMessage)); |
| 123 | Application::getInstance()->getLogger()->addMessage(qPrintable(formattedMessage)); | 120 | Application::getInstance()->getLogger()->addMessage(qPrintable(formattedMessage)); |
| 124 | } | 121 | } |
| @@ -137,7 +134,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 12 unmodified lines | |||
| 137 | QApplication(argc, argv), | 134 | QApplication(argc, argv), |
| 138 | _window(new QMainWindow(desktop())), | 135 | _window(new QMainWindow(desktop())), |
| 139 | _glWidget(new GLCanvas()), | 136 | _glWidget(new GLCanvas()), |
| 140 | _statsExpanded(false), | ||
| 141 | _nodeThread(new QThread(this)), | 137 | _nodeThread(new QThread(this)), |
| 142 | _datagramProcessor(), | 138 | _datagramProcessor(), |
| 143 | _frameCount(0), | 139 | _frameCount(0), |
| @@ -167,8 +163,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 23 unmodified lines | |||
| 167 | _voxelHideShowThread(&_voxels), | 163 | _voxelHideShowThread(&_voxels), |
| 168 | _packetsPerSecond(0), | 164 | _packetsPerSecond(0), |
| 169 | _bytesPerSecond(0), | 165 | _bytesPerSecond(0), |
| 170 | _recentMaxPackets(0), | 166 | _previousScriptLocation(), |
| 171 | _resetRecentMaxPacketsSoon(true), | ||
| 172 | _logger(new FileLogger(this)) | 167 | _logger(new FileLogger(this)) |
| 173 | { | 168 | { |
| 174 | // init GnuTLS for DTLS with domain-servers | 169 | // init GnuTLS for DTLS with domain-servers |
| @@ -176,23 +171,23 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 1 unmodified line | |||
| 176 | 171 | ||
| 177 | // read the ApplicationInfo.ini file for Name/Version/Domain information | 172 | // read the ApplicationInfo.ini file for Name/Version/Domain information |
| 178 | QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); | 173 | QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); |
| 179 | 174 | ||
| 180 | // set the associated application properties | 175 | // set the associated application properties |
| 181 | applicationInfo.beginGroup("INFO"); | 176 | applicationInfo.beginGroup("INFO"); |
| 182 | 177 | ||
| 183 | qDebug() << "[VERSION] Build sequence: " << qPrintable(applicationVersion()); | 178 | qDebug() << "[VERSION] Build sequence: " << qPrintable(applicationVersion()); |
| 184 | 179 | ||
| 185 | setApplicationName(applicationInfo.value("name").toString()); | 180 | setApplicationName(applicationInfo.value("name").toString()); |
| 186 | setApplicationVersion(BUILD_VERSION); | 181 | setApplicationVersion(BUILD_VERSION); |
| 187 | setOrganizationName(applicationInfo.value("organizationName").toString()); | 182 | setOrganizationName(applicationInfo.value("organizationName").toString()); |
| 188 | setOrganizationDomain(applicationInfo.value("organizationDomain").toString()); | 183 | setOrganizationDomain(applicationInfo.value("organizationDomain").toString()); |
| 189 | 184 | ||
| 190 | QSettings::setDefaultFormat(QSettings::IniFormat); | 185 | QSettings::setDefaultFormat(QSettings::IniFormat); |
| 191 | 186 | ||
| 192 | _myAvatar = _avatarManager.getMyAvatar(); | 187 | _myAvatar = _avatarManager.getMyAvatar(); |
| 193 | 188 | ||
| 194 | _applicationStartupTime = startup_time; | 189 | _applicationStartupTime = startup_time; |
| 195 | 190 | ||
| 196 | QFontDatabase::addApplicationFont(Application::resourcesPath() + "styles/Inconsolata.otf"); | 191 | QFontDatabase::addApplicationFont(Application::resourcesPath() + "styles/Inconsolata.otf"); |
| 197 | _window->setWindowTitle("Interface"); | 192 | _window->setWindowTitle("Interface"); |
| 198 | 193 | ||
| @@ -207,19 +202,19 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 8 unmodified lines | |||
| 207 | if (portStr) { | 202 | if (portStr) { |
| 208 | listenPort = atoi(portStr); | 203 | listenPort = atoi(portStr); |
| 209 | } | 204 | } |
| 210 | 205 | ||
| 211 | // start the nodeThread so its event loop is running | 206 | // start the nodeThread so its event loop is running |
| 212 | _nodeThread->start(); | 207 | _nodeThread->start(); |
| 213 | 208 | ||
| 214 | // make sure the node thread is given highest priority | 209 | // make sure the node thread is given highest priority |
| 215 | _nodeThread->setPriority(QThread::TimeCriticalPriority); | 210 | _nodeThread->setPriority(QThread::TimeCriticalPriority); |
| 216 | 211 | ||
| 217 | // put the NodeList and datagram processing on the node thread | 212 | // put the NodeList and datagram processing on the node thread |
| 218 | NodeList* nodeList = NodeList::createInstance(NodeType::Agent, listenPort); | 213 | NodeList* nodeList = NodeList::createInstance(NodeType::Agent, listenPort); |
| 219 | 214 | ||
| 220 | nodeList->moveToThread(_nodeThread); | 215 | nodeList->moveToThread(_nodeThread); |
| 221 | _datagramProcessor.moveToThread(_nodeThread); | 216 | _datagramProcessor.moveToThread(_nodeThread); |
| 222 | 217 | ||
| 223 | // connect the DataProcessor processDatagrams slot to the QUDPSocket readyRead() signal | 218 | // connect the DataProcessor processDatagrams slot to the QUDPSocket readyRead() signal |
| 224 | connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), &_datagramProcessor, SLOT(processDatagrams())); | 219 | connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), &_datagramProcessor, SLOT(processDatagrams())); |
| 225 | 220 | ||
| @@ -241,20 +236,20 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 15 unmodified lines | |||
| 241 | connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); | 236 | connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); |
| 242 | connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle); | 237 | connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle); |
| 243 | connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset); | 238 | connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset); |
| 244 | 239 | ||
| 245 | // connect to appropriate slots on AccountManager | 240 | // connect to appropriate slots on AccountManager |
| 246 | AccountManager& accountManager = AccountManager::getInstance(); | 241 | AccountManager& accountManager = AccountManager::getInstance(); |
| 247 | connect(&accountManager, &AccountManager::authRequired, Menu::getInstance(), &Menu::loginForCurrentDomain); | 242 | connect(&accountManager, &AccountManager::authRequired, Menu::getInstance(), &Menu::loginForCurrentDomain); |
| 248 | connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle); | 243 | connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle); |
| 249 | 244 | ||
| 250 | // set the account manager's root URL and trigger a login request if we don't have the access token | 245 | // set the account manager's root URL and trigger a login request if we don't have the access token |
| 251 | accountManager.setAuthURL(DEFAULT_NODE_AUTH_URL); | 246 | accountManager.setAuthURL(DEFAULT_NODE_AUTH_URL); |
| 252 | 247 | ||
| 253 | // once the event loop has started, check and signal for an access token | 248 | // once the event loop has started, check and signal for an access token |
| 254 | QMetaObject::invokeMethod(&accountManager, "checkAndSignalForAccessToken", Qt::QueuedConnection); | 249 | QMetaObject::invokeMethod(&accountManager, "checkAndSignalForAccessToken", Qt::QueuedConnection); |
| 255 | 250 | ||
| 256 | _settings = new QSettings(this); | 251 | _settings = new QSettings(this); |
| 257 | 252 | ||
| 258 | // Check to see if the user passed in a command line option for loading a local | 253 | // Check to see if the user passed in a command line option for loading a local |
| 259 | // Voxel File. | 254 | // Voxel File. |
| 260 | _voxelsFilename = getCmdOption(argc, constArgv, "-i"); | 255 | _voxelsFilename = getCmdOption(argc, constArgv, "-i"); |
| @@ -268,7 +263,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 7 unmodified lines | |||
| 268 | nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer | 263 | nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer |
| 269 | << NodeType::VoxelServer << NodeType::ParticleServer | 264 | << NodeType::VoxelServer << NodeType::ParticleServer |
| 270 | << NodeType::MetavoxelServer); | 265 | << NodeType::MetavoxelServer); |
| 271 | 266 | ||
| 272 | // connect to the packet sent signal of the _voxelEditSender and the _particleEditSender | 267 | // connect to the packet sent signal of the _voxelEditSender and the _particleEditSender |
| 273 | connect(&_voxelEditSender, &VoxelEditPacketSender::packetSent, this, &Application::packetSent); | 268 | connect(&_voxelEditSender, &VoxelEditPacketSender::packetSent, this, &Application::packetSent); |
| 274 | connect(&_particleEditSender, &ParticleEditPacketSender::packetSent, this, &Application::packetSent); | 269 | connect(&_particleEditSender, &ParticleEditPacketSender::packetSent, this, &Application::packetSent); |
| @@ -278,7 +273,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 3 unmodified lines | |||
| 278 | connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); | 273 | connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); |
| 279 | silentNodeTimer->moveToThread(_nodeThread); | 274 | silentNodeTimer->moveToThread(_nodeThread); |
| 280 | silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS); | 275 | silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS); |
| 281 | 276 | ||
| 282 | // send the identity packet for our avatar each second to our avatar mixer | 277 | // send the identity packet for our avatar each second to our avatar mixer |
| 283 | QTimer* identityPacketTimer = new QTimer(); | 278 | QTimer* identityPacketTimer = new QTimer(); |
| 284 | connect(identityPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendIdentityPacket); | 279 | connect(identityPacketTimer, &QTimer::timeout, _myAvatar, &MyAvatar::sendIdentityPacket); |
| @@ -326,14 +321,18 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 41 unmodified lines | |||
| 326 | 321 | ||
| 327 | // Set the sixense filtering | 322 | // Set the sixense filtering |
| 328 | _sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense)); | 323 | _sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense)); |
| 329 | 324 | ||
| 330 | checkVersion(); | 325 | checkVersion(); |
| 331 | 326 | ||
| 332 | _overlays.init(_glWidget); // do this before scripts load | 327 | _overlays.init(_glWidget); // do this before scripts load |
| 333 | 328 | ||
| 334 | LocalVoxelsList::getInstance()->addPersistantTree(DOMAIN_TREE_NAME, _voxels.getTree()); | 329 | LocalVoxelsList::getInstance()->addPersistantTree(DOMAIN_TREE_NAME, _voxels.getTree()); |
| 335 | LocalVoxelsList::getInstance()->addPersistantTree(CLIPBOARD_TREE_NAME, &_clipboard); | 330 | LocalVoxelsList::getInstance()->addPersistantTree(CLIPBOARD_TREE_NAME, &_clipboard); |
| 336 | 331 | ||
| 332 | _window->addDockWidget(Qt::NoDockWidgetArea, _runningScriptsWidget = new RunningScriptsWidget()); | ||
| 333 | _runningScriptsWidget->setRunningScripts(getRunningScripts()); | ||
| 334 | connect(_runningScriptsWidget, &RunningScriptsWidget::stopScriptName, this, &Application::stopScript); | ||
| 335 | |||
| 337 | // check first run... | 336 | // check first run... |
| 338 | QVariant firstRunValue = _settings->value("firstRun",QVariant(true)); | 337 | QVariant firstRunValue = _settings->value("firstRun",QVariant(true)); |
| 339 | if (firstRunValue.isValid() && firstRunValue.toBool()) { | 338 | if (firstRunValue.isValid() && firstRunValue.toBool()) { |
| @@ -341,7 +340,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 1 unmodified line | |||
| 341 | // clear the scripts, and set out script to our default scripts | 340 | // clear the scripts, and set out script to our default scripts |
| 342 | clearScriptsBeforeRunning(); | 341 | clearScriptsBeforeRunning(); |
| 343 | loadScript("http://public.highfidelity.io/scripts/defaultScripts.js"); | 342 | loadScript("http://public.highfidelity.io/scripts/defaultScripts.js"); |
| 344 | 343 | ||
| 345 | _settings->setValue("firstRun",QVariant(false)); | 344 | _settings->setValue("firstRun",QVariant(false)); |
| 346 | } else { | 345 | } else { |
| 347 | // do this as late as possible so that all required subsystems are inialized | 346 | // do this as late as possible so that all required subsystems are inialized |
| @@ -352,31 +351,34 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : · 4 unmodified lines | |||
| 352 | Application::~Application() { | 351 | Application::~Application() { |
| 353 | 352 | ||
| 354 | qInstallMessageHandler(NULL); | 353 | qInstallMessageHandler(NULL); |
| 355 | 354 | ||
| 356 | // make sure we don't call the idle timer any more | 355 | // make sure we don't call the idle timer any more |
| 357 | delete idleTimer; | 356 | delete idleTimer; |
| 358 | 357 | ||
| 359 | Menu::getInstance()->saveSettings(); | 358 | Menu::getInstance()->saveSettings(); |
| 360 | _rearMirrorTools->saveSettings(_settings); | 359 | _rearMirrorTools->saveSettings(_settings); |
| 361 | 360 | ||
| 362 | _sharedVoxelSystem.changeTree(new VoxelTree); | 361 | _sharedVoxelSystem.changeTree(new VoxelTree); |
| 363 | if (_voxelImporter) { | 362 | if (_voxelImporter) { |
| 364 | _voxelImporter->saveSettings(_settings); | 363 | _voxelImporter->saveSettings(_settings); |
| 365 | delete _voxelImporter; | 364 | delete _voxelImporter; |
| 366 | } | 365 | } |
| 367 | _settings->sync(); | 366 | _settings->sync(); |
| 368 | 367 | ||
| 369 | // let the avatar mixer know we're out | 368 | // let the avatar mixer know we're out |
| 370 | MyAvatar::sendKillAvatar(); | 369 | MyAvatar::sendKillAvatar(); |
| 371 | 370 | ||
| 372 | // ask the datagram processing thread to quit and wait until it is done | 371 | // ask the datagram processing thread to quit and wait until it is done |
| 373 | _nodeThread->quit(); | 372 | _nodeThread->quit(); |
| 374 | _nodeThread->wait(); | 373 | _nodeThread->wait(); |
| 375 | 374 | ||
| 375 | // stop the audio process | ||
| 376 | QMetaObject::invokeMethod(&_audio, "stop"); | ||
| 377 | |||
| 376 | // ask the audio thread to quit and wait until it is done | 378 | // ask the audio thread to quit and wait until it is done |
| 377 | _audio.thread()->quit(); | 379 | _audio.thread()->quit(); |
| 378 | _audio.thread()->wait(); | 380 | _audio.thread()->wait(); |
| 379 | 381 | ||
| 380 | _voxelProcessor.terminate(); | 382 | _voxelProcessor.terminate(); |
| 381 | _voxelHideShowThread.terminate(); | 383 | _voxelHideShowThread.terminate(); |
| 382 | _voxelEditSender.terminate(); | 384 | _voxelEditSender.terminate(); |
| @@ -389,9 +391,9 @@ Application::~Application() { · 6 unmodified lines | |||
| 389 | Menu::getInstance()->deleteLater(); | 391 | Menu::getInstance()->deleteLater(); |
| 390 | 392 | ||
| 391 | _myAvatar = NULL; | 393 | _myAvatar = NULL; |
| 392 | 394 | ||
| 393 | delete _glWidget; | 395 | delete _glWidget; |
| 394 | 396 | ||
| 395 | AccountManager::getInstance().destroy(); | 397 | AccountManager::getInstance().destroy(); |
| 396 | 398 | ||
| 397 | gnutls_global_deinit(); | 399 | gnutls_global_deinit(); |
| @@ -513,7 +515,7 @@ void Application::paintGL() { · 115 unmodified lines | |||
| 513 | _myCamera.setDistance(0.0f); | 515 | _myCamera.setDistance(0.0f); |
| 514 | _myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing | 516 | _myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing |
| 515 | _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition()); | 517 | _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition()); |
| 516 | _myCamera.setTargetRotation(_myAvatar->getHead()->getOrientation()); | 518 | _myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation()); |
| 517 | 519 | ||
| 518 | } else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { | 520 | } else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { |
| 519 | _myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay | 521 | _myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay |
| @@ -585,7 +587,7 @@ void Application::paintGL() { · 65 unmodified lines | |||
| 585 | 587 | ||
| 586 | if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { | 588 | if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { |
| 587 | renderRearViewMirror(_mirrorViewRect); | 589 | renderRearViewMirror(_mirrorViewRect); |
| 588 | 590 | ||
| 589 | } else if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { | 591 | } else if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { |
| 590 | _rearMirrorTools->render(true); | 592 | _rearMirrorTools->render(true); |
| 591 | } | 593 | } |
| @@ -615,6 +617,14 @@ void Application::resizeGL(int width, int height) { · 23 unmodified lines | |||
| 615 | 617 | ||
| 616 | updateProjectionMatrix(); | 618 | updateProjectionMatrix(); |
| 617 | glLoadIdentity(); | 619 | glLoadIdentity(); |
| 620 | |||
| 621 | // update Stats width | ||
| 622 | int horizontalOffset = 0; | ||
| 623 | if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { | ||
| 624 | // mirror is enabled, let's set horizontal offset to give stats some margin | ||
| 625 | horizontalOffset += MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; | ||
| 626 | } | ||
| 627 | Stats::getInstance()->resetWidth(width, horizontalOffset); | ||
| 618 | } | 628 | } |
| 619 | 629 | ||
| 620 | void Application::updateProjectionMatrix() { | 630 | void Application::updateProjectionMatrix() { |
| @@ -658,10 +668,10 @@ void Application::controlledBroadcastToNodes(const QByteArray& packet, const Nod · 37 unmodified lines | |||
| 658 | if (type == NodeType::VoxelServer && !Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { | 668 | if (type == NodeType::VoxelServer && !Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { |
| 659 | continue; | 669 | continue; |
| 660 | } | 670 | } |
| 661 | 671 | ||
| 662 | // Perform the broadcast for one type | 672 | // Perform the broadcast for one type |
| 663 | int nReceivingNodes = NodeList::getInstance()->broadcastToNodes(packet, NodeSet() << type); | 673 | int nReceivingNodes = NodeList::getInstance()->broadcastToNodes(packet, NodeSet() << type); |
| 664 | 674 | ||
| 665 | // Feed number of bytes to corresponding channel of the bandwidth meter, if any (done otherwise) | 675 | // Feed number of bytes to corresponding channel of the bandwidth meter, if any (done otherwise) |
| 666 | BandwidthMeter::ChannelIndex channel; | 676 | BandwidthMeter::ChannelIndex channel; |
| 667 | switch (type) { | 677 | switch (type) { |
| @@ -680,32 +690,15 @@ void Application::controlledBroadcastToNodes(const QByteArray& packet, const Nod · 12 unmodified lines | |||
| 680 | } | 690 | } |
| 681 | 691 | ||
| 682 | bool Application::event(QEvent* event) { | 692 | bool Application::event(QEvent* event) { |
| 683 | 693 | ||
| 684 | // handle custom URL | 694 | // handle custom URL |
| 685 | if (event->type() == QEvent::FileOpen) { | 695 | if (event->type() == QEvent::FileOpen) { |
| 686 | QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event); | 696 | QFileOpenEvent* fileEvent = static_cast<QFileOpenEvent*>(event); |
| 687 | if (!fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(CUSTOM_URL_SCHEME)) { | 697 | bool isHifiSchemeURL = !fileEvent->url().isEmpty() && fileEvent->url().toLocalFile().startsWith(CUSTOM_URL_SCHEME); |
| 688 | QString destination = fileEvent->url().toLocalFile().remove(CUSTOM_URL_SCHEME); | 698 | if (isHifiSchemeURL) { |
| 689 | QStringList urlParts = destination.split('/', QString::SkipEmptyParts); | 699 | Menu::getInstance()->goTo(fileEvent->url().toString()); |
| 690 | |||
| 691 | if (urlParts.count() > 1) { | ||
| 692 | // if url has 2 or more parts, the first one is domain name | ||
| 693 | Menu::getInstance()->goToDomain(urlParts[0]); | ||
| 694 | |||
| 695 | // location coordinates | ||
| 696 | Menu::getInstance()->goToDestination(urlParts[1]); | ||
| 697 | if (urlParts.count() > 2) { | ||
| 698 | |||
| 699 | // location orientation | ||
| 700 | Menu::getInstance()->goToOrientation(urlParts[2]); | ||
| 701 | } | ||
| 702 | } else if (urlParts.count() == 1) { | ||
| 703 | |||
| 704 | // location coordinates | ||
| 705 | Menu::getInstance()->goToDestination(urlParts[0]); | ||
| 706 | } | ||
| 707 | } | 700 | } |
| 708 | 701 | ||
| 709 | return false; | 702 | return false; |
| 710 | } | 703 | } |
| 711 | return QApplication::event(event); | 704 | return QApplication::event(event); |
| @@ -716,7 +709,7 @@ void Application::keyPressEvent(QKeyEvent* event) { · 4 unmodified lines | |||
| 716 | _keysPressed.insert(event->key()); | 709 | _keysPressed.insert(event->key()); |
| 717 | 710 | ||
| 718 | _controllerScriptingInterface.emitKeyPressEvent(event); // send events to any registered scripts | 711 | _controllerScriptingInterface.emitKeyPressEvent(event); // send events to any registered scripts |
| 719 | 712 | ||
| 720 | // if one of our scripts have asked to capture this event, then stop processing it | 713 | // if one of our scripts have asked to capture this event, then stop processing it |
| 721 | if (_controllerScriptingInterface.isKeyCaptured(event)) { | 714 | if (_controllerScriptingInterface.isKeyCaptured(event)) { |
| 722 | return; | 715 | return; |
| @@ -1074,8 +1067,12 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { · 351 unmodified lines | |||
| 1074 | _mousePressed = false; | 1067 | _mousePressed = false; |
| 1075 | checkBandwidthMeterClick(); | 1068 | checkBandwidthMeterClick(); |
| 1076 | if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { | 1069 | if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { |
| 1077 | checkStatsClick(); | 1070 | int horizontalOffset = 0; |
| 1078 | } | 1071 | if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { |
| 1072 | horizontalOffset = MIRROR_VIEW_WIDTH; | ||
| 1073 | } | ||
| 1074 | Stats::getInstance()->checkClick(_mouseX, _mouseY, _mouseDragStartedX, _mouseDragStartedY, horizontalOffset); | ||
| 1075 | } | ||
| 1079 | } | 1076 | } |
| 1080 | } | 1077 | } |
| 1081 | } | 1078 | } |
| @@ -1124,7 +1121,7 @@ void Application::touchBeginEvent(QTouchEvent* event) { · 42 unmodified lines | |||
| 1124 | if (_controllerScriptingInterface.isTouchCaptured()) { | 1121 | if (_controllerScriptingInterface.isTouchCaptured()) { |
| 1125 | return; | 1122 | return; |
| 1126 | } | 1123 | } |
| 1127 | 1124 | ||
| 1128 | // put any application specific touch behavior below here.. | 1125 | // put any application specific touch behavior below here.. |
| 1129 | _lastTouchAvgX = _touchAvgX; | 1126 | _lastTouchAvgX = _touchAvgX; |
| 1130 | _lastTouchAvgY = _touchAvgY; | 1127 | _lastTouchAvgY = _touchAvgY; |
| @@ -1167,13 +1164,13 @@ void Application::dropEvent(QDropEvent *event) { · 36 unmodified lines | |||
| 1167 | break; | 1164 | break; |
| 1168 | } | 1165 | } |
| 1169 | } | 1166 | } |
| 1170 | 1167 | ||
| 1171 | SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath); | 1168 | SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath); |
| 1172 | if (snapshotData) { | 1169 | if (snapshotData) { |
| 1173 | if (!snapshotData->getDomain().isEmpty()) { | 1170 | if (!snapshotData->getDomain().isEmpty()) { |
| 1174 | Menu::getInstance()->goToDomain(snapshotData->getDomain()); | 1171 | Menu::getInstance()->goToDomain(snapshotData->getDomain()); |
| 1175 | } | 1172 | } |
| 1176 | 1173 | ||
| 1177 | _myAvatar->setPosition(snapshotData->getLocation()); | 1174 | _myAvatar->setPosition(snapshotData->getLocation()); |
| 1178 | _myAvatar->setOrientation(snapshotData->getOrientation()); | 1175 | _myAvatar->setOrientation(snapshotData->getOrientation()); |
| 1179 | } else { | 1176 | } else { |
| @@ -1201,19 +1198,19 @@ void Application::timer() { · 21 unmodified lines | |||
| 1201 | } | 1198 | } |
| 1202 | 1199 | ||
| 1203 | _fps = (float)_frameCount / ((float)diffclock(&_timerStart, &_timerEnd) / 1000.f); | 1200 | _fps = (float)_frameCount / ((float)diffclock(&_timerStart, &_timerEnd) / 1000.f); |
| 1204 | 1201 | ||
| 1205 | _packetsPerSecond = (float) _datagramProcessor.getPacketCount() / ((float)diffclock(&_timerStart, &_timerEnd) / 1000.f); | 1202 | _packetsPerSecond = (float) _datagramProcessor.getPacketCount() / ((float)diffclock(&_timerStart, &_timerEnd) / 1000.f); |
| 1206 | _bytesPerSecond = (float) _datagramProcessor.getByteCount() / ((float)diffclock(&_timerStart, &_timerEnd) / 1000.f); | 1203 | _bytesPerSecond = (float) _datagramProcessor.getByteCount() / ((float)diffclock(&_timerStart, &_timerEnd) / 1000.f); |
| 1207 | _frameCount = 0; | 1204 | _frameCount = 0; |
| 1208 | 1205 | ||
| 1209 | _datagramProcessor.resetCounters(); | 1206 | _datagramProcessor.resetCounters(); |
| 1210 | 1207 | ||
| 1211 | gettimeofday(&_timerStart, NULL); | 1208 | gettimeofday(&_timerStart, NULL); |
| 1212 | 1209 | ||
| 1213 | // ask the node list to check in with the domain server | 1210 | // ask the node list to check in with the domain server |
| 1214 | NodeList::getInstance()->sendDomainServerCheckIn(); | 1211 | NodeList::getInstance()->sendDomainServerCheckIn(); |
| 1215 | 1212 | ||
| 1216 | 1213 | ||
| 1217 | } | 1214 | } |
| 1218 | 1215 | ||
| 1219 | void Application::idle() { | 1216 | void Application::idle() { |
| @@ -1250,11 +1247,11 @@ void Application::idle() { · 30 unmodified lines | |||
| 1250 | _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); | 1247 | _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); |
| 1251 | _idleLoopStdev.reset(); | 1248 | _idleLoopStdev.reset(); |
| 1252 | } | 1249 | } |
| 1253 | 1250 | ||
| 1254 | if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) { | 1251 | if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) { |
| 1255 | _buckyBalls.simulate(timeSinceLastUpdate / 1000.f, Application::getInstance()->getAvatar()->getHandData()); | 1252 | _buckyBalls.simulate(timeSinceLastUpdate / 1000.f, Application::getInstance()->getAvatar()->getHandData()); |
| 1256 | } | 1253 | } |
| 1257 | 1254 | ||
| 1258 | // After finishing all of the above work, restart the idle timer, allowing 2ms to process events. | 1255 | // After finishing all of the above work, restart the idle timer, allowing 2ms to process events. |
| 1259 | idleTimer->start(2); | 1256 | idleTimer->start(2); |
| 1260 | } | 1257 | } |
| @@ -1386,7 +1383,7 @@ void Application::exportVoxels(const VoxelDetail& sourceVoxel) { · 125 unmodified lines | |||
| 1386 | tr("Sparse Voxel Octree Files (*.svo)")); | 1383 | tr("Sparse Voxel Octree Files (*.svo)")); |
| 1387 | QByteArray fileNameAscii = fileNameString.toLocal8Bit(); | 1384 | QByteArray fileNameAscii = fileNameString.toLocal8Bit(); |
| 1388 | const char* fileName = fileNameAscii.data(); | 1385 | const char* fileName = fileNameAscii.data(); |
| 1389 | 1386 | ||
| 1390 | VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); | 1387 | VoxelTreeElement* selectedNode = _voxels.getTree()->getVoxelAt(sourceVoxel.x, sourceVoxel.y, sourceVoxel.z, sourceVoxel.s); |
| 1391 | if (selectedNode) { | 1388 | if (selectedNode) { |
| 1392 | VoxelTree exportTree; | 1389 | VoxelTree exportTree; |
| @@ -1400,12 +1397,12 @@ void Application::exportVoxels(const VoxelDetail& sourceVoxel) { · 7 unmodified lines | |||
| 1400 | 1397 | ||
| 1401 | void Application::importVoxels() { | 1398 | void Application::importVoxels() { |
| 1402 | _importSucceded = false; | 1399 | _importSucceded = false; |
| 1403 | 1400 | ||
| 1404 | if (!_voxelImporter) { | 1401 | if (!_voxelImporter) { |
| 1405 | _voxelImporter = new VoxelImporter(_window); | 1402 | _voxelImporter = new VoxelImporter(_window); |
| 1406 | _voxelImporter->loadSettings(_settings); | 1403 | _voxelImporter->loadSettings(_settings); |
| 1407 | } | 1404 | } |
| 1408 | 1405 | ||
| 1409 | if (!_voxelImporter->exec()) { | 1406 | if (!_voxelImporter->exec()) { |
| 1410 | qDebug() << "[DEBUG] Import succeeded." << endl; | 1407 | qDebug() << "[DEBUG] Import succeeded." << endl; |
| 1411 | _importSucceded = true; | 1408 | _importSucceded = true; |
| @@ -1419,7 +1416,7 @@ void Application::importVoxels() { · 7 unmodified lines | |||
| 1419 | 1416 | ||
| 1420 | // restore the main window's active state | 1417 | // restore the main window's active state |
| 1421 | _window->activateWindow(); | 1418 | _window->activateWindow(); |
| 1422 | 1419 | ||
| 1423 | emit importDone(); | 1420 | emit importDone(); |
| 1424 | } | 1421 | } |
| 1425 | 1422 | ||
| @@ -1475,7 +1472,7 @@ void Application::pasteVoxels(const VoxelDetail& sourceVoxel) { · 49 unmodified lines | |||
| 1475 | } | 1472 | } |
| 1476 | 1473 | ||
| 1477 | pasteVoxelsToOctalCode(octalCodeDestination); | 1474 | pasteVoxelsToOctalCode(octalCodeDestination); |
| 1478 | 1475 | ||
| 1479 | if (calculatedOctCode) { | 1476 | if (calculatedOctCode) { |
| 1480 | delete[] calculatedOctCode; | 1477 | delete[] calculatedOctCode; |
| 1481 | } | 1478 | } |
| @@ -1512,9 +1509,9 @@ void Application::init() { · 30 unmodified lines | |||
| 1512 | 1509 | ||
| 1513 | // Cleanup of the original shared tree | 1510 | // Cleanup of the original shared tree |
| 1514 | _sharedVoxelSystem.init(); | 1511 | _sharedVoxelSystem.init(); |
| 1515 | 1512 | ||
| 1516 | _voxelImporter = new VoxelImporter(_window); | 1513 | _voxelImporter = new VoxelImporter(_window); |
| 1517 | 1514 | ||
| 1518 | _environment.init(); | 1515 | _environment.init(); |
| 1519 | 1516 | ||
| 1520 | _glowEffect.init(); | 1517 | _glowEffect.init(); |
| @@ -1556,11 +1553,11 @@ void Application::init() { · 35 unmodified lines | |||
| 1556 | _audio.setJitterBufferSamples(Menu::getInstance()->getAudioJitterBufferSamples()); | 1553 | _audio.setJitterBufferSamples(Menu::getInstance()->getAudioJitterBufferSamples()); |
| 1557 | } | 1554 | } |
| 1558 | qDebug("Loaded settings"); | 1555 | qDebug("Loaded settings"); |
| 1559 | 1556 | ||
| 1560 | // initialize Visage and Faceshift after loading the menu settings | 1557 | // initialize Visage and Faceshift after loading the menu settings |
| 1561 | _faceshift.init(); | 1558 | _faceshift.init(); |
| 1562 | _visage.init(); | 1559 | _visage.init(); |
| 1563 | 1560 | ||
| 1564 | // fire off an immediate domain-server check in now that settings are loaded | 1561 | // fire off an immediate domain-server check in now that settings are loaded |
| 1565 | NodeList::getInstance()->sendDomainServerCheckIn(); | 1562 | NodeList::getInstance()->sendDomainServerCheckIn(); |
| 1566 | 1563 | ||
| @@ -1579,20 +1576,20 @@ void Application::init() { · 12 unmodified lines | |||
| 1579 | _particleCollisionSystem.init(&_particleEditSender, _particles.getTree(), _voxels.getTree(), &_audio, &_avatarManager); | 1576 | _particleCollisionSystem.init(&_particleEditSender, _particles.getTree(), _voxels.getTree(), &_audio, &_avatarManager); |
| 1580 | 1577 | ||
| 1581 | // connect the _particleCollisionSystem to our script engine's ParticleScriptingInterface | 1578 | // connect the _particleCollisionSystem to our script engine's ParticleScriptingInterface |
| 1582 | connect(&_particleCollisionSystem, | 1579 | connect(&_particleCollisionSystem, |
| 1583 | SIGNAL(particleCollisionWithVoxel(const ParticleID&, const VoxelDetail&, const glm::vec3&)), | 1580 | SIGNAL(particleCollisionWithVoxel(const ParticleID&, const VoxelDetail&, const glm::vec3&)), |
| 1584 | ScriptEngine::getParticlesScriptingInterface(), | 1581 | ScriptEngine::getParticlesScriptingInterface(), |
| 1585 | SLOT(forwardParticleCollisionWithVoxel(const ParticleID&, const VoxelDetail&, const glm::vec3&))); | 1582 | SLOT(forwardParticleCollisionWithVoxel(const ParticleID&, const VoxelDetail&, const glm::vec3&))); |
| 1586 | 1583 | ||
| 1587 | connect(&_particleCollisionSystem, | 1584 | connect(&_particleCollisionSystem, |
| 1588 | SIGNAL(particleCollisionWithParticle(const ParticleID&, const ParticleID&, const glm::vec3&)), | 1585 | SIGNAL(particleCollisionWithParticle(const ParticleID&, const ParticleID&, const glm::vec3&)), |
| 1589 | ScriptEngine::getParticlesScriptingInterface(), | 1586 | ScriptEngine::getParticlesScriptingInterface(), |
| 1590 | SLOT(forwardParticleCollisionWithParticle(const ParticleID&, const ParticleID&, const glm::vec3&))); | 1587 | SLOT(forwardParticleCollisionWithParticle(const ParticleID&, const ParticleID&, const glm::vec3&))); |
| 1591 | 1588 | ||
| 1592 | _audio.init(_glWidget); | 1589 | _audio.init(_glWidget); |
| 1593 | 1590 | ||
| 1594 | _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect, _settings); | 1591 | _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect, _settings); |
| 1595 | 1592 | ||
| 1596 | connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); | 1593 | connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); |
| 1597 | connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); | 1594 | connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); |
| 1598 | connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); | 1595 | connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); |
| @@ -1715,7 +1712,7 @@ void Application::updateMyAvatarLookAtPosition() { · 116 unmodified lines | |||
| 1715 | float distance = TREE_SCALE; | 1712 | float distance = TREE_SCALE; |
| 1716 | if (_myAvatar->getLookAtTargetAvatar() && _myAvatar != _myAvatar->getLookAtTargetAvatar()) { | 1713 | if (_myAvatar->getLookAtTargetAvatar() && _myAvatar != _myAvatar->getLookAtTargetAvatar()) { |
| 1717 | distance = glm::distance(_mouseRayOrigin, | 1714 | distance = glm::distance(_mouseRayOrigin, |
| 1718 | static_cast<Avatar*>(_myAvatar->getLookAtTargetAvatar())->getHead()->calculateAverageEyePosition()); | 1715 | static_cast<Avatar*>(_myAvatar->getLookAtTargetAvatar())->getHead()->calculateAverageEyePosition()); |
| 1719 | } | 1716 | } |
| 1720 | const float FIXED_MIN_EYE_DISTANCE = 0.3f; | 1717 | const float FIXED_MIN_EYE_DISTANCE = 0.3f; |
| 1721 | float minEyeDistance = FIXED_MIN_EYE_DISTANCE + (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON ? 0.0f : | 1718 | float minEyeDistance = FIXED_MIN_EYE_DISTANCE + (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON ? 0.0f : |
| @@ -1728,7 +1725,7 @@ void Application::updateMyAvatarLookAtPosition() { · 6 unmodified lines | |||
| 1728 | eyePitch = _faceshift.getEstimatedEyePitch(); | 1725 | eyePitch = _faceshift.getEstimatedEyePitch(); |
| 1729 | eyeYaw = _faceshift.getEstimatedEyeYaw(); | 1726 | eyeYaw = _faceshift.getEstimatedEyeYaw(); |
| 1730 | trackerActive = true; | 1727 | trackerActive = true; |
| 1731 | 1728 | ||
| 1732 | } else if (_visage.isActive()) { | 1729 | } else if (_visage.isActive()) { |
| 1733 | eyePitch = _visage.getEstimatedEyePitch(); | 1730 | eyePitch = _visage.getEstimatedEyePitch(); |
| 1734 | eyeYaw = _visage.getEstimatedEyeYaw(); | 1731 | eyeYaw = _visage.getEstimatedEyeYaw(); |
| @@ -1849,15 +1846,6 @@ void Application::updateDialogs(float deltaTime) { · 114 unmodified lines | |||
| 1849 | } | 1846 | } |
| 1850 | } | 1847 | } |
| 1851 | 1848 | ||
| 1852 | void Application::updateAudio(float deltaTime) { | ||
| 1853 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); | ||
| 1854 | PerformanceWarning warn(showWarnings, "Application::updateAudio()"); | ||
| 1855 | |||
| 1856 | // Update audio stats for procedural sounds | ||
| 1857 | _audio.setLastAcceleration(_myAvatar->getThrust()); | ||
| 1858 | _audio.setLastVelocity(_myAvatar->getVelocity()); | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | void Application::updateCursor(float deltaTime) { | 1849 | void Application::updateCursor(float deltaTime) { |
| 1862 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); | 1850 | bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); |
| 1863 | PerformanceWarning warn(showWarnings, "Application::updateCursor()"); | 1851 | PerformanceWarning warn(showWarnings, "Application::updateCursor()"); |
| @@ -1906,14 +1894,13 @@ void Application::update(float deltaTime) { · 42 unmodified lines | |||
| 1906 | updateMetavoxels(deltaTime); // update metavoxels | 1894 | updateMetavoxels(deltaTime); // update metavoxels |
| 1907 | updateCamera(deltaTime); // handle various camera tweaks like off axis projection | 1895 | updateCamera(deltaTime); // handle various camera tweaks like off axis projection |
| 1908 | updateDialogs(deltaTime); // update various stats dialogs if present | 1896 | updateDialogs(deltaTime); // update various stats dialogs if present |
| 1909 | updateAudio(deltaTime); // Update audio stats for procedural sounds | ||
| 1910 | updateCursor(deltaTime); // Handle cursor updates | 1897 | updateCursor(deltaTime); // Handle cursor updates |
| 1911 | 1898 | ||
| 1912 | _particles.update(); // update the particles... | 1899 | _particles.update(); // update the particles... |
| 1913 | _particleCollisionSystem.update(); // collide the particles... | 1900 | _particleCollisionSystem.update(); // collide the particles... |
| 1914 | 1901 | ||
| 1915 | _overlays.update(deltaTime); | 1902 | _overlays.update(deltaTime); |
| 1916 | 1903 | ||
| 1917 | // let external parties know we're updating | 1904 | // let external parties know we're updating |
| 1918 | emit simulating(deltaTime); | 1905 | emit simulating(deltaTime); |
| 1919 | } | 1906 | } |
| @@ -1937,7 +1924,7 @@ void Application::updateMyAvatar(float deltaTime) { · 17 unmodified lines | |||
| 1937 | // actually need to calculate the view frustum planes to send these details | 1924 | // actually need to calculate the view frustum planes to send these details |
| 1938 | // to the server. | 1925 | // to the server. |
| 1939 | loadViewFrustum(_myCamera, _viewFrustum); | 1926 | loadViewFrustum(_myCamera, _viewFrustum); |
| 1940 | 1927 | ||
| 1941 | // Update my voxel servers with my current voxel query... | 1928 | // Update my voxel servers with my current voxel query... |
| 1942 | quint64 now = usecTimestampNow(); | 1929 | quint64 now = usecTimestampNow(); |
| 1943 | quint64 sinceLastQuery = now - _lastQueriedTime; | 1930 | quint64 sinceLastQuery = now - _lastQueriedTime; |
| @@ -2213,7 +2200,7 @@ void Application::updateShadowMap() { · 269 unmodified lines | |||
| 2213 | } | 2200 | } |
| 2214 | center = inverseRotation * center; | 2201 | center = inverseRotation * center; |
| 2215 | glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius); | 2202 | glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius); |
| 2216 | glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius); | 2203 | glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius); |
| 2217 | 2204 | ||
| 2218 | // stretch out our extents in z so that we get all of the avatars | 2205 | // stretch out our extents in z so that we get all of the avatars |
| 2219 | minima.z -= _viewFrustum.getFarClip() * 0.5f; | 2206 | minima.z -= _viewFrustum.getFarClip() * 0.5f; |
| @@ -2234,7 +2221,7 @@ void Application::updateShadowMap() { · 14 unmodified lines | |||
| 2234 | _shadowViewFrustum.setEyeOffsetPosition(glm::vec3()); | 2221 | _shadowViewFrustum.setEyeOffsetPosition(glm::vec3()); |
| 2235 | _shadowViewFrustum.setEyeOffsetOrientation(glm::quat()); | 2222 | _shadowViewFrustum.setEyeOffsetOrientation(glm::quat()); |
| 2236 | _shadowViewFrustum.calculate(); | 2223 | _shadowViewFrustum.calculate(); |
| 2237 | 2224 | ||
| 2238 | glMatrixMode(GL_PROJECTION); | 2225 | glMatrixMode(GL_PROJECTION); |
| 2239 | glPushMatrix(); | 2226 | glPushMatrix(); |
| 2240 | glLoadIdentity(); | 2227 | glLoadIdentity(); |
| @@ -2289,19 +2276,19 @@ void Application::setupWorldLight() { · 48 unmodified lines | |||
| 2289 | 2276 | ||
| 2290 | QImage Application::renderAvatarBillboard() { | 2277 | QImage Application::renderAvatarBillboard() { |
| 2291 | _textureCache.getPrimaryFramebufferObject()->bind(); | 2278 | _textureCache.getPrimaryFramebufferObject()->bind(); |
| 2292 | 2279 | ||
| 2293 | glDisable(GL_BLEND); | 2280 | glDisable(GL_BLEND); |
| 2294 | 2281 | ||
| 2295 | const int BILLBOARD_SIZE = 64; | 2282 | const int BILLBOARD_SIZE = 64; |
| 2296 | renderRearViewMirror(QRect(0, _glWidget->height() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); | 2283 | renderRearViewMirror(QRect(0, _glWidget->height() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); |
| 2297 | 2284 | ||
| 2298 | QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); | 2285 | QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); |
| 2299 | glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); | 2286 | glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); |
| 2300 | 2287 | ||
| 2301 | glEnable(GL_BLEND); | 2288 | glEnable(GL_BLEND); |
| 2302 | 2289 | ||
| 2303 | _textureCache.getPrimaryFramebufferObject()->release(); | 2290 | _textureCache.getPrimaryFramebufferObject()->release(); |
| 2304 | 2291 | ||
| 2305 | return image; | 2292 | return image; |
| 2306 | } | 2293 | } |
| 2307 | 2294 | ||
| @@ -2402,7 +2389,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 94 unmodified lines | |||
| 2402 | "Application::displaySide() ... metavoxels..."); | 2389 | "Application::displaySide() ... metavoxels..."); |
| 2403 | _metavoxels.render(); | 2390 | _metavoxels.render(); |
| 2404 | } | 2391 | } |
| 2405 | 2392 | ||
| 2406 | if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) { | 2393 | if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) { |
| 2407 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | 2394 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), |
| 2408 | "Application::displaySide() ... bucky balls..."); | 2395 | "Application::displaySide() ... bucky balls..."); |
| @@ -2415,7 +2402,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 6 unmodified lines | |||
| 2415 | "Application::displaySide() ... particles..."); | 2402 | "Application::displaySide() ... particles..."); |
| 2416 | _particles.render(); | 2403 | _particles.render(); |
| 2417 | } | 2404 | } |
| 2418 | 2405 | ||
| 2419 | // render the ambient occlusion effect if enabled | 2406 | // render the ambient occlusion effect if enabled |
| 2420 | if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) { | 2407 | if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) { |
| 2421 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), | 2408 | PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), |
| @@ -2459,7 +2446,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { · 37 unmodified lines | |||
| 2459 | 2446 | ||
| 2460 | // give external parties a change to hook in | 2447 | // give external parties a change to hook in |
| 2461 | emit renderingInWorldInterface(); | 2448 | emit renderingInWorldInterface(); |
| 2462 | 2449 | ||
| 2463 | // render JS/scriptable overlays | 2450 | // render JS/scriptable overlays |
| 2464 | _overlays.render3D(); | 2451 | _overlays.render3D(); |
| 2465 | } | 2452 | } |
| @@ -2509,14 +2496,111 @@ void Application::displayOverlay() { · 43 unmodified lines | |||
| 2509 | } | 2496 | } |
| 2510 | } | 2497 | } |
| 2511 | 2498 | ||
| 2499 | // Audio Scope | ||
| 2500 | const int AUDIO_SCOPE_Y_OFFSET = 135; | ||
| 2512 | if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { | 2501 | if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { |
| 2513 | _audio.renderMuteIcon(1, _glWidget->height() - 50); | ||
| 2514 | if (Menu::getInstance()->isOptionChecked(MenuOption::Oscilloscope)) { | 2502 | if (Menu::getInstance()->isOptionChecked(MenuOption::Oscilloscope)) { |
| 2515 | int oscilloscopeTop = _glWidget->height() - 135; | 2503 | int oscilloscopeTop = _glWidget->height() - AUDIO_SCOPE_Y_OFFSET; |
| 2516 | _audioScope.render(25, oscilloscopeTop); | 2504 | _audioScope.render(MIRROR_VIEW_LEFT_PADDING, oscilloscopeTop); |
| 2517 | } | 2505 | } |
| 2518 | } | 2506 | } |
| 2519 | 2507 | ||
| 2508 | // Audio VU Meter and Mute Icon | ||
| 2509 | const int MUTE_ICON_SIZE = 24; | ||
| 2510 | const int AUDIO_METER_INSET = 2; | ||
| 2511 | const int AUDIO_METER_WIDTH = MIRROR_VIEW_WIDTH - MUTE_ICON_SIZE - AUDIO_METER_INSET; | ||
| 2512 | const int AUDIO_METER_SCALE_WIDTH = AUDIO_METER_WIDTH - 2 * AUDIO_METER_INSET; | ||
| 2513 | const int AUDIO_METER_HEIGHT = 8; | ||
| 2514 | const int AUDIO_METER_Y_GAP = 8; | ||
| 2515 | const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_INSET; | ||
| 2516 | |||
| 2517 | int audioMeterY; | ||
| 2518 | if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { | ||
| 2519 | audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_Y_GAP; | ||
| 2520 | } else { | ||
| 2521 | audioMeterY = AUDIO_METER_Y_GAP; | ||
| 2522 | } | ||
| 2523 | _audio.renderMuteIcon(MIRROR_VIEW_LEFT_PADDING, audioMeterY); | ||
| 2524 | |||
| 2525 | |||
| 2526 | const float AUDIO_METER_BLUE[] = {0.0, 0.0, 1.0}; | ||
| 2527 | const float AUDIO_METER_GREEN[] = {0.0, 1.0, 0.0}; | ||
| 2528 | const float AUDIO_METER_RED[] = {1.0, 0.0, 0.0}; | ||
| 2529 | const float AUDIO_GREEN_START = 0.25 * AUDIO_METER_SCALE_WIDTH; | ||
| 2530 | const float AUDIO_RED_START = 0.80 * AUDIO_METER_SCALE_WIDTH; | ||
| 2531 | const float CLIPPING_INDICATOR_TIME = 1.0f; | ||
| 2532 | const float AUDIO_METER_AVERAGING = 0.5; | ||
| 2533 | const float LOG2 = log(2.f); | ||
| 2534 | const float METER_LOUDNESS_SCALE = 2.8f / 5.f; | ||
| 2535 | const float LOG2_LOUDNESS_FLOOR = 11.f; | ||
| 2536 | float audioLevel = 0.f; | ||
| 2537 | float loudness = _audio.getLastInputLoudness() + 1.f; | ||
| 2538 | |||
| 2539 | _trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.f - AUDIO_METER_AVERAGING) * loudness; | ||
| 2540 | float log2loudness = log(_trailingAudioLoudness) / LOG2; | ||
| 2541 | |||
| 2542 | if (log2loudness <= LOG2_LOUDNESS_FLOOR) { | ||
| 2543 | audioLevel = (log2loudness / LOG2_LOUDNESS_FLOOR) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH; | ||
| 2544 | } else { | ||
| 2545 | audioLevel = (log2loudness - (LOG2_LOUDNESS_FLOOR - 1.f)) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH; | ||
| 2546 | } | ||
| 2547 | if (audioLevel > AUDIO_METER_SCALE_WIDTH) { | ||
| 2548 | audioLevel = AUDIO_METER_SCALE_WIDTH; | ||
| 2549 | } | ||
| 2550 | |||
| 2551 | bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)); | ||
| 2552 | |||
| 2553 | glBegin(GL_QUADS); | ||
| 2554 | if (isClipping) { | ||
| 2555 | glColor3f(1, 0, 0); | ||
| 2556 | } else { | ||
| 2557 | glColor3f(0, 0, 0); | ||
| 2558 | } | ||
| 2559 | // Draw audio meter background Quad | ||
| 2560 | glVertex2i(AUDIO_METER_X, audioMeterY); | ||
| 2561 | glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY); | ||
| 2562 | glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY + AUDIO_METER_HEIGHT); | ||
| 2563 | glVertex2i(AUDIO_METER_X, audioMeterY + AUDIO_METER_HEIGHT); | ||
| 2564 | |||
| 2565 | if (audioLevel > AUDIO_RED_START) { | ||
| 2566 | if (!isClipping) { | ||
| 2567 | glColor3fv(AUDIO_METER_RED); | ||
| 2568 | } else { | ||
| 2569 | glColor3f(1, 1, 1); | ||
| 2570 | } | ||
| 2571 | // Draw Red Quad | ||
| 2572 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START, audioMeterY + AUDIO_METER_INSET); | ||
| 2573 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET); | ||
| 2574 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); | ||
| 2575 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); | ||
| 2576 | audioLevel = AUDIO_RED_START; | ||
| 2577 | } | ||
| 2578 | if (audioLevel > AUDIO_GREEN_START) { | ||
| 2579 | if (!isClipping) { | ||
| 2580 | glColor3fv(AUDIO_METER_GREEN); | ||
| 2581 | } else { | ||
| 2582 | glColor3f(1, 1, 1); | ||
| 2583 | } | ||
| 2584 | // Draw Green Quad | ||
| 2585 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START, audioMeterY + AUDIO_METER_INSET); | ||
| 2586 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET); | ||
| 2587 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); | ||
| 2588 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); | ||
| 2589 | audioLevel = AUDIO_GREEN_START; | ||
| 2590 | } | ||
| 2591 | // Draw Blue Quad | ||
| 2592 | if (!isClipping) { | ||
| 2593 | glColor3fv(AUDIO_METER_BLUE); | ||
| 2594 | } else { | ||
| 2595 | glColor3f(1, 1, 1); | ||
| 2596 | } | ||
| 2597 | // Draw Blue (low level) quad | ||
| 2598 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_INSET); | ||
| 2599 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET); | ||
| 2600 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); | ||
| 2601 | glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); | ||
| 2602 | glEnd(); | ||
| 2603 | |||
| 2520 | if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) { | 2604 | if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) { |
| 2521 | _myAvatar->renderHeadMouse(); | 2605 | _myAvatar->renderHeadMouse(); |
| 2522 | } | 2606 | } |
| @@ -2526,11 +2610,17 @@ void Application::displayOverlay() { · 3 unmodified lines | |||
| 2526 | glPointSize(1.0f); | 2610 | glPointSize(1.0f); |
| 2527 | 2611 | ||
| 2528 | if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { | 2612 | if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { |
| 2613 | int horizontalOffset = 0; | ||
| 2614 | if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { | ||
| 2615 | // mirror is enabled, let's set horizontal offset to give stats some margin | ||
| 2616 | horizontalOffset += MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; | ||
| 2617 | } | ||
| 2618 | int voxelPacketsToProcess = _voxelProcessor.packetsToProcessCount(); | ||
| 2529 | // Onscreen text about position, servers, etc | 2619 | // Onscreen text about position, servers, etc |
| 2530 | displayStats(); | 2620 | Stats::getInstance()->display(WHITE_TEXT, horizontalOffset, _fps, _packetsPerSecond, _bytesPerSecond, voxelPacketsToProcess); |
| 2531 | // Bandwidth meter | 2621 | // Bandwidth meter |
| 2532 | if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) { | 2622 | if (Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) { |
| 2533 | displayStatsBackground(0x33333399, _glWidget->width() - 296, _glWidget->height() - 68, 296, 68); | 2623 | Stats::drawBackground(0x33333399, _glWidget->width() - 296, _glWidget->height() - 68, 296, 68); |
| 2534 | _bandwidthMeter.render(_glWidget->width(), _glWidget->height()); | 2624 | _bandwidthMeter.render(_glWidget->width(), _glWidget->height()); |
| 2535 | } | 2625 | } |
| 2536 | } | 2626 | } |
| @@ -2540,8 +2630,8 @@ void Application::displayOverlay() { · 3 unmodified lines | |||
| 2540 | char frameTimer[10]; | 2630 | char frameTimer[10]; |
| 2541 | quint64 mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5); | 2631 | quint64 mSecsNow = floor(usecTimestampNow() / 1000.0 + 0.5); |
| 2542 | sprintf(frameTimer, "%d\n", (int)(mSecsNow % 1000)); | 2632 | sprintf(frameTimer, "%d\n", (int)(mSecsNow % 1000)); |
| 2543 | int timerBottom = | 2633 | int timerBottom = |
| 2544 | (Menu::getInstance()->isOptionChecked(MenuOption::Stats) && | 2634 | (Menu::getInstance()->isOptionChecked(MenuOption::Stats) && |
| 2545 | Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) | 2635 | Menu::getInstance()->isOptionChecked(MenuOption::Bandwidth)) |
| 2546 | ? 80 : 20; | 2636 | ? 80 : 20; |
| 2547 | drawText(_glWidget->width() - 100, _glWidget->height() - timerBottom, 0.30f, 1.0f, 0.f, frameTimer, WHITE_TEXT); | 2637 | drawText(_glWidget->width() - 100, _glWidget->height() - timerBottom, 0.30f, 1.0f, 0.f, frameTimer, WHITE_TEXT); |
| @@ -2552,415 +2642,6 @@ void Application::displayOverlay() { · 4 unmodified lines | |||
| 2552 | glPopMatrix(); | 2642 | glPopMatrix(); |
| 2553 | } | 2643 | } |
| 2554 | 2644 | ||
| 2555 | // translucent background box that makes stats more readable | ||
| 2556 | void Application::displayStatsBackground(unsigned int rgba, int x, int y, int width, int height) { | ||
| 2557 | glBegin(GL_QUADS); | ||
| 2558 | glColor4f(((rgba >> 24) & 0xff) / 255.0f, | ||
| 2559 | ((rgba >> 16) & 0xff) / 255.0f, | ||
| 2560 | ((rgba >> 8) & 0xff) / 255.0f, | ||
| 2561 | (rgba & 0xff) / 255.0f); | ||
| 2562 | glVertex3f(x, y, 0); | ||
| 2563 | glVertex3f(x + width, y, 0); | ||
| 2564 | glVertex3f(x + width, y + height, 0); | ||
| 2565 | glVertex3f(x , y + height, 0); | ||
| 2566 | glEnd(); | ||
| 2567 | glColor4f(1, 1, 1, 1); | ||
| 2568 | } | ||
| 2569 | |||
| 2570 | // display expanded or contracted stats | ||
| 2571 | |||
| 2572 | void Application::displayStats() { | ||
| 2573 | unsigned int backgroundColor = 0x33333399; | ||
| 2574 | int verticalOffset = 0, horizontalOffset = 0, lines = 0; | ||
| 2575 | bool mirrorEnabled = Menu::getInstance()->isOptionChecked(MenuOption::Mirror); | ||
| 2576 | |||
| 2577 | QLocale locale(QLocale::English); | ||
| 2578 | std::stringstream voxelStats; | ||
| 2579 | |||
| 2580 | glPointSize(1.0f); | ||
| 2581 | |||
| 2582 | // we need to take one avatar out so we don't include ourselves | ||
| 2583 | int totalAvatars = _avatarManager.size() - 1; | ||
| 2584 | int totalServers = NodeList::getInstance()->size(); | ||
| 2585 | |||
| 2586 | if (mirrorEnabled) { | ||
| 2587 | horizontalOffset += MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; | ||
| 2588 | } | ||
| 2589 | |||
| 2590 | lines = _statsExpanded ? 5 : 3; | ||
| 2591 | displayStatsBackground(backgroundColor, horizontalOffset, 0, 165, lines * STATS_PELS_PER_LINE + 10); | ||
| 2592 | horizontalOffset += 5; | ||
| 2593 | |||
| 2594 | char serverNodes[30]; | ||
| 2595 | sprintf(serverNodes, "Servers: %d", totalServers); | ||
| 2596 | char avatarNodes[30]; | ||
| 2597 | sprintf(avatarNodes, "Avatars: %d", totalAvatars); | ||
| 2598 | char framesPerSecond[30]; | ||
| 2599 | sprintf(framesPerSecond, "Framerate: %3.0f FPS", _fps); | ||
| 2600 | |||
| 2601 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2602 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, serverNodes, WHITE_TEXT); | ||
| 2603 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2604 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarNodes, WHITE_TEXT); | ||
| 2605 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2606 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, framesPerSecond, WHITE_TEXT); | ||
| 2607 | |||
| 2608 | if (_statsExpanded) { | ||
| 2609 | char packetsPerSecond[30]; | ||
| 2610 | sprintf(packetsPerSecond, "Pkts/sec: %d", _packetsPerSecond); | ||
| 2611 | char averageMegabitsPerSecond[30]; | ||
| 2612 | sprintf(averageMegabitsPerSecond, "Mbps: %3.2f", (float)_bytesPerSecond * 8.f / 1000000.f); | ||
| 2613 | |||
| 2614 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2615 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, packetsPerSecond, WHITE_TEXT); | ||
| 2616 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2617 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, averageMegabitsPerSecond, WHITE_TEXT); | ||
| 2618 | } | ||
| 2619 | |||
| 2620 | verticalOffset = 0; | ||
| 2621 | horizontalOffset += 161; | ||
| 2622 | |||
| 2623 | if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { | ||
| 2624 | int pingAudio = 0, pingAvatar = 0, pingVoxel = 0, pingVoxelMax = 0; | ||
| 2625 | |||
| 2626 | NodeList* nodeList = NodeList::getInstance(); | ||
| 2627 | SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); | ||
| 2628 | SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer); | ||
| 2629 | |||
| 2630 | pingAudio = audioMixerNode ? audioMixerNode->getPingMs() : 0; | ||
| 2631 | pingAvatar = avatarMixerNode ? avatarMixerNode->getPingMs() : 0; | ||
| 2632 | |||
| 2633 | // Now handle voxel servers, since there could be more than one, we average their ping times | ||
| 2634 | unsigned long totalPingVoxel = 0; | ||
| 2635 | int voxelServerCount = 0; | ||
| 2636 | |||
| 2637 | foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { | ||
| 2638 | if (node->getType() == NodeType::VoxelServer) { | ||
| 2639 | totalPingVoxel += node->getPingMs(); | ||
| 2640 | voxelServerCount++; | ||
| 2641 | if (pingVoxelMax < node->getPingMs()) { | ||
| 2642 | pingVoxelMax = node->getPingMs(); | ||
| 2643 | } | ||
| 2644 | } | ||
| 2645 | } | ||
| 2646 | |||
| 2647 | if (voxelServerCount) { | ||
| 2648 | pingVoxel = totalPingVoxel/voxelServerCount; | ||
| 2649 | } | ||
| 2650 | |||
| 2651 | lines = _statsExpanded ? 4 : 3; | ||
| 2652 | displayStatsBackground(backgroundColor, horizontalOffset, 0, 175, lines * STATS_PELS_PER_LINE + 10); | ||
| 2653 | horizontalOffset += 5; | ||
| 2654 | |||
| 2655 | char audioJitter[30]; | ||
| 2656 | sprintf(audioJitter, | ||
| 2657 | "Buffer msecs %.1f", | ||
| 2658 | (float) (_audio.getNetworkBufferLengthSamplesPerChannel() + (float) _audio.getJitterBufferSamples()) / | ||
| 2659 | (float)_audio.getNetworkSampleRate() * 1000.f); | ||
| 2660 | drawText(30, _glWidget->height() - 22, 0.10f, 0.f, 2.f, audioJitter, WHITE_TEXT); | ||
| 2661 | |||
| 2662 | |||
| 2663 | char audioPing[30]; | ||
| 2664 | sprintf(audioPing, "Audio ping: %d", pingAudio); | ||
| 2665 | |||
| 2666 | |||
| 2667 | char avatarPing[30]; | ||
| 2668 | sprintf(avatarPing, "Avatar ping: %d", pingAvatar); | ||
| 2669 | char voxelAvgPing[30]; | ||
| 2670 | sprintf(voxelAvgPing, "Voxel avg ping: %d", pingVoxel); | ||
| 2671 | |||
| 2672 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2673 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, audioPing, WHITE_TEXT); | ||
| 2674 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2675 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarPing, WHITE_TEXT); | ||
| 2676 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2677 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelAvgPing, WHITE_TEXT); | ||
| 2678 | |||
| 2679 | if (_statsExpanded) { | ||
| 2680 | char voxelMaxPing[30]; | ||
| 2681 | sprintf(voxelMaxPing, "Voxel max ping: %d", pingVoxelMax); | ||
| 2682 | |||
| 2683 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2684 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, voxelMaxPing, WHITE_TEXT); | ||
| 2685 | } | ||
| 2686 | |||
| 2687 | verticalOffset = 0; | ||
| 2688 | horizontalOffset += 171; | ||
| 2689 | } | ||
| 2690 | |||
| 2691 | glm::vec3 avatarPos = _myAvatar->getPosition(); | ||
| 2692 | |||
| 2693 | lines = _statsExpanded ? 5 : 3; | ||
| 2694 | displayStatsBackground(backgroundColor, horizontalOffset, 0, _glWidget->width() - (mirrorEnabled ? 301 : 411) - horizontalOffset, lines * STATS_PELS_PER_LINE + 10); | ||
| 2695 | horizontalOffset += 5; | ||
| 2696 | |||
| 2697 | char avatarPosition[200]; | ||
| 2698 | if (mirrorEnabled) { | ||
| 2699 | // shorthand formatting | ||
| 2700 | sprintf(avatarPosition, "Pos: %.0f,%.0f,%.0f", avatarPos.x, avatarPos.y, avatarPos.z); | ||
| 2701 | } else { | ||
| 2702 | // longhand way | ||
| 2703 | sprintf(avatarPosition, "Position: %.1f, %.1f, %.1f", avatarPos.x, avatarPos.y, avatarPos.z); | ||
| 2704 | } | ||
| 2705 | char avatarVelocity[30]; | ||
| 2706 | sprintf(avatarVelocity, "Velocity: %.1f", glm::length(_myAvatar->getVelocity())); | ||
| 2707 | char avatarBodyYaw[30]; | ||
| 2708 | sprintf(avatarBodyYaw, "Yaw: %.1f", _myAvatar->getBodyYaw()); | ||
| 2709 | char avatarMixerStats[200]; | ||
| 2710 | |||
| 2711 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2712 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarPosition, WHITE_TEXT); | ||
| 2713 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2714 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarVelocity, WHITE_TEXT); | ||
| 2715 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2716 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarBodyYaw, WHITE_TEXT); | ||
| 2717 | |||
| 2718 | if (_statsExpanded) { | ||
| 2719 | SharedNodePointer avatarMixer = NodeList::getInstance()->soloNodeOfType(NodeType::AvatarMixer); | ||
| 2720 | if (avatarMixer) { | ||
| 2721 | sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps", | ||
| 2722 | roundf(avatarMixer->getAverageKilobitsPerSecond()), | ||
| 2723 | roundf(avatarMixer->getAveragePacketsPerSecond())); | ||
| 2724 | } else { | ||
| 2725 | sprintf(avatarMixerStats, "No Avatar Mixer"); | ||
| 2726 | } | ||
| 2727 | |||
| 2728 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2729 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, avatarMixerStats, WHITE_TEXT); | ||
| 2730 | |||
| 2731 | stringstream downloadStats; | ||
| 2732 | downloadStats << "Downloads: "; | ||
| 2733 | foreach (Resource* resource, ResourceCache::getLoadingRequests()) { | ||
| 2734 | const float MAXIMUM_PERCENTAGE = 100.0f; | ||
| 2735 | downloadStats << roundf(resource->getProgress() * MAXIMUM_PERCENTAGE) << "% "; | ||
| 2736 | } | ||
| 2737 | downloadStats << "(" << ResourceCache::getPendingRequestCount() << " pending)"; | ||
| 2738 | |||
| 2739 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2740 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, downloadStats.str().c_str(), WHITE_TEXT); | ||
| 2741 | } | ||
| 2742 | |||
| 2743 | verticalOffset = 0; | ||
| 2744 | horizontalOffset = _glWidget->width() - (mirrorEnabled ? 300 : 410); | ||
| 2745 | |||
| 2746 | lines = _statsExpanded ? 12 : 3; | ||
| 2747 | displayStatsBackground(backgroundColor, horizontalOffset, 0, _glWidget->width() - horizontalOffset, lines * STATS_PELS_PER_LINE + 10); | ||
| 2748 | horizontalOffset += 5; | ||
| 2749 | |||
| 2750 | if (_statsExpanded) { | ||
| 2751 | // Local Voxel Memory Usage | ||
| 2752 | voxelStats.str(""); | ||
| 2753 | voxelStats << "Voxels Memory Nodes: " << VoxelTreeElement::getTotalMemoryUsage() / 1000000.f << "MB"; | ||
| 2754 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2755 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2756 | |||
| 2757 | voxelStats.str(""); | ||
| 2758 | voxelStats << | ||
| 2759 | "Geometry RAM: " << _voxels.getVoxelMemoryUsageRAM() / 1000000.f << "MB / " << | ||
| 2760 | "VBO: " << _voxels.getVoxelMemoryUsageVBO() / 1000000.f << "MB"; | ||
| 2761 | if (_voxels.hasVoxelMemoryUsageGPU()) { | ||
| 2762 | voxelStats << " / GPU: " << _voxels.getVoxelMemoryUsageGPU() / 1000000.f << "MB"; | ||
| 2763 | } | ||
| 2764 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2765 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2766 | |||
| 2767 | // Voxel Rendering | ||
| 2768 | voxelStats.str(""); | ||
| 2769 | voxelStats.precision(4); | ||
| 2770 | voxelStats << "Voxel Rendering Slots Max: " << _voxels.getMaxVoxels() / 1000.f << "K"; | ||
| 2771 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2772 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2773 | } | ||
| 2774 | |||
| 2775 | voxelStats.str(""); | ||
| 2776 | voxelStats.precision(4); | ||
| 2777 | voxelStats << "Drawn: " << _voxels.getVoxelsWritten() / 1000.f << "K " << | ||
| 2778 | "Abandoned: " << _voxels.getAbandonedVoxels() / 1000.f << "K "; | ||
| 2779 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2780 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2781 | |||
| 2782 | // iterate all the current voxel stats, and list their sending modes, and total voxel counts | ||
| 2783 | std::stringstream sendingMode(""); | ||
| 2784 | sendingMode << "Octree Sending Mode: ["; | ||
| 2785 | int serverCount = 0; | ||
| 2786 | int movingServerCount = 0; | ||
| 2787 | unsigned long totalNodes = 0; | ||
| 2788 | unsigned long totalInternal = 0; | ||
| 2789 | unsigned long totalLeaves = 0; | ||
| 2790 | for(NodeToOctreeSceneStatsIterator i = _octreeServerSceneStats.begin(); i != _octreeServerSceneStats.end(); i++) { | ||
| 2791 | //const QUuid& uuid = i->first; | ||
| 2792 | OctreeSceneStats& stats = i->second; | ||
| 2793 | serverCount++; | ||
| 2794 | if (_statsExpanded) { | ||
| 2795 | if (serverCount > 1) { | ||
| 2796 | sendingMode << ","; | ||
| 2797 | } | ||
| 2798 | if (stats.isMoving()) { | ||
| 2799 | sendingMode << "M"; | ||
| 2800 | movingServerCount++; | ||
| 2801 | } else { | ||
| 2802 | sendingMode << "S"; | ||
| 2803 | } | ||
| 2804 | } | ||
| 2805 | |||
| 2806 | // calculate server node totals | ||
| 2807 | totalNodes += stats.getTotalElements(); | ||
| 2808 | if (_statsExpanded) { | ||
| 2809 | totalInternal += stats.getTotalInternal(); | ||
| 2810 | totalLeaves += stats.getTotalLeaves(); | ||
| 2811 | } | ||
| 2812 | } | ||
| 2813 | if (_statsExpanded) { | ||
| 2814 | if (serverCount == 0) { | ||
| 2815 | sendingMode << "---"; | ||
| 2816 | } | ||
| 2817 | sendingMode << "] " << serverCount << " servers"; | ||
| 2818 | if (movingServerCount > 0) { | ||
| 2819 | sendingMode << " <SCENE NOT STABLE>"; | ||
| 2820 | } else { | ||
| 2821 | sendingMode << " <SCENE STABLE>"; | ||
| 2822 | } | ||
| 2823 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2824 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)sendingMode.str().c_str(), WHITE_TEXT); | ||
| 2825 | } | ||
| 2826 | |||
| 2827 | // Incoming packets | ||
| 2828 | int voxelPacketsToProcess = _voxelProcessor.packetsToProcessCount(); | ||
| 2829 | if (_statsExpanded) { | ||
| 2830 | voxelStats.str(""); | ||
| 2831 | QString packetsString = locale.toString((int)voxelPacketsToProcess); | ||
| 2832 | QString maxString = locale.toString((int)_recentMaxPackets); | ||
| 2833 | voxelStats << "Voxel Packets to Process: " << qPrintable(packetsString) | ||
| 2834 | << " [Recent Max: " << qPrintable(maxString) << "]"; | ||
| 2835 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2836 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2837 | } | ||
| 2838 | |||
| 2839 | if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) { | ||
| 2840 | _recentMaxPackets = 0; | ||
| 2841 | _resetRecentMaxPacketsSoon = false; | ||
| 2842 | } | ||
| 2843 | if (voxelPacketsToProcess == 0) { | ||
| 2844 | _resetRecentMaxPacketsSoon = true; | ||
| 2845 | } else { | ||
| 2846 | if (voxelPacketsToProcess > _recentMaxPackets) { | ||
| 2847 | _recentMaxPackets = voxelPacketsToProcess; | ||
| 2848 | } | ||
| 2849 | } | ||
| 2850 | |||
| 2851 | verticalOffset += (_statsExpanded ? STATS_PELS_PER_LINE : 0); | ||
| 2852 | |||
| 2853 | QString serversTotalString = locale.toString((uint)totalNodes); // consider adding: .rightJustified(10, ' '); | ||
| 2854 | |||
| 2855 | // Server Voxels | ||
| 2856 | voxelStats.str(""); | ||
| 2857 | voxelStats << "Server voxels: " << qPrintable(serversTotalString); | ||
| 2858 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2859 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2860 | |||
| 2861 | if (_statsExpanded) { | ||
| 2862 | QString serversInternalString = locale.toString((uint)totalInternal); | ||
| 2863 | QString serversLeavesString = locale.toString((uint)totalLeaves); | ||
| 2864 | |||
| 2865 | voxelStats.str(""); | ||
| 2866 | voxelStats << | ||
| 2867 | "Internal: " << qPrintable(serversInternalString) << " " << | ||
| 2868 | "Leaves: " << qPrintable(serversLeavesString) << ""; | ||
| 2869 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2870 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2871 | } | ||
| 2872 | |||
| 2873 | unsigned long localTotal = VoxelTreeElement::getNodeCount(); | ||
| 2874 | QString localTotalString = locale.toString((uint)localTotal); // consider adding: .rightJustified(10, ' '); | ||
| 2875 | |||
| 2876 | // Local Voxels | ||
| 2877 | voxelStats.str(""); | ||
| 2878 | voxelStats << "Local voxels: " << qPrintable(localTotalString); | ||
| 2879 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2880 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2881 | |||
| 2882 | if (_statsExpanded) { | ||
| 2883 | unsigned long localInternal = VoxelTreeElement::getInternalNodeCount(); | ||
| 2884 | unsigned long localLeaves = VoxelTreeElement::getLeafNodeCount(); | ||
| 2885 | QString localInternalString = locale.toString((uint)localInternal); | ||
| 2886 | QString localLeavesString = locale.toString((uint)localLeaves); | ||
| 2887 | |||
| 2888 | voxelStats.str(""); | ||
| 2889 | voxelStats << | ||
| 2890 | "Internal: " << qPrintable(localInternalString) << " " << | ||
| 2891 | "Leaves: " << qPrintable(localLeavesString) << ""; | ||
| 2892 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2893 | drawText(horizontalOffset, verticalOffset, 0.10f, 0, 2, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2894 | } | ||
| 2895 | |||
| 2896 | // LOD Details | ||
| 2897 | if (_statsExpanded) { | ||
| 2898 | voxelStats.str(""); | ||
| 2899 | QString displayLODDetails = Menu::getInstance()->getLODFeedbackText(); | ||
| 2900 | voxelStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed()); | ||
| 2901 | verticalOffset += STATS_PELS_PER_LINE; | ||
| 2902 | drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, (char*)voxelStats.str().c_str(), WHITE_TEXT); | ||
| 2903 | } | ||
| 2904 | } | ||
| 2905 | |||
| 2906 | // called on mouse click release | ||
| 2907 | // check for clicks over stats in order to expand or contract them | ||
| 2908 | void Application::checkStatsClick() { | ||
| 2909 | if (0 != glm::compMax(glm::abs(glm::ivec2(_mouseX - _mouseDragStartedX, _mouseY - _mouseDragStartedY)))) { | ||
| 2910 | // not worried about dragging on stats | ||
| 2911 | return; | ||
| 2912 | } | ||
| 2913 | |||
| 2914 | int statsHeight = 0, statsWidth = 0, statsX = 0, statsY = 0, lines = 0; | ||
| 2915 | |||
| 2916 | if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { | ||
| 2917 | statsX += MIRROR_VIEW_WIDTH; | ||
| 2918 | } | ||
| 2919 | |||
| 2920 | // top-left stats click | ||
| 2921 | lines = _statsExpanded ? 5 : 3; | ||
| 2922 | statsHeight = lines * STATS_PELS_PER_LINE + 10; | ||
| 2923 | statsWidth = 165; | ||
| 2924 | if (_mouseX > statsX && _mouseX < statsX + statsWidth && _mouseY > statsY && _mouseY < statsY + statsHeight) { | ||
| 2925 | toggleStatsExpanded(); | ||
| 2926 | return; | ||
| 2927 | } | ||
| 2928 | |||
| 2929 | // ping stats click | ||
| 2930 | lines = _statsExpanded ? 4 : 3; | ||
| 2931 | statsX += statsWidth; | ||
| 2932 | statsHeight = lines * STATS_PELS_PER_LINE + 10; | ||
| 2933 | statsWidth = 175; | ||
| 2934 | if (_mouseX > statsX && _mouseX < statsX + statsWidth && _mouseY > statsY && _mouseY < statsY + statsHeight) { | ||
| 2935 | toggleStatsExpanded(); | ||
| 2936 | return; | ||
| 2937 | } | ||
| 2938 | |||
| 2939 | // top-center stats panel click | ||
| 2940 | lines = _statsExpanded ? 4 : 3; | ||
| 2941 | statsX += statsWidth; | ||
| 2942 | statsHeight = lines * STATS_PELS_PER_LINE + 10; | ||
| 2943 | statsWidth = _glWidget->width() - 411 - statsX; | ||
| 2944 | if (_mouseX > statsX && _mouseX < statsX + statsWidth && _mouseY > statsY && _mouseY < statsY + statsHeight) { | ||
| 2945 | toggleStatsExpanded(); | ||
| 2946 | return; | ||
| 2947 | } | ||
| 2948 | |||
| 2949 | // top-right stats click | ||
| 2950 | lines = _statsExpanded ? 11 : 3; | ||
| 2951 | statsX = _glWidget->width() - 410; | ||
| 2952 | statsHeight = lines * STATS_PELS_PER_LINE + 10; | ||
| 2953 | statsWidth = _glWidget->width() - statsX; | ||
| 2954 | if (_mouseX > statsX && _mouseX < statsX + statsWidth && _mouseY > statsY && _mouseY < statsY + statsHeight) { | ||
| 2955 | toggleStatsExpanded(); | ||
| 2956 | return; | ||
| 2957 | } | ||
| 2958 | } | ||
| 2959 | |||
| 2960 | void Application::toggleStatsExpanded() { | ||
| 2961 | _statsExpanded = !_statsExpanded; | ||
| 2962 | } | ||
| 2963 | |||
| 2964 | glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { | 2645 | glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { |
| 2965 | float horizontalScale = _glWidget->width() / 2.0f; | 2646 | float horizontalScale = _glWidget->width() / 2.0f; |
| 2966 | float verticalScale = _glWidget->height() / 2.0f; | 2647 | float verticalScale = _glWidget->height() / 2.0f; |
| @@ -2993,12 +2674,12 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { · 26 unmodified lines | |||
| 2993 | _mirrorCamera.setFieldOfView(BILLBOARD_FIELD_OF_VIEW); // degees | 2674 | _mirrorCamera.setFieldOfView(BILLBOARD_FIELD_OF_VIEW); // degees |
| 2994 | _mirrorCamera.setDistance(BILLBOARD_DISTANCE * _myAvatar->getScale()); | 2675 | _mirrorCamera.setDistance(BILLBOARD_DISTANCE * _myAvatar->getScale()); |
| 2995 | _mirrorCamera.setTargetPosition(_myAvatar->getPosition()); | 2676 | _mirrorCamera.setTargetPosition(_myAvatar->getPosition()); |
| 2996 | 2677 | ||
| 2997 | } else if (_rearMirrorTools->getZoomLevel() == BODY) { | 2678 | } else if (_rearMirrorTools->getZoomLevel() == BODY) { |
| 2998 | _mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees | 2679 | _mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees |
| 2999 | _mirrorCamera.setDistance(MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); | 2680 | _mirrorCamera.setDistance(MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); |
| 3000 | _mirrorCamera.setTargetPosition(_myAvatar->getChestPosition()); | 2681 | _mirrorCamera.setTargetPosition(_myAvatar->getChestPosition()); |
| 3001 | 2682 | ||
| 3002 | } else { // HEAD zoom level | 2683 | } else { // HEAD zoom level |
| 3003 | _mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees | 2684 | _mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees |
| 3004 | _mirrorCamera.setDistance(MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); | 2685 | _mirrorCamera.setDistance(MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); |
| @@ -3013,7 +2694,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { · 8 unmodified lines | |||
| 3013 | } | 2694 | } |
| 3014 | } | 2695 | } |
| 3015 | _mirrorCamera.setAspectRatio((float)region.width() / region.height()); | 2696 | _mirrorCamera.setAspectRatio((float)region.width() / region.height()); |
| 3016 | 2697 | ||
| 3017 | _mirrorCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); | 2698 | _mirrorCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); |
| 3018 | _mirrorCamera.update(1.0f/_fps); | 2699 | _mirrorCamera.update(1.0f/_fps); |
| 3019 | 2700 | ||
| @@ -3058,7 +2739,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { · 38 unmodified lines | |||
| 3058 | if (!billboard) { | 2739 | if (!billboard) { |
| 3059 | _rearMirrorTools->render(false); | 2740 | _rearMirrorTools->render(false); |
| 3060 | } | 2741 | } |
| 3061 | 2742 | ||
| 3062 | // reset Viewport and projection matrix | 2743 | // reset Viewport and projection matrix |
| 3063 | glViewport(0, 0, _glWidget->width(), _glWidget->height()); | 2744 | glViewport(0, 0, _glWidget->width(), _glWidget->height()); |
| 3064 | glDisable(GL_SCISSOR_TEST); | 2745 | glDisable(GL_SCISSOR_TEST); |
| @@ -3278,14 +2959,13 @@ void Application::setMenuShortcutsEnabled(bool enabled) { · 213 unmodified lines | |||
| 3278 | } | 2959 | } |
| 3279 | 2960 | ||
| 3280 | void Application::updateWindowTitle(){ | 2961 | void Application::updateWindowTitle(){ |
| 3281 | 2962 | ||
| 3282 | QString buildVersion = " (build " + applicationVersion() + ")"; | 2963 | QString buildVersion = " (build " + applicationVersion() + ")"; |
| 3283 | NodeList* nodeList = NodeList::getInstance(); | 2964 | NodeList* nodeList = NodeList::getInstance(); |
| 3284 | 2965 | ||
| 3285 | QString username = AccountManager::getInstance().getUsername(); | 2966 | QString username = AccountManager::getInstance().getUsername(); |
| 3286 | QString title = QString() + (!username.isEmpty() ? username + " " : QString()) + nodeList->getSessionUUID().toString() | 2967 | QString title = QString() + (!username.isEmpty() ? username + " " : QString()) + nodeList->getSessionUUID().toString() |
| 3287 | + " @ " + nodeList->getDomainHandler().getHostname() + buildVersion; | 2968 | + " @ " + nodeList->getDomainHandler().getHostname() + buildVersion; |
| 3288 | |||
| 3289 | qDebug("Application title set to: %s", title.toStdString().c_str()); | 2969 | qDebug("Application title set to: %s", title.toStdString().c_str()); |
| 3290 | _window->setWindowTitle(title); | 2970 | _window->setWindowTitle(title); |
| 3291 | } | 2971 | } |
| @@ -3300,7 +2980,7 @@ void Application::domainChanged(const QString& domainHostname) { · 8 unmodified lines | |||
| 3300 | _voxelServerJurisdictions.clear(); | 2980 | _voxelServerJurisdictions.clear(); |
| 3301 | _octreeServerSceneStats.clear(); | 2981 | _octreeServerSceneStats.clear(); |
| 3302 | _particleServerJurisdictions.clear(); | 2982 | _particleServerJurisdictions.clear(); |
| 3303 | 2983 | ||
| 3304 | // reset the particle renderer | 2984 | // reset the particle renderer |
| 3305 | _particles.clear(); | 2985 | _particles.clear(); |
| 3306 | 2986 | ||
| @@ -3310,12 +2990,12 @@ void Application::domainChanged(const QString& domainHostname) { · 3 unmodified lines | |||
| 3310 | 2990 | ||
| 3311 | void Application::connectedToDomain(const QString& hostname) { | 2991 | void Application::connectedToDomain(const QString& hostname) { |
| 3312 | AccountManager& accountManager = AccountManager::getInstance(); | 2992 | AccountManager& accountManager = AccountManager::getInstance(); |
| 3313 | 2993 | ||
| 3314 | if (accountManager.isLoggedIn()) { | 2994 | if (accountManager.isLoggedIn()) { |
| 3315 | // update our domain-server with the data-server we're logged in with | 2995 | // update our domain-server with the data-server we're logged in with |
| 3316 | 2996 | ||
| 3317 | QString domainPutJsonString = "{\"address\":{\"domain\":\"" + hostname + "\"}}"; | 2997 | QString domainPutJsonString = "{\"address\":{\"domain\":\"" + hostname + "\"}}"; |
| 3318 | 2998 | ||
| 3319 | accountManager.authenticatedRequest("/api/v1/users/address", QNetworkAccessManager::PutOperation, | 2999 | accountManager.authenticatedRequest("/api/v1/users/address", QNetworkAccessManager::PutOperation, |
| 3320 | JSONCallbackParameters(), domainPutJsonString.toUtf8()); | 3000 | JSONCallbackParameters(), domainPutJsonString.toUtf8()); |
| 3321 | } | 3001 | } |
| @@ -3480,13 +3160,13 @@ void Application::loadScripts() { · 158 unmodified lines | |||
| 3480 | // loads all saved scripts | 3160 | // loads all saved scripts |
| 3481 | QSettings* settings = new QSettings(this); | 3161 | QSettings* settings = new QSettings(this); |
| 3482 | int size = settings->beginReadArray("Settings"); | 3162 | int size = settings->beginReadArray("Settings"); |
| 3483 | 3163 | ||
| 3484 | for (int i = 0; i < size; ++i){ | 3164 | for (int i = 0; i < size; ++i){ |
| 3485 | settings->setArrayIndex(i); | 3165 | settings->setArrayIndex(i); |
| 3486 | QString string = settings->value("script").toString(); | 3166 | QString string = settings->value("script").toString(); |
| 3487 | loadScript(string); | 3167 | loadScript(string); |
| 3488 | } | 3168 | } |
| 3489 | 3169 | ||
| 3490 | settings->endArray(); | 3170 | settings->endArray(); |
| 3491 | } | 3171 | } |
| 3492 | 3172 | ||
| @@ -3501,72 +3181,98 @@ void Application::saveScripts() { · 8 unmodified lines | |||
| 3501 | // saves all current running scripts | 3181 | // saves all current running scripts |
| 3502 | QSettings* settings = new QSettings(this); | 3182 | QSettings* settings = new QSettings(this); |
| 3503 | settings->beginWriteArray("Settings"); | 3183 | settings->beginWriteArray("Settings"); |
| 3504 | for (int i = 0; i < _activeScripts.size(); ++i){ | 3184 | for (int i = 0; i < getRunningScripts().size(); ++i){ |
| 3505 | settings->setArrayIndex(i); | 3185 | settings->setArrayIndex(i); |
| 3506 | settings->setValue("script", _activeScripts.at(i)); | 3186 | settings->setValue("script", getRunningScripts().at(i)); |
| 3507 | } | 3187 | } |
| 3508 | 3188 | ||
| 3509 | settings->endArray(); | 3189 | settings->endArray(); |
| 3510 | } | 3190 | } |
| 3511 | 3191 | ||
| 3512 | void Application::stopAllScripts() { | 3192 | void Application::stopAllScripts() { |
| 3513 | // stops all current running scripts | 3193 | // stops all current running scripts |
| 3514 | QList<QAction*> scriptActions = Menu::getInstance()->getActiveScriptsMenu()->actions(); | 3194 | for (int i = 0; i < _scriptEnginesHash.size(); ++i) { |
| 3515 | foreach (QAction* scriptAction, scriptActions) { | 3195 | _scriptEnginesHash.values().at(i)->stop(); |
| 3516 | scriptAction->activate(QAction::Trigger); | 3196 | qDebug() << "stopping script..." << getRunningScripts().at(i); |
| 3517 | qDebug() << "stopping script..." << scriptAction->text(); | ||
| 3518 | } | 3197 | } |
| 3519 | _activeScripts.clear(); | 3198 | _scriptEnginesHash.clear(); |
| 3199 | _runningScriptsWidget->setRunningScripts(getRunningScripts()); | ||
| 3200 | } | ||
| 3201 | |||
| 3202 | void Application::stopScript(const QString &scriptName) | ||
| 3203 | { | ||
| 3204 | _scriptEnginesHash.value(scriptName)->stop(); | ||
| 3205 | qDebug() << "stopping script..." << scriptName; | ||
| 3206 | _scriptEnginesHash.remove(scriptName); | ||
| 3207 | _runningScriptsWidget->setRunningScripts(getRunningScripts()); | ||
| 3520 | } | 3208 | } |
| 3521 | 3209 | ||
| 3522 | void Application::reloadAllScripts() { | 3210 | void Application::reloadAllScripts() { |
| 3523 | // remember all the current scripts so we can reload them | 3211 | // remember all the current scripts so we can reload them |
| 3524 | QStringList reloadList = _activeScripts; | 3212 | QStringList reloadList = getRunningScripts(); |
| 3525 | // reloads all current running scripts | 3213 | // reloads all current running scripts |
| 3526 | QList<QAction*> scriptActions = Menu::getInstance()->getActiveScriptsMenu()->actions(); | 3214 | stopAllScripts(); |
| 3527 | foreach (QAction* scriptAction, scriptActions) { | ||
| 3528 | scriptAction->activate(QAction::Trigger); | ||
| 3529 | qDebug() << "stopping script..." << scriptAction->text(); | ||
| 3530 | } | ||
| 3531 | 3215 | ||
| 3532 | // NOTE: we don't need to clear the _activeScripts list because that is handled on script shutdown. | ||
| 3533 | |||
| 3534 | foreach (QString scriptName, reloadList){ | 3216 | foreach (QString scriptName, reloadList){ |
| 3535 | qDebug() << "reloading script..." << scriptName; | 3217 | qDebug() << "reloading script..." << scriptName; |
| 3536 | loadScript(scriptName); | 3218 | loadScript(scriptName); |
| 3537 | } | 3219 | } |
| 3538 | } | 3220 | } |
| 3539 | 3221 | ||
| 3540 | void Application::uploadFST() { | 3222 | void Application::toggleRunningScriptsWidget() |
| 3541 | FstReader reader; | 3223 | { |
| 3542 | if (reader.zip()) { | 3224 | if (!_runningScriptsWidget->toggleViewAction()->isChecked()) { |
| 3543 | reader.send(); | 3225 | _runningScriptsWidget->move(_window->geometry().topLeft().x(), _window->geometry().topLeft().y()); |
| 3226 | _runningScriptsWidget->resize(0, _window->height()); | ||
| 3227 | _runningScriptsWidget->toggleViewAction()->trigger(); | ||
| 3228 | _runningScriptsWidget->grabKeyboard(); | ||
| 3229 | |||
| 3230 | QPropertyAnimation* slideAnimation = new QPropertyAnimation(_runningScriptsWidget, "geometry", _runningScriptsWidget); | ||
| 3231 | slideAnimation->setStartValue(_runningScriptsWidget->geometry()); | ||
| 3232 | slideAnimation->setEndValue(QRect(_window->geometry().topLeft().x(), _window->geometry().topLeft().y(), | ||
| 3233 | 310, _runningScriptsWidget->height())); | ||
| 3234 | slideAnimation->setDuration(250); | ||
| 3235 | slideAnimation->start(QAbstractAnimation::DeleteWhenStopped); | ||
| 3236 | } else { | ||
| 3237 | _runningScriptsWidget->releaseKeyboard(); | ||
| 3238 | |||
| 3239 | QPropertyAnimation* slideAnimation = new QPropertyAnimation(_runningScriptsWidget, "geometry", _runningScriptsWidget); | ||
| 3240 | slideAnimation->setStartValue(_runningScriptsWidget->geometry()); | ||
| 3241 | slideAnimation->setEndValue(QRect(_window->geometry().topLeft().x(), _window->geometry().topLeft().y(), | ||
| 3242 | 0, _runningScriptsWidget->height())); | ||
| 3243 | slideAnimation->setDuration(250); | ||
| 3244 | slideAnimation->start(QAbstractAnimation::DeleteWhenStopped); | ||
| 3245 | |||
| 3246 | QTimer::singleShot(260, _runningScriptsWidget->toggleViewAction(), SLOT(trigger())); | ||
| 3247 | } | ||
| 3248 | } | ||
| 3249 | |||
| 3250 | void Application::uploadFST(bool isHead) { | ||
| 3251 | ModelUploader* uploader = new ModelUploader(isHead); | ||
| 3252 | if (uploader->zip()) { | ||
| 3253 | uploader->send(); | ||
| 3544 | } | 3254 | } |
| 3545 | } | 3255 | } |
| 3546 | 3256 | ||
| 3547 | void Application::removeScriptName(const QString& fileNameString) { | 3257 | void Application::uploadHead() { |
| 3548 | _activeScripts.removeOne(fileNameString); | 3258 | uploadFST(true); |
| 3549 | } | 3259 | } |
| 3550 | 3260 | ||
| 3551 | void Application::cleanupScriptMenuItem(const QString& scriptMenuName) { | 3261 | void Application::uploadSkeleton() { |
| 3552 | Menu::getInstance()->removeAction(Menu::getInstance()->getActiveScriptsMenu(), scriptMenuName); | 3262 | uploadFST(false); |
| 3553 | } | 3263 | } |
| 3554 | 3264 | ||
| 3555 | void Application::loadScript(const QString& scriptName) { | 3265 | void Application::loadScript(const QString& scriptName) { |
| 3556 | 3266 | ||
| 3557 | // start the script on a new thread... | 3267 | // start the script on a new thread... |
| 3558 | bool wantMenuItems = true; // tells the ScriptEngine object to add menu items for itself | 3268 | ScriptEngine* scriptEngine = new ScriptEngine(QUrl(scriptName), &_controllerScriptingInterface); |
| 3559 | ScriptEngine* scriptEngine = new ScriptEngine(QUrl(scriptName), wantMenuItems, &_controllerScriptingInterface); | 3269 | _scriptEnginesHash.insert(scriptName, scriptEngine); |
| 3560 | 3270 | ||
| 3561 | if (!scriptEngine->hasScript()) { | 3271 | if (!scriptEngine->hasScript()) { |
| 3562 | qDebug() << "Application::loadScript(), script failed to load..."; | 3272 | qDebug() << "Application::loadScript(), script failed to load..."; |
| 3563 | return; | 3273 | return; |
| 3564 | } | 3274 | } |
| 3565 | _activeScripts.append(scriptName); | 3275 | _runningScriptsWidget->setRunningScripts(getRunningScripts()); |
| 3566 | |||
| 3567 | // add a stop menu item | ||
| 3568 | Menu::getInstance()->addActionToQMenuAndActionHash(Menu::getInstance()->getActiveScriptsMenu(), | ||
| 3569 | scriptEngine->getScriptMenuName(), 0, scriptEngine, SLOT(stop())); | ||
| 3570 | 3276 | ||
| 3571 | // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so | 3277 | // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so |
| 3572 | // we can use the same ones from the application. | 3278 | // we can use the same ones from the application. |
| @@ -3574,7 +3280,7 @@ void Application::loadScript(const QString& scriptName) { · 1 unmodified line | |||
| 3574 | scriptEngine->getVoxelsScriptingInterface()->setVoxelTree(_voxels.getTree()); | 3280 | scriptEngine->getVoxelsScriptingInterface()->setVoxelTree(_voxels.getTree()); |
| 3575 | scriptEngine->getParticlesScriptingInterface()->setPacketSender(&_particleEditSender); | 3281 | scriptEngine->getParticlesScriptingInterface()->setPacketSender(&_particleEditSender); |
| 3576 | scriptEngine->getParticlesScriptingInterface()->setParticleTree(_particles.getTree()); | 3282 | scriptEngine->getParticlesScriptingInterface()->setParticleTree(_particles.getTree()); |
| 3577 | 3283 | ||
| 3578 | // hook our avatar object into this script engine | 3284 | // hook our avatar object into this script engine |
| 3579 | scriptEngine->setAvatarData(_myAvatar, "MyAvatar"); // leave it as a MyAvatar class to expose thrust features | 3285 | scriptEngine->setAvatarData(_myAvatar, "MyAvatar"); // leave it as a MyAvatar class to expose thrust features |
| 3580 | 3286 | ||
| @@ -3599,8 +3305,6 @@ void Application::loadScript(const QString& scriptName) { · 18 unmodified lines | |||
| 3599 | // when the thread is terminated, add both scriptEngine and thread to the deleteLater queue | 3305 | // when the thread is terminated, add both scriptEngine and thread to the deleteLater queue |
| 3600 | connect(scriptEngine, SIGNAL(finished(const QString&)), scriptEngine, SLOT(deleteLater())); | 3306 | connect(scriptEngine, SIGNAL(finished(const QString&)), scriptEngine, SLOT(deleteLater())); |
| 3601 | connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); | 3307 | connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); |
| 3602 | connect(scriptEngine, SIGNAL(finished(const QString&)), this, SLOT(removeScriptName(const QString&))); | ||
| 3603 | connect(scriptEngine, SIGNAL(cleanupMenuItem(const QString&)), this, SLOT(cleanupScriptMenuItem(const QString&))); | ||
| 3604 | 3308 | ||
| 3605 | // when the application is about to quit, stop our script engine so it unwinds properly | 3309 | // when the application is about to quit, stop our script engine so it unwinds properly |
| 3606 | connect(this, SIGNAL(aboutToQuit()), scriptEngine, SLOT(stop())); | 3310 | connect(this, SIGNAL(aboutToQuit()), scriptEngine, SLOT(stop())); |
| @@ -3615,13 +3319,21 @@ void Application::loadScript(const QString& scriptName) { · 8 unmodified lines | |||
| 3615 | } | 3319 | } |
| 3616 | 3320 | ||
| 3617 | void Application::loadDialog() { | 3321 | void Application::loadDialog() { |
| 3618 | // shut down and stop any existing script | 3322 | QString suggestedName; |
| 3619 | QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); | 3323 | |
| 3620 | QString suggestedName = desktopLocation.append("/script.js"); | 3324 | if (_previousScriptLocation.isEmpty()) { |
| 3325 | QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); | ||
| 3326 | suggestedName = desktopLocation.append("/script.js"); | ||
| 3327 | } else { | ||
| 3328 | suggestedName = _previousScriptLocation; | ||
| 3329 | } | ||
| 3621 | 3330 | ||
| 3622 | QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Open Script"), suggestedName, | 3331 | QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Open Script"), suggestedName, |
| 3623 | tr("JavaScript Files (*.js)")); | 3332 | tr("JavaScript Files (*.js)")); |
| 3624 | 3333 | if (!fileNameString.isEmpty()) { | |
| 3334 | _previousScriptLocation = fileNameString; | ||
| 3335 | } | ||
| 3336 | |||
| 3625 | loadScript(fileNameString); | 3337 | loadScript(fileNameString); |
| 3626 | } | 3338 | } |
| 3627 | 3339 | ||
| @@ -3632,7 +3344,7 @@ void Application::loadScriptURLDialog() { · 4 unmodified lines | |||
| 3632 | scriptURLDialog.setLabelText("Script:"); | 3344 | scriptURLDialog.setLabelText("Script:"); |
| 3633 | scriptURLDialog.setWindowFlags(Qt::Sheet); | 3345 | scriptURLDialog.setWindowFlags(Qt::Sheet); |
| 3634 | const float DIALOG_RATIO_OF_WINDOW = 0.30f; | 3346 | const float DIALOG_RATIO_OF_WINDOW = 0.30f; |
| 3635 | scriptURLDialog.resize(scriptURLDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, | 3347 | scriptURLDialog.resize(scriptURLDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, |
| 3636 | scriptURLDialog.size().height()); | 3348 | scriptURLDialog.size().height()); |
| 3637 | 3349 | ||
| 3638 | int dialogReturn = scriptURLDialog.exec(); | 3350 | int dialogReturn = scriptURLDialog.exec(); |
| @@ -3670,29 +3382,29 @@ void Application::checkVersion() { · 31 unmodified lines | |||
| 3670 | } | 3382 | } |
| 3671 | 3383 | ||
| 3672 | void Application::parseVersionXml() { | 3384 | void Application::parseVersionXml() { |
| 3673 | 3385 | ||
| 3674 | #ifdef Q_OS_WIN32 | 3386 | #ifdef Q_OS_WIN32 |
| 3675 | QString operatingSystem("win"); | 3387 | QString operatingSystem("win"); |
| 3676 | #endif | 3388 | #endif |
| 3677 | 3389 | ||
| 3678 | #ifdef Q_OS_MAC | 3390 | #ifdef Q_OS_MAC |
| 3679 | QString operatingSystem("mac"); | 3391 | QString operatingSystem("mac"); |
| 3680 | #endif | 3392 | #endif |
| 3681 | 3393 | ||
| 3682 | #ifdef Q_OS_LINUX | 3394 | #ifdef Q_OS_LINUX |
| 3683 | QString operatingSystem("ubuntu"); | 3395 | QString operatingSystem("ubuntu"); |
| 3684 | #endif | 3396 | #endif |
| 3685 | 3397 | ||
| 3686 | QString releaseDate; | 3398 | QString releaseDate; |
| 3687 | QString releaseNotes; | 3399 | QString releaseNotes; |
| 3688 | QString latestVersion; | 3400 | QString latestVersion; |
| 3689 | QUrl downloadUrl; | 3401 | QUrl downloadUrl; |
| 3690 | QObject* sender = QObject::sender(); | 3402 | QObject* sender = QObject::sender(); |
| 3691 | 3403 | ||
| 3692 | QXmlStreamReader xml(qobject_cast<QNetworkReply*>(sender)); | 3404 | QXmlStreamReader xml(qobject_cast<QNetworkReply*>(sender)); |
| 3693 | while (!xml.atEnd() && !xml.hasError()) { | 3405 | while (!xml.atEnd() && !xml.hasError()) { |
| 3694 | QXmlStreamReader::TokenType token = xml.readNext(); | 3406 | QXmlStreamReader::TokenType token = xml.readNext(); |
| 3695 | 3407 | ||
| 3696 | if (token == QXmlStreamReader::StartElement) { | 3408 | if (token == QXmlStreamReader::StartElement) { |
| 3697 | if (xml.name() == "ReleaseDate") { | 3409 | if (xml.name() == "ReleaseDate") { |
| 3698 | xml.readNext(); | 3410 | xml.readNext(); |