mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 19:16:56 +02:00
commit
715ee0b019
18 changed files with 287 additions and 30 deletions
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include "AssetServer.h"
|
#include "AssetServer.h"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
#include <QtCore/QCryptographicHash>
|
#include <QtCore/QCryptographicHash>
|
||||||
#include <QtCore/QDateTime>
|
#include <QtCore/QDateTime>
|
||||||
|
@ -21,6 +23,7 @@
|
||||||
#include <QtCore/QJsonDocument>
|
#include <QtCore/QJsonDocument>
|
||||||
#include <QtCore/QString>
|
#include <QtCore/QString>
|
||||||
|
|
||||||
|
#include <SharedUtil.h>
|
||||||
#include <ServerPathUtils.h>
|
#include <ServerPathUtils.h>
|
||||||
|
|
||||||
#include "NetworkLogging.h"
|
#include "NetworkLogging.h"
|
||||||
|
@ -28,8 +31,44 @@
|
||||||
#include "SendAssetTask.h"
|
#include "SendAssetTask.h"
|
||||||
#include "UploadAssetTask.h"
|
#include "UploadAssetTask.h"
|
||||||
|
|
||||||
|
static const uint8_t MIN_CORES_FOR_MULTICORE = 4;
|
||||||
|
static const uint8_t CPU_AFFINITY_COUNT_HIGH = 2;
|
||||||
|
static const uint8_t CPU_AFFINITY_COUNT_LOW = 1;
|
||||||
|
static const int INTERFACE_RUNNING_CHECK_FREQUENCY_MS = 1000;
|
||||||
|
|
||||||
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
const QString ASSET_SERVER_LOGGING_TARGET_NAME = "asset-server";
|
||||||
|
|
||||||
|
bool interfaceRunning() {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QSharedMemory sharedMemory { getInterfaceSharedMemoryName() };
|
||||||
|
result = sharedMemory.attach(QSharedMemory::ReadOnly);
|
||||||
|
if (result) {
|
||||||
|
sharedMemory.detach();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateConsumedCores() {
|
||||||
|
static bool wasInterfaceRunning = false;
|
||||||
|
bool isInterfaceRunning = interfaceRunning();
|
||||||
|
// If state is unchanged, return early
|
||||||
|
if (isInterfaceRunning == wasInterfaceRunning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wasInterfaceRunning = isInterfaceRunning;
|
||||||
|
auto coreCount = std::thread::hardware_concurrency();
|
||||||
|
if (isInterfaceRunning) {
|
||||||
|
coreCount = coreCount > MIN_CORES_FOR_MULTICORE ? CPU_AFFINITY_COUNT_HIGH : CPU_AFFINITY_COUNT_LOW;
|
||||||
|
}
|
||||||
|
qDebug() << "Setting max consumed cores to " << coreCount;
|
||||||
|
setMaxCores(coreCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AssetServer::AssetServer(ReceivedMessage& message) :
|
AssetServer::AssetServer(ReceivedMessage& message) :
|
||||||
ThreadedAssignment(message),
|
ThreadedAssignment(message),
|
||||||
_taskPool(this)
|
_taskPool(this)
|
||||||
|
@ -45,6 +84,20 @@ AssetServer::AssetServer(ReceivedMessage& message) :
|
||||||
packetReceiver.registerListener(PacketType::AssetGetInfo, this, "handleAssetGetInfo");
|
packetReceiver.registerListener(PacketType::AssetGetInfo, this, "handleAssetGetInfo");
|
||||||
packetReceiver.registerListener(PacketType::AssetUpload, this, "handleAssetUpload");
|
packetReceiver.registerListener(PacketType::AssetUpload, this, "handleAssetUpload");
|
||||||
packetReceiver.registerListener(PacketType::AssetMappingOperation, this, "handleAssetMappingOperation");
|
packetReceiver.registerListener(PacketType::AssetMappingOperation, this, "handleAssetMappingOperation");
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
updateConsumedCores();
|
||||||
|
QTimer* timer = new QTimer(this);
|
||||||
|
auto timerConnection = connect(timer, &QTimer::timeout, [] {
|
||||||
|
updateConsumedCores();
|
||||||
|
});
|
||||||
|
connect(qApp, &QCoreApplication::aboutToQuit, [this, timerConnection] {
|
||||||
|
disconnect(timerConnection);
|
||||||
|
});
|
||||||
|
timer->setInterval(INTERFACE_RUNNING_CHECK_FREQUENCY_MS);
|
||||||
|
timer->setTimerType(Qt::CoarseTimer);
|
||||||
|
timer->start();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetServer::run() {
|
void AssetServer::run() {
|
||||||
|
|
|
@ -262,8 +262,12 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
// setup a PacketList for the avatarPackets
|
// setup a PacketList for the avatarPackets
|
||||||
auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData);
|
auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData);
|
||||||
|
|
||||||
if (avatar.getSessionDisplayName().isEmpty() && // We haven't set it yet...
|
if (nodeData->getAvatarSessionDisplayNameMustChange()) {
|
||||||
nodeData->getReceivedIdentity()) { // ... but we have processed identity (with possible displayName).
|
const QString& existingBaseDisplayName = nodeData->getBaseDisplayName();
|
||||||
|
if (--_sessionDisplayNames[existingBaseDisplayName].second <= 0) {
|
||||||
|
_sessionDisplayNames.remove(existingBaseDisplayName);
|
||||||
|
}
|
||||||
|
|
||||||
QString baseName = avatar.getDisplayName().trimmed();
|
QString baseName = avatar.getDisplayName().trimmed();
|
||||||
const QRegularExpression curses{ "fuck|shit|damn|cock|cunt" }; // POC. We may eventually want something much more elaborate (subscription?).
|
const QRegularExpression curses{ "fuck|shit|damn|cock|cunt" }; // POC. We may eventually want something much more elaborate (subscription?).
|
||||||
baseName = baseName.replace(curses, "*"); // Replace rather than remove, so that people have a clue that the person's a jerk.
|
baseName = baseName.replace(curses, "*"); // Replace rather than remove, so that people have a clue that the person's a jerk.
|
||||||
|
@ -276,11 +280,14 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
QPair<int, int>& soFar = _sessionDisplayNames[baseName]; // Inserts and answers 0, 0 if not already present, which is what we want.
|
QPair<int, int>& soFar = _sessionDisplayNames[baseName]; // Inserts and answers 0, 0 if not already present, which is what we want.
|
||||||
int& highWater = soFar.first;
|
int& highWater = soFar.first;
|
||||||
nodeData->setBaseDisplayName(baseName);
|
nodeData->setBaseDisplayName(baseName);
|
||||||
avatar.setSessionDisplayName((highWater > 0) ? baseName + "_" + QString::number(highWater) : baseName);
|
QString sessionDisplayName = (highWater > 0) ? baseName + "_" + QString::number(highWater) : baseName;
|
||||||
|
avatar.setSessionDisplayName(sessionDisplayName);
|
||||||
highWater++;
|
highWater++;
|
||||||
soFar.second++; // refcount
|
soFar.second++; // refcount
|
||||||
nodeData->flagIdentityChange();
|
nodeData->flagIdentityChange();
|
||||||
sendIdentityPacket(nodeData, node); // Tell new node about its sessionUUID. Others will find out below.
|
nodeData->setAvatarSessionDisplayNameMustChange(false);
|
||||||
|
sendIdentityPacket(nodeData, node); // Tell node whose name changed about its new session display name. Others will find out below.
|
||||||
|
qDebug() << "Giving session display name" << sessionDisplayName << "to node with ID" << node->getUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is an AGENT we have received head data from
|
// this is an AGENT we have received head data from
|
||||||
|
@ -584,7 +591,7 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
|
||||||
if (avatar.processAvatarIdentity(identity)) {
|
if (avatar.processAvatarIdentity(identity)) {
|
||||||
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
||||||
nodeData->flagIdentityChange();
|
nodeData->flagIdentityChange();
|
||||||
nodeData->setReceivedIdentity();
|
nodeData->setAvatarSessionDisplayNameMustChange(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,8 +53,8 @@ public:
|
||||||
|
|
||||||
HRCTime getIdentityChangeTimestamp() const { return _identityChangeTimestamp; }
|
HRCTime getIdentityChangeTimestamp() const { return _identityChangeTimestamp; }
|
||||||
void flagIdentityChange() { _identityChangeTimestamp = p_high_resolution_clock::now(); }
|
void flagIdentityChange() { _identityChangeTimestamp = p_high_resolution_clock::now(); }
|
||||||
bool getReceivedIdentity() const { return _gotIdentity; }
|
bool getAvatarSessionDisplayNameMustChange() const { return _avatarSessionDisplayNameMustChange; }
|
||||||
void setReceivedIdentity() { _gotIdentity = true; }
|
void setAvatarSessionDisplayNameMustChange(bool set = true) { _avatarSessionDisplayNameMustChange = set; }
|
||||||
|
|
||||||
void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; }
|
void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; }
|
||||||
float getFullRateDistance() const { return _fullRateDistance; }
|
float getFullRateDistance() const { return _fullRateDistance; }
|
||||||
|
@ -112,7 +112,7 @@ private:
|
||||||
std::unordered_set<QUuid> _hasReceivedFirstPacketsFrom;
|
std::unordered_set<QUuid> _hasReceivedFirstPacketsFrom;
|
||||||
|
|
||||||
HRCTime _identityChangeTimestamp;
|
HRCTime _identityChangeTimestamp;
|
||||||
bool _gotIdentity { false };
|
bool _avatarSessionDisplayNameMustChange{ false };
|
||||||
|
|
||||||
float _fullRateDistance = FLT_MAX;
|
float _fullRateDistance = FLT_MAX;
|
||||||
float _maxAvatarDistance = FLT_MAX;
|
float _maxAvatarDistance = FLT_MAX;
|
||||||
|
|
Binary file not shown.
|
@ -28,7 +28,7 @@ Item {
|
||||||
property string uuid: ""
|
property string uuid: ""
|
||||||
property string displayName: ""
|
property string displayName: ""
|
||||||
property string userName: ""
|
property string userName: ""
|
||||||
property int displayTextHeight: 18
|
property real displayNameTextPixelSize: 18
|
||||||
property int usernameTextHeight: 12
|
property int usernameTextHeight: 12
|
||||||
property real audioLevel: 0.0
|
property real audioLevel: 0.0
|
||||||
property bool isMyCard: false
|
property bool isMyCard: false
|
||||||
|
@ -55,18 +55,112 @@ Item {
|
||||||
width: parent.width - /*avatarImage.width - parent.spacing - */parent.anchors.leftMargin - parent.anchors.rightMargin
|
width: parent.width - /*avatarImage.width - parent.spacing - */parent.anchors.leftMargin - parent.anchors.rightMargin
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
// DisplayName Text
|
|
||||||
|
// DisplayName field for my card
|
||||||
|
Rectangle {
|
||||||
|
id: myDisplayName
|
||||||
|
visible: isMyCard
|
||||||
|
// Size
|
||||||
|
width: parent.width + 70
|
||||||
|
height: 35
|
||||||
|
// Anchors
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: -10
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.textFieldLightBackground
|
||||||
|
border.color: hifi.colors.blueHighlight
|
||||||
|
border.width: 0
|
||||||
|
TextInput {
|
||||||
|
id: myDisplayNameText
|
||||||
|
// Properties
|
||||||
|
text: thisNameCard.displayName
|
||||||
|
maximumLength: 256
|
||||||
|
clip: true
|
||||||
|
// Size
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
// Anchors
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 10
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: editGlyph.width + editGlyph.anchors.rightMargin
|
||||||
|
// Style
|
||||||
|
color: hifi.colors.darkGray
|
||||||
|
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||||
|
font.family: firaSansSemiBold.name
|
||||||
|
font.pixelSize: displayNameTextPixelSize
|
||||||
|
selectionColor: hifi.colors.blueHighlight
|
||||||
|
selectedTextColor: "black"
|
||||||
|
// Text Positioning
|
||||||
|
verticalAlignment: TextInput.AlignVCenter
|
||||||
|
horizontalAlignment: TextInput.AlignLeft
|
||||||
|
// Signals
|
||||||
|
onEditingFinished: {
|
||||||
|
pal.sendToScript({method: 'displayNameUpdate', params: text})
|
||||||
|
cursorPosition = 0
|
||||||
|
focus = false
|
||||||
|
myDisplayName.border.width = 0
|
||||||
|
color = hifi.colors.darkGray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: {
|
||||||
|
myDisplayName.border.width = 1
|
||||||
|
myDisplayNameText.focus ? myDisplayNameText.cursorPosition = myDisplayNameText.positionAt(mouseX, mouseY, TextInput.CursorOnCharacter) : myDisplayNameText.selectAll();
|
||||||
|
myDisplayNameText.focus = true
|
||||||
|
myDisplayNameText.color = "black"
|
||||||
|
}
|
||||||
|
onDoubleClicked: {
|
||||||
|
myDisplayNameText.selectAll();
|
||||||
|
myDisplayNameText.focus = true;
|
||||||
|
}
|
||||||
|
onEntered: myDisplayName.color = hifi.colors.lightGrayText
|
||||||
|
onExited: myDisplayName.color = hifi.colors.textFieldLightBackground
|
||||||
|
}
|
||||||
|
// Edit pencil glyph
|
||||||
|
HiFiGlyphs {
|
||||||
|
id: editGlyph
|
||||||
|
text: hifi.glyphs.editPencil
|
||||||
|
// Text Size
|
||||||
|
size: displayNameTextPixelSize*1.5
|
||||||
|
// Anchors
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
// Style
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
color: hifi.colors.baseGray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Spacer for DisplayName for my card
|
||||||
|
Rectangle {
|
||||||
|
id: myDisplayNameSpacer
|
||||||
|
width: myDisplayName.width
|
||||||
|
// Anchors
|
||||||
|
anchors.top: myDisplayName.bottom
|
||||||
|
height: 5
|
||||||
|
visible: isMyCard
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
// DisplayName Text for others' cards
|
||||||
FiraSansSemiBold {
|
FiraSansSemiBold {
|
||||||
id: displayNameText
|
id: displayNameText
|
||||||
// Properties
|
// Properties
|
||||||
text: thisNameCard.displayName
|
text: thisNameCard.displayName
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
visible: !isMyCard
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: parent.width
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
// Text Size
|
// Text Size
|
||||||
size: thisNameCard.displayTextHeight
|
size: displayNameTextPixelSize
|
||||||
// Text Positioning
|
// Text Positioning
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
// Style
|
// Style
|
||||||
|
@ -83,7 +177,7 @@ Item {
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: parent.width
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: displayNameText.bottom
|
anchors.top: isMyCard ? myDisplayNameSpacer.bottom : displayNameText.bottom
|
||||||
// Text Size
|
// Text Size
|
||||||
size: thisNameCard.usernameTextHeight
|
size: thisNameCard.usernameTextHeight
|
||||||
// Text Positioning
|
// Text Positioning
|
||||||
|
@ -105,7 +199,7 @@ Item {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: nameCardVUMeter
|
id: nameCardVUMeter
|
||||||
// Size
|
// Size
|
||||||
width: ((gainSlider.value - gainSlider.minimumValue)/(gainSlider.maximumValue - gainSlider.minimumValue)) * parent.width
|
width: isMyCard ? myDisplayName.width - 20 : ((gainSlider.value - gainSlider.minimumValue)/(gainSlider.maximumValue - gainSlider.minimumValue)) * parent.width
|
||||||
height: 8
|
height: 8
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors.top: spacer.bottom
|
anchors.top: spacer.bottom
|
||||||
|
|
|
@ -35,6 +35,17 @@ Rectangle {
|
||||||
// Keep a local list of per-avatar gainSliderValueDBs. Far faster than fetching this data from the server.
|
// Keep a local list of per-avatar gainSliderValueDBs. Far faster than fetching this data from the server.
|
||||||
// NOTE: if another script modifies the per-avatar gain, this value won't be accurate!
|
// NOTE: if another script modifies the per-avatar gain, this value won't be accurate!
|
||||||
property var gainSliderValueDB: ({});
|
property var gainSliderValueDB: ({});
|
||||||
|
|
||||||
|
// The letterbox used for popup messages
|
||||||
|
LetterboxMessage {
|
||||||
|
id: letterboxMessage
|
||||||
|
z: 999 // Force the popup on top of everything else
|
||||||
|
}
|
||||||
|
function letterbox(message) {
|
||||||
|
letterboxMessage.text = message
|
||||||
|
letterboxMessage.visible = true
|
||||||
|
letterboxMessage.popupRadius = 0
|
||||||
|
}
|
||||||
|
|
||||||
// This is the container for the PAL
|
// This is the container for the PAL
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -176,8 +187,6 @@ Rectangle {
|
||||||
TableViewColumn {
|
TableViewColumn {
|
||||||
visible: iAmAdmin
|
visible: iAmAdmin
|
||||||
role: "kick"
|
role: "kick"
|
||||||
// The hacky spaces used to center text over the button, since I don't know how to apply a margin
|
|
||||||
// to column header text.
|
|
||||||
title: "BAN"
|
title: "BAN"
|
||||||
width: actionButtonWidth
|
width: actionButtonWidth
|
||||||
movable: false
|
movable: false
|
||||||
|
@ -337,11 +346,6 @@ Rectangle {
|
||||||
visible: iAmAdmin
|
visible: iAmAdmin
|
||||||
color: hifi.colors.lightGrayText
|
color: hifi.colors.lightGrayText
|
||||||
}
|
}
|
||||||
function letterbox(message) {
|
|
||||||
letterboxMessage.text = message;
|
|
||||||
letterboxMessage.visible = true
|
|
||||||
|
|
||||||
}
|
|
||||||
// This Rectangle refers to the [?] popup button next to "NAMES"
|
// This Rectangle refers to the [?] popup button next to "NAMES"
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: hifi.colors.tableBackgroundLight
|
color: hifi.colors.tableBackgroundLight
|
||||||
|
@ -402,9 +406,6 @@ Rectangle {
|
||||||
onExited: adminHelpText.color = hifi.colors.redHighlight
|
onExited: adminHelpText.color = hifi.colors.redHighlight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LetterboxMessage {
|
|
||||||
id: letterboxMessage
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
||||||
|
@ -502,6 +503,10 @@ Rectangle {
|
||||||
ignored = {};
|
ignored = {};
|
||||||
gainSliderValueDB = {};
|
gainSliderValueDB = {};
|
||||||
break;
|
break;
|
||||||
|
case 'avatarDisconnected':
|
||||||
|
var sessionID = message.params[0];
|
||||||
|
delete ignored[sessionID];
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('Unrecognized message:', JSON.stringify(message));
|
console.log('Unrecognized message:', JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
|
|
@ -312,10 +312,11 @@ Item {
|
||||||
readonly property string error: "="
|
readonly property string error: "="
|
||||||
readonly property string settings: "@"
|
readonly property string settings: "@"
|
||||||
readonly property string trash: "{"
|
readonly property string trash: "{"
|
||||||
readonly property string objectGroup: ""
|
readonly property string objectGroup: "\ue000"
|
||||||
readonly property string cm: "}"
|
readonly property string cm: "}"
|
||||||
readonly property string msvg79: "~"
|
readonly property string msvg79: "~"
|
||||||
readonly property string deg: "\\"
|
readonly property string deg: "\\"
|
||||||
readonly property string px: "|"
|
readonly property string px: "|"
|
||||||
|
readonly property string editPencil: "\ue00d"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1236,8 +1236,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
|
|
||||||
// Add periodic checks to send user activity data
|
// Add periodic checks to send user activity data
|
||||||
static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000;
|
static int CHECK_NEARBY_AVATARS_INTERVAL_MS = 10000;
|
||||||
static int SEND_STATS_INTERVAL_MS = 10000;
|
|
||||||
static int NEARBY_AVATAR_RADIUS_METERS = 10;
|
static int NEARBY_AVATAR_RADIUS_METERS = 10;
|
||||||
|
|
||||||
|
// setup the stats interval depending on if the 1s faster hearbeat was requested
|
||||||
|
static const QString FAST_STATS_ARG = "--fast-heartbeat";
|
||||||
|
static int SEND_STATS_INTERVAL_MS = arguments().indexOf(FAST_STATS_ARG) != -1 ? 1000 : 10000;
|
||||||
|
|
||||||
static glm::vec3 lastAvatarPosition = myAvatar->getPosition();
|
static glm::vec3 lastAvatarPosition = myAvatar->getPosition();
|
||||||
static glm::mat4 lastHMDHeadPose = getHMDSensorPose();
|
static glm::mat4 lastHMDHeadPose = getHMDSensorPose();
|
||||||
|
|
|
@ -260,6 +260,10 @@ void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar
|
||||||
}
|
}
|
||||||
if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble || removalReason == YourAvatarEnteredTheirBubble) {
|
if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble || removalReason == YourAvatarEnteredTheirBubble) {
|
||||||
DependencyManager::get<NodeList>()->radiusIgnoreNodeBySessionID(avatar->getSessionUUID(), true);
|
DependencyManager::get<NodeList>()->radiusIgnoreNodeBySessionID(avatar->getSessionUUID(), true);
|
||||||
|
} else if (removalReason == KillAvatarReason::AvatarDisconnected) {
|
||||||
|
// remove from node sets, if present
|
||||||
|
DependencyManager::get<NodeList>()->removeFromIgnoreMuteSets(avatar->getSessionUUID());
|
||||||
|
DependencyManager::get<UsersScriptingInterface>()->avatarDisconnected(avatar->getSessionUUID());
|
||||||
}
|
}
|
||||||
_avatarFades.push_back(removedAvatar);
|
_avatarFades.push_back(removedAvatar);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ int main(int argc, const char* argv[]) {
|
||||||
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
||||||
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
||||||
|
|
||||||
QString applicationName = "High Fidelity Interface - " + qgetenv("USERNAME");
|
const QString& applicationName = getInterfaceSharedMemoryName();
|
||||||
|
|
||||||
bool instanceMightBeRunning = true;
|
bool instanceMightBeRunning = true;
|
||||||
|
|
||||||
|
|
|
@ -1050,7 +1050,7 @@ bool AvatarData::processAvatarIdentity(const Identity& identity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (identity.displayName != _displayName) {
|
if (identity.displayName != _displayName) {
|
||||||
setDisplayName(identity.displayName);
|
_displayName = identity.displayName;
|
||||||
hasIdentityChanged = true;
|
hasIdentityChanged = true;
|
||||||
}
|
}
|
||||||
maybeUpdateSessionDisplayNameFromTransport(identity.sessionDisplayName);
|
maybeUpdateSessionDisplayNameFromTransport(identity.sessionDisplayName);
|
||||||
|
@ -1097,6 +1097,9 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
|
|
||||||
void AvatarData::setDisplayName(const QString& displayName) {
|
void AvatarData::setDisplayName(const QString& displayName) {
|
||||||
_displayName = displayName;
|
_displayName = displayName;
|
||||||
|
_sessionDisplayName = "";
|
||||||
|
|
||||||
|
sendIdentityPacket();
|
||||||
|
|
||||||
qCDebug(avatars) << "Changing display name for avatar to" << displayName;
|
qCDebug(avatars) << "Changing display name for avatar to" << displayName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -847,6 +847,16 @@ void NodeList::ignoreNodeBySessionID(const QUuid& nodeID, bool ignoreEnabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeList::removeFromIgnoreMuteSets(const QUuid& nodeID) {
|
||||||
|
// don't remove yourself, or nobody
|
||||||
|
if (!nodeID.isNull() && _sessionUUID != nodeID) {
|
||||||
|
QWriteLocker ignoredSetLocker{ &_ignoredSetLock };
|
||||||
|
QWriteLocker personalMutedSetLocker{ &_personalMutedSetLock };
|
||||||
|
_ignoredNodeIDs.unsafe_erase(nodeID);
|
||||||
|
_personalMutedNodeIDs.unsafe_erase(nodeID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool NodeList::isIgnoringNode(const QUuid& nodeID) const {
|
bool NodeList::isIgnoringNode(const QUuid& nodeID) const {
|
||||||
QReadLocker ignoredSetLocker{ &_ignoredSetLock };
|
QReadLocker ignoredSetLocker{ &_ignoredSetLock };
|
||||||
return _ignoredNodeIDs.find(nodeID) != _ignoredNodeIDs.cend();
|
return _ignoredNodeIDs.find(nodeID) != _ignoredNodeIDs.cend();
|
||||||
|
|
|
@ -90,6 +90,8 @@ public:
|
||||||
bool getRequestsDomainListData() { return _requestsDomainListData; }
|
bool getRequestsDomainListData() { return _requestsDomainListData; }
|
||||||
void setRequestsDomainListData(bool isRequesting);
|
void setRequestsDomainListData(bool isRequesting);
|
||||||
|
|
||||||
|
void removeFromIgnoreMuteSets(const QUuid& nodeID);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void reset();
|
void reset();
|
||||||
void sendDomainServerCheckIn();
|
void sendDomainServerCheckIn();
|
||||||
|
|
|
@ -211,7 +211,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
|
||||||
HandControllerJoints,
|
HandControllerJoints,
|
||||||
HasKillAvatarReason,
|
HasKillAvatarReason,
|
||||||
SessionDisplayName,
|
SessionDisplayName,
|
||||||
Unignore
|
Unignore,
|
||||||
|
ImmediateSessionDisplayNameUpdates
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DomainConnectRequestVersion : PacketVersion {
|
enum class DomainConnectRequestVersion : PacketVersion {
|
||||||
|
|
|
@ -139,6 +139,13 @@ signals:
|
||||||
*/
|
*/
|
||||||
void usernameFromIDReply(const QString& nodeID, const QString& username, const QString& machineFingerprint);
|
void usernameFromIDReply(const QString& nodeID, const QString& username, const QString& machineFingerprint);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Notifies scripts that a user has disconnected from the domain
|
||||||
|
* @function Users.avatar.avatarDisconnected
|
||||||
|
* @param {nodeID} NodeID The session ID of the avatar that has disconnected
|
||||||
|
*/
|
||||||
|
void avatarDisconnected(const QUuid& nodeID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getRequestsDomainListData();
|
bool getRequestsDomainListData();
|
||||||
void setRequestsDomainListData(bool requests);
|
void setRequestsDomainListData(bool requests);
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
@ -1022,4 +1024,54 @@ bool getProcessorInfo(ProcessorInfo& info) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const QString& getInterfaceSharedMemoryName() {
|
||||||
|
static const QString applicationName = "High Fidelity Interface - " + qgetenv("USERNAME");
|
||||||
|
return applicationName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<uint8_t>& getAvailableCores() {
|
||||||
|
static std::vector<uint8_t> availableCores;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
static std::once_flag once;
|
||||||
|
std::call_once(once, [&] {
|
||||||
|
DWORD_PTR defaultProcessAffinity = 0, defaultSystemAffinity = 0;
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
GetProcessAffinityMask(process, &defaultProcessAffinity, &defaultSystemAffinity);
|
||||||
|
for (uint64_t i = 0; i < sizeof(DWORD_PTR) * BITS_IN_BYTE; ++i) {
|
||||||
|
DWORD_PTR coreMask = 1;
|
||||||
|
coreMask <<= i;
|
||||||
|
if (0 != (defaultSystemAffinity & coreMask)) {
|
||||||
|
availableCores.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
return availableCores;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMaxCores(uint8_t maxCores) {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
auto availableCores = getAvailableCores();
|
||||||
|
if (availableCores.size() <= maxCores) {
|
||||||
|
DWORD_PTR currentProcessAffinity = 0, currentSystemAffinity = 0;
|
||||||
|
GetProcessAffinityMask(process, ¤tProcessAffinity, ¤tSystemAffinity);
|
||||||
|
SetProcessAffinityMask(GetCurrentProcess(), currentSystemAffinity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD_PTR newProcessAffinity = 0;
|
||||||
|
while (maxCores) {
|
||||||
|
int index = randIntInRange(0, (int)availableCores.size() - 1);
|
||||||
|
DWORD_PTR coreMask = 1;
|
||||||
|
coreMask <<= availableCores[index];
|
||||||
|
newProcessAffinity |= coreMask;
|
||||||
|
availableCores.erase(availableCores.begin() + index);
|
||||||
|
maxCores--;
|
||||||
|
}
|
||||||
|
SetProcessAffinityMask(process, newProcessAffinity);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -231,4 +231,8 @@ struct ProcessorInfo {
|
||||||
|
|
||||||
bool getProcessorInfo(ProcessorInfo& info);
|
bool getProcessorInfo(ProcessorInfo& info);
|
||||||
|
|
||||||
|
const QString& getInterfaceSharedMemoryName();
|
||||||
|
|
||||||
|
void setMaxCores(uint8_t maxCores);
|
||||||
|
|
||||||
#endif // hifi_SharedUtil_h
|
#endif // hifi_SharedUtil_h
|
||||||
|
|
|
@ -237,6 +237,11 @@ pal.fromQml.connect(function (message) { // messages are {method, params}, like
|
||||||
data = message.params;
|
data = message.params;
|
||||||
Users.setAvatarGain(data['sessionId'], data['gain']);
|
Users.setAvatarGain(data['sessionId'], data['gain']);
|
||||||
break;
|
break;
|
||||||
|
case 'displayNameUpdate':
|
||||||
|
if (MyAvatar.displayName != message.params) {
|
||||||
|
MyAvatar.displayName = message.params;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
print('Unrecognized message from Pal.qml:', JSON.stringify(message));
|
print('Unrecognized message from Pal.qml:', JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
@ -646,7 +651,10 @@ function onClicked() {
|
||||||
>>>>>>> b02a5f85ec6733b8c6cf5e3f19ce34ed8a375300
|
>>>>>>> b02a5f85ec6733b8c6cf5e3f19ce34ed8a375300
|
||||||
pal.setVisible(!pal.visible);
|
pal.setVisible(!pal.visible);
|
||||||
}
|
}
|
||||||
|
function avatarDisconnected(nodeID) {
|
||||||
|
// remove from the pal list
|
||||||
|
pal.sendToQml({method: 'avatarDisconnected', params: [nodeID]});
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Button state.
|
// Button state.
|
||||||
//
|
//
|
||||||
|
@ -659,6 +667,8 @@ button.clicked.connect(onClicked);
|
||||||
pal.visibleChanged.connect(onVisibleChanged);
|
pal.visibleChanged.connect(onVisibleChanged);
|
||||||
pal.closed.connect(off);
|
pal.closed.connect(off);
|
||||||
Users.usernameFromIDReply.connect(usernameFromIDReply);
|
Users.usernameFromIDReply.connect(usernameFromIDReply);
|
||||||
|
Users.avatarDisconnected.connect(avatarDisconnected);
|
||||||
|
|
||||||
function clearLocalQMLDataAndClosePAL() {
|
function clearLocalQMLDataAndClosePAL() {
|
||||||
pal.sendToQml({ method: 'clearLocalQMLData' });
|
pal.sendToQml({ method: 'clearLocalQMLData' });
|
||||||
if (pal.visible) {
|
if (pal.visible) {
|
||||||
|
@ -681,6 +691,7 @@ Script.scriptEnding.connect(function () {
|
||||||
Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL);
|
Window.domainConnectionRefused.disconnect(clearLocalQMLDataAndClosePAL);
|
||||||
Messages.unsubscribe(CHANNEL);
|
Messages.unsubscribe(CHANNEL);
|
||||||
Messages.messageReceived.disconnect(receiveMessage);
|
Messages.messageReceived.disconnect(receiveMessage);
|
||||||
|
Users.avatarDisconnected.disconnect(avatarDisconnected);
|
||||||
off();
|
off();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue