diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 3b4300b6fd..8fe618b70d 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -175,9 +175,6 @@ AssignmentClient::~AssignmentClient() { void AssignmentClient::aboutToQuit() { stopAssignmentClient(); - - // clear the log handler so that Qt doesn't call the destructor on LogHandler - qInstallMessageHandler(0); } void AssignmentClient::setUpStatusToMonitor() { diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index c425a239dd..68e7b9b997 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -45,9 +45,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : setApplicationName("assignment-client"); setApplicationVersion(BuildInfo::VERSION); - // use the verbose message handler in Logging - qInstallMessageHandler(LogHandler::verboseMessageHandler); - // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity Assignment Client"); diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 8ba253d549..1ee876ceea 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -126,9 +126,6 @@ void AssignmentClientMonitor::stopChildProcesses() { void AssignmentClientMonitor::aboutToQuit() { stopChildProcesses(); - - // clear the log handler so that Qt doesn't call the destructor on LogHandler - qInstallMessageHandler(0); } void AssignmentClientMonitor::spawnChildClient() { diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 052c4755f8..cf8d9ebe31 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -9,8 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - +#include #include #include "AssignmentClientApp.h" @@ -18,10 +17,14 @@ int main(int argc, char* argv[]) { disableQtBearerPoll(); // Fixes wifi ping spikes + qInstallMessageHandler(LogHandler::verboseMessageHandler); + qInfo() << "Starting."; + AssignmentClientApp app(argc, argv); int acReturn = app.exec(); qDebug() << "assignment-client process" << app.applicationPid() << "exiting with status code" << acReturn; - + + qInfo() << "Quitting."; return acReturn; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8b73b851b2..d13f9b883f 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -72,13 +72,10 @@ DomainServer::DomainServer(int argc, char* argv[]) : _iceServerPort(ICE_SERVER_DEFAULT_PORT) { parseCommandLine(); - qInstallMessageHandler(LogHandler::verboseMessageHandler); LogUtils::init(); Setting::init(); - connect(this, &QCoreApplication::aboutToQuit, this, &DomainServer::aboutToQuit); - setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); setOrganizationDomain("highfidelity.io"); setApplicationName("domain-server"); @@ -211,6 +208,7 @@ void DomainServer::parseCommandLine() { } DomainServer::~DomainServer() { + qInfo() << "Domain Server is shutting down."; // destroy the LimitedNodeList before the DomainServer QCoreApplication is down DependencyManager::destroy(); } @@ -223,12 +221,6 @@ void DomainServer::queuedQuit(QString quitMessage, int exitCode) { QCoreApplication::exit(exitCode); } -void DomainServer::aboutToQuit() { - - // clear the log handler so that Qt doesn't call the destructor on LogHandler - qInstallMessageHandler(0); -} - void DomainServer::restart() { qDebug() << "domain-server is restarting."; diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 6330cf51a5..c14ec5eee0 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -72,8 +72,6 @@ public slots: void processICEServerHeartbeatACK(QSharedPointer message); private slots: - void aboutToQuit(); - void setupPendingAssignmentCredits(); void sendPendingTransactionsToServer(); @@ -150,13 +148,9 @@ private: bool isAuthenticatedRequest(HTTPConnection* connection, const QUrl& url); - void handleTokenRequestFinished(); QNetworkReply* profileRequestGivenTokenReply(QNetworkReply* tokenReply); - void handleProfileRequestFinished(); Headers setupCookieHeadersFromProfileReply(QNetworkReply* profileReply); - void loadExistingSessionsFromSettings(); - QJsonObject jsonForSocket(const HifiSockAddr& socket); QJsonObject jsonObjectForNode(const SharedNodePointer& node); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index b3b5c8b9be..fdf7a598aa 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -15,8 +15,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include #include @@ -29,6 +27,9 @@ int main(int argc, char* argv[]) { setvbuf(stdout, NULL, _IOLBF, 0); #endif + qInstallMessageHandler(LogHandler::verboseMessageHandler); + qInfo() << "Starting."; + int currentExitCode = 0; // use a do-while to handle domain-server restart @@ -37,7 +38,7 @@ int main(int argc, char* argv[]) { currentExitCode = domainServer.exec(); } while (currentExitCode == DomainServer::EXIT_CODE_REBOOT); - + qInfo() << "Quitting."; return currentExitCode; } diff --git a/ice-server/src/main.cpp b/ice-server/src/main.cpp index 2326984668..ec8b9957cf 100644 --- a/ice-server/src/main.cpp +++ b/ice-server/src/main.cpp @@ -19,8 +19,9 @@ int main(int argc, char* argv[]) { #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif - + qInstallMessageHandler(LogHandler::verboseMessageHandler); + qInfo() << "Starting."; IceServer iceServer(argc, argv); return iceServer.exec(); diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 1c5df5c71d..9c55b1ce2d 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -189,6 +189,15 @@ Item { Column { id: octreeCol spacing: 4; x: 4; y: 4; + StatText { + text: " Frame timing:" + } + StatText { + text: " Batch: " + root.batchFrameTime.toFixed(1) + " ms" + } + StatText { + text: " GPU: " + root.gpuFrameTime.toFixed(1) + " ms" + } StatText { text: "Triangles: " + root.triangles + " / Material Switches: " + root.materialSwitches diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 867761e012..8408d2cf46 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1238,7 +1238,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto glInfo = getGLContextData(); properties["gl_info"] = glInfo; + properties["gpu_used_memory"] = (int)BYTES_TO_MB(gpu::Context::getUsedGPUMemory()); properties["gpu_free_memory"] = (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemory()); + properties["gpu_frame_time"] = (float)(qApp->getGPUContext()->getFrameTimerGPUAverage()); + properties["batch_frame_time"] = (float)(qApp->getGPUContext()->getFrameTimerBatchAverage()); properties["ideal_thread_count"] = QThread::idealThreadCount(); auto hmdHeadPose = getHMDSensorPose(); @@ -1654,7 +1657,8 @@ Application::~Application() { _window->deleteLater(); - qInstallMessageHandler(nullptr); // NOTE: Do this as late as possible so we continue to get our log messages + // Can't log to file passed this point, FileLogger about to be deleted + qInstallMessageHandler(LogHandler::verboseMessageHandler); } void Application::initializeGL() { @@ -3378,13 +3382,31 @@ void Application::loadSettings() { // If there is a preferred plugin, we probably messed it up with the menu settings, so fix it. auto pluginManager = PluginManager::getInstance(); auto plugins = pluginManager->getPreferredDisplayPlugins(); - for (auto plugin : plugins) { - auto menu = Menu::getInstance(); - if (auto action = menu->getActionForOption(plugin->getName())) { - action->setChecked(true); - action->trigger(); - // Find and activated highest priority plugin, bail for the rest - break; + auto menu = Menu::getInstance(); + if (plugins.size() > 0) { + for (auto plugin : plugins) { + if (auto action = menu->getActionForOption(plugin->getName())) { + action->setChecked(true); + action->trigger(); + // Find and activated highest priority plugin, bail for the rest + break; + } + } + } else { + // If this is our first run, and no preferred devices were set, default to + // an HMD device if available. + Setting::Handle firstRun { Settings::firstRun, true }; + if (firstRun.get()) { + auto displayPlugins = pluginManager->getDisplayPlugins(); + for (auto& plugin : displayPlugins) { + if (plugin->isHmd()) { + if (auto action = menu->getActionForOption(plugin->getName())) { + action->setChecked(true); + action->trigger(); + break; + } + } + } } } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 05632cb1e6..edf72d9758 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -290,6 +290,12 @@ void Stats::updateStats(bool force) { STAT_UPDATE(sendingMode, sendingModeResult); } + auto gpuContext = qApp->getGPUContext(); + + // Update Frame timing (in ms) + STAT_UPDATE(gpuFrameTime, (float)gpuContext->getFrameTimerGPUAverage()); + STAT_UPDATE(batchFrameTime, (float)gpuContext->getFrameTimerBatchAverage()); + STAT_UPDATE(gpuBuffers, (int)gpu::Context::getBufferGPUCount()); STAT_UPDATE(gpuBufferMemory, (int)BYTES_TO_MB(gpu::Context::getBufferGPUMemoryUsage())); STAT_UPDATE(gpuTextures, (int)gpu::Context::getTextureGPUCount()); @@ -302,7 +308,7 @@ void Stats::updateStats(bool force) { STAT_UPDATE(gpuTextureVirtualMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUVirtualMemoryUsage())); STAT_UPDATE(gpuTextureFramebufferMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUFramebufferMemoryUsage())); STAT_UPDATE(gpuTextureSparseMemory, (int)BYTES_TO_MB(gpu::Texture::getTextureGPUSparseMemoryUsage())); - STAT_UPDATE(gpuSparseTextureEnabled, qApp->getGPUContext()->getBackend()->isTextureManagementSparseEnabled() ? 1 : 0); + STAT_UPDATE(gpuSparseTextureEnabled, gpuContext->getBackend()->isTextureManagementSparseEnabled() ? 1 : 0); STAT_UPDATE(gpuFreeMemory, (int)BYTES_TO_MB(gpu::Context::getFreeGPUMemory())); STAT_UPDATE(rectifiedTextureCount, (int)RECTIFIED_TEXTURE_COUNT.load()); STAT_UPDATE(decimatedTextureCount, (int)DECIMATED_TEXTURE_COUNT.load()); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 76c6effed7..ffa5c08bc6 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -101,6 +101,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, gpuTextureSparseMemory, 0) STATS_PROPERTY(int, gpuSparseTextureEnabled, 0) STATS_PROPERTY(int, gpuFreeMemory, 0) + STATS_PROPERTY(float, gpuFrameTime, 0) + STATS_PROPERTY(float, batchFrameTime, 0) public: static Stats* getInstance(); @@ -198,6 +200,8 @@ signals: void gpuTextureSparseMemoryChanged(); void gpuSparseTextureEnabledChanged(); void gpuFreeMemoryChanged(); + void gpuFrameTimeChanged(); + void batchFrameTimeChanged(); void rectifiedTextureCountChanged(); void decimatedTextureCountChanged(); diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index a379ebd80a..0fd8ff595f 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -228,9 +228,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints) } } -#ifndef NDEBUG -#define DUMP_FBX_JOINTS -void AnimSkeleton::dump() const { +void AnimSkeleton::dump(bool verbose) const { qCDebug(animation) << "["; for (int i = 0; i < getNumJoints(); i++) { qCDebug(animation) << " {"; @@ -240,24 +238,24 @@ void AnimSkeleton::dump() const { qCDebug(animation) << " relBindPose =" << getRelativeBindPose(i); qCDebug(animation) << " absDefaultPose =" << getAbsoluteDefaultPose(i); qCDebug(animation) << " relDefaultPose =" << getRelativeDefaultPose(i); -#ifdef DUMP_FBX_JOINTS - qCDebug(animation) << " fbxJoint ="; - qCDebug(animation) << " isFree =" << _joints[i].isFree; - qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage; - qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex; - qCDebug(animation) << " translation =" << _joints[i].translation; - qCDebug(animation) << " preTransform =" << _joints[i].preTransform; - qCDebug(animation) << " preRotation =" << _joints[i].preRotation; - qCDebug(animation) << " rotation =" << _joints[i].rotation; - qCDebug(animation) << " postRotation =" << _joints[i].postRotation; - qCDebug(animation) << " postTransform =" << _joints[i].postTransform; - qCDebug(animation) << " transform =" << _joints[i].transform; - qCDebug(animation) << " rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax; - qCDebug(animation) << " inverseDefaultRotation" << _joints[i].inverseDefaultRotation; - qCDebug(animation) << " inverseBindRotation" << _joints[i].inverseBindRotation; - qCDebug(animation) << " bindTransform" << _joints[i].bindTransform; - qCDebug(animation) << " isSkeletonJoint" << _joints[i].isSkeletonJoint; -#endif + if (verbose) { + qCDebug(animation) << " fbxJoint ="; + qCDebug(animation) << " isFree =" << _joints[i].isFree; + qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage; + qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex; + qCDebug(animation) << " translation =" << _joints[i].translation; + qCDebug(animation) << " preTransform =" << _joints[i].preTransform; + qCDebug(animation) << " preRotation =" << _joints[i].preRotation; + qCDebug(animation) << " rotation =" << _joints[i].rotation; + qCDebug(animation) << " postRotation =" << _joints[i].postRotation; + qCDebug(animation) << " postTransform =" << _joints[i].postTransform; + qCDebug(animation) << " transform =" << _joints[i].transform; + qCDebug(animation) << " rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax; + qCDebug(animation) << " inverseDefaultRotation" << _joints[i].inverseDefaultRotation; + qCDebug(animation) << " inverseBindRotation" << _joints[i].inverseBindRotation; + qCDebug(animation) << " bindTransform" << _joints[i].bindTransform; + qCDebug(animation) << " isSkeletonJoint" << _joints[i].isSkeletonJoint; + } if (getParentIndex(i) >= 0) { qCDebug(animation) << " parent =" << getJointName(getParentIndex(i)); } @@ -284,4 +282,4 @@ void AnimSkeleton::dump(const AnimPoseVec& poses) const { } qCDebug(animation) << "]"; } -#endif + diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index e1c6ae95c8..f588c14f90 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -63,10 +63,8 @@ public: void mirrorRelativePoses(AnimPoseVec& poses) const; void mirrorAbsolutePoses(AnimPoseVec& poses) const; -#ifndef NDEBUG - void dump() const; + void dump(bool verbose) const; void dump(const AnimPoseVec& poses) const; -#endif protected: void buildSkeletonFromJoints(const std::vector& joints); diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index ab6bba178a..4344cd4d2c 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -34,6 +34,10 @@ void Context::beginFrame(const glm::mat4& renderPose) { _frameActive = true; _currentFrame = std::make_shared(); _currentFrame->pose = renderPose; + + if (!_frameRangeTimer) { + _frameRangeTimer = std::make_shared(); + } } void Context::appendFrameBatch(Batch& batch) { @@ -73,10 +77,18 @@ void Context::executeFrame(const FramePointer& frame) const { consumeFrameUpdates(frame); _backend->setStereoState(frame->stereoState); { + Batch beginBatch; + _frameRangeTimer->begin(beginBatch); + _backend->render(beginBatch); + // Execute the frame rendering commands for (auto& batch : frame->batches) { _backend->render(batch); } + + Batch endBatch; + _frameRangeTimer->end(endBatch); + _backend->render(endBatch); } } @@ -127,6 +139,20 @@ void Context::getStats(ContextStats& stats) const { _backend->getStats(stats); } +double Context::getFrameTimerGPUAverage() const { + if (_frameRangeTimer) { + return _frameRangeTimer->getGPUAverage(); + } + return 0.0; +} + +double Context::getFrameTimerBatchAverage() const { + if (_frameRangeTimer) { + return _frameRangeTimer->getBatchAverage(); + } + return 0.0; +} + const Backend::TransformCamera& Backend::TransformCamera::recomputeDerived(const Transform& xformView) const { _projectionInverse = glm::inverse(_projection); @@ -183,6 +209,10 @@ Size Context::getFreeGPUMemory() { return _freeGPUMemory.load(); } +Size Context::getUsedGPUMemory() { + return getTextureGPUMemoryUsage() + getBufferGPUMemoryUsage(); +}; + void Context::incrementBufferGPUCount() { static std::atomic max { 0 }; auto total = ++_bufferGPUCount; @@ -349,3 +379,5 @@ void Backend::updateTextureGPUFramebufferMemoryUsage(Resource::Size prevObjectSi void Backend::updateTextureGPUSparseMemoryUsage(Resource::Size prevObjectSize, Resource::Size newObjectSize) { Context::updateTextureGPUSparseMemoryUsage(prevObjectSize, newObjectSize); } void Backend::incrementTextureGPUTransferCount() { Context::incrementTextureGPUTransferCount(); } void Backend::decrementTextureGPUTransferCount() { Context::decrementTextureGPUTransferCount(); } + + diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index e174e9d728..3564655a3d 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -205,12 +205,16 @@ public: void getStats(ContextStats& stats) const; + double getFrameTimerGPUAverage() const; + double getFrameTimerBatchAverage() const; + static uint32_t getBufferGPUCount(); static Size getBufferGPUMemoryUsage(); static uint32_t getTextureGPUCount(); static uint32_t getTextureGPUSparseCount(); static Size getFreeGPUMemory(); + static Size getUsedGPUMemory(); static Size getTextureGPUMemoryUsage(); static Size getTextureGPUVirtualMemoryUsage(); static Size getTextureGPUFramebufferMemoryUsage(); @@ -223,8 +227,12 @@ protected: std::shared_ptr _backend; bool _frameActive { false }; FramePointer _currentFrame; + RangeTimerPointer _frameRangeTimer; StereoState _stereo; + double getGPUAverage() const; + double getBatchAverage() const; + // This function can only be called by "static Shader::makeProgram()" // makeProgramShader(...) make a program shader ready to be used in a Batch. // It compiles the sub shaders, link them and defines the Slots and their bindings. diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index d142e3f839..35a3361c38 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -10,17 +10,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - -#include -#include -#include -#include -#include -#include - #include "LogHandler.h" +#include + +#include +#include +#include +#include +#include +#include +#include + QMutex LogHandler::_mutex; LogHandler& LogHandler::getInstance() { @@ -28,16 +29,15 @@ LogHandler& LogHandler::getInstance() { return staticInstance; } -LogHandler::LogHandler() -{ - // setup our timer to flush the verbose logs every 5 seconds - QTimer* logFlushTimer = new QTimer(this); - connect(logFlushTimer, &QTimer::timeout, this, &LogHandler::flushRepeatedMessages); - logFlushTimer->start(VERBOSE_LOG_INTERVAL_SECONDS * 1000); - +LogHandler::LogHandler() { // when the log handler is first setup we should print our timezone QString timezoneString = "Time zone: " + QDateTime::currentDateTime().toString("t"); - printf("%s\n", qPrintable(timezoneString)); + printMessage(LogMsgType::LogInfo, QMessageLogContext(), timezoneString); +} + +LogHandler::~LogHandler() { + flushRepeatedMessages(); + printMessage(LogMsgType::LogDebug, QMessageLogContext(), "LogHandler shutdown."); } const char* stringForLogType(LogMsgType msgType) { @@ -165,7 +165,7 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont stringForLogType(type), context.category); if (_shouldOutputProcessID) { - prefixString.append(QString(" [%1]").arg(QCoreApplication::instance()->applicationPid())); + prefixString.append(QString(" [%1]").arg(QCoreApplication::applicationPid())); } if (_shouldOutputThreadID) { @@ -187,6 +187,14 @@ void LogHandler::verboseMessageHandler(QtMsgType type, const QMessageLogContext& } const QString& LogHandler::addRepeatedMessageRegex(const QString& regexString) { + static std::once_flag once; + std::call_once(once, [&] { + // setup our timer to flush the verbose logs every 5 seconds + QTimer* logFlushTimer = new QTimer(this); + connect(logFlushTimer, &QTimer::timeout, this, &LogHandler::flushRepeatedMessages); + logFlushTimer->start(VERBOSE_LOG_INTERVAL_SECONDS * 1000); + }); + QMutexLocker lock(&_mutex); return *_repeatedMessageRegexes.insert(regexString); } diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index 890497b891..f80fad4c6a 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -52,8 +52,10 @@ public: const QString& addRepeatedMessageRegex(const QString& regexString); const QString& addOnlyOnceMessageRegex(const QString& regexString); + private: LogHandler(); + ~LogHandler(); void flushRepeatedMessages(); diff --git a/libraries/shared/src/ShutdownEventListener.cpp b/libraries/shared/src/ShutdownEventListener.cpp index e640126b7b..6f043cd43e 100644 --- a/libraries/shared/src/ShutdownEventListener.cpp +++ b/libraries/shared/src/ShutdownEventListener.cpp @@ -9,8 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - #include "ShutdownEventListener.h" #ifdef Q_OS_WIN @@ -19,6 +17,9 @@ #include #endif +#include +#include + ShutdownEventListener& ShutdownEventListener::getInstance() { static ShutdownEventListener staticInstance; return staticInstance; @@ -29,9 +30,7 @@ void signalHandler(int param) { QMetaObject::invokeMethod(qApp, "quit"); } -ShutdownEventListener::ShutdownEventListener(QObject* parent) : - QObject(parent) -{ +ShutdownEventListener::ShutdownEventListener(QObject* parent) : QObject(parent) { #ifndef Q_OS_WIN // be a signal handler for SIGTERM so we can stop our children when we get it signal(SIGTERM, signalHandler); diff --git a/libraries/shared/src/shared/FileLogger.cpp b/libraries/shared/src/shared/FileLogger.cpp index ef3436a8d7..143438ba68 100644 --- a/libraries/shared/src/shared/FileLogger.cpp +++ b/libraries/shared/src/shared/FileLogger.cpp @@ -109,7 +109,8 @@ bool FilePersistThread::processQueueItems(const Queue& messages) { } FileLogger::FileLogger(QObject* parent) : - AbstractLoggerInterface(parent), _fileName(getLogFilename()) + AbstractLoggerInterface(parent), + _fileName(getLogFilename()) { _persistThreadInstance = new FilePersistThread(*this); _persistThreadInstance->initialize(true, QThread::LowestPriority); diff --git a/libraries/shared/src/shared/FileLogger.h b/libraries/shared/src/shared/FileLogger.h index 697b96c6d8..f0f6dd5c09 100644 --- a/libraries/shared/src/shared/FileLogger.h +++ b/libraries/shared/src/shared/FileLogger.h @@ -24,7 +24,7 @@ public: FileLogger(QObject* parent = NULL); virtual ~FileLogger(); - QString getFilename() { return _fileName; } + QString getFilename() const { return _fileName; } virtual void addMessage(const QString&) override; virtual QString getLogData() override; virtual void locateLog() override; diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index d6d9098e21..4fe13196f3 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -445,13 +445,11 @@ function hideUserDataTextArea() { }; function showStaticUserData() { - $('#static-userdata').show(); - $('#static-userdata').css('height', $('#userdata-editor').height()) if (editor !== null) { + $('#static-userdata').show(); + $('#static-userdata').css('height', $('#userdata-editor').height()) $('#static-userdata').text(editor.getText()); } - - }; function removeStaticUserData() { diff --git a/server-console/src/main.js b/server-console/src/main.js index 6c82230601..a7855ab063 100644 --- a/server-console/src/main.js +++ b/server-console/src/main.js @@ -623,6 +623,7 @@ function checkNewContent() { } else { // They don't want to update, mark content set as current userConfig.set('homeContentLastModified', new Date()); + userConfig.save(configPath); } }); } @@ -676,6 +677,7 @@ function maybeInstallDefaultContentSet(onComplete) { } log.debug('Copied home content over to: ' + getRootHifiDataDirectory()); userConfig.set('homeContentLastModified', new Date()); + userConfig.save(configPath); onComplete(); }); return; @@ -756,6 +758,7 @@ function maybeInstallDefaultContentSet(onComplete) { // response and decompression complete, return log.debug("Finished unarchiving home content set"); userConfig.set('homeContentLastModified', new Date()); + userConfig.save(configPath); sendStateUpdate('complete'); }); @@ -766,6 +769,7 @@ function maybeInstallDefaultContentSet(onComplete) { }); userConfig.set('hasRun', true); + userConfig.save(configPath); }); } diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index cf0e25a757..a85a112bf5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -13,3 +13,7 @@ set_target_properties(ice-client PROPERTIES FOLDER "Tools") add_subdirectory(ac-client) set_target_properties(ac-client PROPERTIES FOLDER "Tools") + +add_subdirectory(skeleton-dump) +set_target_properties(skeleton-dump PROPERTIES FOLDER "Tools") + diff --git a/tools/skeleton-dump/CMakeLists.txt b/tools/skeleton-dump/CMakeLists.txt new file mode 100644 index 0000000000..04d450d9c2 --- /dev/null +++ b/tools/skeleton-dump/CMakeLists.txt @@ -0,0 +1,4 @@ +set(TARGET_NAME skeleton-dump) +setup_hifi_project(Core Widgets) +link_hifi_libraries(shared fbx model gpu gl animation) + diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.cpp b/tools/skeleton-dump/src/SkeletonDumpApp.cpp new file mode 100644 index 0000000000..e9d8243e38 --- /dev/null +++ b/tools/skeleton-dump/src/SkeletonDumpApp.cpp @@ -0,0 +1,63 @@ +// +// SkeletonDumpApp.cpp +// tools/skeleton-dump/src +// +// Created by Anthony Thibault on 11/4/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SkeletonDumpApp.h" +#include +#include +#include +#include + +SkeletonDumpApp::SkeletonDumpApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { + + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity FBX Skeleton Analyzer"); + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption verboseOutput("v", "verbose output"); + parser.addOption(verboseOutput); + + const QCommandLineOption inputFilenameOption("i", "input file", "filename.fbx"); + parser.addOption(inputFilenameOption); + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + _returnCode = 1; + return; + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + return; + } + + bool verbose = parser.isSet(verboseOutput); + + QString inputFilename; + if (parser.isSet(inputFilenameOption)) { + inputFilename = parser.value(inputFilenameOption); + } + + QFile file(inputFilename); + if (!file.open(QIODevice::ReadOnly)) { + qCritical() << "Failed to open file " << inputFilename; + _returnCode = 2; + return; + } + QByteArray blob = file.readAll(); + std::unique_ptr fbxGeometry(readFBX(blob, QVariantHash())); + std::unique_ptr skeleton(new AnimSkeleton(*fbxGeometry)); + skeleton->dump(verbose); +} + +SkeletonDumpApp::~SkeletonDumpApp() { +} diff --git a/tools/skeleton-dump/src/SkeletonDumpApp.h b/tools/skeleton-dump/src/SkeletonDumpApp.h new file mode 100644 index 0000000000..40df98eb65 --- /dev/null +++ b/tools/skeleton-dump/src/SkeletonDumpApp.h @@ -0,0 +1,29 @@ +// +// SkeletonDumpApp.h +// tools/skeleton-dump/src +// +// Created by Anthony Thibault on 11/4/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SkeletonDumpApp_h +#define hifi_SkeletonDumpApp_h + +#include + +class SkeletonDumpApp : public QCoreApplication { + Q_OBJECT +public: + SkeletonDumpApp(int argc, char* argv[]); + ~SkeletonDumpApp(); + + int getReturnCode() const { return _returnCode; } + +private: + int _returnCode { 0 }; +}; + +#endif //hifi_SkeletonDumpApp_h diff --git a/tools/skeleton-dump/src/main.cpp b/tools/skeleton-dump/src/main.cpp new file mode 100644 index 0000000000..6cf4d41f31 --- /dev/null +++ b/tools/skeleton-dump/src/main.cpp @@ -0,0 +1,22 @@ +// +// main.cpp +// tools/skeleton-dump/src +// +// Created by Anthony Thibault on 11/4/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include +#include +#include +#include +#include + +#include "SkeletonDumpApp.h" + +int main(int argc, char * argv[]) { + SkeletonDumpApp app(argc, argv); + return app.getReturnCode(); +} diff --git a/tutorial/tutorial.js b/tutorial/tutorial.js index 3d2b4ce36b..957316734a 100644 --- a/tutorial/tutorial.js +++ b/tutorial/tutorial.js @@ -233,7 +233,7 @@ function playSuccessSound() { function playFirecrackerSound(position) { Audio.playSound(firecrackerSound, { position: position, - volume: 0.7, + volume: 0.5, loop: false }); }