Merge branch 'master' of https://github.com/highfidelity/hifi into addViewFrustumToAvatarMixer

This commit is contained in:
Brad Hefta-Gaub 2016-12-15 16:42:41 -08:00
commit 8497ad1e29
87 changed files with 1667 additions and 334 deletions

View file

@ -12,7 +12,6 @@
#include <assert.h>
#include <QProcess>
#include <QSettings>
#include <QSharedMemory>
#include <QThread>
#include <QTimer>
@ -49,8 +48,6 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
{
LogUtils::init();
QSettings::setDefaultFormat(QSettings::IniFormat);
DependencyManager::set<AccountManager>();
auto scriptableAvatar = DependencyManager::set<ScriptableAvatar>();

View file

@ -12,7 +12,6 @@
#include <QCommandLineParser>
#include <QThread>
#include <BuildInfo.h>
#include <LogHandler.h>
#include <SharedUtil.h>
#include <HifiConfigVariantMap.h>
@ -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");

View file

@ -13,10 +13,16 @@
#include <SharedUtil.h>
#include "AssignmentClientApp.h"
#include <BuildInfo.h>
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.";

View file

@ -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 <QString>
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@";
}

View file

@ -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;

View file

@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "DomainServerSettingsManager.h"
#include <algorithm>
#include <QtCore/QCoreApplication>
@ -16,23 +18,21 @@
#include <QtCore/QFile>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonObject>
#include <QtCore/QSettings>
#include <QtCore/QStandardPaths>
#include <QtCore/QUrl>
#include <QtCore/QUrlQuery>
#include <AccountManager.h>
#include <QTimeZone>
#include <AccountManager.h>
#include <Assignment.h>
#include <HifiConfigVariantMap.h>
#include <HTTPConnection.h>
#include <NLPacketList.h>
#include <NumericalConstants.h>
#include <SettingHandle.h>
#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<double> 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() {

View file

@ -14,6 +14,7 @@
#include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument>
#include <QtNetwork/QNetworkReply>
#include <HifiConfigVariantMap.h>
#include <HTTPManager.h>
@ -21,6 +22,8 @@
#include <ReceivedMessage.h>
#include "NodePermissions.h"
#include <Node.h>
const QString SETTINGS_PATHS_KEY = "paths";
const QString SETTINGS_PATH = "/settings";

View file

@ -17,12 +17,18 @@
#include <LogHandler.h>
#include <SharedUtil.h>
#include <BuildInfo.h>
#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

View file

@ -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

View file

@ -1,4 +0,0 @@
[INFO]
name=Interface
organizationName=High Fidelity
organizationDomain=highfidelity.io

View file

@ -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;
}
}

View file

@ -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();
}
}
}

View file

@ -90,20 +90,21 @@
#include <PerfStat.h>
#include <PhysicsEngine.h>
#include <PhysicsHelpers.h>
#include <plugins/CodecPlugin.h>
#include <plugins/PluginManager.h>
#include <plugins/PluginUtils.h>
#include <plugins/CodecPlugin.h>
#include <plugins/SteamClientPlugin.h>
#include <RecordingScriptingInterface.h>
#include <RenderableWebEntityItem.h>
#include <RenderShadowTask.h>
#include <RenderDeferredTask.h>
#include <RenderForwardTask.h>
#include <ResourceCache.h>
#include <SandboxUtils.h>
#include <SceneScriptingInterface.h>
#include <ScriptEngines.h>
#include <ScriptCache.h>
#include <SoundCache.h>
#include <steamworks-wrapper/SteamClient.h>
#include <Tooltip.h>
#include <udt/PacketHeaders.h>
#include <UserActivityLogger.h>
@ -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<EntityActionFactoryInterface, InterfaceActionFactory>();
DependencyManager::registerInheritance<SpatialParentFinder, InterfaceParentFinder>();
Setting::init();
// Set dependencies
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
DependencyManager::set<ScriptEngines>();
@ -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>("RenderShadowTask", cullFunctor);
_renderEngine->addJob<RenderDeferredTask>("RenderDeferredTask", cullFunctor);
static const QString RENDER_FORWARD = "RENDER_FORWARD";
if (QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD)) {
_renderEngine->addJob<RenderForwardTask>("RenderForwardTask", cullFunctor);
} else {
_renderEngine->addJob<RenderDeferredTask>("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<AvatarManager>().data());
rootContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().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<UserActivityLoggerScriptingInterface>().data());
scriptEngine->registerGlobalObject("Users", DependencyManager::get<UsersScriptingInterface>().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<controller::ScriptingInterface>();
scriptEngine->registerGlobalObject("Controller", scriptingInterface.data());
UserInputMapper::registerControllerTypes(scriptEngine);

View file

@ -18,19 +18,18 @@
#include <QLabel>
#include <PathUtils.h>
#include <QRadioButton>
#include <QSettings>
#include <QStandardPaths>
#include <QVBoxLayout>
#include <QtCore/QUrl>
#include "Application.h"
#include "Menu.h"
#include <SettingHandle.h>
#include <RunningMarker.h>
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";

View file

@ -15,7 +15,8 @@
#include <AddressManager.h>
#include <DomainHandler.h>
#include <NodeList.h>
#include <steamworks-wrapper/SteamClient.h>
#include <plugins/PluginManager.h>
#include <plugins/SteamClientPlugin.h>
#include <UserActivityLogger.h>
#include <UUID.h>
@ -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) {

View file

@ -14,7 +14,6 @@
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QSettings>
#include <gpu/Batch.h>

View file

@ -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

View file

@ -15,14 +15,13 @@
#include <QDir>
#include <QLocalSocket>
#include <QLocalServer>
#include <QSettings>
#include <QSharedMemory>
#include <QTranslator>
#include <BuildInfo.h>
#include <gl/OpenGLVersionChecker.h>
#include <SharedUtil.h>
#include <steamworks-wrapper/SteamClient.h>
#include "AddressManager.h"
#include "Application.h"
@ -32,7 +31,6 @@
#include <QtCore/QProcess>
#ifdef HAS_BUGSPLAT
#include <BuildInfo.h>
#include <BugSplat.h>
#include <CrashReporter.h>
#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<char**>(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

View file

@ -17,7 +17,8 @@
#include <QtNetwork/QNetworkReply>
#include <NetworkingConstants.h>
#include <steamworks-wrapper/SteamClient.h>
#include <plugins/PluginManager.h>
#include <plugins/SteamClientPlugin.h>
#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<AccountManager>()->requestAccessTokenWithSteam(ticket);
});
DependencyManager::get<AccountManager>()->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>();
accountManager->sendRequest(LINK_STEAM_PATH, AccountManagerAuth::Required,
QNetworkAccessManager::PostOperation, callbackParams,
QJsonDocument(payload).toJson());
});
auto accountManager = DependencyManager::get<AccountManager>();
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>();
accountManager->sendRequest(CREATE_ACCOUNT_FROM_STEAM_PATH, AccountManagerAuth::None,
QNetworkAccessManager::PostOperation, callbackParams,
QJsonDocument(payload).toJson());
});
auto accountManager = DependencyManager::get<AccountManager>();
accountManager->sendRequest(CREATE_ACCOUNT_FROM_STEAM_PATH, AccountManagerAuth::None,
QNetworkAccessManager::PostOperation, callbackParams,
QJsonDocument(payload).toJson());
});
}
}

View file

@ -292,23 +292,24 @@ void setupPreferences() {
{
static const QString RENDER("Graphics");
auto renderConfig = qApp->getRenderEngine()->getConfiguration();
if (renderConfig) {
auto ambientOcclusionConfig = renderConfig->getConfig<AmbientOcclusionEffect>();
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<AmbientOcclusionEffect>();
{
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<RenderShadowTask>();
{
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<RenderShadowTask>();
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);
}
}
}
{

View file

@ -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);
}

View file

@ -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 {

View file

@ -12,8 +12,6 @@
#ifndef hifi_AutoUpdater_h
#define hifi_AutoUpdater_h
#include <QtCore/QSettings>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QMap>

View file

@ -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);
}

View file

@ -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<InputPlugin>;
using InputPluginList = std::vector<InputPluginPointer>;
using CodecPluginPointer = std::shared_ptr<CodecPlugin>;
using CodecPluginList = std::vector<CodecPluginPointer>;
using SteamClientPluginPointer = std::shared_ptr<SteamClientPlugin>;

View file

@ -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<SteamClientProvider*>(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

View file

@ -19,6 +19,7 @@ public:
const DisplayPluginList& getDisplayPlugins();
const InputPluginList& getInputPlugins();
const CodecPluginList& getCodecPlugins();
const SteamClientPluginPointer getSteamClientPlugin();
DisplayPluginList getPreferredDisplayPlugins();
void setPreferredDisplayPlugins(const QStringList& displays);

View file

@ -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)

View file

@ -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 <functional>
#include <QtCore/QObject>
#include <QtCore/QByteArray>
using Ticket = QByteArray;
using TicketRequestCallback = std::function<void(Ticket)>;
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 */

0
libraries/render-utils/src/DeferredBuffer.slh Executable file → Normal file
View file

0
libraries/render-utils/src/DeferredBufferWrite.slh Executable file → Normal file
View file

0
libraries/render-utils/src/DeferredGlobalLight.slh Executable file → Normal file
View file

0
libraries/render-utils/src/DeferredLighting.slh Executable file → Normal file
View file

View file

@ -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);

View file

@ -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;

0
libraries/render-utils/src/RenderDeferredTask.cpp Executable file → Normal file
View file

0
libraries/render-utils/src/RenderDeferredTask.h Executable file → Normal file
View file

View file

@ -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 <PerfStat.h>
#include <PathUtils.h>
#include <RenderArgs.h>
#include <ViewFrustum.h>
#include <gpu/Context.h>
#include <render/CullTask.h>
#include <render/SortTask.h>
#include <render/DrawTask.h>
#include <render/DrawStatus.h>
#include <render/DrawSceneOctree.h>
#include <render/BlurTask.h>
#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 <gpu/StandardShaderLib.h>
#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<ShapePlumber>();
initDeferredPipelines(*shapePlumber);
// CPU jobs:
// Fetch and cull the items from the scene
const auto spatialSelection = addJob<FetchSpatialTree>("FetchSceneSelection");
cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; };
auto spatialFilter = ItemFilter::Builder::visibleWorldItems().withoutLayered();
const auto culledSpatialSelection = addJob<CullSpatialSelection>("CullSceneSelection", spatialSelection, cullFunctor, RenderDetails::ITEM, spatialFilter);
// Overlays are not culled
const auto nonspatialSelection = addJob<FetchNonspatialItems>("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<NUM_FILTERS>::ItemFilterArray spatialFilters = { {
ItemFilter::Builder::opaqueShape(),
ItemFilter::Builder::transparentShape(),
ItemFilter::Builder::light()
} };
MultiFilterItem<NUM_FILTERS>::ItemFilterArray nonspatialFilters = { {
ItemFilter::Builder::opaqueShape(),
ItemFilter::Builder::transparentShape(),
ItemFilter::Builder::background()
} };
const auto filteredSpatialBuckets = addJob<MultiFilterItem<NUM_FILTERS>>("FilterSceneSelection", culledSpatialSelection, spatialFilters).get<MultiFilterItem<NUM_FILTERS>::ItemBoundsArray>();
const auto filteredNonspatialBuckets = addJob<MultiFilterItem<NUM_FILTERS>>("FilterOverlaySelection", nonspatialSelection, nonspatialFilters).get<MultiFilterItem<NUM_FILTERS>::ItemBoundsArray>();
// Extract / Sort opaques / Transparents / Lights / Overlays
const auto opaques = addJob<DepthSortItems>("DepthSortOpaque", filteredSpatialBuckets[OPAQUE_SHAPE_BUCKET]);
const auto transparents = addJob<DepthSortItems>("DepthSortTransparent", filteredSpatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false));
const auto lights = filteredSpatialBuckets[LIGHT_BUCKET];
const auto overlayOpaques = addJob<DepthSortItems>("DepthSortOverlayOpaque", filteredNonspatialBuckets[OPAQUE_SHAPE_BUCKET]);
const auto overlayTransparents = addJob<DepthSortItems>("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false));
const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET];
const auto framebuffer = addJob<PrepareFramebuffer>("PrepareFramebuffer");
// Blit!
addJob<Blit>("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<Config>(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<FramebufferCache>();
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;
}

View file

@ -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 <gpu/Pipeline.h>
#include <render/CullTask.h>
#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<RenderForwardTask, Config>;
};
class PrepareFramebuffer {
public:
using JobModel = render::Job::ModelO<PrepareFramebuffer, gpu::FramebufferPointer>;
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer);
private:
gpu::FramebufferPointer _framebuffer;
};
#endif // hifi_RenderForwardTask_h

0
libraries/render-utils/src/Shadow.slh Executable file → Normal file
View file

0
libraries/render-utils/src/deferred_light_spot.slv Executable file → Normal file
View file

View file

View file

0
libraries/render-utils/src/model.slf Executable file → Normal file
View file

0
libraries/render-utils/src/model.slv Executable file → Normal file
View file

0
libraries/render-utils/src/model_lightmap.slf Executable file → Normal file
View file

0
libraries/render-utils/src/model_lightmap.slv Executable file → Normal file
View file

View file

View file

View file

View file

0
libraries/render-utils/src/model_normal_map.slf Executable file → Normal file
View file

0
libraries/render-utils/src/model_normal_map.slv Executable file → Normal file
View file

View file

0
libraries/render-utils/src/model_shadow.slf Executable file → Normal file
View file

0
libraries/render-utils/src/model_shadow.slv Executable file → Normal file
View file

0
libraries/render-utils/src/model_specular_map.slf Executable file → Normal file
View file

0
libraries/render-utils/src/model_translucent.slf Executable file → Normal file
View file

0
libraries/render-utils/src/skin_model.slv Executable file → Normal file
View file

0
libraries/render-utils/src/skin_model_normal_map.slv Executable file → Normal file
View file

0
libraries/render-utils/src/skin_model_shadow.slv Executable file → Normal file
View file

View file

@ -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);

View file

@ -19,16 +19,12 @@
const QString Settings::firstRun { "firstRun" };
Settings::Settings() :
_manager(DependencyManager::get<Setting::Manager>()),
_locker(&(_manager->getLock()))
Settings::Settings() : _manager(DependencyManager::get<Setting::Manager>())
{
}
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 {

View file

@ -14,7 +14,6 @@
#include <type_traits>
#include <QtCore/QSettings>
#include <QtCore/QStack>
#include <QtCore/QString>
#include <QtCore/QVariant>
@ -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<Setting::Manager> _manager;
QWriteLocker _locker;
QStack<QString> _prefixes;
};
namespace Setting {

View file

@ -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 <QDataStream>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QPoint>
#include <QRect>
#include <QSettings>
#include <QSize>
#include <QStringList>
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<QRect>(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<QSize>(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<QPoint>(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;
}

View file

@ -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 <QSettings>
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

View file

@ -17,13 +17,12 @@
#include <QThread>
#include "PathUtils.h"
#include "SettingHelpers.h"
#include "SettingManager.h"
#include "SharedLogging.h"
namespace Setting {
static QSharedPointer<Manager> 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);

View file

@ -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; }

View file

@ -9,12 +9,13 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "SettingManager.h"
#include <QtCore/QThread>
#include <QtCore/QDebug>
#include <QtCore/QUuid>
#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([&] {

View file

@ -1,5 +0,0 @@
set(TARGET_NAME steamworks-wrapper)
setup_hifi_library()
link_hifi_libraries()
target_steamworks()

View file

@ -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 <functional>
#include <QtCore/QObject>
#include <QtCore/QByteArray>
using Ticket = QByteArray;
using TicketRequestCallback = std::function<void(Ticket)>;
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

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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()

View file

@ -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 <atomic>
@ -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();

View file

@ -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 <plugins/SteamClientPlugin.h>
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

View file

@ -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 <mutex>
#include <QtCore/QObject>
#include <QtCore/QtPlugin>
#include <QtCore/QStringList>
#include <plugins/RuntimePlugin.h>
#include <plugins/SteamClientPlugin.h>
#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<SteamAPIPlugin>();
});
return _steamClientPlugin;
}
private:
SteamClientPluginPointer _steamClientPlugin;
};
#include "SteamClientProvider.moc"

View file

@ -0,0 +1 @@
{"name":"Steam Client"}

View file

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 50 200.1" style="enable-background:new 0 0 50 200.1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#414042;}
.st1{fill:#FFFFFF;}
.st2{fill:#1E1E1E;}
.st3{fill:#333333;}
</style>
<g id="Layer_2">
<g>
<g>
<path class="st0" d="M50.1,146.1c0,2.2-1.8,4-4,4h-42c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V146.1z"/>
</g>
</g>
<g>
<g>
<path class="st0" d="M50,196.1c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V196.1z"/>
</g>
</g>
<g>
<g>
<path class="st1" d="M50,46c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4V4c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V46z"/>
</g>
</g>
<g>
<path class="st2" d="M50,96.1c0,2.2-1.8,4-4,4H4c-2.2,0-4-1.8-4-4v-42c0-2.2,1.8-4,4-4h42c2.2,0,4,1.8,4,4V96.1z"/>
</g>
</g>
<g id="Layer_3">
</g>
<g>
<path class="st1" d="M8.1,92.5v-6.4h2.7c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2H9.3v2.1H8.1z M9.3,89.2h1.4
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1,0-0.2-0.1-0.3-0.1H9.3V89.2z"/>
<path class="st1" d="M18.3,91.4v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H18.3z"/>
<path class="st1" d="M22.1,92.5c-0.5,0-0.9-0.1-1.2-0.3s-0.7-0.4-1-0.7c-0.3-0.3-0.5-0.6-0.6-1c-0.1-0.4-0.2-0.8-0.2-1.2
c0-0.4,0.1-0.8,0.2-1.2s0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7s0.8-0.3,1.2-0.3c0.5,0,0.9,0.1,1.2,0.3s0.7,0.4,1,0.7
c0.3,0.3,0.5,0.7,0.6,1c0.1,0.4,0.2,0.8,0.2,1.2c0,0.4-0.1,0.8-0.2,1.2c-0.2,0.4-0.4,0.7-0.6,1c-0.3,0.3-0.6,0.5-1,0.7
C22.9,92.4,22.5,92.5,22.1,92.5z M20.3,89.3c0,0.3,0,0.5,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7c0.2,0.2,0.3,0.4,0.6,0.5s0.5,0.2,0.8,0.2
c0.3,0,0.5-0.1,0.8-0.2s0.4-0.3,0.6-0.5c0.1-0.2,0.3-0.4,0.3-0.7s0.1-0.5,0.1-0.8c0-0.3,0-0.5-0.1-0.8c-0.1-0.3-0.2-0.5-0.4-0.7
c-0.2-0.2-0.3-0.4-0.6-0.5c-0.2-0.1-0.5-0.2-0.7-0.2c-0.3,0-0.5,0.1-0.8,0.2s-0.4,0.3-0.6,0.5c-0.2,0.2-0.3,0.4-0.3,0.7
C20.4,88.7,20.3,89,20.3,89.3z"/>
<path class="st1" d="M26.3,92.5v-6.4H29c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2h-1.5v2.1H26.3z M27.6,89.2H29
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1,0-0.2-0.1-0.3-0.1h-1.4V89.2z"/>
<path class="st1" d="M32.1,92.5v-6.4h1.2v5.3h3.3v1.1H32.1z"/>
<path class="st1" d="M42.1,91.4v1.1h-4.4v-6.4H42v1.1h-3.1v1.5h2.7v1h-2.7v1.7H42.1z"/>
</g>
<g>
<circle class="st1" cx="25" cy="64" r="4.5"/>
<path class="st1" d="M28.2,70.9h-6.1c-2.6,0-4.6,2.2-4.6,4.7V78c2.1,1.6,4.5,2.5,7.3,2.5c3.1,0,5.9-1.2,8-3.1v-1.8
C32.8,73,30.8,70.9,28.2,70.9z"/>
<circle class="st1" cx="34" cy="65.3" r="2"/>
<path class="st1" d="M35.2,69.1h-2.3c-0.5,0-0.9,0.2-1.3,0.5c0.7,0.3,1.3,0.9,1.7,1.4c0.6,0.7,0.9,1.5,0.9,2.4
c0.2,0.5,0.2,1,0.1,1.6v0.3c0.9-1.2,1.8-3.3,2.2-4.6v-0.2C36.7,70.1,36,69.1,35.2,69.1z"/>
<circle class="st1" cx="16" cy="65.8" r="2"/>
<path class="st1" d="M15.4,75.8c-0.1-0.4-0.1-0.8,0-1.2l0-0.1c0-0.1,0-0.2,0-0.3c0-0.1,0-0.2,0-0.3c0-0.1,0-0.2,0-0.3
c0.1-1.2,0.9-2.5,1.8-3.2c0.2-0.2,0.5-0.3,0.8-0.5c-0.3-0.3-0.7-0.4-1.1-0.4h-2.3c-0.8,0-1.5,1-1.4,1.5v0.2
C13.5,72.4,14.5,74.5,15.4,75.8z"/>
</g>
<g>
<path class="st1" d="M8.1,142.5v-6.4h2.7c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2H9.3v2.1H8.1z M9.3,139.2h1.4
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1,0-0.2-0.1-0.3-0.1H9.3V139.2z"/>
<path class="st1" d="M18.3,141.4v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H18.3z"/>
<path class="st1" d="M22.1,142.5c-0.5,0-0.9-0.1-1.2-0.3s-0.7-0.4-1-0.7c-0.3-0.3-0.5-0.6-0.6-1c-0.1-0.4-0.2-0.8-0.2-1.2
c0-0.4,0.1-0.8,0.2-1.2s0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7s0.8-0.3,1.2-0.3c0.5,0,0.9,0.1,1.2,0.3s0.7,0.4,1,0.7
c0.3,0.3,0.5,0.7,0.6,1c0.1,0.4,0.2,0.8,0.2,1.2c0,0.4-0.1,0.8-0.2,1.2c-0.2,0.4-0.4,0.7-0.6,1c-0.3,0.3-0.6,0.5-1,0.7
C22.9,142.4,22.5,142.5,22.1,142.5z M20.3,139.3c0,0.3,0,0.5,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7c0.2,0.2,0.3,0.4,0.6,0.5
s0.5,0.2,0.8,0.2c0.3,0,0.5-0.1,0.8-0.2s0.4-0.3,0.6-0.5c0.1-0.2,0.3-0.4,0.3-0.7s0.1-0.5,0.1-0.8c0-0.3,0-0.5-0.1-0.8
c-0.1-0.3-0.2-0.5-0.4-0.7c-0.2-0.2-0.3-0.4-0.6-0.5c-0.2-0.1-0.5-0.2-0.7-0.2c-0.3,0-0.5,0.1-0.8,0.2s-0.4,0.3-0.6,0.5
c-0.2,0.2-0.3,0.4-0.3,0.7C20.4,138.7,20.3,139,20.3,139.3z"/>
<path class="st1" d="M26.3,142.5v-6.4H29c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2h-1.5v2.1H26.3z M27.6,139.2H29
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1,0-0.2-0.1-0.3-0.1h-1.4V139.2z"/>
<path class="st1" d="M32.1,142.5v-6.4h1.2v5.3h3.3v1.1H32.1z"/>
<path class="st1" d="M42.1,141.4v1.1h-4.4v-6.4H42v1.1h-3.1v1.5h2.7v1h-2.7v1.7H42.1z"/>
</g>
<g>
<circle class="st1" cx="25" cy="114" r="4.5"/>
<path class="st1" d="M28.2,120.9h-6.1c-2.6,0-4.6,2.2-4.6,4.7v2.4c2.1,1.6,4.5,2.5,7.3,2.5c3.1,0,5.9-1.2,8-3.1v-1.8
C32.8,123,30.8,120.9,28.2,120.9z"/>
<circle class="st1" cx="34" cy="115.3" r="2"/>
<path class="st1" d="M35.2,119.1h-2.3c-0.5,0-0.9,0.2-1.3,0.5c0.7,0.3,1.3,0.9,1.7,1.4c0.6,0.7,0.9,1.5,0.9,2.4
c0.2,0.5,0.2,1,0.1,1.6v0.3c0.9-1.2,1.8-3.3,2.2-4.6v-0.2C36.7,120.1,36,119.1,35.2,119.1z"/>
<circle class="st1" cx="16" cy="115.8" r="2"/>
<path class="st1" d="M15.4,125.8c-0.1-0.4-0.1-0.8,0-1.2l0-0.1c0-0.1,0-0.2,0-0.3c0-0.1,0-0.2,0-0.3c0-0.1,0-0.2,0-0.3
c0.1-1.2,0.9-2.5,1.8-3.2c0.2-0.2,0.5-0.3,0.8-0.5c-0.3-0.3-0.7-0.4-1.1-0.4h-2.3c-0.8,0-1.5,1-1.4,1.5v0.2
C13.5,122.4,14.5,124.5,15.4,125.8z"/>
</g>
<g>
<path class="st3" d="M8.1,42.5v-6.4h2.7c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2H9.3v2.1H8.1z M9.3,39.2h1.4
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1,0-0.2-0.1-0.3-0.1H9.3V39.2z"/>
<path class="st3" d="M18.3,41.4v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H18.3z"/>
<path class="st3" d="M22.1,42.5c-0.5,0-0.9-0.1-1.2-0.3s-0.7-0.4-1-0.7c-0.3-0.3-0.5-0.6-0.6-1c-0.1-0.4-0.2-0.8-0.2-1.2
c0-0.4,0.1-0.8,0.2-1.2s0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7s0.8-0.3,1.2-0.3c0.5,0,0.9,0.1,1.2,0.3s0.7,0.4,1,0.7
c0.3,0.3,0.5,0.7,0.6,1c0.1,0.4,0.2,0.8,0.2,1.2c0,0.4-0.1,0.8-0.2,1.2c-0.2,0.4-0.4,0.7-0.6,1c-0.3,0.3-0.6,0.5-1,0.7
C22.9,42.4,22.5,42.5,22.1,42.5z M20.3,39.3c0,0.3,0,0.5,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7c0.2,0.2,0.3,0.4,0.6,0.5s0.5,0.2,0.8,0.2
c0.3,0,0.5-0.1,0.8-0.2s0.4-0.3,0.6-0.5c0.1-0.2,0.3-0.4,0.3-0.7s0.1-0.5,0.1-0.8c0-0.3,0-0.5-0.1-0.8c-0.1-0.3-0.2-0.5-0.4-0.7
c-0.2-0.2-0.3-0.4-0.6-0.5c-0.2-0.1-0.5-0.2-0.7-0.2c-0.3,0-0.5,0.1-0.8,0.2s-0.4,0.3-0.6,0.5c-0.2,0.2-0.3,0.4-0.3,0.7
C20.4,38.7,20.3,39,20.3,39.3z"/>
<path class="st3" d="M26.3,42.5v-6.4H29c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2h-1.5v2.1H26.3z M27.6,39.2H29
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1,0-0.2-0.1-0.3-0.1h-1.4V39.2z"/>
<path class="st3" d="M32.1,42.5v-6.4h1.2v5.3h3.3v1.1H32.1z"/>
<path class="st3" d="M42.1,41.4v1.1h-4.4v-6.4H42v1.1h-3.1v1.5h2.7v1h-2.7v1.7H42.1z"/>
</g>
<g>
<circle class="st3" cx="25" cy="14" r="4.5"/>
<path class="st3" d="M28.2,20.9h-6.1c-2.6,0-4.6,2.2-4.6,4.7V28c2.1,1.6,4.5,2.5,7.3,2.5c3.1,0,5.9-1.2,8-3.1v-1.8
C32.8,23,30.8,20.9,28.2,20.9z"/>
<circle class="st3" cx="34" cy="15.3" r="2"/>
<path class="st3" d="M35.2,19.1h-2.3c-0.5,0-0.9,0.2-1.3,0.5c0.7,0.3,1.3,0.9,1.7,1.4c0.6,0.7,0.9,1.5,0.9,2.4
c0.2,0.5,0.2,1,0.1,1.6v0.3c0.9-1.2,1.8-3.3,2.2-4.6v-0.2C36.7,20.1,36,19.1,35.2,19.1z"/>
<circle class="st3" cx="16" cy="15.8" r="2"/>
<path class="st3" d="M15.4,25.8c-0.1-0.4-0.1-0.8,0-1.2l0-0.1c0-0.1,0-0.2,0-0.3c0-0.1,0-0.2,0-0.3c0-0.1,0-0.2,0-0.3
c0.1-1.2,0.9-2.5,1.8-3.2c0.2-0.2,0.5-0.3,0.8-0.5c-0.3-0.3-0.7-0.4-1.1-0.4h-2.3c-0.8,0-1.5,1-1.4,1.5v0.2
C13.5,22.4,14.5,24.5,15.4,25.8z"/>
</g>
<g>
<path class="st1" d="M8.1,192.6v-6.4h2.7c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2H9.3v2.1H8.1z M9.3,189.3h1.4
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1,0-0.2-0.1-0.3-0.1H9.3V189.3z"/>
<path class="st1" d="M18.3,191.5v1.1h-4.4v-6.4h4.4v1.1h-3.1v1.5h2.7v1h-2.7v1.7H18.3z"/>
<path class="st1" d="M22.1,192.6c-0.5,0-0.9-0.1-1.2-0.3s-0.7-0.4-1-0.7c-0.3-0.3-0.5-0.6-0.6-1c-0.1-0.4-0.2-0.8-0.2-1.2
c0-0.4,0.1-0.8,0.2-1.2s0.4-0.7,0.6-1c0.3-0.3,0.6-0.5,1-0.7s0.8-0.3,1.2-0.3c0.5,0,0.9,0.1,1.2,0.3s0.7,0.4,1,0.7
c0.3,0.3,0.5,0.7,0.6,1c0.1,0.4,0.2,0.8,0.2,1.2c0,0.4-0.1,0.8-0.2,1.2c-0.2,0.4-0.4,0.7-0.6,1c-0.3,0.3-0.6,0.5-1,0.7
C22.9,192.5,22.5,192.6,22.1,192.6z M20.3,189.4c0,0.3,0,0.5,0.1,0.8c0.1,0.3,0.2,0.5,0.4,0.7c0.2,0.2,0.3,0.4,0.6,0.5
s0.5,0.2,0.8,0.2c0.3,0,0.5-0.1,0.8-0.2s0.4-0.3,0.6-0.5c0.1-0.2,0.3-0.4,0.3-0.7s0.1-0.5,0.1-0.8c0-0.3,0-0.5-0.1-0.8
c-0.1-0.3-0.2-0.5-0.4-0.7c-0.2-0.2-0.3-0.4-0.6-0.5c-0.2-0.1-0.5-0.2-0.7-0.2c-0.3,0-0.5,0.1-0.8,0.2s-0.4,0.3-0.6,0.5
c-0.2,0.2-0.3,0.4-0.3,0.7C20.4,188.8,20.3,189.1,20.3,189.4z"/>
<path class="st1" d="M26.3,192.6v-6.4H29c0.3,0,0.6,0.1,0.8,0.2s0.5,0.3,0.6,0.5c0.2,0.2,0.3,0.4,0.4,0.7c0.1,0.3,0.2,0.5,0.2,0.8
c0,0.3,0,0.5-0.1,0.8c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.4,0.4-0.6,0.5c-0.2,0.1-0.5,0.2-0.8,0.2h-1.5v2.1H26.3z M27.6,189.3H29
c0.2,0,0.4-0.1,0.6-0.3c0.2-0.2,0.2-0.4,0.2-0.8c0-0.2,0-0.3-0.1-0.4c0-0.1-0.1-0.2-0.2-0.3c-0.1-0.1-0.2-0.2-0.3-0.2
c-0.1,0-0.2-0.1-0.3-0.1h-1.4V189.3z"/>
<path class="st1" d="M32.1,192.6v-6.4h1.2v5.3h3.3v1.1H32.1z"/>
<path class="st1" d="M42.1,191.5v1.1h-4.4v-6.4H42v1.1h-3.1v1.5h2.7v1h-2.7v1.7H42.1z"/>
</g>
<g>
<circle class="st1" cx="25" cy="164.2" r="4.5"/>
<path class="st1" d="M28.2,171h-6.1c-2.6,0-4.6,2.2-4.6,4.7v2.4c2.1,1.6,4.5,2.5,7.3,2.5c3.1,0,5.9-1.2,8-3.1v-1.8
C32.8,173.1,30.8,171,28.2,171z"/>
<circle class="st1" cx="34" cy="165.4" r="2"/>
<path class="st1" d="M35.2,169.2h-2.3c-0.5,0-0.9,0.2-1.3,0.5c0.7,0.3,1.3,0.9,1.7,1.4c0.6,0.7,0.9,1.5,0.9,2.4
c0.2,0.5,0.2,1,0.1,1.6v0.3c0.9-1.2,1.8-3.3,2.2-4.6v-0.2C36.7,170.2,36,169.2,35.2,169.2z"/>
<circle class="st1" cx="16" cy="165.9" r="2"/>
<path class="st1" d="M15.4,175.9c-0.1-0.4-0.1-0.8,0-1.2l0-0.1c0-0.1,0-0.2,0-0.3c0-0.1,0-0.2,0-0.3c0-0.1,0-0.2,0-0.3
c0.1-1.2,0.9-2.5,1.8-3.2c0.2-0.2,0.5-0.3,0.8-0.5c-0.3-0.3-0.7-0.4-1.1-0.4h-2.3c-0.8,0-1.5,1-1.4,1.5v0.2
C13.5,172.5,14.5,174.6,15.4,175.9z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -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();

265
scripts/system/pal.js Normal file
View file

@ -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

View file

@ -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);

View file

@ -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) ;

View file

@ -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));

View file

@ -81,9 +81,8 @@ ACClientApp::ACClientApp(int argc, char* argv[]) :
listenPort = parser.value(listenPortOption).toInt();
}
Setting::preInit();
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
Setting::init();
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
DependencyManager::set<AccountManager>([&]{ return QString("Mozilla/5.0 (HighFidelityACClient)"); });
DependencyManager::set<AddressManager>();

View file

@ -13,11 +13,19 @@
#include <string>
#include <vector>
#include <BuildInfo.h>
#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();
}