mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:21:24 +02:00
Merge pull request #8084 from huffman/feat/user-actions
Add client-side session id generation and new user activities
This commit is contained in:
commit
a48cce2975
34 changed files with 399 additions and 27 deletions
|
@ -68,6 +68,7 @@
|
||||||
#include <input-plugins/InputPlugin.h>
|
#include <input-plugins/InputPlugin.h>
|
||||||
#include <controllers/UserInputMapper.h>
|
#include <controllers/UserInputMapper.h>
|
||||||
#include <controllers/StateController.h>
|
#include <controllers/StateController.h>
|
||||||
|
#include <UserActivityLoggerScriptingInterface.h>
|
||||||
#include <LogHandler.h>
|
#include <LogHandler.h>
|
||||||
#include <MainWindow.h>
|
#include <MainWindow.h>
|
||||||
#include <MessagesClient.h>
|
#include <MessagesClient.h>
|
||||||
|
@ -149,6 +150,8 @@
|
||||||
#include "InterfaceParentFinder.h"
|
#include "InterfaceParentFinder.h"
|
||||||
|
|
||||||
#include "FrameTimingsScriptingInterface.h"
|
#include "FrameTimingsScriptingInterface.h"
|
||||||
|
#include <GPUIdent.h>
|
||||||
|
#include <gl/GLHelpers.h>
|
||||||
|
|
||||||
// On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
|
// On Windows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
|
||||||
// FIXME seems to be broken.
|
// FIXME seems to be broken.
|
||||||
|
@ -435,7 +438,7 @@ bool setupEssentials(int& argc, char** argv) {
|
||||||
DependencyManager::set<WindowScriptingInterface>();
|
DependencyManager::set<WindowScriptingInterface>();
|
||||||
DependencyManager::set<HMDScriptingInterface>();
|
DependencyManager::set<HMDScriptingInterface>();
|
||||||
DependencyManager::set<ResourceScriptingInterface>();
|
DependencyManager::set<ResourceScriptingInterface>();
|
||||||
|
DependencyManager::set<UserActivityLoggerScriptingInterface>();
|
||||||
|
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||||
DependencyManager::set<SpeechRecognizer>();
|
DependencyManager::set<SpeechRecognizer>();
|
||||||
|
@ -673,10 +676,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
accountManager->setIsAgent(true);
|
accountManager->setIsAgent(true);
|
||||||
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
|
accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL);
|
||||||
|
|
||||||
// sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value.
|
|
||||||
// The value will be 0 if the user blew away settings this session, which is both a feature and a bug.
|
|
||||||
UserActivityLogger::getInstance().launch(applicationVersion(), _previousSessionCrashed, sessionRunTime.get());
|
|
||||||
|
|
||||||
auto addressManager = DependencyManager::get<AddressManager>();
|
auto addressManager = DependencyManager::get<AddressManager>();
|
||||||
|
|
||||||
// use our MyAvatar position and quat for address manager path
|
// use our MyAvatar position and quat for address manager path
|
||||||
|
@ -766,6 +765,39 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
// Make sure we don't time out during slow operations at startup
|
// Make sure we don't time out during slow operations at startup
|
||||||
updateHeartbeat();
|
updateHeartbeat();
|
||||||
|
|
||||||
|
|
||||||
|
// sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value.
|
||||||
|
// The value will be 0 if the user blew away settings this session, which is both a feature and a bug.
|
||||||
|
auto gpuIdent = GPUIdent::getInstance();
|
||||||
|
auto glContextData = getGLContextData();
|
||||||
|
QJsonObject properties = {
|
||||||
|
{ "previousSessionCrashed", _previousSessionCrashed },
|
||||||
|
{ "previousSessionRuntime", sessionRunTime.get() },
|
||||||
|
{ "cpu_architecture", QSysInfo::currentCpuArchitecture() },
|
||||||
|
{ "kernel_type", QSysInfo::kernelType() },
|
||||||
|
{ "kernel_version", QSysInfo::kernelVersion() },
|
||||||
|
{ "os_type", QSysInfo::productType() },
|
||||||
|
{ "os_version", QSysInfo::productVersion() },
|
||||||
|
{ "gpu_name", gpuIdent->getName() },
|
||||||
|
{ "gpu_driver", gpuIdent->getDriver() },
|
||||||
|
{ "gpu_memory", static_cast<qint64>(gpuIdent->getMemory()) },
|
||||||
|
{ "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) },
|
||||||
|
{ "gl_version", glContextData["version"] },
|
||||||
|
{ "gl_vender", glContextData["vendor"] },
|
||||||
|
{ "gl_sl_version", glContextData["slVersion"] },
|
||||||
|
{ "gl_renderer", glContextData["renderer"] }
|
||||||
|
};
|
||||||
|
auto macVersion = QSysInfo::macVersion();
|
||||||
|
if (macVersion != QSysInfo::MV_None) {
|
||||||
|
properties["os_osx_version"] = QSysInfo::macVersion();
|
||||||
|
}
|
||||||
|
auto windowsVersion = QSysInfo::windowsVersion();
|
||||||
|
if (windowsVersion != QSysInfo::WV_None) {
|
||||||
|
properties["os_win_version"] = QSysInfo::windowsVersion();
|
||||||
|
}
|
||||||
|
UserActivityLogger::getInstance().logAction("launch", properties);
|
||||||
|
|
||||||
|
|
||||||
// Tell our entity edit sender about our known jurisdictions
|
// Tell our entity edit sender about our known jurisdictions
|
||||||
_entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
|
_entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
|
||||||
_entityEditSender.setMyAvatar(getMyAvatar());
|
_entityEditSender.setMyAvatar(getMyAvatar());
|
||||||
|
@ -1061,6 +1093,89 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add periodic checks to send user activity data
|
||||||
|
static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000;
|
||||||
|
static int SEND_STATS_INTERVAL_MS = 10000;
|
||||||
|
static int NEARBY_AVATAR_RADIUS_METERS = 10;
|
||||||
|
|
||||||
|
// Periodically send fps as a user activity event
|
||||||
|
QTimer* sendStatsTimer = new QTimer(this);
|
||||||
|
sendStatsTimer->setInterval(SEND_STATS_INTERVAL_MS);
|
||||||
|
connect(sendStatsTimer, &QTimer::timeout, this, [this]() {
|
||||||
|
QJsonObject properties = {};
|
||||||
|
MemoryInfo memInfo;
|
||||||
|
if (getMemoryInfo(memInfo)) {
|
||||||
|
properties["system_memory_total"] = static_cast<qint64>(memInfo.totalMemoryBytes);
|
||||||
|
properties["system_memory_used"] = static_cast<qint64>(memInfo.usedMemoryBytes);
|
||||||
|
properties["process_memory_used"] = static_cast<qint64>(memInfo.processUsedMemoryBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||||
|
|
||||||
|
properties["fps"] = _frameCounter.rate();
|
||||||
|
properties["present_rate"] = displayPlugin->presentRate();
|
||||||
|
properties["new_frame_present_rate"] = displayPlugin->newFramePresentRate();
|
||||||
|
properties["dropped_frame_rate"] = displayPlugin->droppedFrameRate();
|
||||||
|
properties["sim_rate"] = getAverageSimsPerSecond();
|
||||||
|
properties["avatar_sim_rate"] = getAvatarSimrate();
|
||||||
|
|
||||||
|
auto bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
|
||||||
|
properties["packet_rate_in"] = bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond();
|
||||||
|
properties["packet_rate_out"] = bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond();
|
||||||
|
properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond();
|
||||||
|
properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond();
|
||||||
|
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer);
|
||||||
|
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||||
|
SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer);
|
||||||
|
SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||||
|
SharedNodePointer messagesMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer);
|
||||||
|
properties["entity_ping"] = entityServerNode ? entityServerNode->getPingMs() : -1;
|
||||||
|
properties["audio_ping"] = audioMixerNode ? audioMixerNode->getPingMs() : -1;
|
||||||
|
properties["avatar_ping"] = avatarMixerNode ? avatarMixerNode->getPingMs() : -1;
|
||||||
|
properties["asset_ping"] = assetServerNode ? assetServerNode->getPingMs() : -1;
|
||||||
|
properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1;
|
||||||
|
|
||||||
|
auto loadingRequests = ResourceCache::getLoadingRequests();
|
||||||
|
properties["active_downloads"] = loadingRequests.size();
|
||||||
|
properties["pending_downloads"] = ResourceCache::getPendingRequestCount();
|
||||||
|
|
||||||
|
properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;
|
||||||
|
|
||||||
|
UserActivityLogger::getInstance().logAction("stats", properties);
|
||||||
|
});
|
||||||
|
sendStatsTimer->start();
|
||||||
|
|
||||||
|
|
||||||
|
// Periodically check for count of nearby avatars
|
||||||
|
static int lastCountOfNearbyAvatars = -1;
|
||||||
|
QTimer* checkNearbyAvatarsTimer = new QTimer(this);
|
||||||
|
checkNearbyAvatarsTimer->setInterval(CHECK_NEARBY_AVATARS_INTERVAL_MS);
|
||||||
|
connect(checkNearbyAvatarsTimer, &QTimer::timeout, this, [this]() {
|
||||||
|
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||||
|
int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(),
|
||||||
|
NEARBY_AVATAR_RADIUS_METERS) - 1;
|
||||||
|
if (nearbyAvatars != lastCountOfNearbyAvatars) {
|
||||||
|
lastCountOfNearbyAvatars = nearbyAvatars;
|
||||||
|
UserActivityLogger::getInstance().logAction("nearby_avatars", { { "count", nearbyAvatars } });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
checkNearbyAvatarsTimer->start();
|
||||||
|
|
||||||
|
// Track user activity event when we receive a mute packet
|
||||||
|
auto onMutedByMixer = []() {
|
||||||
|
UserActivityLogger::getInstance().logAction("received_mute_packet");
|
||||||
|
};
|
||||||
|
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::mutedByMixer, this, onMutedByMixer);
|
||||||
|
|
||||||
|
// Track when the address bar is opened
|
||||||
|
auto onAddressBarToggled = [this]() {
|
||||||
|
// Record time
|
||||||
|
UserActivityLogger::getInstance().logAction("opened_address_bar", { { "uptime_ms", _sessionRunTimer.elapsed() } });
|
||||||
|
};
|
||||||
|
connect(DependencyManager::get<DialogsManager>().data(), &DialogsManager::addressBarToggled, this, onAddressBarToggled);
|
||||||
|
|
||||||
// Make sure we don't time out during slow operations at startup
|
// Make sure we don't time out during slow operations at startup
|
||||||
updateHeartbeat();
|
updateHeartbeat();
|
||||||
|
|
||||||
|
@ -4574,6 +4689,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||||
scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface());
|
scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface());
|
||||||
|
|
||||||
|
scriptEngine->registerGlobalObject("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::canAcceptURL(const QString& urlString) const {
|
bool Application::canAcceptURL(const QString& urlString) const {
|
||||||
|
@ -5176,6 +5293,11 @@ void Application::updateDisplayMode() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserActivityLogger::getInstance().logAction("changed_display_mode", {
|
||||||
|
{ "previous_display_mode", _displayPlugin ? _displayPlugin->getName() : "" },
|
||||||
|
{ "display_mode", newDisplayPlugin ? newDisplayPlugin->getName() : "" }
|
||||||
|
});
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
|
||||||
// Make the switch atomic from the perspective of other threads
|
// Make the switch atomic from the perspective of other threads
|
||||||
|
|
|
@ -211,6 +211,8 @@ public:
|
||||||
|
|
||||||
float getRenderResolutionScale() const;
|
float getRenderResolutionScale() const;
|
||||||
|
|
||||||
|
qint64 getCurrentSessionRuntime() const { return _sessionRunTimer.elapsed(); }
|
||||||
|
|
||||||
bool isAboutToQuit() const { return _aboutToQuit; }
|
bool isAboutToQuit() const { return _aboutToQuit; }
|
||||||
|
|
||||||
// the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display
|
// the isHMDMode is true whenever we use the interface from an HMD and not a standard flat display
|
||||||
|
|
|
@ -80,7 +80,8 @@ void DiscoverabilityManager::updateLocation() {
|
||||||
locationObject.insert(FRIENDS_ONLY_KEY_IN_LOCATION, (_mode.get() == Discoverability::Friends));
|
locationObject.insert(FRIENDS_ONLY_KEY_IN_LOCATION, (_mode.get() == Discoverability::Friends));
|
||||||
|
|
||||||
// if we have a session ID add it now, otherwise add a null value
|
// if we have a session ID add it now, otherwise add a null value
|
||||||
rootObject[SESSION_ID_KEY] = _sessionID.isEmpty() ? QJsonValue() : _sessionID;
|
auto sessionID = accountManager->getSessionID();
|
||||||
|
rootObject[SESSION_ID_KEY] = sessionID.isNull() ? QJsonValue() : sessionID.toString();
|
||||||
|
|
||||||
JSONCallbackParameters callbackParameters;
|
JSONCallbackParameters callbackParameters;
|
||||||
callbackParameters.jsonCallbackReceiver = this;
|
callbackParameters.jsonCallbackReceiver = this;
|
||||||
|
@ -110,11 +111,8 @@ void DiscoverabilityManager::updateLocation() {
|
||||||
callbackParameters.jsonCallbackMethod = "handleHeartbeatResponse";
|
callbackParameters.jsonCallbackMethod = "handleHeartbeatResponse";
|
||||||
|
|
||||||
QJsonObject heartbeatObject;
|
QJsonObject heartbeatObject;
|
||||||
if (!_sessionID.isEmpty()) {
|
auto sessionID = accountManager->getSessionID();
|
||||||
heartbeatObject[SESSION_ID_KEY] = _sessionID;
|
heartbeatObject[SESSION_ID_KEY] = sessionID.isNull() ? QJsonValue() : sessionID.toString();
|
||||||
} else {
|
|
||||||
heartbeatObject[SESSION_ID_KEY] = QJsonValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
accountManager->sendRequest(API_USER_HEARTBEAT_PATH, AccountManagerAuth::Optional,
|
accountManager->sendRequest(API_USER_HEARTBEAT_PATH, AccountManagerAuth::Optional,
|
||||||
QNetworkAccessManager::PutOperation, callbackParameters,
|
QNetworkAccessManager::PutOperation, callbackParameters,
|
||||||
|
@ -126,11 +124,11 @@ void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply& requestReply
|
||||||
auto dataObject = AccountManager::dataObjectFromResponse(requestReply);
|
auto dataObject = AccountManager::dataObjectFromResponse(requestReply);
|
||||||
|
|
||||||
if (!dataObject.isEmpty()) {
|
if (!dataObject.isEmpty()) {
|
||||||
_sessionID = dataObject[SESSION_ID_KEY].toString();
|
auto sessionID = dataObject[SESSION_ID_KEY].toString();
|
||||||
|
|
||||||
// give that session ID to the account manager
|
// give that session ID to the account manager
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
accountManager->setSessionID(_sessionID);
|
accountManager->setSessionID(sessionID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,6 @@ private:
|
||||||
DiscoverabilityManager();
|
DiscoverabilityManager();
|
||||||
|
|
||||||
Setting::Handle<int> _mode;
|
Setting::Handle<int> _mode;
|
||||||
QString _sessionID;
|
|
||||||
QJsonObject _lastLocationObject;
|
QJsonObject _lastLocationObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,20 @@ bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AvatarHashMap::numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters) {
|
||||||
|
auto hashCopy = getHashCopy();
|
||||||
|
auto rangeMeters2 = rangeMeters * rangeMeters;
|
||||||
|
int count = 0;
|
||||||
|
for (const AvatarSharedPointer& sharedAvatar : hashCopy) {
|
||||||
|
glm::vec3 avatarPosition = sharedAvatar->getPosition();
|
||||||
|
auto distance2 = glm::distance2(avatarPosition, position);
|
||||||
|
if (distance2 < rangeMeters2) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
AvatarSharedPointer AvatarHashMap::newSharedAvatar() {
|
AvatarSharedPointer AvatarHashMap::newSharedAvatar() {
|
||||||
return std::make_shared<AvatarData>();
|
return std::make_shared<AvatarData>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
Q_INVOKABLE AvatarData* getAvatar(QUuid avatarID);
|
Q_INVOKABLE AvatarData* getAvatar(QUuid avatarID);
|
||||||
|
|
||||||
virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) { return findAvatar(sessionID); }
|
virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) { return findAvatar(sessionID); }
|
||||||
|
int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void avatarAddedEvent(const QUuid& sessionUUID);
|
void avatarAddedEvent(const QUuid& sessionUUID);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <QtGui/QSurfaceFormat>
|
#include <QtGui/QSurfaceFormat>
|
||||||
#include <QtOpenGL/QGL>
|
#include <QtOpenGL/QGL>
|
||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
|
#include <QtCore/QRegularExpression>
|
||||||
|
|
||||||
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
||||||
static QSurfaceFormat format;
|
static QSurfaceFormat format;
|
||||||
|
@ -39,6 +40,13 @@ const QGLFormat& getDefaultGLFormat() {
|
||||||
return glFormat;
|
return glFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int glVersionToInteger(QString glVersion) {
|
||||||
|
QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]"));
|
||||||
|
int majorNumber = versionParts[0].toInt();
|
||||||
|
int minorNumber = versionParts[1].toInt();
|
||||||
|
return majorNumber * 100 + minorNumber * 10;
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject getGLContextData() {
|
QJsonObject getGLContextData() {
|
||||||
if (!QOpenGLContext::currentContext()) {
|
if (!QOpenGLContext::currentContext()) {
|
||||||
return QJsonObject();
|
return QJsonObject();
|
||||||
|
|
|
@ -27,5 +27,6 @@ void setGLFormatVersion(F& format, int major = 4, int minor = 5) { format.setVer
|
||||||
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat();
|
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat();
|
||||||
const QGLFormat& getDefaultGLFormat();
|
const QGLFormat& getDefaultGLFormat();
|
||||||
QJsonObject getGLContextData();
|
QJsonObject getGLContextData();
|
||||||
|
int glVersionToInteger(QString glVersion);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -44,6 +44,7 @@ Q_DECLARE_METATYPE(QNetworkAccessManager::Operation)
|
||||||
Q_DECLARE_METATYPE(JSONCallbackParameters)
|
Q_DECLARE_METATYPE(JSONCallbackParameters)
|
||||||
|
|
||||||
const QString ACCOUNTS_GROUP = "accounts";
|
const QString ACCOUNTS_GROUP = "accounts";
|
||||||
|
static const auto METAVERSE_SESSION_ID_HEADER = QString("HFM-SessionID").toLocal8Bit();
|
||||||
|
|
||||||
JSONCallbackParameters::JSONCallbackParameters(QObject* jsonCallbackReceiver, const QString& jsonCallbackMethod,
|
JSONCallbackParameters::JSONCallbackParameters(QObject* jsonCallbackReceiver, const QString& jsonCallbackMethod,
|
||||||
QObject* errorCallbackReceiver, const QString& errorCallbackMethod,
|
QObject* errorCallbackReceiver, const QString& errorCallbackMethod,
|
||||||
|
@ -222,8 +223,7 @@ void AccountManager::sendRequest(const QString& path,
|
||||||
// if we're allowed to send usage data, include whatever the current session ID is with this request
|
// if we're allowed to send usage data, include whatever the current session ID is with this request
|
||||||
auto& activityLogger = UserActivityLogger::getInstance();
|
auto& activityLogger = UserActivityLogger::getInstance();
|
||||||
if (activityLogger.isEnabled()) {
|
if (activityLogger.isEnabled()) {
|
||||||
static const QString METAVERSE_SESSION_ID_HEADER = "HFM-SessionID";
|
networkRequest.setRawHeader(METAVERSE_SESSION_ID_HEADER,
|
||||||
networkRequest.setRawHeader(METAVERSE_SESSION_ID_HEADER.toLocal8Bit(),
|
|
||||||
uuidStringWithoutCurlyBraces(_sessionID).toLocal8Bit());
|
uuidStringWithoutCurlyBraces(_sessionID).toLocal8Bit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,6 +322,9 @@ void AccountManager::processReply() {
|
||||||
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||||
|
|
||||||
if (requestReply->error() == QNetworkReply::NoError) {
|
if (requestReply->error() == QNetworkReply::NoError) {
|
||||||
|
if (requestReply->hasRawHeader(METAVERSE_SESSION_ID_HEADER)) {
|
||||||
|
_sessionID = requestReply->rawHeader(METAVERSE_SESSION_ID_HEADER);
|
||||||
|
}
|
||||||
passSuccessToCallback(requestReply);
|
passSuccessToCallback(requestReply);
|
||||||
} else {
|
} else {
|
||||||
passErrorToCallback(requestReply);
|
passErrorToCallback(requestReply);
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
|
|
||||||
class JSONCallbackParameters {
|
class JSONCallbackParameters {
|
||||||
public:
|
public:
|
||||||
JSONCallbackParameters(QObject* jsonCallbackReceiver = NULL, const QString& jsonCallbackMethod = QString(),
|
JSONCallbackParameters(QObject* jsonCallbackReceiver = nullptr, const QString& jsonCallbackMethod = QString(),
|
||||||
QObject* errorCallbackReceiver = NULL, const QString& errorCallbackMethod = QString(),
|
QObject* errorCallbackReceiver = nullptr, const QString& errorCallbackMethod = QString(),
|
||||||
QObject* updateReceiver = NULL, const QString& updateSlot = QString());
|
QObject* updateReceiver = nullptr, const QString& updateSlot = QString());
|
||||||
|
|
||||||
bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; }
|
bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; }
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ public:
|
||||||
|
|
||||||
static QJsonObject dataObjectFromResponse(QNetworkReply& requestReply);
|
static QJsonObject dataObjectFromResponse(QNetworkReply& requestReply);
|
||||||
|
|
||||||
|
QUuid getSessionID() const { return _sessionID; }
|
||||||
void setSessionID(const QUuid& sessionID) { _sessionID = sessionID; }
|
void setSessionID(const QUuid& sessionID) { _sessionID = sessionID; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -139,7 +140,7 @@ private:
|
||||||
bool _isWaitingForKeypairResponse { false };
|
bool _isWaitingForKeypairResponse { false };
|
||||||
QByteArray _pendingPrivateKey;
|
QByteArray _pendingPrivateKey;
|
||||||
|
|
||||||
QUuid _sessionID;
|
QUuid _sessionID { QUuid::createUuid() };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AccountManager_h
|
#endif // hifi_AccountManager_h
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "AddressManager.h"
|
#include "AddressManager.h"
|
||||||
#include "NodeList.h"
|
#include "NodeList.h"
|
||||||
#include "NetworkLogging.h"
|
#include "NetworkLogging.h"
|
||||||
|
#include "UserActivityLogger.h"
|
||||||
|
|
||||||
|
|
||||||
const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager";
|
const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager";
|
||||||
|
@ -130,6 +131,10 @@ const JSONCallbackParameters& AddressManager::apiCallbackParameters() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
|
static QString URL_TYPE_USER = "user";
|
||||||
|
static QString URL_TYPE_DOMAIN_ID = "domain_id";
|
||||||
|
static QString URL_TYPE_PLACE = "place";
|
||||||
|
static QString URL_TYPE_NETWORK_ADDRESS = "network_address";
|
||||||
if (lookupUrl.scheme() == HIFI_URL_SCHEME) {
|
if (lookupUrl.scheme() == HIFI_URL_SCHEME) {
|
||||||
|
|
||||||
qCDebug(networking) << "Trying to go to URL" << lookupUrl.toString();
|
qCDebug(networking) << "Trying to go to URL" << lookupUrl.toString();
|
||||||
|
@ -147,6 +152,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
if (handleUsername(lookupUrl.authority())) {
|
if (handleUsername(lookupUrl.authority())) {
|
||||||
// handled a username for lookup
|
// handled a username for lookup
|
||||||
|
|
||||||
|
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_USER, lookupUrl.toString());
|
||||||
|
|
||||||
// in case we're failing to connect to where we thought this user was
|
// in case we're failing to connect to where we thought this user was
|
||||||
// store their username as previous lookup so we can refresh their location via API
|
// store their username as previous lookup so we can refresh their location via API
|
||||||
_previousLookup = lookupUrl;
|
_previousLookup = lookupUrl;
|
||||||
|
@ -157,6 +164,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
if (handleNetworkAddress(lookupUrl.host()
|
if (handleNetworkAddress(lookupUrl.host()
|
||||||
+ (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())), trigger, hostChanged)) {
|
+ (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())), trigger, hostChanged)) {
|
||||||
|
|
||||||
|
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_NETWORK_ADDRESS, lookupUrl.toString());
|
||||||
|
|
||||||
// a network address lookup clears the previous lookup since we don't expect to re-attempt it
|
// a network address lookup clears the previous lookup since we don't expect to re-attempt it
|
||||||
_previousLookup.clear();
|
_previousLookup.clear();
|
||||||
|
|
||||||
|
@ -174,6 +183,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
// we may have a path that defines a relative viewpoint - if so we should jump to that now
|
// we may have a path that defines a relative viewpoint - if so we should jump to that now
|
||||||
handlePath(path, trigger);
|
handlePath(path, trigger);
|
||||||
} else if (handleDomainID(lookupUrl.host())){
|
} else if (handleDomainID(lookupUrl.host())){
|
||||||
|
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_DOMAIN_ID, lookupUrl.toString());
|
||||||
|
|
||||||
// store this domain ID as the previous lookup in case we're failing to connect and want to refresh API info
|
// store this domain ID as the previous lookup in case we're failing to connect and want to refresh API info
|
||||||
_previousLookup = lookupUrl;
|
_previousLookup = lookupUrl;
|
||||||
|
|
||||||
|
@ -181,6 +192,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl, LookupTrigger trigger) {
|
||||||
// try to look up the domain ID on the metaverse API
|
// try to look up the domain ID on the metaverse API
|
||||||
attemptDomainIDLookup(lookupUrl.host(), lookupUrl.path(), trigger);
|
attemptDomainIDLookup(lookupUrl.host(), lookupUrl.path(), trigger);
|
||||||
} else {
|
} else {
|
||||||
|
UserActivityLogger::getInstance().wentTo(trigger, URL_TYPE_PLACE, lookupUrl.toString());
|
||||||
|
|
||||||
// store this place name as the previous lookup in case we fail to connect and want to refresh API info
|
// store this place name as the previous lookup in case we fail to connect and want to refresh API info
|
||||||
_previousLookup = lookupUrl;
|
_previousLookup = lookupUrl;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "UserActivityLogger.h"
|
#include "UserActivityLogger.h"
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
#include "AddressManager.h"
|
||||||
|
|
||||||
static const QString USER_ACTIVITY_URL = "/api/v1/user_activities";
|
static const QString USER_ACTIVITY_URL = "/api/v1/user_activities";
|
||||||
|
|
||||||
|
@ -125,6 +126,19 @@ void UserActivityLogger::changedDomain(QString domainURL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceName) {
|
void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceName) {
|
||||||
|
static QStringList DEVICE_BLACKLIST = {
|
||||||
|
"Desktop",
|
||||||
|
"NullDisplayPlugin",
|
||||||
|
"3D TV - Side by Side Stereo",
|
||||||
|
"3D TV - Interleaved",
|
||||||
|
|
||||||
|
"Keyboard/Mouse"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DEVICE_BLACKLIST.contains(deviceName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const QString ACTION_NAME = "connected_device";
|
const QString ACTION_NAME = "connected_device";
|
||||||
QJsonObject actionDetails;
|
QJsonObject actionDetails;
|
||||||
const QString TYPE_OF_DEVICE = "type_of_device";
|
const QString TYPE_OF_DEVICE = "type_of_device";
|
||||||
|
@ -148,12 +162,34 @@ void UserActivityLogger::loadedScript(QString scriptName) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserActivityLogger::wentTo(QString destinationType, QString destinationName) {
|
void UserActivityLogger::wentTo(AddressManager::LookupTrigger lookupTrigger, QString destinationType, QString destinationName) {
|
||||||
|
// Only accept these types of triggers. Other triggers are usually used internally in AddressManager.
|
||||||
|
QString trigger;
|
||||||
|
switch (lookupTrigger) {
|
||||||
|
case AddressManager::UserInput:
|
||||||
|
trigger = "UserInput";
|
||||||
|
break;
|
||||||
|
case AddressManager::Back:
|
||||||
|
trigger = "Back";
|
||||||
|
break;
|
||||||
|
case AddressManager::Forward:
|
||||||
|
trigger = "Forward";
|
||||||
|
break;
|
||||||
|
case AddressManager::StartupFromSettings:
|
||||||
|
trigger = "StartupFromSettings";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const QString ACTION_NAME = "went_to";
|
const QString ACTION_NAME = "went_to";
|
||||||
QJsonObject actionDetails;
|
QJsonObject actionDetails;
|
||||||
|
const QString TRIGGER_TYPE_KEY = "trigger";
|
||||||
const QString DESTINATION_TYPE_KEY = "destination_type";
|
const QString DESTINATION_TYPE_KEY = "destination_type";
|
||||||
const QString DESTINATION_NAME_KEY = "detination_name";
|
const QString DESTINATION_NAME_KEY = "detination_name";
|
||||||
|
|
||||||
|
actionDetails.insert(TRIGGER_TYPE_KEY, trigger);
|
||||||
actionDetails.insert(DESTINATION_TYPE_KEY, destinationType);
|
actionDetails.insert(DESTINATION_TYPE_KEY, destinationType);
|
||||||
actionDetails.insert(DESTINATION_NAME_KEY, destinationName);
|
actionDetails.insert(DESTINATION_NAME_KEY, destinationName);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
|
#include "AddressManager.h"
|
||||||
|
|
||||||
class UserActivityLogger : public QObject {
|
class UserActivityLogger : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -42,7 +43,7 @@ public slots:
|
||||||
void changedDomain(QString domainURL);
|
void changedDomain(QString domainURL);
|
||||||
void connectedDevice(QString typeOfDevice, QString deviceName);
|
void connectedDevice(QString typeOfDevice, QString deviceName);
|
||||||
void loadedScript(QString scriptName);
|
void loadedScript(QString scriptName);
|
||||||
void wentTo(QString destinationType, QString destinationName);
|
void wentTo(AddressManager::LookupTrigger trigger, QString destinationType, QString destinationName);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void requestError(QNetworkReply& errorReply);
|
void requestError(QNetworkReply& errorReply);
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// UserActivityLoggerScriptingInterface.h
|
||||||
|
// libraries/networking/src
|
||||||
|
//
|
||||||
|
// Created by Ryan Huffman on 6/06/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 "UserActivityLoggerScriptingInterface.h"
|
||||||
|
#include "UserActivityLogger.h"
|
||||||
|
|
||||||
|
void UserActivityLoggerScriptingInterface::enabledEdit() {
|
||||||
|
logAction("enabled_edit");
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserActivityLoggerScriptingInterface::openedMarketplace() {
|
||||||
|
logAction("opened_marketplace");
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserActivityLoggerScriptingInterface::toggledAway(bool isAway) {
|
||||||
|
logAction("toggled_away", { { "is_away", isAway } });
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserActivityLoggerScriptingInterface::logAction(QString action, QJsonObject details) {
|
||||||
|
QMetaObject::invokeMethod(&UserActivityLogger::getInstance(), "logAction",
|
||||||
|
Q_ARG(QString, action),
|
||||||
|
Q_ARG(QJsonObject, details));
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
//
|
||||||
|
// UserActivityLoggerScriptingInterface.h
|
||||||
|
// libraries/networking/src
|
||||||
|
//
|
||||||
|
// Created by Ryan Huffman on 6/06/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_UserActivityLoggerScriptingInterface_h
|
||||||
|
#define hifi_UserActivityLoggerScriptingInterface_h
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
|
class UserActivityLoggerScriptingInterface : public QObject, public Dependency {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Q_INVOKABLE void enabledEdit();
|
||||||
|
Q_INVOKABLE void openedMarketplace();
|
||||||
|
Q_INVOKABLE void toggledAway(bool isAway);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void logAction(QString action, QJsonObject details = {});
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_UserActivityLoggerScriptingInterface_h
|
|
@ -15,6 +15,7 @@
|
||||||
#include "Forward.h"
|
#include "Forward.h"
|
||||||
|
|
||||||
class Plugin : public QObject {
|
class Plugin : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
/// \return human-readable name
|
/// \return human-readable name
|
||||||
virtual const QString& getName() const = 0;
|
virtual const QString& getName() const = 0;
|
||||||
|
@ -63,6 +64,13 @@ public:
|
||||||
virtual void saveSettings() const {}
|
virtual void saveSettings() const {}
|
||||||
virtual void loadSettings() {}
|
virtual void loadSettings() {}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
// These signals should be emitted when a device is first known to be available. In some cases this will
|
||||||
|
// be in `init()`, in other cases, like Neuron, this isn't known until activation.
|
||||||
|
// SDL2 isn't a device itself, but can have 0+ subdevices. subdeviceConnected is used in this case.
|
||||||
|
void deviceConnected(QString pluginName) const;
|
||||||
|
void subdeviceConnected(QString pluginName, QString subdeviceName) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _active { false };
|
bool _active { false };
|
||||||
PluginContainer* _container { nullptr };
|
PluginContainer* _container { nullptr };
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QPluginLoader>
|
#include <QtCore/QPluginLoader>
|
||||||
|
|
||||||
|
#include <DependencyManager.h>
|
||||||
|
#include <UserActivityLogger.h>
|
||||||
|
|
||||||
#include "RuntimePlugin.h"
|
#include "RuntimePlugin.h"
|
||||||
#include "DisplayPlugin.h"
|
#include "DisplayPlugin.h"
|
||||||
#include "InputPlugin.h"
|
#include "InputPlugin.h"
|
||||||
|
@ -119,6 +122,15 @@ static DisplayPluginList displayPlugins;
|
||||||
|
|
||||||
const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
|
static auto deviceAddedCallback = [](QString deviceName) {
|
||||||
|
qDebug() << "Added device: " << deviceName;
|
||||||
|
UserActivityLogger::getInstance().connectedDevice("display", deviceName);
|
||||||
|
};
|
||||||
|
static auto subdeviceAddedCallback = [](QString pluginName, QString deviceName) {
|
||||||
|
qDebug() << "Added subdevice: " << deviceName;
|
||||||
|
UserActivityLogger::getInstance().connectedDevice("display", pluginName + " | " + deviceName);
|
||||||
|
};
|
||||||
|
|
||||||
std::call_once(once, [&] {
|
std::call_once(once, [&] {
|
||||||
// Grab the built in plugins
|
// Grab the built in plugins
|
||||||
displayPlugins = ::getDisplayPlugins();
|
displayPlugins = ::getDisplayPlugins();
|
||||||
|
@ -133,6 +145,8 @@ const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto plugin : displayPlugins) {
|
for (auto plugin : displayPlugins) {
|
||||||
|
connect(plugin.get(), &Plugin::deviceConnected, this, deviceAddedCallback, Qt::QueuedConnection);
|
||||||
|
connect(plugin.get(), &Plugin::subdeviceConnected, this, subdeviceAddedCallback, Qt::QueuedConnection);
|
||||||
plugin->setContainer(_container);
|
plugin->setContainer(_container);
|
||||||
plugin->init();
|
plugin->init();
|
||||||
}
|
}
|
||||||
|
@ -154,6 +168,15 @@ void PluginManager::disableDisplayPlugin(const QString& name) {
|
||||||
const InputPluginList& PluginManager::getInputPlugins() {
|
const InputPluginList& PluginManager::getInputPlugins() {
|
||||||
static InputPluginList inputPlugins;
|
static InputPluginList inputPlugins;
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
|
static auto deviceAddedCallback = [](QString deviceName) {
|
||||||
|
qDebug() << "Added device: " << deviceName;
|
||||||
|
UserActivityLogger::getInstance().connectedDevice("input", deviceName);
|
||||||
|
};
|
||||||
|
static auto subdeviceAddedCallback = [](QString pluginName, QString deviceName) {
|
||||||
|
qDebug() << "Added subdevice: " << deviceName;
|
||||||
|
UserActivityLogger::getInstance().connectedDevice("input", pluginName + " | " + deviceName);
|
||||||
|
};
|
||||||
|
|
||||||
std::call_once(once, [&] {
|
std::call_once(once, [&] {
|
||||||
inputPlugins = ::getInputPlugins();
|
inputPlugins = ::getInputPlugins();
|
||||||
|
|
||||||
|
@ -170,6 +193,8 @@ const InputPluginList& PluginManager::getInputPlugins() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto plugin : inputPlugins) {
|
for (auto plugin : inputPlugins) {
|
||||||
|
connect(plugin.get(), &Plugin::deviceConnected, this, deviceAddedCallback, Qt::QueuedConnection);
|
||||||
|
connect(plugin.get(), &Plugin::subdeviceConnected, this, subdeviceAddedCallback, Qt::QueuedConnection);
|
||||||
plugin->setContainer(_container);
|
plugin->setContainer(_container);
|
||||||
plugin->init();
|
plugin->init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer)
|
||||||
}
|
}
|
||||||
if (count > bestCount) {
|
if (count > bestCount) {
|
||||||
bestCount = count;
|
bestCount = count;
|
||||||
_name = sString;
|
_name = QString(sString).trimmed();
|
||||||
|
|
||||||
hr = spInstance->Get(CComBSTR(_T("DriverVersion")), 0, &var, 0, 0);
|
hr = spInstance->Get(CComBSTR(_T("DriverVersion")), 0, &var, 0, 0);
|
||||||
if (hr == S_OK) {
|
if (hr == S_OK) {
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include "CPUIdent.h"
|
#include "CPUIdent.h"
|
||||||
|
#include <Psapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -843,3 +844,29 @@ void printSystemInformation() {
|
||||||
(envVariables.contains(env) ? " = " + envVariables.value(env) : " NOT FOUND");
|
(envVariables.contains(env) ? " = " + envVariables.value(env) : " NOT FOUND");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getMemoryInfo(MemoryInfo& info) {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
MEMORYSTATUSEX ms;
|
||||||
|
ms.dwLength = sizeof(ms);
|
||||||
|
if (!GlobalMemoryStatusEx(&ms)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.totalMemoryBytes = ms.ullTotalPhys;
|
||||||
|
info.availMemoryBytes = ms.ullAvailPhys;
|
||||||
|
info.usedMemoryBytes = ms.ullTotalPhys - ms.ullAvailPhys;
|
||||||
|
|
||||||
|
|
||||||
|
PROCESS_MEMORY_COUNTERS_EX pmc;
|
||||||
|
if (!GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&pmc), sizeof(pmc))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
info.processUsedMemoryBytes = pmc.PrivateUsage;
|
||||||
|
info.processPeakUsedMemoryBytes = pmc.PeakPagefileUsage;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -204,4 +204,14 @@ void disableQtBearerPoll();
|
||||||
|
|
||||||
void printSystemInformation();
|
void printSystemInformation();
|
||||||
|
|
||||||
|
struct MemoryInfo {
|
||||||
|
uint64_t totalMemoryBytes;
|
||||||
|
uint64_t availMemoryBytes;
|
||||||
|
uint64_t usedMemoryBytes;
|
||||||
|
uint64_t processUsedMemoryBytes;
|
||||||
|
uint64_t processPeakUsedMemoryBytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool getMemoryInfo(MemoryInfo& info);
|
||||||
|
|
||||||
#endif // hifi_SharedUtil_h
|
#endif // hifi_SharedUtil_h
|
||||||
|
|
|
@ -387,6 +387,8 @@ bool NeuronPlugin::activate() {
|
||||||
} else {
|
} else {
|
||||||
qCDebug(inputplugins) << "NeuronPlugin: success connecting to " << _serverAddress.c_str() << ":" << _serverPort;
|
qCDebug(inputplugins) << "NeuronPlugin: success connecting to " << _serverAddress.c_str() << ":" << _serverPort;
|
||||||
|
|
||||||
|
emit deviceConnected(getName());
|
||||||
|
|
||||||
BRRegisterAutoSyncParmeter(_socketRef, Cmd_CombinationMode);
|
BRRegisterAutoSyncParmeter(_socketRef, Cmd_CombinationMode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ void SDL2Manager::init() {
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
userInputMapper->registerDevice(joystick);
|
userInputMapper->registerDevice(joystick);
|
||||||
emit joystickAdded(joystick.get());
|
emit joystickAdded(joystick.get());
|
||||||
|
emit subdeviceConnected(getName(), SDL_GameControllerName(controller));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +158,7 @@ void SDL2Manager::pluginUpdate(float deltaTime, const controller::InputCalibrati
|
||||||
_openJoysticks[id] = joystick;
|
_openJoysticks[id] = joystick;
|
||||||
userInputMapper->registerDevice(joystick);
|
userInputMapper->registerDevice(joystick);
|
||||||
emit joystickAdded(joystick.get());
|
emit joystickAdded(joystick.get());
|
||||||
|
emit subdeviceConnected(getName(), SDL_GameControllerName(controller));
|
||||||
}
|
}
|
||||||
} else if (event.type == SDL_CONTROLLERDEVICEREMOVED) {
|
} else if (event.type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||||
if (_openJoysticks.contains(event.cdevice.which)) {
|
if (_openJoysticks.contains(event.cdevice.which)) {
|
||||||
|
|
|
@ -137,6 +137,12 @@ void SixenseManager::setSixenseFilter(bool filter) {
|
||||||
void SixenseManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
void SixenseManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
||||||
BAIL_IF_NOT_LOADED
|
BAIL_IF_NOT_LOADED
|
||||||
|
|
||||||
|
static bool sixenseHasBeenConnected { false };
|
||||||
|
if (!sixenseHasBeenConnected && sixenseIsBaseConnected(0)) {
|
||||||
|
sixenseHasBeenConnected = true;
|
||||||
|
emit deviceConnected(getName());
|
||||||
|
}
|
||||||
|
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
userInputMapper->withLock([&, this]() {
|
userInputMapper->withLock([&, this]() {
|
||||||
_inputDevice->update(deltaTime, inputCalibrationData);
|
_inputDevice->update(deltaTime, inputCalibrationData);
|
||||||
|
|
|
@ -58,7 +58,6 @@ bool SpacemouseManager::activate() {
|
||||||
if (instance->getDeviceID() == controller::Input::INVALID_DEVICE) {
|
if (instance->getDeviceID() == controller::Input::INVALID_DEVICE) {
|
||||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||||
userInputMapper->registerDevice(instance);
|
userInputMapper->registerDevice(instance);
|
||||||
UserActivityLogger::getInstance().connectedDevice("controller", NAME);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -329,7 +328,6 @@ bool SpacemouseManager::RawInputEventFilter(void* msg, long* result) {
|
||||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||||
if (Is3dmouseAttached() && instance->getDeviceID() == controller::Input::INVALID_DEVICE) {
|
if (Is3dmouseAttached() && instance->getDeviceID() == controller::Input::INVALID_DEVICE) {
|
||||||
userInputMapper->registerDevice(instance);
|
userInputMapper->registerDevice(instance);
|
||||||
UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse");
|
|
||||||
}
|
}
|
||||||
else if (!Is3dmouseAttached() && instance->getDeviceID() != controller::Input::INVALID_DEVICE) {
|
else if (!Is3dmouseAttached() && instance->getDeviceID() != controller::Input::INVALID_DEVICE) {
|
||||||
userInputMapper->removeDevice(instance->getDeviceID());
|
userInputMapper->removeDevice(instance->getDeviceID());
|
||||||
|
@ -856,7 +854,7 @@ void SpacemouseManager::init() {
|
||||||
if (Is3dmouseAttached() && instance->getDeviceID() == controller::Input::INVALID_DEVICE) {
|
if (Is3dmouseAttached() && instance->getDeviceID() == controller::Input::INVALID_DEVICE) {
|
||||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||||
userInputMapper->registerDevice(instance);
|
userInputMapper->registerDevice(instance);
|
||||||
UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse");
|
emit deviceConnected(getName());
|
||||||
}
|
}
|
||||||
//let one axis be dominant
|
//let one axis be dominant
|
||||||
//ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchDominant | kConnexionSwitchEnableAll, NULL);
|
//ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchDominant | kConnexionSwitchEnableAll, NULL);
|
||||||
|
|
|
@ -28,6 +28,12 @@ bool OculusDisplayPlugin::internalActivate() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OculusDisplayPlugin::init() {
|
||||||
|
Plugin::init();
|
||||||
|
|
||||||
|
emit deviceConnected(getName());
|
||||||
|
}
|
||||||
|
|
||||||
void OculusDisplayPlugin::cycleDebugOutput() {
|
void OculusDisplayPlugin::cycleDebugOutput() {
|
||||||
if (_session) {
|
if (_session) {
|
||||||
currentDebugMode = static_cast<ovrPerfHudMode>((currentDebugMode + 1) % ovrPerfHud_Count);
|
currentDebugMode = static_cast<ovrPerfHudMode>((currentDebugMode + 1) % ovrPerfHud_Count);
|
||||||
|
|
|
@ -17,6 +17,8 @@ class OculusDisplayPlugin : public OculusBaseDisplayPlugin {
|
||||||
public:
|
public:
|
||||||
const QString& getName() const override { return NAME; }
|
const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
|
||||||
QString getPreferredAudioInDevice() const override;
|
QString getPreferredAudioInDevice() const override;
|
||||||
QString getPreferredAudioOutDevice() const override;
|
QString getPreferredAudioOutDevice() const override;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,12 @@ const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift");
|
||||||
OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() {
|
OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OculusLegacyDisplayPlugin::init() {
|
||||||
|
Plugin::init();
|
||||||
|
|
||||||
|
emit deviceConnected(getName());
|
||||||
|
}
|
||||||
|
|
||||||
void OculusLegacyDisplayPlugin::resetSensors() {
|
void OculusLegacyDisplayPlugin::resetSensors() {
|
||||||
ovrHmd_RecenterPose(_hmd);
|
ovrHmd_RecenterPose(_hmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ public:
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
const QString& getName() const override { return NAME; }
|
const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
|
||||||
int getHmdScreen() const override;
|
int getHmdScreen() const override;
|
||||||
|
|
||||||
// Stereo specific methods
|
// Stereo specific methods
|
||||||
|
|
|
@ -41,6 +41,12 @@ bool OpenVrDisplayPlugin::isSupported() const {
|
||||||
return openVrSupported();
|
return openVrSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenVrDisplayPlugin::init() {
|
||||||
|
Plugin::init();
|
||||||
|
|
||||||
|
emit deviceConnected(getName());
|
||||||
|
}
|
||||||
|
|
||||||
bool OpenVrDisplayPlugin::internalActivate() {
|
bool OpenVrDisplayPlugin::internalActivate() {
|
||||||
_container->setIsOptionChecked(StandingHMDSensorMode, true);
|
_container->setIsOptionChecked(StandingHMDSensorMode, true);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ public:
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
const QString& getName() const override { return NAME; }
|
const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
|
||||||
float getTargetFrameRate() const override { return TARGET_RATE_OpenVr; }
|
float getTargetFrameRate() const override { return TARGET_RATE_OpenVr; }
|
||||||
|
|
||||||
void customizeContext() override;
|
void customizeContext() override;
|
||||||
|
|
|
@ -229,7 +229,6 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu
|
||||||
if (!_registeredWithInputMapper && _inputDevice->_trackedControllers > 0) {
|
if (!_registeredWithInputMapper && _inputDevice->_trackedControllers > 0) {
|
||||||
userInputMapper->registerDevice(_inputDevice);
|
userInputMapper->registerDevice(_inputDevice);
|
||||||
_registeredWithInputMapper = true;
|
_registeredWithInputMapper = true;
|
||||||
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "steamVR");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,8 @@ function goAway() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserActivityLogger.toggledAway(true);
|
||||||
|
|
||||||
isAway = true;
|
isAway = true;
|
||||||
print('going "away"');
|
print('going "away"');
|
||||||
wasMuted = AudioDevice.getMuted();
|
wasMuted = AudioDevice.getMuted();
|
||||||
|
@ -189,6 +191,9 @@ function goActive() {
|
||||||
if (!isAway) {
|
if (!isAway) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserActivityLogger.toggledAway(false);
|
||||||
|
|
||||||
isAway = false;
|
isAway = false;
|
||||||
print('going "active"');
|
print('going "active"');
|
||||||
if (!wasMuted) {
|
if (!wasMuted) {
|
||||||
|
|
|
@ -150,6 +150,8 @@ function showMarketplace(marketplaceID) {
|
||||||
marketplaceWindow.setURL(url);
|
marketplaceWindow.setURL(url);
|
||||||
marketplaceWindow.setVisible(true);
|
marketplaceWindow.setVisible(true);
|
||||||
marketplaceWindow.raise();
|
marketplaceWindow.raise();
|
||||||
|
|
||||||
|
UserActivityLogger.logAction("opened_marketplace");
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideMarketplace() {
|
function hideMarketplace() {
|
||||||
|
@ -347,6 +349,7 @@ var toolBar = (function() {
|
||||||
selectionManager.clearSelections();
|
selectionManager.clearSelections();
|
||||||
cameraManager.disable();
|
cameraManager.disable();
|
||||||
} else {
|
} else {
|
||||||
|
UserActivityLogger.enabledEdit();
|
||||||
hasShownPropertiesTool = false;
|
hasShownPropertiesTool = false;
|
||||||
entityListTool.setVisible(true);
|
entityListTool.setVisible(true);
|
||||||
gridTool.setVisible(true);
|
gridTool.setVisible(true);
|
||||||
|
|
|
@ -37,6 +37,8 @@ function showExamples(marketplaceID) {
|
||||||
print("setting examples URL to " + url);
|
print("setting examples URL to " + url);
|
||||||
examplesWindow.setURL(url);
|
examplesWindow.setURL(url);
|
||||||
examplesWindow.setVisible(true);
|
examplesWindow.setVisible(true);
|
||||||
|
|
||||||
|
UserActivityLogger.openedMarketplace();
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideExamples() {
|
function hideExamples() {
|
||||||
|
|
Loading…
Reference in a new issue