diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 8fe618b70d..c5024055c0 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -49,8 +48,6 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri { LogUtils::init(); - QSettings::setDefaultFormat(QSettings::IniFormat); - DependencyManager::set(); auto scriptableAvatar = DependencyManager::set(); diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 68e7b9b997..90d759dffa 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -40,11 +39,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : ShutdownEventListener::getInstance(); # endif - setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); - setOrganizationDomain("highfidelity.io"); - setApplicationName("assignment-client"); - setApplicationVersion(BuildInfo::VERSION); - // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity Assignment Client"); diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index cf8d9ebe31..4f64bf8f7f 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -13,10 +13,16 @@ #include #include "AssignmentClientApp.h" +#include int main(int argc, char* argv[]) { disableQtBearerPoll(); // Fixes wifi ping spikes + QCoreApplication::setApplicationName(BuildInfo::ASSIGNMENT_CLIENT_NAME); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + qInstallMessageHandler(LogHandler::verboseMessageHandler); qInfo() << "Starting."; diff --git a/cmake/templates/BuildInfo.h.in b/cmake/templates/BuildInfo.h.in index 3d388a907f..b0af1c0524 100644 --- a/cmake/templates/BuildInfo.h.in +++ b/cmake/templates/BuildInfo.h.in @@ -1,6 +1,6 @@ // // BuildInfo.h.in -// cmake/macros +// cmake/templates // // Created by Stephen Birarda on 1/14/16. // Copyright 2015 High Fidelity, Inc. @@ -11,10 +11,19 @@ #define USE_STABLE_GLOBAL_SERVICES @USE_STABLE_GLOBAL_SERVICES@ +#include + namespace BuildInfo { + // WARNING: This file has been auto-generated. + // Check cmake/templates/BuildInfo.h.in if you want to modify it. + + const QString INTERFACE_NAME = "Interface"; + const QString ASSIGNMENT_CLIENT_NAME = "assignment-client"; + const QString DOMAIN_SERVER_NAME = "domain-server"; + const QString AC_CLIENT_SERVER_NAME = "ac-client"; const QString MODIFIED_ORGANIZATION = "@BUILD_ORGANIZATION@"; + const QString ORGANIZATION_DOMAIN = "highfidelity.io"; const QString VERSION = "@BUILD_VERSION@"; const QString BUILD_BRANCH = "@BUILD_BRANCH@"; const QString BUILD_GLOBAL_SERVICES = "@BUILD_GLOBAL_SERVICES@"; } - diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 6668ed54dc..711a5b6fc2 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -76,14 +76,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : LogUtils::init(); Setting::init(); - setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); - setOrganizationDomain("highfidelity.io"); - setApplicationName("domain-server"); - setApplicationVersion(BuildInfo::VERSION); - QSettings::setDefaultFormat(QSettings::IniFormat); - qDebug() << "Setting up domain-server"; - qDebug() << "[VERSION] Build sequence:" << qPrintable(applicationVersion()); qDebug() << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION; qDebug() << "[VERSION] VERSION:" << BuildInfo::VERSION; diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 21214ed5f6..18a46e0658 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DomainServerSettingsManager.h" + #include #include @@ -16,23 +18,21 @@ #include #include #include -#include #include #include #include -#include #include +#include #include #include #include #include #include +#include #include "DomainServerNodeData.h" -#include "DomainServerSettingsManager.h" - const QString SETTINGS_DESCRIPTION_RELATIVE_PATH = "/resources/describe-settings.json"; const QString DESCRIPTION_SETTINGS_KEY = "settings"; @@ -43,6 +43,8 @@ const QString DESCRIPTION_COLUMNS_KEY = "columns"; const QString SETTINGS_VIEWPOINT_KEY = "viewpoint"; +static Setting::Handle JSON_SETTING_VERSION("json-settings/version", 0.0); + DomainServerSettingsManager::DomainServerSettingsManager() : _descriptionArray(), _configMap() @@ -103,9 +105,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList // What settings version were we before and what are we using now? // Do we need to do any re-mapping? - QSettings appSettings; - const QString JSON_SETTINGS_VERSION_KEY = "json-settings/version"; - double oldVersion = appSettings.value(JSON_SETTINGS_VERSION_KEY, 0.0).toDouble(); + double oldVersion = JSON_SETTING_VERSION.get(); if (oldVersion != _descriptionVersion) { const QString ALLOWED_USERS_SETTINGS_KEYPATH = "security.allowed_users"; @@ -301,7 +301,7 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList unpackPermissions(); // write the current description version to our settings - appSettings.setValue(JSON_SETTINGS_VERSION_KEY, _descriptionVersion); + JSON_SETTING_VERSION.set(_descriptionVersion); } QVariantMap& DomainServerSettingsManager::getDescriptorsMap() { diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index fcc3e9d91d..06ad7decd1 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -21,6 +22,8 @@ #include #include "NodePermissions.h" +#include + const QString SETTINGS_PATHS_KEY = "paths"; const QString SETTINGS_PATH = "/settings"; diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index fdf7a598aa..725a04ec46 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -17,12 +17,18 @@ #include #include +#include #include "DomainServer.h" int main(int argc, char* argv[]) { disableQtBearerPoll(); // Fixes wifi ping spikes + QCoreApplication::setApplicationName(BuildInfo::DOMAIN_SERVER_NAME); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index e32df6bc62..868a2cf933 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -166,6 +166,7 @@ if (WIN32) add_dependency_external_projects(OpenVR) add_dependency_external_projects(neuron) add_dependency_external_projects(wasapi) + add_dependency_external_projects(steamworks) endif() # disable /OPT:REF and /OPT:ICF for the Debug builds @@ -175,10 +176,6 @@ if (WIN32) set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG "/OPT:NOREF /OPT:NOICF") endif() -if (NOT ANDROID) - set(NON_ANDROID_LIBRARIES steamworks-wrapper) -endif () - # link required hifi libraries link_hifi_libraries( shared octree gpu gl gpu-gl procedural model render diff --git a/interface/resources/info/ApplicationInfo.ini b/interface/resources/info/ApplicationInfo.ini deleted file mode 100644 index 1a7142cb76..0000000000 --- a/interface/resources/info/ApplicationInfo.ini +++ /dev/null @@ -1,4 +0,0 @@ -[INFO] -name=Interface -organizationName=High Fidelity -organizationDomain=highfidelity.io \ No newline at end of file diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml new file mode 100644 index 0000000000..ffb42d2fff --- /dev/null +++ b/interface/resources/qml/hifi/NameCard.qml @@ -0,0 +1,36 @@ +// +// NameCard.qml +// qml/hifi +// +// Created by Howard Stearns on 12/9/2016 +// 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 +// + +import Hifi 1.0 +import QtQuick 2.5 +import "../styles-uit" + + +Column { + property string displayName: ""; + property string userName: ""; + property int displayTextHeight: 18; + property int usernameTextHeight: 12; + + RalewaySemiBold { + text: parent.displayName; + size: parent.displayTextHeight; + elide: Text.ElideRight; + width: parent.width; + } + RalewayLight { + visible: parent.displayName; + text: parent.userName; + size: parent.usernameTextHeight; + elide: Text.ElideRight; + width: parent.width; + } +} diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml new file mode 100644 index 0000000000..382b8fc962 --- /dev/null +++ b/interface/resources/qml/hifi/Pal.qml @@ -0,0 +1,207 @@ +// +// Pal.qml +// qml/hifi +// +// People Action List +// +// Created by Howard Stearns on 12/12/2016 +// 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 +// + +/* TODO: + + prototype: + - only show kick/mute when canKick + - margins everywhere + - column head centering + - column head font + - proper button .svg on toolbar + + mvp: + - Show all participants, including ignored, and populate initial ignore/mute status. + - If name is elided, hover should scroll name left so the full name can be read. + + */ + +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Rectangle { + id: pal; + property int keepFromHorizontalScroll: 1; + width: parent.width - keepFromHorizontalScroll; + height: parent.height; + + property int nameWidth: width/2; + property int actionWidth: nameWidth / (table.columnCount - 1); + property int rowHeight: 50; + property var userData: []; + property var myData: ({displayName: "", userName: ""}); // valid dummy until set + property bool iAmAdmin: false; + function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml + var i, data = optionalData || userData, length = data.length; + for (var i = 0; i < length; i++) { + if (data[i].sessionId === sessionId) { + return i; + } + } + return -1; + } + function fromScript(message) { + switch (message.method) { + case 'users': + var data = message.params; + var myIndex = findSessionIndex('', data); + iAmAdmin = Users.canKick; + myData = data[myIndex]; + data.splice(myIndex, 1); + userData = data; + sortModel(); + break; + case 'select': + var sessionId = message.params[0]; + var selected = message.params[1]; + var userIndex = findSessionIndex(sessionId); + if (selected) { + table.selection.clear(); // for now, no multi-select + table.selection.select(userIndex); + } else { + table.selection.deselect(userIndex); + } + break; + default: + console.log('Unrecognized message:', JSON.stringify(message)); + } + } + ListModel { + id: userModel + } + function sortModel() { + var sortProperty = table.getColumn(table.sortIndicatorColumn).role; + var before = (table.sortIndicatorOrder === Qt.AscendingOrder) ? -1 : 1; + var after = -1 * before; + userData.sort(function (a, b) { + var aValue = a[sortProperty].toString().toLowerCase(), bValue = b[sortProperty].toString().toLowerCase(); + switch (true) { + case (aValue < bValue): return before; + case (aValue > bValue): return after; + default: return 0; + } + }); + table.selection.clear(); + userModel.clear(); + var userIndex = 0; + userData.forEach(function (datum) { + function init(property) { + if (datum[property] === undefined) { + datum[property] = false; + } + } + ['ignore', 'spacer', 'mute', 'kick'].forEach(init); + datum.userIndex = userIndex++; + userModel.append(datum); + }); + } + signal sendToScript(var message); + function noticeSelection() { + var userIds = []; + table.selection.forEach(function (userIndex) { + userIds.push(userData[userIndex].sessionId); + }); + pal.sendToScript({method: 'selected', params: userIds}); + } + Connections { + target: table.selection + onSelectionChanged: pal.noticeSelection() + } + + Column { + NameCard { + id: myCard; + width: nameWidth; + displayName: myData.displayName; + userName: myData.userName; + } + TableView { + id: table; + TableViewColumn { + role: "displayName"; + title: "Name"; + width: nameWidth + } + TableViewColumn { + role: "ignore"; + title: "Ignore" + width: actionWidth + } + TableViewColumn { + title: ""; + width: actionWidth + } + TableViewColumn { + visible: iAmAdmin; + role: "mute"; + title: "Mute"; + width: actionWidth + } + TableViewColumn { + visible: iAmAdmin; + role: "kick"; + title: "Ban" + width: actionWidth + } + model: userModel; + rowDelegate: Rectangle { // The only way I know to specify a row height. + height: rowHeight; + // The rest of this is cargo-culted to restore the default styling + SystemPalette { + id: myPalette; + colorGroup: SystemPalette.Active + } + color: { + var baseColor = styleData.alternate?myPalette.alternateBase:myPalette.base + return styleData.selected?myPalette.highlight:baseColor + } + } + itemDelegate: Item { + id: itemCell; + property bool isCheckBox: typeof(styleData.value) === 'boolean'; + NameCard { + id: nameCard; + visible: !isCheckBox; + width: nameWidth; + displayName: styleData.value; + userName: model.userName; + } + Rectangle { + radius: itemCell.height / 4; + visible: isCheckBox; + color: styleData.value ? "green" : "red"; + anchors.fill: parent; + MouseArea { + anchors.fill: parent; + acceptedButtons: Qt.LeftButton; + hoverEnabled: true; + onClicked: { + var newValue = !model[styleData.role]; + var datum = userData[model.userIndex]; + datum[styleData.role] = model[styleData.role] = newValue; + Users[styleData.role](model.sessionId); + // Just for now, while we cannot undo things: + userData.splice(model.userIndex, 1); + sortModel(); + } + } + } + } + height: pal.height - myCard.height; + width: pal.width; + sortIndicatorVisible: true; + onSortIndicatorColumnChanged: sortModel(); + onSortIndicatorOrderChanged: sortModel(); + } + } +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8c3e3fad73..10801776fa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -90,20 +90,21 @@ #include #include #include +#include #include #include -#include +#include #include #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -416,10 +417,11 @@ bool setupEssentials(int& argc, char** argv) { const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); const int listenPort = portStr ? atoi(portStr) : INVALID_PORT; - // Set build version - QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + Setting::init(); - Setting::preInit(); + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->init(); + } #if defined(Q_OS_WIN) // Select appropriate audio DLL @@ -441,8 +443,6 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); - Setting::init(); - // Set dependencies DependencyManager::set(std::bind(&Application::getUserAgent, qApp)); DependencyManager::set(); @@ -551,7 +551,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _maxOctreePPS(maxOctreePacketsPerSecond.get()), _lastFaceTrackerUpdate(0) { - setProperty(hifi::properties::STEAM, SteamClient::isRunning()); + auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); + setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); { @@ -606,7 +607,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _deadlockWatchdogThread = new DeadlockWatchdogThread(); _deadlockWatchdogThread->start(); - qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << SteamClient::getSteamVRBuildID(); + if (steamClient) { + qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << steamClient->getSteamVRBuildID(); + } qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion()); qCDebug(interfaceapp) << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION; qCDebug(interfaceapp) << "[VERSION] VERSION:" << BuildInfo::VERSION; @@ -1695,6 +1698,10 @@ Application::~Application() { Leapmotion::destroy(); + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->shutdown(); + } + #if 0 ConnexionClient::getInstance().destroy(); #endif @@ -1739,10 +1746,14 @@ void Application::initializeGL() { // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; _renderEngine->addJob("RenderShadowTask", cullFunctor); - _renderEngine->addJob("RenderDeferredTask", cullFunctor); + static const QString RENDER_FORWARD = "RENDER_FORWARD"; + if (QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD)) { + _renderEngine->addJob("RenderForwardTask", cullFunctor); + } else { + _renderEngine->addJob("RenderDeferredTask", cullFunctor); + } _renderEngine->load(); _renderEngine->registerScene(_main3DScene); - // TODO: Load a cached config file // The UI can't be created until the primary OpenGL // context is created, because it needs to share @@ -1838,6 +1849,7 @@ void Application::initializeUi() { rootContext->setContextProperty("Assets", new AssetMappingsScriptingInterface()); rootContext->setContextProperty("AvatarList", DependencyManager::get().data()); + rootContext->setContextProperty("Users", DependencyManager::get().data()); rootContext->setContextProperty("Camera", &_myCamera); @@ -1874,8 +1886,10 @@ void Application::initializeUi() { rootContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor()); - rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine)); - + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + rootContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get())); + } + _glWidget->installEventFilter(offscreenUi.data()); offscreenUi->setMouseTranslator([=](const QPointF& pt) { @@ -3201,7 +3215,9 @@ void Application::idle(float nsecsElapsed) { PROFILE_RANGE(__FUNCTION__); - SteamClient::runCallbacks(); + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->runCallbacks(); + } float secondsSinceLastUpdate = nsecsElapsed / NSECS_PER_MSEC / MSECS_PER_SECOND; @@ -3533,12 +3549,16 @@ void Application::init() { _timerStart.start(); _lastTimeUpdated.start(); - // when +connect_lobby in command line, join steam lobby - const QString STEAM_LOBBY_COMMAND_LINE_KEY = "+connect_lobby"; - int lobbyIndex = arguments().indexOf(STEAM_LOBBY_COMMAND_LINE_KEY); - if (lobbyIndex != -1) { - QString lobbyId = arguments().value(lobbyIndex + 1); - SteamClient::joinLobby(lobbyId); + + + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + // when +connect_lobby in command line, join steam lobby + const QString STEAM_LOBBY_COMMAND_LINE_KEY = "+connect_lobby"; + int lobbyIndex = arguments().indexOf(STEAM_LOBBY_COMMAND_LINE_KEY); + if (lobbyIndex != -1) { + QString lobbyId = arguments().value(lobbyIndex + 1); + steamClient->joinLobby(lobbyId); + } } @@ -5202,8 +5222,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine)); - + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine, steamClient.get())); + } auto scriptingInterface = DependencyManager::get(); scriptEngine->registerGlobalObject("Controller", scriptingInterface.data()); UserInputMapper::registerControllerTypes(scriptEngine); diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index 0c9698ffc3..b254cd58de 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -18,19 +18,18 @@ #include #include #include -#include #include #include #include #include "Application.h" #include "Menu.h" +#include #include bool CrashHandler::checkForResetSettings(bool suppressPrompt) { - QSettings::setDefaultFormat(QSettings::IniFormat); - QSettings settings; + Settings settings; settings.beginGroup("Developer"); QVariant displayCrashOptions = settings.value(MenuOption::DisplayCrashOptions); QVariant askToResetSettingsOption = settings.value(MenuOption::AskToResetSettings); @@ -110,8 +109,7 @@ void CrashHandler::handleCrash(CrashHandler::Action action) { return; } - QSettings::setDefaultFormat(QSettings::IniFormat); - QSettings settings; + Settings settings; const QString ADDRESS_MANAGER_GROUP = "AddressManager"; const QString ADDRESS_KEY = "address"; const QString AVATAR_GROUP = "Avatar"; diff --git a/interface/src/DiscoverabilityManager.cpp b/interface/src/DiscoverabilityManager.cpp index eb9a7c7f6d..8fcc1e5477 100644 --- a/interface/src/DiscoverabilityManager.cpp +++ b/interface/src/DiscoverabilityManager.cpp @@ -15,7 +15,8 @@ #include #include #include -#include +#include +#include #include #include @@ -111,7 +112,9 @@ void DiscoverabilityManager::updateLocation() { } // Update Steam - SteamClient::updateLocation(domainHandler.getHostname(), addressManager->currentFacingShareableAddress()); + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->updateLocation(domainHandler.getHostname(), addressManager->currentFacingShareableAddress()); + } } void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply) { diff --git a/interface/src/Util.h b/interface/src/Util.h index e3938502d2..60e38ae0ec 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -14,7 +14,6 @@ #include #include -#include #include diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1b1bd9f30d..9547d769fa 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -57,7 +57,6 @@ using namespace std; -const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f); const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f; const float MAX_WALKING_SPEED = 2.6f; // human walking speed diff --git a/interface/src/main.cpp b/interface/src/main.cpp index a88388050b..c83f7a989c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -15,14 +15,13 @@ #include #include #include -#include #include #include +#include #include #include -#include #include "AddressManager.h" #include "Application.h" @@ -32,7 +31,6 @@ #include #ifdef HAS_BUGSPLAT -#include #include #include #endif @@ -51,7 +49,13 @@ int main(int argc, const char* argv[]) { #endif disableQtBearerPoll(); // Fixes wifi ping spikes - + + // Set application infos + QCoreApplication::setApplicationName(BuildInfo::INTERFACE_NAME); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + QString applicationName = "High Fidelity Interface - " + qgetenv("USERNAME"); bool instanceMightBeRunning = true; @@ -129,8 +133,10 @@ int main(int argc, const char* argv[]) { } QCommandLineParser parser; + QCommandLineOption checkMinSpecOption("checkMinSpec", "Check if machine meets minimum specifications"); QCommandLineOption runServerOption("runServer", "Whether to run the server"); QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath"); + parser.addOption(checkMinSpecOption); parser.addOption(runServerOption); parser.addOption(serverContentPathOption); parser.parse(arguments); @@ -157,11 +163,9 @@ int main(int argc, const char* argv[]) { // or in the main window ctor, before GL startup. Application::initPlugins(arguments); - SteamClient::init(); - #ifdef Q_OS_WIN // If we're running in steam mode, we need to do an explicit check to ensure we're up to the required min spec - if (SteamClient::isRunning()) { + if (parser.isSet(checkMinSpecOption)) { QString appPath; { char filename[MAX_PATH]; @@ -183,7 +187,6 @@ int main(int argc, const char* argv[]) { int exitCode; { - QSettings::setDefaultFormat(QSettings::IniFormat); Application app(argc, const_cast(argv), startupTime, runServer, serverContentPathOptionValue); // If we failed the OpenGLVersion check, log it. @@ -245,8 +248,6 @@ int main(int argc, const char* argv[]) { Application::shutdownPlugins(); - SteamClient::shutdown(); - qCDebug(interfaceapp, "Normal exit."); #if !defined(DEBUG) && !defined(Q_OS_LINUX) // HACK: exit immediately (don't handle shutdown callbacks) for Release build diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index d27c3e907a..e333bb1b88 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -17,7 +17,8 @@ #include #include -#include +#include +#include #include "AccountManager.h" #include "DependencyManager.h" @@ -56,7 +57,8 @@ void LoginDialog::toggleAction() { } bool LoginDialog::isSteamRunning() const { - return SteamClient::isRunning(); + auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); + return steamClient && steamClient->isRunning(); } void LoginDialog::login(const QString& username, const QString& password) const { @@ -66,69 +68,75 @@ void LoginDialog::login(const QString& username, const QString& password) const void LoginDialog::loginThroughSteam() { qDebug() << "Attempting to login through Steam"; - SteamClient::requestTicket([this](Ticket ticket) { - if (ticket.isNull()) { - emit handleLoginFailed(); - return; - } + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->requestTicket([this](Ticket ticket) { + if (ticket.isNull()) { + emit handleLoginFailed(); + return; + } - DependencyManager::get()->requestAccessTokenWithSteam(ticket); - }); + DependencyManager::get()->requestAccessTokenWithSteam(ticket); + }); + } } void LoginDialog::linkSteam() { qDebug() << "Attempting to link Steam account"; - SteamClient::requestTicket([this](Ticket ticket) { - if (ticket.isNull()) { - emit handleLoginFailed(); - return; - } + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->requestTicket([this](Ticket ticket) { + if (ticket.isNull()) { + emit handleLoginFailed(); + return; + } - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; - callbackParams.jsonCallbackMethod = "linkCompleted"; - callbackParams.errorCallbackReceiver = this; - callbackParams.errorCallbackMethod = "linkFailed"; + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "linkCompleted"; + callbackParams.errorCallbackReceiver = this; + callbackParams.errorCallbackMethod = "linkFailed"; - const QString LINK_STEAM_PATH = "api/v1/user/steam/link"; + const QString LINK_STEAM_PATH = "api/v1/user/steam/link"; - QJsonObject payload; - payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); + QJsonObject payload; + payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); - auto accountManager = DependencyManager::get(); - accountManager->sendRequest(LINK_STEAM_PATH, AccountManagerAuth::Required, - QNetworkAccessManager::PostOperation, callbackParams, - QJsonDocument(payload).toJson()); - }); + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(LINK_STEAM_PATH, AccountManagerAuth::Required, + QNetworkAccessManager::PostOperation, callbackParams, + QJsonDocument(payload).toJson()); + }); + } } void LoginDialog::createAccountFromStream(QString username) { qDebug() << "Attempting to create account from Steam info"; - SteamClient::requestTicket([this, username](Ticket ticket) { - if (ticket.isNull()) { - emit handleLoginFailed(); - return; - } + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->requestTicket([this, username](Ticket ticket) { + if (ticket.isNull()) { + emit handleLoginFailed(); + return; + } - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; - callbackParams.jsonCallbackMethod = "createCompleted"; - callbackParams.errorCallbackReceiver = this; - callbackParams.errorCallbackMethod = "createFailed"; + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "createCompleted"; + callbackParams.errorCallbackReceiver = this; + callbackParams.errorCallbackMethod = "createFailed"; - const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/steam/create"; + const QString CREATE_ACCOUNT_FROM_STEAM_PATH = "api/v1/user/steam/create"; - QJsonObject payload; - payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); - if (!username.isEmpty()) { - payload.insert("username", QJsonValue::fromVariant(QVariant(username))); - } + QJsonObject payload; + payload.insert("steam_auth_ticket", QJsonValue::fromVariant(QVariant(ticket))); + if (!username.isEmpty()) { + payload.insert("username", QJsonValue::fromVariant(QVariant(username))); + } - auto accountManager = DependencyManager::get(); - accountManager->sendRequest(CREATE_ACCOUNT_FROM_STEAM_PATH, AccountManagerAuth::None, - QNetworkAccessManager::PostOperation, callbackParams, - QJsonDocument(payload).toJson()); - }); + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(CREATE_ACCOUNT_FROM_STEAM_PATH, AccountManagerAuth::None, + QNetworkAccessManager::PostOperation, callbackParams, + QJsonDocument(payload).toJson()); + }); + } } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 2c6440094b..a4cb62cc13 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -292,23 +292,24 @@ void setupPreferences() { { static const QString RENDER("Graphics"); auto renderConfig = qApp->getRenderEngine()->getConfiguration(); + if (renderConfig) { + auto ambientOcclusionConfig = renderConfig->getConfig(); + if (ambientOcclusionConfig) { + auto getter = [ambientOcclusionConfig]()->QString { return ambientOcclusionConfig->getPreset(); }; + auto setter = [ambientOcclusionConfig](QString preset) { ambientOcclusionConfig->setPreset(preset); }; + auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter); + preference->setItems(ambientOcclusionConfig->getPresetList()); + preferences->addPreference(preference); + } - auto ambientOcclusionConfig = renderConfig->getConfig(); - { - auto getter = [ambientOcclusionConfig]()->QString { return ambientOcclusionConfig->getPreset(); }; - auto setter = [ambientOcclusionConfig](QString preset) { ambientOcclusionConfig->setPreset(preset); }; - auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter); - preference->setItems(ambientOcclusionConfig->getPresetList()); - preferences->addPreference(preference); - } - - auto shadowConfig = renderConfig->getConfig(); - { - auto getter = [shadowConfig]()->QString { return shadowConfig->getPreset(); }; - auto setter = [shadowConfig](QString preset) { shadowConfig->setPreset(preset); }; - auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter); - preference->setItems(shadowConfig->getPresetList()); - preferences->addPreference(preference); + auto shadowConfig = renderConfig->getConfig(); + if (shadowConfig) { + auto getter = [shadowConfig]()->QString { return shadowConfig->getPreset(); }; + auto setter = [shadowConfig](QString preset) { shadowConfig->setPreset(preset); }; + auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter); + preference->setItems(shadowConfig->getPresetList()); + preferences->addPreference(preference); + } } } { diff --git a/interface/src/ui/SnapshotAnimated.cpp b/interface/src/ui/SnapshotAnimated.cpp index 62dbc7aea4..cf89504d92 100644 --- a/interface/src/ui/SnapshotAnimated.cpp +++ b/interface/src/ui/SnapshotAnimated.cpp @@ -55,10 +55,6 @@ void SnapshotAnimated::saveSnapshotAnimated(QString pathStill, float aspectRatio // Start the snapshotAnimatedTimer QTimer - argument for this is in milliseconds SnapshotAnimated::snapshotAnimatedTimerRunning = true; SnapshotAnimated::snapshotAnimatedTimer->start(SNAPSNOT_ANIMATED_FRAME_DELAY_MSEC); - // If we're already in the middle of capturing an animated snapshot... - } else { - // Just tell the dependency manager that the capture of the still snapshot has taken place. - emit dm->snapshotTaken(pathStill, "", false); } } @@ -88,9 +84,6 @@ void SnapshotAnimated::captureFrames() { // If that was the last frame... if ((SnapshotAnimated::snapshotAnimatedTimestamp - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp) >= (SnapshotAnimated::snapshotAnimatedDuration.get() * MSECS_PER_SECOND)) { SnapshotAnimated::snapshotAnimatedTimerRunning = false; - // Reset the current frame timestamp - SnapshotAnimated::snapshotAnimatedTimestamp = 0; - SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp = 0; // Notify the user that we're processing the snapshot emit SnapshotAnimated::snapshotAnimatedDM->processingGif(); @@ -136,7 +129,10 @@ void SnapshotAnimated::processFrames() { SnapshotAnimated::snapshotAnimatedFrameVector.squeeze(); SnapshotAnimated::snapshotAnimatedFrameDelayVector.clear(); SnapshotAnimated::snapshotAnimatedFrameDelayVector.squeeze(); + // Reset the current frame timestamp + SnapshotAnimated::snapshotAnimatedTimestamp = 0; + SnapshotAnimated::snapshotAnimatedFirstFrameTimestamp = 0; - // Let the dependency manager know that the snapshots have been taken. + // Let the window scripting interface know that the snapshots have been taken. emit SnapshotAnimated::snapshotAnimatedDM->snapshotTaken(SnapshotAnimated::snapshotStillPath, SnapshotAnimated::snapshotAnimatedPath, false); } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 45790524d1..49363c96e2 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -973,10 +973,6 @@ void Rig::updateFromEyeParameters(const EyeParameters& params) { params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); } -static const glm::vec3 X_AXIS(1.0f, 0.0f, 0.0f); -static const glm::vec3 Y_AXIS(0.0f, 1.0f, 0.0f); -static const glm::vec3 Z_AXIS(0.0f, 0.0f, 1.0f); - void Rig::computeHeadNeckAnimVars(const AnimPose& hmdPose, glm::vec3& headPositionOut, glm::quat& headOrientationOut, glm::vec3& neckPositionOut, glm::quat& neckOrientationOut) const { diff --git a/libraries/auto-updater/src/AutoUpdater.h b/libraries/auto-updater/src/AutoUpdater.h index 70867e5a44..1e62ce0283 100644 --- a/libraries/auto-updater/src/AutoUpdater.h +++ b/libraries/auto-updater/src/AutoUpdater.h @@ -12,8 +12,6 @@ #ifndef hifi_AutoUpdater_h #define hifi_AutoUpdater_h - -#include #include #include #include diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 240c722872..8583b59c89 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -105,7 +105,7 @@ QUrl AddressManager::currentFacingShareableAddress() const { void AddressManager::loadSettings(const QString& lookupString) { if (lookupString.isEmpty()) { - handleUrl(currentAddressHandle.get().toString(), LookupTrigger::StartupFromSettings); + handleUrl(currentAddressHandle.get(), LookupTrigger::StartupFromSettings); } else { handleUrl(lookupString, LookupTrigger::StartupFromSettings); } diff --git a/libraries/plugins/src/plugins/Forward.h b/libraries/plugins/src/plugins/Forward.h index 723c4f321e..b95bf4c2e6 100644 --- a/libraries/plugins/src/plugins/Forward.h +++ b/libraries/plugins/src/plugins/Forward.h @@ -19,6 +19,7 @@ enum class PluginType { class DisplayPlugin; class InputPlugin; class CodecPlugin; +class SteamClientPlugin; class Plugin; class PluginContainer; class PluginManager; @@ -29,4 +30,4 @@ using InputPluginPointer = std::shared_ptr; using InputPluginList = std::vector; using CodecPluginPointer = std::shared_ptr; using CodecPluginList = std::vector; - +using SteamClientPluginPointer = std::shared_ptr; diff --git a/libraries/plugins/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp index 21e652dc40..75b0f1e3bc 100644 --- a/libraries/plugins/src/plugins/PluginManager.cpp +++ b/libraries/plugins/src/plugins/PluginManager.cpp @@ -147,6 +147,22 @@ const CodecPluginList& PluginManager::getCodecPlugins() { return codecPlugins; } +const SteamClientPluginPointer PluginManager::getSteamClientPlugin() { + static SteamClientPluginPointer steamClientPlugin; + static std::once_flag once; + std::call_once(once, [&] { + // Now grab the dynamic plugins + for (auto loader : getLoadedPlugins()) { + SteamClientProvider* steamClientProvider = qobject_cast(loader->instance()); + if (steamClientProvider) { + steamClientPlugin = steamClientProvider->getSteamClientPlugin(); + break; + } + } + }); + return steamClientPlugin; +} + #ifndef Q_OS_ANDROID // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class diff --git a/libraries/plugins/src/plugins/PluginManager.h b/libraries/plugins/src/plugins/PluginManager.h index 83aad7abcd..687e5c9e9b 100644 --- a/libraries/plugins/src/plugins/PluginManager.h +++ b/libraries/plugins/src/plugins/PluginManager.h @@ -19,6 +19,7 @@ public: const DisplayPluginList& getDisplayPlugins(); const InputPluginList& getInputPlugins(); const CodecPluginList& getCodecPlugins(); + const SteamClientPluginPointer getSteamClientPlugin(); DisplayPluginList getPreferredDisplayPlugins(); void setPreferredDisplayPlugins(const QStringList& displays); diff --git a/libraries/plugins/src/plugins/RuntimePlugin.h b/libraries/plugins/src/plugins/RuntimePlugin.h index bb6f0251c2..9a7d6e0638 100644 --- a/libraries/plugins/src/plugins/RuntimePlugin.h +++ b/libraries/plugins/src/plugins/RuntimePlugin.h @@ -45,3 +45,11 @@ public: #define CodecProvider_iid "com.highfidelity.plugins.codec" Q_DECLARE_INTERFACE(CodecProvider, CodecProvider_iid) +class SteamClientProvider { +public: + virtual ~SteamClientProvider() {} + virtual SteamClientPluginPointer getSteamClientPlugin() = 0; +}; + +#define SteamClientProvider_iid "com.highfidelity.plugins.steamclient" +Q_DECLARE_INTERFACE(SteamClientProvider, SteamClientProvider_iid) diff --git a/libraries/plugins/src/plugins/SteamClientPlugin.h b/libraries/plugins/src/plugins/SteamClientPlugin.h new file mode 100644 index 0000000000..f87ebd2e66 --- /dev/null +++ b/libraries/plugins/src/plugins/SteamClientPlugin.h @@ -0,0 +1,59 @@ +// +// SteamClientPlugin.h +// libraries/plugins/src/plugins +// +// Created by Clement Brisset on 12/14/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_SteamClientPlugin_h +#define hifi_SteamClientPlugin_h + +#include + +#include +#include + +using Ticket = QByteArray; +using TicketRequestCallback = std::function; + +class SteamClientPlugin { +public: + virtual ~SteamClientPlugin() {}; + + virtual bool init() = 0; + virtual void shutdown() = 0; + + virtual bool isRunning() = 0; + + virtual void runCallbacks() = 0; + + virtual void requestTicket(TicketRequestCallback callback) = 0; + virtual void updateLocation(QString status, QUrl locationUrl) = 0; + virtual void openInviteOverlay() = 0; + virtual void joinLobby(QString lobbyId) = 0; + + virtual int getSteamVRBuildID() = 0; +}; + +class SteamScriptingInterface : public QObject { + Q_OBJECT + + Q_PROPERTY(bool isRunning READ isRunning) + +public: + SteamScriptingInterface(QObject* parent, SteamClientPlugin* plugin) : QObject(parent) {} + + public slots: + bool isRunning() const { return _plugin->isRunning(); } + void openInviteOverlay() const { _plugin->openInviteOverlay(); } + +private: + SteamClientPlugin* _plugin; +}; + +#endif /* hifi_SteamClientPlugin_h */ diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/DeferredLighting.slh b/libraries/render-utils/src/DeferredLighting.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index ed0ed8d04d..50499cf31a 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -58,7 +58,6 @@ float frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) return (-eposZ - rangeNear) / (rangeFar - rangeNear); } - vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) { vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0], epos.y * projection[1][1] + epos.z * projection[2][1], @@ -126,15 +125,11 @@ int frustumGrid_eyeDepthToClusterLayer(float eyeZ) { } ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { - if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) { - return ivec3(-2); - } - - if (eyePos.z > -frustumGrid.rangeNear) { - return ivec3(0,0,-1); - } - - vec3 volumePos = frustumGrid_eyeToVolume(eyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); + + // make sure the frontEyePos is always in the front to eval the grid pos correctly + vec3 frontEyePos = eyePos; + frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z); + vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims); @@ -143,10 +138,20 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { gridPos.z = frustumGrid.dims.z; } + ivec3 igridPos = ivec3(floor(gridPos)); - return ivec3(floor(gridPos)); + if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) { + return ivec3(igridPos.x, igridPos.y, - 2); + } + + if (eyePos.z > -frustumGrid.rangeNear) { + return ivec3(igridPos.x, igridPos.y, -1); + } + + return igridPos; } + int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { return (eyeDir.x > 0 ? frustumGrid.dims.x : -1); diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 8dc95da65b..b9ba309fd5 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -279,6 +279,7 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan // FInd the light origin cluster auto centerCluster = grid.frustumGrid_eyeToClusterPos(glm::vec3(eyePosRadius)); + int center_z = centerCluster.z; int center_y = centerCluster.y; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp new file mode 100755 index 0000000000..da7fcf5cdd --- /dev/null +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -0,0 +1,163 @@ + +// +// RenderForwardTask.cpp +// render-utils/src/ +// +// Created by Zach Pomerantz on 12/13/2016. +// 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 "RenderForwardTask.h" +#include "RenderDeferredTask.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "LightingModel.h" +#include "DebugDeferredBuffer.h" +#include "DeferredFramebuffer.h" +#include "DeferredLightingEffect.h" +#include "SurfaceGeometryPass.h" +#include "FramebufferCache.h" +#include "HitEffect.h" +#include "TextureCache.h" + +#include "AmbientOcclusionEffect.h" +#include "AntialiasingEffect.h" +#include "ToneMappingEffect.h" +#include "SubsurfaceScattering.h" + +#include + +#include "drawOpaqueStencil_frag.h" + + +using namespace render; +extern void initOverlay3DPipelines(render::ShapePlumber& plumber); +extern void initDeferredPipelines(render::ShapePlumber& plumber); + +RenderForwardTask::RenderForwardTask(CullFunctor cullFunctor) { + // Prepare the ShapePipelines + ShapePlumberPointer shapePlumber = std::make_shared(); + initDeferredPipelines(*shapePlumber); + + // CPU jobs: + // Fetch and cull the items from the scene + const auto spatialSelection = addJob("FetchSceneSelection"); + + cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; + auto spatialFilter = ItemFilter::Builder::visibleWorldItems().withoutLayered(); + const auto culledSpatialSelection = addJob("CullSceneSelection", spatialSelection, cullFunctor, RenderDetails::ITEM, spatialFilter); + + // Overlays are not culled + const auto nonspatialSelection = addJob("FetchOverlaySelection"); + + // Multi filter visible items into different buckets + const int NUM_FILTERS = 3; + const int OPAQUE_SHAPE_BUCKET = 0; + const int TRANSPARENT_SHAPE_BUCKET = 1; + const int LIGHT_BUCKET = 2; + const int BACKGROUND_BUCKET = 2; + MultiFilterItem::ItemFilterArray spatialFilters = { { + ItemFilter::Builder::opaqueShape(), + ItemFilter::Builder::transparentShape(), + ItemFilter::Builder::light() + } }; + MultiFilterItem::ItemFilterArray nonspatialFilters = { { + ItemFilter::Builder::opaqueShape(), + ItemFilter::Builder::transparentShape(), + ItemFilter::Builder::background() + } }; + const auto filteredSpatialBuckets = addJob>("FilterSceneSelection", culledSpatialSelection, spatialFilters).get::ItemBoundsArray>(); + const auto filteredNonspatialBuckets = addJob>("FilterOverlaySelection", nonspatialSelection, nonspatialFilters).get::ItemBoundsArray>(); + + // Extract / Sort opaques / Transparents / Lights / Overlays + const auto opaques = addJob("DepthSortOpaque", filteredSpatialBuckets[OPAQUE_SHAPE_BUCKET]); + const auto transparents = addJob("DepthSortTransparent", filteredSpatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); + const auto lights = filteredSpatialBuckets[LIGHT_BUCKET]; + + const auto overlayOpaques = addJob("DepthSortOverlayOpaque", filteredNonspatialBuckets[OPAQUE_SHAPE_BUCKET]); + const auto overlayTransparents = addJob("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); + const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET]; + + const auto framebuffer = addJob("PrepareFramebuffer"); + + // Blit! + addJob("Blit", framebuffer); +} + +void RenderForwardTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + // sanity checks + assert(sceneContext); + if (!sceneContext->_scene) { + return; + } + + + // Is it possible that we render without a viewFrustum ? + if (!(renderContext->args && renderContext->args->hasViewFrustum())) { + return; + } + + auto config = std::static_pointer_cast(renderContext->jobConfig); + + for (auto job : _jobs) { + job.run(sceneContext, renderContext); + } +} + +void PrepareFramebuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { + auto framebufferCache = DependencyManager::get(); + auto framebufferSize = framebufferCache->getFrameBufferSize(); + glm::uvec2 frameSize(framebufferSize.width(), framebufferSize.height()); + + // Resizing framebuffers instead of re-building them seems to cause issues with threaded rendering + if (_framebuffer && _framebuffer->getSize() != frameSize) { + _framebuffer.reset(); + } + + if (!_framebuffer) { + _framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("forward")); + + auto colorFormat = gpu::Element::COLOR_SRGBA_32; + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + auto colorTexture = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, frameSize.x, frameSize.y, defaultSampler)); + _framebuffer->setRenderBuffer(0, colorTexture); + + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format + auto depthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, frameSize.x, frameSize.y, defaultSampler)); + _framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); + } + + auto args = renderContext->args; + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + batch.setFramebuffer(_framebuffer); + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_COLOR0 | + gpu::Framebuffer::BUFFER_COLOR1 | + gpu::Framebuffer::BUFFER_COLOR2 | + gpu::Framebuffer::BUFFER_COLOR3 | + gpu::Framebuffer::BUFFER_DEPTH | + gpu::Framebuffer::BUFFER_STENCIL, + vec4(vec3(0), 0), 1.0, 0.0, true); + }); + + framebuffer = _framebuffer; +} diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h new file mode 100755 index 0000000000..9c4634a8ee --- /dev/null +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -0,0 +1,42 @@ +// +// RenderForwardTask.h +// render-utils/src/ +// +// Created by Zach Pomerantz on 12/13/2016. +// 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_RenderForwardTask_h +#define hifi_RenderForwardTask_h + +#include +#include +#include "LightingModel.h" + +using RenderForwardTaskConfig = render::GPUTaskConfig; + +class RenderForwardTask : public render::Task { +public: + using Config = RenderForwardTaskConfig; + RenderForwardTask(render::CullFunctor cullFunctor); + + void configure(const Config& config) {} + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + + using JobModel = Model; +}; + +class PrepareFramebuffer { +public: + using JobModel = render::Job::ModelO; + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer); + +private: + gpu::FramebufferPointer _framebuffer; +}; + +#endif // hifi_RenderForwardTask_h diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slv b/libraries/render-utils/src/model_lightmap_normal_map.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_shadow.slf b/libraries/render-utils/src/model_shadow.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_shadow.slv b/libraries/render-utils/src/model_shadow.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv old mode 100755 new mode 100644 diff --git a/libraries/render-utils/src/skin_model_shadow.slv b/libraries/render-utils/src/skin_model_shadow.slv old mode 100755 new mode 100644 diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index cb6291a8dc..b3092be55a 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -283,43 +283,6 @@ void ScriptEngines::loadScripts() { // loads all saved scripts Settings settings; - - - // START of backward compatibility code - // This following if statement is only meant to update the settings file still using the old setting key. - // If you read that comment and it has been more than a couple months since it was merged, - // then by all means, feel free to remove it. - if (!settings.childGroups().contains(SETTINGS_KEY)) { - qWarning() << "Detected old script settings config, loading from previous location"; - const QString oldKey = "Settings"; - - // Load old scripts array from settings - int size = settings.beginReadArray(oldKey); - for (int i = 0; i < size; ++i) { - settings.setArrayIndex(i); - QString string = settings.value("script").toString(); - if (!string.isEmpty()) { - loadScript(string); - } - } - settings.endArray(); - - // Cleanup old scripts array from settings - settings.beginWriteArray(oldKey); - for (int i = 0; i < size; ++i) { - settings.setArrayIndex(i); - settings.remove(""); - } - settings.endArray(); - settings.beginGroup(oldKey); - settings.remove("size"); - settings.endGroup(); - - return; - } - // END of backward compatibility code - - int size = settings.beginReadArray(SETTINGS_KEY); for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); diff --git a/libraries/shared/src/SettingHandle.cpp b/libraries/shared/src/SettingHandle.cpp index 13f9ea48ce..626d7e7ef5 100644 --- a/libraries/shared/src/SettingHandle.cpp +++ b/libraries/shared/src/SettingHandle.cpp @@ -19,16 +19,12 @@ const QString Settings::firstRun { "firstRun" }; -Settings::Settings() : - _manager(DependencyManager::get()), - _locker(&(_manager->getLock())) +Settings::Settings() : _manager(DependencyManager::get()) { } -Settings::~Settings() { - if (_prefixes.size() != 0) { - qFatal("Unstable Settings Prefixes: You must call endGroup for every beginGroup and endArray for every begin*Array call"); - } +QString Settings::fileName() const { + return _manager->fileName(); } void Settings::remove(const QString& key) { @@ -53,18 +49,15 @@ bool Settings::contains(const QString& key) const { return _manager->contains(key); } -int Settings::beginReadArray(const QString & prefix) { - _prefixes.push(prefix); +int Settings::beginReadArray(const QString& prefix) { return _manager->beginReadArray(prefix); } void Settings::beginWriteArray(const QString& prefix, int size) { - _prefixes.push(prefix); _manager->beginWriteArray(prefix, size); } void Settings::endArray() { - _prefixes.pop(); _manager->endArray(); } @@ -73,19 +66,15 @@ void Settings::setArrayIndex(int i) { } void Settings::beginGroup(const QString& prefix) { - _prefixes.push(prefix); _manager->beginGroup(prefix); } void Settings::endGroup() { - _prefixes.pop(); _manager->endGroup(); } void Settings::setValue(const QString& name, const QVariant& value) { - if (_manager->value(name) != value) { - _manager->setValue(name, value); - } + _manager->setValue(name, value); } QVariant Settings::value(const QString& name, const QVariant& defaultValue) const { diff --git a/libraries/shared/src/SettingHandle.h b/libraries/shared/src/SettingHandle.h index 5133a9cb2a..54694dfd0a 100644 --- a/libraries/shared/src/SettingHandle.h +++ b/libraries/shared/src/SettingHandle.h @@ -14,7 +14,6 @@ #include -#include #include #include #include @@ -32,7 +31,8 @@ class Settings { public: static const QString firstRun; Settings(); - ~Settings(); + + QString fileName() const; void remove(const QString& key); QStringList childGroups() const; @@ -61,8 +61,6 @@ public: private: QSharedPointer _manager; - QWriteLocker _locker; - QStack _prefixes; }; namespace Setting { diff --git a/libraries/shared/src/SettingHelpers.cpp b/libraries/shared/src/SettingHelpers.cpp new file mode 100644 index 0000000000..f7d2510458 --- /dev/null +++ b/libraries/shared/src/SettingHelpers.cpp @@ -0,0 +1,283 @@ +// +// SettingHelpers.cpp +// libraries/shared/src +// +// Created by Clement on 9/13/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 "SettingHelpers.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +QSettings::SettingsMap jsonDocumentToVariantMap(const QJsonDocument& document); +QJsonDocument variantMapToJsonDocument(const QSettings::SettingsMap& map); + +bool readJSONFile(QIODevice& device, QSettings::SettingsMap& map) { + QJsonParseError jsonParseError; + + auto bytesRead = device.readAll(); + auto document = QJsonDocument::fromJson(bytesRead, &jsonParseError); + + if (jsonParseError.error != QJsonParseError::NoError) { + qDebug() << "Error parsing QSettings file:" << jsonParseError.errorString(); + return false; + } + + map = jsonDocumentToVariantMap(document); + + return true; +} + +bool writeJSONFile(QIODevice& device, const QSettings::SettingsMap& map) { + auto document = variantMapToJsonDocument(map); + auto jsonByteArray = document.toJson(QJsonDocument::Indented); + auto bytesWritten = device.write(jsonByteArray); + return bytesWritten == jsonByteArray.size(); +} + +void loadOldINIFile(QSettings& settings) { + QSettings::setDefaultFormat(QSettings::IniFormat); + + QSettings iniSettings; + if (!iniSettings.allKeys().isEmpty()) { + qDebug() << "No data in json settings file, trying to load old ini settings file."; + + for (auto key : iniSettings.allKeys()) { + auto variant = iniSettings.value(key); + + if (variant.type() == QVariant::String) { + auto string = variant.toString(); + if (string == "true") { + variant = true; + } else if (string == "false") { + variant = false; + } else { + bool ok; + double value = string.toDouble(&ok); + if (ok) { + variant = value; + } + } + } + settings.setValue(key, variant); + } + + qDebug() << "Loaded" << settings.allKeys().size() << "keys from ini settings file."; + } + + QSettings::setDefaultFormat(JSON_FORMAT); +} + +QStringList splitArgs(const QString& string, int idx) { + int length = string.length(); + Q_ASSERT(length > 0); + Q_ASSERT(string.at(idx) == QLatin1Char('(')); + Q_ASSERT(string.at(length - 1) == QLatin1Char(')')); + + QStringList result; + QString item; + + for (++idx; idx < length; ++idx) { + QChar c = string.at(idx); + if (c == QLatin1Char(')')) { + Q_ASSERT(idx == length - 1); + result.append(item); + } else if (c == QLatin1Char(' ')) { + result.append(item); + item.clear(); + } else { + item.append(c); + } + } + + return result; +} + +QJsonDocument variantMapToJsonDocument(const QSettings::SettingsMap& map) { + QJsonObject object; + for (auto it = map.cbegin(); it != map.cend(); ++it) { + auto& key = it.key(); + auto& variant = it.value(); + auto variantType = variant.type(); + + // Switch some types so they are readable/modifiable in the json file + if (variantType == QVariant(1.0f).type()) { // float + variantType = QVariant::Double; + } + if (variantType == QVariant((quint16)0).type()) { // uint16 + variantType = QVariant::UInt; + } + if (variantType == QVariant::Url) { // QUrl + variantType = QVariant::String; + } + + switch (variantType) { + case QVariant::Map: + case QVariant::List: + case QVariant::Hash: { + qCritical() << "Unsupported variant type" << variant.typeName(); + Q_ASSERT(false); + break; + } + + case QVariant::Invalid: + object.insert(key, QJsonValue()); + break; + case QVariant::LongLong: + case QVariant::ULongLong: + case QVariant::Int: + case QVariant::UInt: + case QVariant::Bool: + case QVariant::Double: + object.insert(key, QJsonValue::fromVariant(variant)); + break; + + case QVariant::String: { + QString result = variant.toString(); + if (result.startsWith(QLatin1Char('@'))) { + result.prepend(QLatin1Char('@')); + } + object.insert(key, result); + break; + } + + case QVariant::ByteArray: { + QByteArray a = variant.toByteArray(); + QString result = QLatin1String("@ByteArray("); + result += QString::fromLatin1(a.constData(), a.size()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + case QVariant::Rect: { + QRect r = qvariant_cast(variant); + QString result = QLatin1String("@Rect("); + result += QString::number(r.x()); + result += QLatin1Char(' '); + result += QString::number(r.y()); + result += QLatin1Char(' '); + result += QString::number(r.width()); + result += QLatin1Char(' '); + result += QString::number(r.height()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + case QVariant::Size: { + QSize s = qvariant_cast(variant); + QString result = QLatin1String("@Size("); + result += QString::number(s.width()); + result += QLatin1Char(' '); + result += QString::number(s.height()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + case QVariant::Point: { + QPoint p = qvariant_cast(variant); + QString result = QLatin1String("@Point("); + result += QString::number(p.x()); + result += QLatin1Char(' '); + result += QString::number(p.y()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + + default: { + QByteArray array; + { + QDataStream stream(&array, QIODevice::WriteOnly); + stream.setVersion(QDataStream::Qt_4_0); + stream << variant; + } + + QString result = QLatin1String("@Variant("); + result += QString::fromLatin1(array.constData(), array.size()); + result += QLatin1Char(')'); + object.insert(key, result); + break; + } + } + } + + return QJsonDocument(object); +} + + +QSettings::SettingsMap jsonDocumentToVariantMap(const QJsonDocument& document) { + if (!document.isObject()) { + qWarning() << "Settings file does not contain a JSON object"; + return QSettings::SettingsMap(); + } + auto object = document.object(); + QSettings::SettingsMap map; + + for (auto it = object.begin(); it != object.end(); ++it) { + + QVariant result; + + if (!it->isString()) { + result = it->toVariant(); + } else { + auto string = it->toString(); + + if (string.startsWith(QLatin1String("@@"))) { // Standard string starting with '@' + result = QVariant(string.mid(1)); + + } else if (string.startsWith(QLatin1Char('@'))) { // Custom type to string + + if (string.endsWith(QLatin1Char(')'))) { + + if (string.startsWith(QLatin1String("@ByteArray("))) { + result = QVariant(string.toLatin1().mid(11, string.size() - 12)); + + } else if (string.startsWith(QLatin1String("@Variant("))) { + QByteArray a(string.toLatin1().mid(9)); + QDataStream stream(&a, QIODevice::ReadOnly); + stream.setVersion(QDataStream::Qt_4_0); + stream >> result; + + } else if (string.startsWith(QLatin1String("@Rect("))) { + QStringList args = splitArgs(string, 5); + if (args.size() == 4) { + result = QRect(args[0].toInt(), args[1].toInt(), + args[2].toInt(), args[3].toInt()); + } + + } else if (string.startsWith(QLatin1String("@Size("))) { + QStringList args = splitArgs(string, 5); + if (args.size() == 2) { + result = QSize(args[0].toInt(), args[1].toInt()); + } + + } else if (string.startsWith(QLatin1String("@Point("))) { + QStringList args = splitArgs(string, 6); + if (args.size() == 2) { + result = QPoint(args[0].toInt(), args[1].toInt()); + } + } + } + } else { // Standard string + result = string; + } + } + + map.insert(it.key(), result); + } + + return map; +} diff --git a/libraries/shared/src/SettingHelpers.h b/libraries/shared/src/SettingHelpers.h new file mode 100644 index 0000000000..122e56957c --- /dev/null +++ b/libraries/shared/src/SettingHelpers.h @@ -0,0 +1,25 @@ +// +// SettingHelpers.h +// libraries/shared/src +// +// Created by Clement on 9/13/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_SettingHelpers_h +#define hifi_SettingHelpers_h + +#include + +bool readJSONFile(QIODevice& device, QSettings::SettingsMap& map); +bool writeJSONFile(QIODevice& device, const QSettings::SettingsMap& map); + +static const auto JSON_FORMAT = QSettings::registerFormat("json", readJSONFile, writeJSONFile); + +void loadOldINIFile(QSettings& settings); + + +#endif // hifi_SettingHelpers_h diff --git a/libraries/shared/src/SettingInterface.cpp b/libraries/shared/src/SettingInterface.cpp index 9db84055f7..01b9f3884f 100644 --- a/libraries/shared/src/SettingInterface.cpp +++ b/libraries/shared/src/SettingInterface.cpp @@ -17,13 +17,12 @@ #include #include "PathUtils.h" +#include "SettingHelpers.h" #include "SettingManager.h" #include "SharedLogging.h" namespace Setting { static QSharedPointer globalManager; - - const QString Interface::FIRST_RUN { "firstRun" }; // cleans up the settings private instance. Should only be run once at closing down. void cleanupPrivateInstance() { @@ -40,30 +39,27 @@ namespace Setting { settingsManagerThread->quit(); settingsManagerThread->wait(); } + + // Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand, + void init() { + // Set settings format + QSettings::setDefaultFormat(JSON_FORMAT); + QSettings settings; + qCDebug(shared) << "Settings file:" << settings.fileName(); - // Set up application settings. Should only be run once at startup. - void preInit() { - // read the ApplicationInfo.ini file for Name/Version/Domain information - QSettings::setDefaultFormat(QSettings::IniFormat); - QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); - // set the associated application properties - applicationInfo.beginGroup("INFO"); - QCoreApplication::setApplicationName(applicationInfo.value("name").toString()); - QCoreApplication::setOrganizationName(applicationInfo.value("organizationName").toString()); - QCoreApplication::setOrganizationDomain(applicationInfo.value("organizationDomain").toString()); + if (settings.allKeys().isEmpty()) { + loadOldINIFile(settings); + } // Delete Interface.ini.lock file if it exists, otherwise Interface freezes. - QSettings settings; QString settingsLockFilename = settings.fileName() + ".lock"; QFile settingsLockFile(settingsLockFilename); if (settingsLockFile.exists()) { bool deleted = settingsLockFile.remove(); qCDebug(shared) << (deleted ? "Deleted" : "Failed to delete") << "settings lock file" << settingsLockFilename; } - } - - // Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand, - void init() { + + // Let's set up the settings Private instance on its own thread QThread* thread = new QThread(); Q_CHECK_PTR(thread); diff --git a/libraries/shared/src/SettingInterface.h b/libraries/shared/src/SettingInterface.h index 5e23d42223..082adf3e54 100644 --- a/libraries/shared/src/SettingInterface.h +++ b/libraries/shared/src/SettingInterface.h @@ -20,14 +20,11 @@ namespace Setting { class Manager; - void preInit(); void init(); void cleanupSettings(); class Interface { public: - static const QString FIRST_RUN; - const QString& getKey() const { return _key; } bool isSet() const { return _isSet; } diff --git a/libraries/shared/src/SettingManager.cpp b/libraries/shared/src/SettingManager.cpp index a42e62c1c8..929fe2b0ff 100644 --- a/libraries/shared/src/SettingManager.cpp +++ b/libraries/shared/src/SettingManager.cpp @@ -9,12 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "SettingManager.h" + #include #include #include #include "SettingInterface.h" -#include "SettingManager.h" namespace Setting { @@ -32,7 +33,6 @@ namespace Setting { // Custom deleter does nothing, because we need to shutdown later than the dependency manager void Manager::customDeleter() { } - void Manager::registerHandle(Interface* handle) { const QString& key = handle->getKey(); withWriteLock([&] { diff --git a/libraries/steamworks-wrapper/CMakeLists.txt b/libraries/steamworks-wrapper/CMakeLists.txt deleted file mode 100644 index 0cbe3bb5ad..0000000000 --- a/libraries/steamworks-wrapper/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(TARGET_NAME steamworks-wrapper) -setup_hifi_library() -link_hifi_libraries() - -target_steamworks() \ No newline at end of file diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h b/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h deleted file mode 100644 index a191adee97..0000000000 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// SteamClient.h -// steamworks-wrapper/src/steamworks-wrapper -// -// Created by Clement Brisset on 6/8/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_SteamClient_h -#define hifi_SteamClient_h - -#include - -#include -#include - -using Ticket = QByteArray; -using TicketRequestCallback = std::function; - -class QUrl; - -class SteamClient { -public: - static bool isRunning(); - - static bool init(); - static void shutdown(); - - static void runCallbacks(); - - static void requestTicket(TicketRequestCallback callback); - static void updateLocation(QString status, QUrl locationUrl); - static void openInviteOverlay(); - static void joinLobby(QString lobbyId); - - static int getSteamVRBuildID(); -}; - -class SteamScriptingInterface : public QObject { - Q_OBJECT - - Q_PROPERTY(bool isRunning READ isRunning) - -public: - SteamScriptingInterface(QObject* parent) : QObject(parent) {} - -public slots: - bool isRunning() const { return SteamClient::isRunning(); } - void openInviteOverlay() const { SteamClient::openInviteOverlay(); } - -}; - -#endif // hifi_SteamClient_h \ No newline at end of file diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4553b80793..82ca2a7d38 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -26,9 +26,10 @@ if (NOT SERVER_ONLY AND NOT ANDROID) add_subdirectory(${DIR}) set(DIR "hifiNeuron") add_subdirectory(${DIR}) - set(DIR "hifiKinect") add_subdirectory(${DIR}) + set(DIR "steamClient") + add_subdirectory(${DIR}) endif() # server-side plugins diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index f56d594919..ce59eafd50 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -206,7 +206,7 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, const control } int numTrackedControllers = 0; - static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked & ovrStatus_PositionTracked; + static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked; auto tracking = ovr_GetTrackingState(_parent._session, 0, false); ovr_for_each_hand([&](ovrHandType hand) { ++numTrackedControllers; diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index 56a5dd3f5b..09713e9f57 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -370,7 +370,7 @@ void showMinSpecWarning() { auto headPose = toGlm(vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); auto overlayPose = toOpenVr(headPose * glm::translate(glm::mat4(), vec3(0, 0, -1))); vrOverlay->SetOverlayTransformAbsolute(minSpecFailedOverlay, vr::TrackingUniverseSeated, &overlayPose); - + vr::VREvent_t event; while (vrSystem->PollNextEvent(&event, sizeof(event))) { switch (event.eventType) { @@ -405,7 +405,7 @@ bool checkMinSpecImpl() { return true; } - // If we have at least 5 cores, pass + // If we have at least MIN_CORES_SPEC cores, pass auto coreCount = QThread::idealThreadCount(); if (coreCount >= MIN_CORES_SPEC) { return true; diff --git a/plugins/steamClient/CMakeLists.txt b/plugins/steamClient/CMakeLists.txt new file mode 100644 index 0000000000..326628f8e4 --- /dev/null +++ b/plugins/steamClient/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Created by Clément Brisset on 12/14/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 +# + +set(TARGET_NAME steamClient) +setup_hifi_plugin(Gui) +link_hifi_libraries(plugins) +target_steamworks() diff --git a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp b/plugins/steamClient/src/SteamAPIPlugin.cpp similarity index 95% rename from libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp rename to plugins/steamClient/src/SteamAPIPlugin.cpp index 9936027302..853a53e881 100644 --- a/libraries/steamworks-wrapper/src/steamworks-wrapper/SteamClient.cpp +++ b/plugins/steamClient/src/SteamAPIPlugin.cpp @@ -1,6 +1,6 @@ // -// SteamClient.cpp -// steamworks-wrapper/src/steamworks-wrapper +// SteamAPIPlugin.cpp +// plugins/steamClient/src // // Created by Clement Brisset on 6/8/16. // Copyright 2016 High Fidelity, Inc. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "SteamClient.h" +#include "SteamAPIPlugin.h" #include @@ -226,18 +226,18 @@ static std::atomic_bool initialized { false }; static SteamCallbackManager steamCallbackManager; -bool SteamClient::isRunning() { +bool SteamAPIPlugin::isRunning() { return initialized; } -bool SteamClient::init() { +bool SteamAPIPlugin::init() { if (SteamAPI_IsSteamRunning() && !initialized) { initialized = SteamAPI_Init(); } return initialized; } -void SteamClient::shutdown() { +void SteamAPIPlugin::shutdown() { if (initialized) { SteamAPI_Shutdown(); } @@ -245,7 +245,7 @@ void SteamClient::shutdown() { steamCallbackManager.getTicketRequests().stopAll(); } -int SteamClient::getSteamVRBuildID() { +int SteamAPIPlugin::getSteamVRBuildID() { if (initialized) { static const int MAX_PATH_SIZE = 512; static const int STEAMVR_APPID = 250820; @@ -271,7 +271,7 @@ int SteamClient::getSteamVRBuildID() { } -void SteamClient::runCallbacks() { +void SteamAPIPlugin::runCallbacks() { if (!initialized) { return; } @@ -285,7 +285,7 @@ void SteamClient::runCallbacks() { Steam_RunCallbacks(steamPipe, false); } -void SteamClient::requestTicket(TicketRequestCallback callback) { +void SteamAPIPlugin::requestTicket(TicketRequestCallback callback) { if (!initialized) { if (SteamAPI_IsSteamRunning()) { init(); @@ -304,7 +304,7 @@ void SteamClient::requestTicket(TicketRequestCallback callback) { steamCallbackManager.getTicketRequests().startRequest(callback); } -void SteamClient::updateLocation(QString status, QUrl locationUrl) { +void SteamAPIPlugin::updateLocation(QString status, QUrl locationUrl) { if (!initialized) { return; } @@ -315,7 +315,7 @@ void SteamClient::updateLocation(QString status, QUrl locationUrl) { SteamFriends()->SetRichPresence("connect", connectStr.toLocal8Bit().data()); } -void SteamClient::openInviteOverlay() { +void SteamAPIPlugin::openInviteOverlay() { if (!initialized) { return; } @@ -326,7 +326,7 @@ void SteamClient::openInviteOverlay() { } -void SteamClient::joinLobby(QString lobbyIdStr) { +void SteamAPIPlugin::joinLobby(QString lobbyIdStr) { if (!initialized) { if (SteamAPI_IsSteamRunning()) { init(); diff --git a/plugins/steamClient/src/SteamAPIPlugin.h b/plugins/steamClient/src/SteamAPIPlugin.h new file mode 100644 index 0000000000..90fda06de3 --- /dev/null +++ b/plugins/steamClient/src/SteamAPIPlugin.h @@ -0,0 +1,37 @@ +// +// SteamAPIPlugin.h +// plugins/steamClient/src +// +// Created by Clement Brisset on 6/8/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_SteamAPIPlugin_h +#define hifi_SteamAPIPlugin_h + +#include + +class QUrl; + +class SteamAPIPlugin : public SteamClientPlugin { +public: + bool isRunning(); + + bool init(); + void shutdown(); + + void runCallbacks(); + + void requestTicket(TicketRequestCallback callback); + void updateLocation(QString status, QUrl locationUrl); + void openInviteOverlay(); + void joinLobby(QString lobbyId); + + int getSteamVRBuildID(); +}; + +#endif // hifi_SteamAPIPlugin_h diff --git a/plugins/steamClient/src/SteamClientProvider.cpp b/plugins/steamClient/src/SteamClientProvider.cpp new file mode 100644 index 0000000000..a873d51729 --- /dev/null +++ b/plugins/steamClient/src/SteamClientProvider.cpp @@ -0,0 +1,41 @@ +// +// Created by Clément Brisset on 12/14/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 + +#include "SteamAPIPlugin.h" + +class SteamAPIProvider : public QObject, public SteamClientProvider { + Q_OBJECT + Q_PLUGIN_METADATA(IID SteamClientProvider_iid FILE "plugin.json") + Q_INTERFACES(SteamClientProvider) + +public: + SteamAPIProvider(QObject* parent = nullptr) : QObject(parent) {} + virtual ~SteamAPIProvider() {} + + virtual SteamClientPluginPointer getSteamClientPlugin() override { + static std::once_flag once; + std::call_once(once, [&] { + _steamClientPlugin = std::make_shared(); + }); + return _steamClientPlugin; + } + +private: + SteamClientPluginPointer _steamClientPlugin; +}; + +#include "SteamClientProvider.moc" diff --git a/plugins/steamClient/src/plugin.json b/plugins/steamClient/src/plugin.json new file mode 100644 index 0000000000..dfe37917d2 --- /dev/null +++ b/plugins/steamClient/src/plugin.json @@ -0,0 +1 @@ +{"name":"Steam Client"} diff --git a/scripts/system/assets/images/tools/people.svg b/scripts/system/assets/images/tools/people.svg new file mode 100644 index 0000000000..5fedfefa75 --- /dev/null +++ b/scripts/system/assets/images/tools/people.svg @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index ff1407cbf0..cdd66a905a 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -703,6 +703,8 @@ function MyController(hand) { this.autoUnequipCounter = 0; this.grabPointIntersectsEntity = false; + this.shouldScale = false; + // handPosition is where the avatar's hand appears to be, in-world. this.getHandPosition = function () { if (this.hand === RIGHT_HAND) { @@ -771,6 +773,11 @@ function MyController(hand) { this.updateSmoothedTrigger(); + // If both trigger and grip buttons squeezed and nothing is held, rescale my avatar! + if (this.hand === RIGHT_HAND && this.state === STATE_SEARCHING && this.getOtherHandController().state === STATE_SEARCHING) { + this.maybeScaleMyAvatar(); + } + if (this.ignoreInput()) { this.turnOffVisualizations(); return; @@ -1614,6 +1621,8 @@ function MyController(hand) { this.clearEquipHaptics(); this.grabPointSphereOff(); + this.shouldScale = false; + var worldControllerPosition = getControllerWorldLocation(this.handToController(), true).position; // transform the position into room space @@ -1773,6 +1782,7 @@ function MyController(hand) { } } + this.maybeScale(grabbedProperties); // visualizations var rayPickInfo = this.calcRayPickInfo(this.hand); @@ -1882,6 +1892,8 @@ function MyController(hand) { this.dropGestureReset(); this.clearEquipHaptics(); + this.shouldScale = false; + Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); if (this.entityActivated) { @@ -2151,6 +2163,10 @@ function MyController(hand) { this.callEntityMethodOnGrabbed("continueNearGrab"); } + if (this.state == STATE_NEAR_GRABBING) { + this.maybeScale(props); + } + if (this.actionID && this.actionTimeout - now < ACTION_TTL_REFRESH * MSECS_PER_SEC) { // if less than a 5 seconds left, refresh the actions ttl var success = Entities.updateAction(this.grabbedEntity, this.actionID, { @@ -2173,6 +2189,43 @@ function MyController(hand) { } }; + this.maybeScale = function(props) { + if (!this.shouldScale) { + // If both secondary triggers squeezed, and the non-holding hand is empty, start scaling + if (this.secondarySqueezed() && this.getOtherHandController().secondarySqueezed() && this.getOtherHandController().state === STATE_OFF) { + this.scalingStartDistance = Vec3.length(Vec3.subtract(this.getHandPosition(), this.getOtherHandController().getHandPosition())); + this.scalingStartDimensions = props.dimensions; + this.shouldScale = true; + } + } else if (!this.secondarySqueezed() || !this.getOtherHandController().secondarySqueezed()) { + this.shouldScale = false; + } + if (this.shouldScale) { + var scalingCurrentDistance = Vec3.length(Vec3.subtract(this.getHandPosition(), this.getOtherHandController().getHandPosition())); + var currentRescale = scalingCurrentDistance / this.scalingStartDistance; + var newDimensions = Vec3.multiply(currentRescale, this.scalingStartDimensions); + Entities.editEntity(this.grabbedEntity, { dimensions: newDimensions }) + } + } + + this.maybeScaleMyAvatar = function() { + if (!this.shouldScale) { + // If both secondary triggers squeezed, start scaling + if (this.secondarySqueezed() && this.getOtherHandController().secondarySqueezed()) { + this.scalingStartDistance = Vec3.length(Vec3.subtract(this.getHandPosition(), this.getOtherHandController().getHandPosition())); + this.scalingStartAvatarScale = MyAvatar.scale; + this.shouldScale = true; + } + } else if (!this.secondarySqueezed() || !this.getOtherHandController().secondarySqueezed()) { + this.shouldScale = false; + } + if (this.shouldScale) { + var scalingCurrentDistance = Vec3.length(Vec3.subtract(this.getHandPosition(), this.getOtherHandController().getHandPosition())); + var newAvatarScale = (scalingCurrentDistance / this.scalingStartDistance) * this.scalingStartAvatarScale; + MyAvatar.scale = newAvatarScale; + } + } + this.nearTriggerEnter = function() { this.clearEquipHaptics(); this.grabPointSphereOff(); diff --git a/scripts/system/pal.js b/scripts/system/pal.js new file mode 100644 index 0000000000..175418cd2e --- /dev/null +++ b/scripts/system/pal.js @@ -0,0 +1,265 @@ +"use strict"; +/*jslint vars: true, plusplus: true, forin: true*/ +/*globals Script, AvatarList, Camera, Overlays, OverlayWindow, Toolbars, Vec3, Quat, Controller, print, getControllerWorldLocation */ +// +// pal.js +// +// Created by Howard Stearns on December 9, 2016 +// 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 +// + +// FIXME when we make this a defaultScript: (function() { // BEGIN LOCAL_SCOPE + +Script.include("/~/system/libraries/controllers.js"); + +// +// Overlays. +// +var overlays = {}; // Keeps track of all our extended overlay data objects, keyed by target identifier. +function ExtendedOverlay(key, type, properties, selected) { // A wrapper around overlays to store the key it is associated with. + overlays[key] = this; + this.key = key; + this.selected = selected || false; // not undefined + this.activeOverlay = Overlays.addOverlay(type, properties); // We could use different overlays for (un)selected... +} +// Instance methods: +ExtendedOverlay.prototype.deleteOverlay = function () { // remove display and data of this overlay + Overlays.deleteOverlay(this.activeOverlay); + delete overlays[this.key]; +}; + +ExtendedOverlay.prototype.editOverlay = function (properties) { // change display of this overlay + Overlays.editOverlay(this.activeOverlay, properties); +}; +const UNSELECTED_COLOR = {red: 20, green: 250, blue: 20}; +const SELECTED_COLOR = {red: 250, green: 20, blue: 20}; +function color(selected) { return selected ? SELECTED_COLOR : UNSELECTED_COLOR; } +ExtendedOverlay.prototype.select = function (selected) { + if (this.selected === selected) { + return; + } + this.editOverlay({color: color(selected)}); + this.selected = selected; +}; +// Class methods: +var selectedIds = []; +ExtendedOverlay.isSelected = function (id) { + return -1 !== selectedIds.indexOf(id); +} +ExtendedOverlay.get = function (key) { // answer the extended overlay data object associated with the given avatar identifier + return overlays[key]; +}; +ExtendedOverlay.some = function (iterator) { // Bails early as soon as iterator returns truthy. + var key; + for (key in overlays) { + if (iterator(ExtendedOverlay.get(key))) { + return; + } + } +}; +ExtendedOverlay.applyPickRay = function (pickRay, cb) { // cb(overlay) on the one overlay intersected by pickRay, if any. + var pickedOverlay = Overlays.findRayIntersection(pickRay); // Depends on nearer coverOverlays to extend closer to us than farther ones. + if (!pickedOverlay.intersects) { + return; + } + ExtendedOverlay.some(function (overlay) { // See if pickedOverlay is one of ours. + if ((overlay.activeOverlay) === pickedOverlay.overlayID) { + cb(overlay); + return true; + } + }); +}; + +// +// The qml window and communications. +// +var pal = new OverlayWindow({ + title: 'People Action List', + source: 'hifi/Pal.qml', + width: 480, + height: 640, + visible: false +}); +pal.fromQml.connect(function (message) { // messages are {method, params}, like json-rpc. See also sendToQml. + print('From PAL QML:', JSON.stringify(message)); + switch (message.method) { + case 'selected': + selectedIds = message.params; + ExtendedOverlay.some(function (overlay) { + var id = overlay.key; + var selected = ExtendedOverlay.isSelected(id); + overlay.select(selected); + }); + break; + default: + print('Unrecognized message from Pal.qml:', JSON.stringify(message)); + } +}); + +// +// Main operations. +// +function addAvatarNode(id) { + var selected = ExtendedOverlay.isSelected(id); + return new ExtendedOverlay(id, "sphere", { // 3d so we don't go cross-eyed looking at it, but on top of everything + solid: true, + alpha: 0.8, + color: color(selected), + drawInFront: true + }, selected); +} +function populateUserList() { + var data = []; + var counter = 1; + AvatarList.getAvatarIdentifiers().sort().forEach(function (id) { // sorting the identifiers is just an aid for debugging + var avatar = AvatarList.getAvatar(id); + var avatarPalDatum = { + displayName: avatar.displayName || ('anonymous ' + counter++), + userName: "fakeAcct" + (id || "Me"), + sessionId: id || '' + }; + data.push(avatarPalDatum); + if (id) { // No overlay for ourself. + addAvatarNode(id); + } + print('PAL data:', JSON.stringify(avatarPalDatum)); + }); + pal.sendToQml({method: 'users', params: data}); +} +var pingPong = true; +function updateOverlays() { + var eye = Camera.position; + AvatarList.getAvatarIdentifiers().forEach(function (id) { + if (!id) { + return; // don't update ourself + } + var overlay = ExtendedOverlay.get(id); + if (!overlay) { // For now, we're treating this as a temporary loss, as from the personal space bubble. Add it back. + print('Adding non-PAL avatar node', id); + overlay = addAvatarNode(id); + } + var avatar = AvatarList.getAvatar(id); + var target = avatar.position; + var distance = Vec3.distance(target, eye); + overlay.ping = pingPong; + overlay.editOverlay({ + position: target, + dimensions: 0.05 * distance // constant apparent size + }); + }); + pingPong = !pingPong; + ExtendedOverlay.some(function (overlay) { // Remove any that weren't updated. (User is gone.) + if (overlay.ping === pingPong) { + overlay.deleteOverlay(); + } + }); + // We could re-populateUserList if anything added or removed, but not for now. +} +function removeOverlays() { + selectedIds = []; + ExtendedOverlay.some(function (overlay) { overlay.deleteOverlay(); }); +} + +// +// Clicks. +// +function handleClick(pickRay) { + ExtendedOverlay.applyPickRay(pickRay, function (overlay) { + // Don't select directly. Tell qml, who will give us back a list of ids. + var message = {method: 'select', params: [overlay.key, !overlay.selected]}; + pal.sendToQml(message); + return true; + }); +} +function handleMouseEvent(mousePressEvent) { // handleClick if we get one. + if (!mousePressEvent.isLeftButton) { + return; + } + handleClick(Camera.computePickRay(mousePressEvent.x, mousePressEvent.y)); +} +// We get mouseMoveEvents from the handControllers, via handControllerPointer. +// But we don't get mousePressEvents. +var triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click'); +function controllerComputePickRay(hand) { + var controllerPose = getControllerWorldLocation(hand, true); + if (controllerPose.valid) { + return { origin: controllerPose.position, direction: Quat.getUp(controllerPose.orientation) }; + } +} +function makeClickHandler(hand) { + return function (clicked) { + if (clicked > 0.85) { + var pickRay = controllerComputePickRay(hand); + handleClick(pickRay); + } + }; +} +triggerMapping.from(Controller.Standard.RTClick).peek().to(makeClickHandler(Controller.Standard.RightHand)); +triggerMapping.from(Controller.Standard.LTClick).peek().to(makeClickHandler(Controller.Standard.LeftHand)); + +// +// Manage the connection between the button and the window. +// +var toolBar = Toolbars.getToolbar("com.highfidelity.interface.toolbar.system"); +var buttonName = "pal"; +var button = toolBar.addButton({ + objectName: buttonName, + imageURL: Script.resolvePath("assets/images/tools/people.svg"), + visible: true, + hoverState: 2, + defaultState: 1, + buttonState: 1, + alpha: 0.9 +}); +var isWired = false; +function off() { + if (isWired) { // It is not ok to disconnect these twice, hence guard. + Script.update.disconnect(updateOverlays); + Controller.mousePressEvent.disconnect(handleMouseEvent); + isWired = false; + } + triggerMapping.disable(); // It's ok if we disable twice. + removeOverlays(); +} +function onClicked() { + if (!pal.visible) { + populateUserList(); + pal.raise(); + isWired = true; + Script.update.connect(updateOverlays); + Controller.mousePressEvent.connect(handleMouseEvent); + triggerMapping.enable(); + } else { + off(); + } + pal.setVisible(!pal.visible); +} + +// +// Button state. +// +function onVisibileChanged() { + button.writeProperty('buttonState', pal.visible ? 0 : 1); + button.writeProperty('defaultState', pal.visible ? 0 : 1); + button.writeProperty('hoverState', pal.visible ? 2 : 3); +} +button.clicked.connect(onClicked); +pal.visibleChanged.connect(onVisibileChanged); +pal.closed.connect(off); + +// +// Cleanup. +// +Script.scriptEnding.connect(function () { + button.clicked.disconnect(onClicked); + toolBar.removeButton(buttonName); + pal.visibleChanged.disconnect(onVisibileChanged); + pal.closed.disconnect(off); + off(); +}); + + +// FIXME: }()); // END LOCAL_SCOPE diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index edc2eb6a20..d79a6e46cb 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -166,6 +166,9 @@ function resetButtons(pathStillSnapshot, pathAnimatedSnapshot, notify) { if (resetOverlays) { Menu.setIsOptionChecked("Overlays", true); } + } else { + // Allow the user to click the snapshot HUD button again + button.clicked.connect(onClicked); } // update button states button.writeProperty("buttonState", 1); @@ -177,14 +180,16 @@ function resetButtons(pathStillSnapshot, pathAnimatedSnapshot, notify) { // during which time the user may have moved. So stash that info in the dialog so that // it records the correct href. (We can also stash in .jpegs, but not .gifs.) // last element in data array tells dialog whether we can share or not - confirmShare([ - { localPath: pathAnimatedSnapshot, href: href }, + var confirmShareContents = [ { localPath: pathStillSnapshot, href: href }, { canShare: !!isDomainOpen(domainId), openFeedAfterShare: shouldOpenFeedAfterShare() - } - ]); + }]; + if (pathAnimatedSnapshot !== "") { + confirmShareContents.unshift({ localPath: pathAnimatedSnapshot, href: href }); + } + confirmShare(confirmShareContents); if (clearOverlayWhenMoving) { MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog } @@ -196,9 +201,11 @@ function processingGif() { Reticle.visible = reticleVisible; // update button states - button.writeProperty("buttonState", 1); - button.writeProperty("defaultState", 1); - button.writeProperty("hoverState", 3); + button.writeProperty("buttonState", 0); + button.writeProperty("defaultState", 0); + button.writeProperty("hoverState", 2); + // Don't allow the user to click the snapshot button yet + button.clicked.disconnect(onClicked); // show overlays if they were on if (resetOverlays) { Menu.setIsOptionChecked("Overlays", true); diff --git a/tests/render-texture-load/src/GLIHelpers.cpp b/tests/render-texture-load/src/GLIHelpers.cpp index 8067993b49..be39e7f1c8 100644 --- a/tests/render-texture-load/src/GLIHelpers.cpp +++ b/tests/render-texture-load/src/GLIHelpers.cpp @@ -48,7 +48,7 @@ QString convertTexture(const QString& sourceFile) { fromQImageFormat(sourceImage.format()), gli::extent2d(sourceImage.width(), sourceImage.height())); auto sourceSize = sourceImage.byteCount(); - assert(sourceSize == workTexture[workTexture.base_level()].size()); + assert(sourceSize == (int)workTexture[workTexture.base_level()].size()); memcpy(workTexture[workTexture.base_level()].data(), sourceImage.constBits(), sourceSize); QString resultFile = getKtxFileName(sourceFile) ; diff --git a/tests/render-utils/src/main.cpp b/tests/render-utils/src/main.cpp index c38bd6765c..7e909bf31f 100644 --- a/tests/render-utils/src/main.cpp +++ b/tests/render-utils/src/main.cpp @@ -152,7 +152,6 @@ protected: //static const wchar_t* EXAMPLE_TEXT = L"Hello"; //static const wchar_t* EXAMPLE_TEXT = L"\xC1y Hello 1.0\ny\xC1 line 2\n\xC1y"; -static const glm::uvec2 QUAD_OFFSET(10, 10); void testShaderBuild(const char* vs_src, const char * fs_src) { auto vs = gpu::Shader::createVertex(std::string(vs_src)); diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index dad0a6d617..4c12a09388 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -81,9 +81,8 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : listenPort = parser.value(listenPortOption).toInt(); } - Setting::preInit(); - DependencyManager::registerInheritance(); Setting::init(); + DependencyManager::registerInheritance(); DependencyManager::set([&]{ return QString("Mozilla/5.0 (HighFidelityACClient)"); }); DependencyManager::set(); diff --git a/tools/ac-client/src/main.cpp b/tools/ac-client/src/main.cpp index 918df6413f..12c5e6f5f8 100644 --- a/tools/ac-client/src/main.cpp +++ b/tools/ac-client/src/main.cpp @@ -13,11 +13,19 @@ #include #include +#include + #include "ACClientApp.h" using namespace std; int main(int argc, char * argv[]) { + QCoreApplication::setApplicationName(BuildInfo::AC_CLIENT_SERVER_NAME); + QCoreApplication::setOrganizationName(BuildInfo::MODIFIED_ORGANIZATION); + QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); + QCoreApplication::setApplicationVersion(BuildInfo::VERSION); + ACClientApp app(argc, argv); + return app.exec(); }