mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-27 21:58:47 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into hdr
This commit is contained in:
commit
a05e42138c
85 changed files with 670 additions and 210 deletions
|
@ -94,6 +94,7 @@ AudioMixer::AudioMixer(ReceivedMessage& message) :
|
||||||
packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket");
|
packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket");
|
||||||
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
|
packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket");
|
||||||
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
||||||
|
packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket");
|
||||||
|
|
||||||
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
|
connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled);
|
||||||
}
|
}
|
||||||
|
@ -599,6 +600,23 @@ void AudioMixer::handleNodeKilled(SharedNodePointer killedNode) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioMixer::handleNodeMuteRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
QUuid nodeUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||||
|
if (sendingNode->getCanKick()) {
|
||||||
|
auto node = nodeList->nodeWithUUID(nodeUUID);
|
||||||
|
if (node) {
|
||||||
|
// we need to set a flag so we send them the appropriate packet to mute them
|
||||||
|
AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData();
|
||||||
|
nodeData->setShouldMuteClient(true);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Node mute packet received for unknown node " << uuidStringWithoutCurlyBraces(nodeUUID);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qWarning() << "Node mute packet received from node that cannot mute, ignoring";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AudioMixer::handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
|
void AudioMixer::handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode) {
|
||||||
auto clientData = dynamic_cast<AudioMixerClientData*>(sendingNode->getLinkedData());
|
auto clientData = dynamic_cast<AudioMixerClientData*>(sendingNode->getLinkedData());
|
||||||
if (clientData) {
|
if (clientData) {
|
||||||
|
@ -814,9 +832,13 @@ void AudioMixer::broadcastMixes() {
|
||||||
|
|
||||||
// if the stream should be muted, send mute packet
|
// if the stream should be muted, send mute packet
|
||||||
if (nodeData->getAvatarAudioStream()
|
if (nodeData->getAvatarAudioStream()
|
||||||
&& shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) {
|
&& (shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())
|
||||||
|
|| nodeData->shouldMuteClient())) {
|
||||||
auto mutePacket = NLPacket::create(PacketType::NoisyMute, 0);
|
auto mutePacket = NLPacket::create(PacketType::NoisyMute, 0);
|
||||||
nodeList->sendPacket(std::move(mutePacket), *node);
|
nodeList->sendPacket(std::move(mutePacket), *node);
|
||||||
|
|
||||||
|
// probably now we just reset the flag, once should do it (?)
|
||||||
|
nodeData->setShouldMuteClient(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->getType() == NodeType::Agent && node->getActiveSocket()
|
if (node->getType() == NodeType::Agent && node->getActiveSocket()
|
||||||
|
|
|
@ -49,6 +49,7 @@ private slots:
|
||||||
void handleNodeKilled(SharedNodePointer killedNode);
|
void handleNodeKilled(SharedNodePointer killedNode);
|
||||||
void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
void handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
|
void handleNodeMuteRequestPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer sendingNode);
|
||||||
|
|
||||||
void removeHRTFsForFinishedInjector(const QUuid& streamID);
|
void removeHRTFsForFinishedInjector(const QUuid& streamID);
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,9 @@ public:
|
||||||
|
|
||||||
QString getCodecName() { return _selectedCodecName; }
|
QString getCodecName() { return _selectedCodecName; }
|
||||||
|
|
||||||
|
bool shouldMuteClient() { return _shouldMuteClient; }
|
||||||
|
void setShouldMuteClient(bool shouldMuteClient) { _shouldMuteClient = shouldMuteClient; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void injectorStreamFinished(const QUuid& streamIdentifier);
|
void injectorStreamFinished(const QUuid& streamIdentifier);
|
||||||
|
|
||||||
|
@ -114,6 +117,8 @@ private:
|
||||||
Decoder* _decoder{ nullptr }; // for mic stream
|
Decoder* _decoder{ nullptr }; // for mic stream
|
||||||
|
|
||||||
bool _shouldFlushEncoder { false };
|
bool _shouldFlushEncoder { false };
|
||||||
|
|
||||||
|
bool _shouldMuteClient { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AudioMixerClientData_h
|
#endif // hifi_AudioMixerClientData_h
|
||||||
|
|
|
@ -512,13 +512,20 @@ void AvatarMixer::domainSettingsRequestComplete() {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
|
nodeList->addNodeTypeToInterestSet(NodeType::Agent);
|
||||||
|
|
||||||
nodeList->linkedDataCreateCallback = [] (Node* node) {
|
|
||||||
node->setLinkedData(std::unique_ptr<AvatarMixerClientData> { new AvatarMixerClientData });
|
|
||||||
};
|
|
||||||
|
|
||||||
// parse the settings to pull out the values we need
|
// parse the settings to pull out the values we need
|
||||||
parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject());
|
parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject());
|
||||||
|
|
||||||
|
float domainMinimumScale = _domainMinimumScale;
|
||||||
|
float domainMaximumScale = _domainMaximumScale;
|
||||||
|
|
||||||
|
nodeList->linkedDataCreateCallback = [domainMinimumScale, domainMaximumScale] (Node* node) {
|
||||||
|
auto clientData = std::unique_ptr<AvatarMixerClientData> { new AvatarMixerClientData };
|
||||||
|
clientData->getAvatar().setDomainMinimumScale(domainMinimumScale);
|
||||||
|
clientData->getAvatar().setDomainMaximumScale(domainMaximumScale);
|
||||||
|
|
||||||
|
node->setLinkedData(std::move(clientData));
|
||||||
|
};
|
||||||
|
|
||||||
// start the broadcastThread
|
// start the broadcastThread
|
||||||
_broadcastThread.start();
|
_broadcastThread.start();
|
||||||
}
|
}
|
||||||
|
@ -549,4 +556,22 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
|
||||||
|
|
||||||
_maxKbpsPerNode = nodeBandwidthValue.toDouble(DEFAULT_NODE_SEND_BANDWIDTH) * KILO_PER_MEGA;
|
_maxKbpsPerNode = nodeBandwidthValue.toDouble(DEFAULT_NODE_SEND_BANDWIDTH) * KILO_PER_MEGA;
|
||||||
qDebug() << "The maximum send bandwidth per node is" << _maxKbpsPerNode << "kbps.";
|
qDebug() << "The maximum send bandwidth per node is" << _maxKbpsPerNode << "kbps.";
|
||||||
|
|
||||||
|
const QString AVATARS_SETTINGS_KEY = "avatars";
|
||||||
|
|
||||||
|
static const QString MIN_SCALE_OPTION = "min_avatar_scale";
|
||||||
|
float settingMinScale = domainSettings[AVATARS_SETTINGS_KEY].toObject()[MIN_SCALE_OPTION].toDouble(MIN_AVATAR_SCALE);
|
||||||
|
_domainMinimumScale = glm::clamp(settingMinScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||||
|
|
||||||
|
static const QString MAX_SCALE_OPTION = "max_avatar_scale";
|
||||||
|
float settingMaxScale = domainSettings[AVATARS_SETTINGS_KEY].toObject()[MAX_SCALE_OPTION].toDouble(MAX_AVATAR_SCALE);
|
||||||
|
_domainMaximumScale = glm::clamp(settingMaxScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||||
|
|
||||||
|
// make sure that the domain owner didn't flip min and max
|
||||||
|
if (_domainMinimumScale > _domainMaximumScale) {
|
||||||
|
std::swap(_domainMinimumScale, _domainMaximumScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "This domain requires a minimum avatar scale of" << _domainMinimumScale
|
||||||
|
<< "and a maximum avatar scale of" << _domainMaximumScale;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,9 @@ private:
|
||||||
|
|
||||||
float _maxKbpsPerNode = 0.0f;
|
float _maxKbpsPerNode = 0.0f;
|
||||||
|
|
||||||
|
float _domainMinimumScale { MIN_AVATAR_SCALE };
|
||||||
|
float _domainMaximumScale { MAX_AVATAR_SCALE };
|
||||||
|
|
||||||
QTimer* _broadcastTimer = nullptr;
|
QTimer* _broadcastTimer = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ if (HIFI_MEMORY_DEBUGGING)
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -U_FORTIFY_SOURCE -fno-stack-protector -fno-omit-frame-pointer")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -U_FORTIFY_SOURCE -fno-stack-protector -fno-omit-frame-pointer")
|
||||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libasan -static-libstdc++ -fsanitize=address")
|
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libasan -static-libstdc++ -fsanitize=address")
|
||||||
|
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libasan -static-libstdc++ -fsanitize=address")
|
||||||
endif (UNIX)
|
endif (UNIX)
|
||||||
endif ()
|
endif ()
|
||||||
endmacro(SETUP_MEMORY_DEBUGGER)
|
endmacro(SETUP_MEMORY_DEBUGGER)
|
||||||
|
|
|
@ -388,6 +388,23 @@
|
||||||
"default": "",
|
"default": "",
|
||||||
"advanced": false
|
"advanced": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "ac_subnet_whitelist",
|
||||||
|
"label": "Assignment Client IP address Whitelist",
|
||||||
|
"type": "table",
|
||||||
|
"can_add_new_rows": true,
|
||||||
|
"help": "The IP addresses or subnets of ACs that can connect to this server. You can specify an IP address or a subnet in CIDR notation ('A.B.C.D/E', Example: '10.0.0.0/24'). Local ACs (localhost) are always permitted and do not need to be added here.",
|
||||||
|
"numbered": false,
|
||||||
|
"advanced": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "ip",
|
||||||
|
"label": "IP Address",
|
||||||
|
"type": "ip",
|
||||||
|
"can_set": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "standard_permissions",
|
"name": "standard_permissions",
|
||||||
"type": "table",
|
"type": "table",
|
||||||
|
@ -866,6 +883,29 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "avatars",
|
||||||
|
"label": "Avatars",
|
||||||
|
"assignment-types": [1, 2],
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"name": "min_avatar_scale",
|
||||||
|
"type": "double",
|
||||||
|
"label": "Minimum Avatar Scale",
|
||||||
|
"help": "Limits the scale of avatars in your domain. Must be at least 0.005.",
|
||||||
|
"placeholder": 0.25,
|
||||||
|
"default": 0.25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_avatar_scale",
|
||||||
|
"type": "double",
|
||||||
|
"label": "Maximum Avatar Scale",
|
||||||
|
"help": "Limits the scale of avatars in your domain. Cannot be greater than 1000.",
|
||||||
|
"placeholder": 3.0,
|
||||||
|
"default": 3.0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "audio_env",
|
"name": "audio_env",
|
||||||
"label": "Audio Environment",
|
"label": "Audio Environment",
|
||||||
|
|
|
@ -158,6 +158,42 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
|
|
||||||
|
|
||||||
qDebug() << "domain-server is running";
|
qDebug() << "domain-server is running";
|
||||||
|
static const QString AC_SUBNET_WHITELIST_SETTING_PATH = "security.ac_subnet_whitelist";
|
||||||
|
|
||||||
|
static const Subnet LOCALHOST { QHostAddress("127.0.0.1"), 32 };
|
||||||
|
_acSubnetWhitelist = { LOCALHOST };
|
||||||
|
|
||||||
|
auto whitelist = _settingsManager.valueOrDefaultValueForKeyPath(AC_SUBNET_WHITELIST_SETTING_PATH).toStringList();
|
||||||
|
for (auto& subnet : whitelist) {
|
||||||
|
auto netmaskParts = subnet.trimmed().split("/");
|
||||||
|
|
||||||
|
if (netmaskParts.size() > 2) {
|
||||||
|
qDebug() << "Ignoring subnet in whitelist, malformed: " << subnet;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The default netmask is 32 if one has not been specified, which will
|
||||||
|
// match only the ip provided.
|
||||||
|
int netmask = 32;
|
||||||
|
|
||||||
|
if (netmaskParts.size() == 2) {
|
||||||
|
bool ok;
|
||||||
|
netmask = netmaskParts[1].toInt(&ok);
|
||||||
|
if (!ok) {
|
||||||
|
qDebug() << "Ignoring subnet in whitelist, bad netmask: " << subnet;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ip = QHostAddress(netmaskParts[0]);
|
||||||
|
|
||||||
|
if (!ip.isNull()) {
|
||||||
|
qDebug() << "Adding AC whitelist subnet: " << subnet << " -> " << (ip.toString() + "/" + QString::number(netmask));
|
||||||
|
_acSubnetWhitelist.push_back({ ip , netmask });
|
||||||
|
} else {
|
||||||
|
qDebug() << "Ignoring subnet in whitelist, invalid ip portion: " << subnet;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainServer::parseCommandLine() {
|
void DomainServer::parseCommandLine() {
|
||||||
|
@ -1001,6 +1037,21 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer<ReceivedMessage
|
||||||
// construct the requested assignment from the packet data
|
// construct the requested assignment from the packet data
|
||||||
Assignment requestAssignment(*message);
|
Assignment requestAssignment(*message);
|
||||||
|
|
||||||
|
auto senderAddr = message->getSenderSockAddr().getAddress();
|
||||||
|
|
||||||
|
auto isHostAddressInSubnet = [&senderAddr](const Subnet& mask) -> bool {
|
||||||
|
return senderAddr.isInSubnet(mask);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto it = find_if(_acSubnetWhitelist.begin(), _acSubnetWhitelist.end(), isHostAddressInSubnet);
|
||||||
|
if (it == _acSubnetWhitelist.end()) {
|
||||||
|
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(
|
||||||
|
"Received an assignment connect request from a disallowed ip address: [^ ]+");
|
||||||
|
qDebug() << "Received an assignment connect request from a disallowed ip address:"
|
||||||
|
<< senderAddr.toString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Suppress these for Assignment::AgentType to once per 5 seconds
|
// Suppress these for Assignment::AgentType to once per 5 seconds
|
||||||
static QElapsedTimer noisyMessageTimer;
|
static QElapsedTimer noisyMessageTimer;
|
||||||
static bool wasNoisyTimerStarted = false;
|
static bool wasNoisyTimerStarted = false;
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
typedef QSharedPointer<Assignment> SharedAssignmentPointer;
|
typedef QSharedPointer<Assignment> SharedAssignmentPointer;
|
||||||
typedef QMultiHash<QUuid, WalletTransaction*> TransactionHash;
|
typedef QMultiHash<QUuid, WalletTransaction*> TransactionHash;
|
||||||
|
|
||||||
|
using Subnet = QPair<QHostAddress, int>;
|
||||||
|
using SubnetList = std::vector<Subnet>;
|
||||||
|
|
||||||
class DomainServer : public QCoreApplication, public HTTPSRequestHandler {
|
class DomainServer : public QCoreApplication, public HTTPSRequestHandler {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -156,6 +159,8 @@ private:
|
||||||
|
|
||||||
void setupGroupCacheRefresh();
|
void setupGroupCacheRefresh();
|
||||||
|
|
||||||
|
SubnetList _acSubnetWhitelist;
|
||||||
|
|
||||||
DomainGatekeeper _gatekeeper;
|
DomainGatekeeper _gatekeeper;
|
||||||
|
|
||||||
HTTPManager _httpManager;
|
HTTPManager _httpManager;
|
||||||
|
|
|
@ -634,7 +634,6 @@ bool DomainServerSettingsManager::ensurePermissionsForGroupRanks() {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
void DomainServerSettingsManager::processNodeKickRequestPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) {
|
||||||
// before we do any processing on this packet make sure it comes from a node that is allowed to kick
|
// before we do any processing on this packet make sure it comes from a node that is allowed to kick
|
||||||
if (sendingNode->getCanKick()) {
|
if (sendingNode->getCanKick()) {
|
||||||
|
@ -1077,6 +1076,9 @@ QJsonObject DomainServerSettingsManager::settingDescriptionFromGroup(const QJson
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject) {
|
bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject) {
|
||||||
|
static const QString SECURITY_ROOT_KEY = "security";
|
||||||
|
static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist";
|
||||||
|
|
||||||
auto& settingsVariant = _configMap.getConfig();
|
auto& settingsVariant = _configMap.getConfig();
|
||||||
bool needRestart = false;
|
bool needRestart = false;
|
||||||
|
|
||||||
|
@ -1127,7 +1129,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
|
||||||
|
|
||||||
if (!matchingDescriptionObject.isEmpty()) {
|
if (!matchingDescriptionObject.isEmpty()) {
|
||||||
updateSetting(rootKey, rootValue, *thisMap, matchingDescriptionObject);
|
updateSetting(rootKey, rootValue, *thisMap, matchingDescriptionObject);
|
||||||
if (rootKey != "security") {
|
if (rootKey != SECURITY_ROOT_KEY) {
|
||||||
needRestart = true;
|
needRestart = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1143,7 +1145,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ
|
||||||
if (!matchingDescriptionObject.isEmpty()) {
|
if (!matchingDescriptionObject.isEmpty()) {
|
||||||
QJsonValue settingValue = rootValue.toObject()[settingKey];
|
QJsonValue settingValue = rootValue.toObject()[settingKey];
|
||||||
updateSetting(settingKey, settingValue, *thisMap, matchingDescriptionObject);
|
updateSetting(settingKey, settingValue, *thisMap, matchingDescriptionObject);
|
||||||
if (rootKey != "security") {
|
if (rootKey != SECURITY_ROOT_KEY || settingKey == AC_SUBNET_WHITELIST_KEY) {
|
||||||
needRestart = true;
|
needRestart = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
{ "from": "GamePad.RS", "to": "Standard.RS" },
|
{ "from": "GamePad.RS", "to": "Standard.RS" },
|
||||||
|
|
||||||
{ "from": "GamePad.Start", "to": "Actions.CycleCamera" },
|
{ "from": "GamePad.Start", "to": "Actions.CycleCamera" },
|
||||||
{ "from": "GamePad.Back", "to": "Actions.ContextMenu" },
|
{ "from": "GamePad.Back", "to": "Standard.Start" },
|
||||||
|
|
||||||
{ "from": "GamePad.DU", "to": "Standard.DU" },
|
{ "from": "GamePad.DU", "to": "Standard.DU" },
|
||||||
{ "from": "GamePad.DD", "to": "Standard.DD" },
|
{ "from": "GamePad.DD", "to": "Standard.DD" },
|
||||||
|
|
|
@ -69,6 +69,10 @@ Item {
|
||||||
StatText {
|
StatText {
|
||||||
text: "Present Drop Rate: " + root.presentdroprate.toFixed(2);
|
text: "Present Drop Rate: " + root.presentdroprate.toFixed(2);
|
||||||
}
|
}
|
||||||
|
StatText {
|
||||||
|
text: "Stutter Rate: " + root.stutterrate.toFixed(3);
|
||||||
|
visible: root.stutterrate != -1;
|
||||||
|
}
|
||||||
StatText {
|
StatText {
|
||||||
text: "Simrate: " + root.simrate
|
text: "Simrate: " + root.simrate
|
||||||
}
|
}
|
||||||
|
@ -241,7 +245,7 @@ Item {
|
||||||
text: "GPU Buffers: "
|
text: "GPU Buffers: "
|
||||||
}
|
}
|
||||||
StatText {
|
StatText {
|
||||||
text: " Count: " + root.gpuTextures;
|
text: " Count: " + root.gpuBuffers;
|
||||||
}
|
}
|
||||||
StatText {
|
StatText {
|
||||||
text: " Memory: " + root.gpuBufferMemory;
|
text: " Memory: " + root.gpuBufferMemory;
|
||||||
|
|
|
@ -1197,6 +1197,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
properties["present_rate"] = displayPlugin->presentRate();
|
properties["present_rate"] = displayPlugin->presentRate();
|
||||||
properties["new_frame_present_rate"] = displayPlugin->newFramePresentRate();
|
properties["new_frame_present_rate"] = displayPlugin->newFramePresentRate();
|
||||||
properties["dropped_frame_rate"] = displayPlugin->droppedFrameRate();
|
properties["dropped_frame_rate"] = displayPlugin->droppedFrameRate();
|
||||||
|
properties["stutter_rate"] = displayPlugin->stutterRate();
|
||||||
properties["sim_rate"] = getAverageSimsPerSecond();
|
properties["sim_rate"] = getAverageSimsPerSecond();
|
||||||
properties["avatar_sim_rate"] = getAvatarSimrate();
|
properties["avatar_sim_rate"] = getAvatarSimrate();
|
||||||
properties["has_async_reprojection"] = displayPlugin->hasAsyncReprojection();
|
properties["has_async_reprojection"] = displayPlugin->hasAsyncReprojection();
|
||||||
|
|
|
@ -165,16 +165,17 @@ AABox Avatar::getBounds() const {
|
||||||
|
|
||||||
void Avatar::animateScaleChanges(float deltaTime) {
|
void Avatar::animateScaleChanges(float deltaTime) {
|
||||||
float currentScale = getUniformScale();
|
float currentScale = getUniformScale();
|
||||||
if (currentScale != _targetScale) {
|
auto desiredScale = getDomainLimitedScale();
|
||||||
// use exponential decay toward _targetScale
|
if (currentScale != desiredScale) {
|
||||||
|
// use exponential decay toward the domain limit clamped scale
|
||||||
const float SCALE_ANIMATION_TIMESCALE = 0.5f;
|
const float SCALE_ANIMATION_TIMESCALE = 0.5f;
|
||||||
float blendFactor = glm::clamp(deltaTime / SCALE_ANIMATION_TIMESCALE, 0.0f, 1.0f);
|
float blendFactor = glm::clamp(deltaTime / SCALE_ANIMATION_TIMESCALE, 0.0f, 1.0f);
|
||||||
float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * _targetScale;
|
float animatedScale = (1.0f - blendFactor) * currentScale + blendFactor * desiredScale;
|
||||||
|
|
||||||
// snap to the end when we get close enough
|
// snap to the end when we get close enough
|
||||||
const float MIN_RELATIVE_SCALE_ERROR = 0.03f;
|
const float MIN_RELATIVE_SCALE_ERROR = 0.03f;
|
||||||
if (fabsf(_targetScale - currentScale) / _targetScale < MIN_RELATIVE_SCALE_ERROR) {
|
if (fabsf(desiredScale - currentScale) / desiredScale < MIN_RELATIVE_SCALE_ERROR) {
|
||||||
animatedScale = _targetScale;
|
animatedScale = desiredScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
setScale(glm::vec3(animatedScale)); // avatar scale is uniform
|
setScale(glm::vec3(animatedScale)); // avatar scale is uniform
|
||||||
|
|
|
@ -152,7 +152,7 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm::
|
||||||
Transform avatarTransform;
|
Transform avatarTransform;
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
avatarTransform = myAvatar->getTransform();
|
avatarTransform = myAvatar->getTransform();
|
||||||
palmPosition = avatarTransform.transform(pose.getTranslation() / myAvatar->getTargetScale());
|
palmPosition = avatarTransform.transform(pose.getTranslation() / myAvatar->getDomainLimitedScale());
|
||||||
palmRotation = avatarTransform.getRotation() * pose.getRotation();
|
palmRotation = avatarTransform.getRotation() * pose.getRotation();
|
||||||
} else {
|
} else {
|
||||||
glm::vec3 avatarRigidBodyPosition;
|
glm::vec3 avatarRigidBodyPosition;
|
||||||
|
|
|
@ -130,6 +130,15 @@ MyAvatar::MyAvatar(RigPointer rig) :
|
||||||
connect(DependencyManager::get<AddressManager>().data(), &AddressManager::locationChangeRequired,
|
connect(DependencyManager::get<AddressManager>().data(), &AddressManager::locationChangeRequired,
|
||||||
this, static_cast<SlotType>(&MyAvatar::goToLocation));
|
this, static_cast<SlotType>(&MyAvatar::goToLocation));
|
||||||
|
|
||||||
|
// handle scale constraints imposed on us by the domain-server
|
||||||
|
auto& domainHandler = DependencyManager::get<NodeList>()->getDomainHandler();
|
||||||
|
|
||||||
|
// when we connect to a domain and retrieve its settings, we restrict our max/min scale based on those settings
|
||||||
|
connect(&domainHandler, &DomainHandler::settingsReceived, this, &MyAvatar::restrictScaleFromDomainSettings);
|
||||||
|
|
||||||
|
// when we leave a domain we lift whatever restrictions that domain may have placed on our scale
|
||||||
|
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, &MyAvatar::clearScaleRestriction);
|
||||||
|
|
||||||
_characterController.setEnabled(true);
|
_characterController.setEnabled(true);
|
||||||
|
|
||||||
_bodySensorMatrix = deriveBodyFromHMDSensor();
|
_bodySensorMatrix = deriveBodyFromHMDSensor();
|
||||||
|
@ -1823,25 +1832,104 @@ bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::increaseSize() {
|
// There can be a separation between the _targetScale and the actual scale of the rendered avatar in a domain.
|
||||||
if ((1.0f + SCALING_RATIO) * _targetScale < MAX_AVATAR_SCALE) {
|
// When the avatar enters a domain where their target scale is not allowed according to the min/max
|
||||||
_targetScale *= (1.0f + SCALING_RATIO);
|
// we do not change their saved target scale. Instead, we use getDomainLimitedScale() to render the avatar
|
||||||
|
// at a domain appropriate size. When the avatar leaves the limiting domain, we'll return them to their previous target scale.
|
||||||
|
// While connected to a domain that limits avatar scale if the user manually changes their avatar scale, we change
|
||||||
|
// target scale to match the new scale they have chosen. When they leave the domain they will not return to the scale they were
|
||||||
|
// before they entered the limiting domain.
|
||||||
|
|
||||||
|
void MyAvatar::clampTargetScaleToDomainLimits() {
|
||||||
|
// when we're about to change the target scale because the user has asked to increase or decrease their scale,
|
||||||
|
// we first make sure that we're starting from a target scale that is allowed by the current domain
|
||||||
|
|
||||||
|
auto clampedTargetScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale);
|
||||||
|
|
||||||
|
if (clampedTargetScale != _targetScale) {
|
||||||
|
qCDebug(interfaceapp, "Clamped scale to %f since original target scale %f was not allowed by domain",
|
||||||
|
(double)clampedTargetScale, (double)_targetScale);
|
||||||
|
|
||||||
|
setTargetScale(clampedTargetScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::clampScaleChangeToDomainLimits(float desiredScale) {
|
||||||
|
auto clampedTargetScale = glm::clamp(desiredScale, _domainMinimumScale, _domainMaximumScale);
|
||||||
|
|
||||||
|
if (clampedTargetScale != desiredScale) {
|
||||||
|
qCDebug(interfaceapp, "Forcing scale to %f since %f is not allowed by domain",
|
||||||
|
clampedTargetScale, desiredScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTargetScale(clampedTargetScale);
|
||||||
qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale);
|
qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::increaseSize() {
|
||||||
|
// make sure we're starting from an allowable scale
|
||||||
|
clampTargetScaleToDomainLimits();
|
||||||
|
|
||||||
|
// calculate what our new scale should be
|
||||||
|
float updatedTargetScale = _targetScale * (1.0f + SCALING_RATIO);
|
||||||
|
|
||||||
|
// attempt to change to desired scale (clamped to the domain limits)
|
||||||
|
clampScaleChangeToDomainLimits(updatedTargetScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::decreaseSize() {
|
void MyAvatar::decreaseSize() {
|
||||||
if (MIN_AVATAR_SCALE < (1.0f - SCALING_RATIO) * _targetScale) {
|
// make sure we're starting from an allowable scale
|
||||||
_targetScale *= (1.0f - SCALING_RATIO);
|
clampTargetScaleToDomainLimits();
|
||||||
qCDebug(interfaceapp, "Changed scale to %f", (double)_targetScale);
|
|
||||||
}
|
// calculate what our new scale should be
|
||||||
|
float updatedTargetScale = _targetScale * (1.0f - SCALING_RATIO);
|
||||||
|
|
||||||
|
// attempt to change to desired scale (clamped to the domain limits)
|
||||||
|
clampScaleChangeToDomainLimits(updatedTargetScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::resetSize() {
|
void MyAvatar::resetSize() {
|
||||||
_targetScale = 1.0f;
|
// attempt to reset avatar size to the default (clamped to domain limits)
|
||||||
qCDebug(interfaceapp, "Reset scale to %f", (double)_targetScale);
|
const float DEFAULT_AVATAR_SCALE = 1.0f;
|
||||||
|
|
||||||
|
clampScaleChangeToDomainLimits(DEFAULT_AVATAR_SCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettingsObject) {
|
||||||
|
// pull out the minimum and maximum scale and set them to restrict our scale
|
||||||
|
|
||||||
|
static const QString AVATAR_SETTINGS_KEY = "avatars";
|
||||||
|
auto avatarsObject = domainSettingsObject[AVATAR_SETTINGS_KEY].toObject();
|
||||||
|
|
||||||
|
static const QString MIN_SCALE_OPTION = "min_avatar_scale";
|
||||||
|
float settingMinScale = avatarsObject[MIN_SCALE_OPTION].toDouble(MIN_AVATAR_SCALE);
|
||||||
|
setDomainMinimumScale(settingMinScale);
|
||||||
|
|
||||||
|
static const QString MAX_SCALE_OPTION = "max_avatar_scale";
|
||||||
|
float settingMaxScale = avatarsObject[MAX_SCALE_OPTION].toDouble(MAX_AVATAR_SCALE);
|
||||||
|
setDomainMaximumScale(settingMaxScale);
|
||||||
|
|
||||||
|
// make sure that the domain owner didn't flip min and max
|
||||||
|
if (_domainMinimumScale > _domainMaximumScale) {
|
||||||
|
std::swap(_domainMinimumScale, _domainMaximumScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(interfaceapp, "This domain requires a minimum avatar scale of %f and a maximum avatar scale of %f",
|
||||||
|
(double)_domainMinimumScale, (double)_domainMaximumScale);
|
||||||
|
|
||||||
|
// debug to log if this avatar's scale in this domain will be clamped
|
||||||
|
auto clampedScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale);
|
||||||
|
|
||||||
|
if (_targetScale != clampedScale) {
|
||||||
|
qCDebug(interfaceapp, "Avatar scale will be clamped to %f because %f is not allowed by current domain",
|
||||||
|
(double)clampedScale, (double)_targetScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::clearScaleRestriction() {
|
||||||
|
_domainMinimumScale = MIN_AVATAR_SCALE;
|
||||||
|
_domainMaximumScale = MAX_AVATAR_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::goToLocation(const QVariant& propertiesVar) {
|
void MyAvatar::goToLocation(const QVariant& propertiesVar) {
|
||||||
qCDebug(interfaceapp, "MyAvatar QML goToLocation");
|
qCDebug(interfaceapp, "MyAvatar QML goToLocation");
|
||||||
|
|
|
@ -292,6 +292,9 @@ public slots:
|
||||||
bool shouldFaceLocation = false);
|
bool shouldFaceLocation = false);
|
||||||
void goToLocation(const QVariant& properties);
|
void goToLocation(const QVariant& properties);
|
||||||
|
|
||||||
|
void restrictScaleFromDomainSettings(const QJsonObject& domainSettingsObject);
|
||||||
|
void clearScaleRestriction();
|
||||||
|
|
||||||
// Set/Get update the thrust that will move the avatar around
|
// Set/Get update the thrust that will move the avatar around
|
||||||
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
void addThrust(glm::vec3 newThrust) { _thrust += newThrust; };
|
||||||
glm::vec3 getThrust() { return _thrust; };
|
glm::vec3 getThrust() { return _thrust; };
|
||||||
|
@ -369,6 +372,8 @@ private:
|
||||||
virtual void updatePalms() override {}
|
virtual void updatePalms() override {}
|
||||||
void lateUpdatePalms();
|
void lateUpdatePalms();
|
||||||
|
|
||||||
|
void clampTargetScaleToDomainLimits();
|
||||||
|
void clampScaleChangeToDomainLimits(float desiredScale);
|
||||||
|
|
||||||
float _driveKeys[MAX_DRIVE_KEYS];
|
float _driveKeys[MAX_DRIVE_KEYS];
|
||||||
bool _wasPushing;
|
bool _wasPushing;
|
||||||
|
|
|
@ -128,7 +128,8 @@ void Stats::updateStats(bool force) {
|
||||||
STAT_UPDATE(renderrate, displayPlugin->renderRate());
|
STAT_UPDATE(renderrate, displayPlugin->renderRate());
|
||||||
STAT_UPDATE(presentrate, displayPlugin->presentRate());
|
STAT_UPDATE(presentrate, displayPlugin->presentRate());
|
||||||
STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate());
|
STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate());
|
||||||
STAT_UPDATE(presentdroprate, qApp->getActiveDisplayPlugin()->droppedFrameRate());
|
STAT_UPDATE(presentdroprate, displayPlugin->droppedFrameRate());
|
||||||
|
STAT_UPDATE(stutterrate, displayPlugin->stutterRate());
|
||||||
} else {
|
} else {
|
||||||
STAT_UPDATE(presentrate, -1);
|
STAT_UPDATE(presentrate, -1);
|
||||||
STAT_UPDATE(presentnewrate, -1);
|
STAT_UPDATE(presentnewrate, -1);
|
||||||
|
|
|
@ -36,6 +36,8 @@ class Stats : public QQuickItem {
|
||||||
STATS_PROPERTY(float, renderrate, 0)
|
STATS_PROPERTY(float, renderrate, 0)
|
||||||
// How often the display plugin is presenting to the device
|
// How often the display plugin is presenting to the device
|
||||||
STATS_PROPERTY(float, presentrate, 0)
|
STATS_PROPERTY(float, presentrate, 0)
|
||||||
|
// How often the display device reprojecting old frames
|
||||||
|
STATS_PROPERTY(float, stutterrate, 0)
|
||||||
|
|
||||||
STATS_PROPERTY(float, presentnewrate, 0)
|
STATS_PROPERTY(float, presentnewrate, 0)
|
||||||
STATS_PROPERTY(float, presentdroprate, 0)
|
STATS_PROPERTY(float, presentdroprate, 0)
|
||||||
|
@ -140,6 +142,7 @@ signals:
|
||||||
void presentrateChanged();
|
void presentrateChanged();
|
||||||
void presentnewrateChanged();
|
void presentnewrateChanged();
|
||||||
void presentdroprateChanged();
|
void presentdroprateChanged();
|
||||||
|
void stutterrateChanged();
|
||||||
void simrateChanged();
|
void simrateChanged();
|
||||||
void avatarSimrateChanged();
|
void avatarSimrateChanged();
|
||||||
void avatarCountChanged();
|
void avatarCountChanged();
|
||||||
|
|
|
@ -210,7 +210,7 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||||
packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 0), bodyEulerAngles.y);
|
packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 0), bodyEulerAngles.y);
|
||||||
packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 1), bodyEulerAngles.x);
|
packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 1), bodyEulerAngles.x);
|
||||||
packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 2), bodyEulerAngles.z);
|
packFloatAngleToTwoByte((uint8_t*)(header->localOrientation + 2), bodyEulerAngles.z);
|
||||||
packFloatRatioToTwoByte((uint8_t*)(&header->scale), _targetScale);
|
packFloatRatioToTwoByte((uint8_t*)(&header->scale), getDomainLimitedScale());
|
||||||
header->lookAtPosition[0] = _headData->_lookAtPosition.x;
|
header->lookAtPosition[0] = _headData->_lookAtPosition.x;
|
||||||
header->lookAtPosition[1] = _headData->_lookAtPosition.y;
|
header->lookAtPosition[1] = _headData->_lookAtPosition.y;
|
||||||
header->lookAtPosition[2] = _headData->_lookAtPosition.z;
|
header->lookAtPosition[2] = _headData->_lookAtPosition.z;
|
||||||
|
@ -516,7 +516,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
||||||
}
|
}
|
||||||
return buffer.size();
|
return buffer.size();
|
||||||
}
|
}
|
||||||
_targetScale = std::max(MIN_AVATAR_SCALE, std::min(MAX_AVATAR_SCALE, scale));
|
setTargetScale(scale);
|
||||||
|
|
||||||
glm::vec3 lookAt = glm::vec3(header->lookAtPosition[0], header->lookAtPosition[1], header->lookAtPosition[2]);
|
glm::vec3 lookAt = glm::vec3(header->lookAtPosition[0], header->lookAtPosition[1], header->lookAtPosition[2]);
|
||||||
if (isNaN(lookAt)) {
|
if (isNaN(lookAt)) {
|
||||||
|
@ -1439,7 +1439,7 @@ QJsonObject AvatarData::toJson() const {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
qDebug() << "Warning -- AvatarData::toJson couldn't get avatar transform";
|
qDebug() << "Warning -- AvatarData::toJson couldn't get avatar transform";
|
||||||
}
|
}
|
||||||
avatarTransform.setScale(getTargetScale());
|
avatarTransform.setScale(getDomainLimitedScale());
|
||||||
if (recordingBasis) {
|
if (recordingBasis) {
|
||||||
root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis);
|
root[JSON_AVATAR_BASIS] = Transform::toJson(*recordingBasis);
|
||||||
// Find the relative transform
|
// Find the relative transform
|
||||||
|
@ -1451,7 +1451,7 @@ QJsonObject AvatarData::toJson() const {
|
||||||
root[JSON_AVATAR_RELATIVE] = Transform::toJson(avatarTransform);
|
root[JSON_AVATAR_RELATIVE] = Transform::toJson(avatarTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto scale = getTargetScale();
|
auto scale = getDomainLimitedScale();
|
||||||
if (scale != 1.0f) {
|
if (scale != 1.0f) {
|
||||||
root[JSON_AVATAR_SCALE] = scale;
|
root[JSON_AVATAR_SCALE] = scale;
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,12 @@ public:
|
||||||
void setTargetScale(float targetScale);
|
void setTargetScale(float targetScale);
|
||||||
void setTargetScaleVerbose(float targetScale);
|
void setTargetScaleVerbose(float targetScale);
|
||||||
|
|
||||||
|
float getDomainLimitedScale() const { return glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale); }
|
||||||
|
void setDomainMinimumScale(float domainMinimumScale)
|
||||||
|
{ _domainMinimumScale = glm::clamp(domainMinimumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); }
|
||||||
|
void setDomainMaximumScale(float domainMaximumScale)
|
||||||
|
{ _domainMaximumScale = glm::clamp(domainMaximumScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE); }
|
||||||
|
|
||||||
// Hand State
|
// Hand State
|
||||||
Q_INVOKABLE void setHandState(char s) { _handState = s; }
|
Q_INVOKABLE void setHandState(char s) { _handState = s; }
|
||||||
Q_INVOKABLE char getHandState() const { return _handState; }
|
Q_INVOKABLE char getHandState() const { return _handState; }
|
||||||
|
@ -377,6 +383,8 @@ protected:
|
||||||
|
|
||||||
// Body scale
|
// Body scale
|
||||||
float _targetScale;
|
float _targetScale;
|
||||||
|
float _domainMinimumScale { MIN_AVATAR_SCALE };
|
||||||
|
float _domainMaximumScale { MAX_AVATAR_SCALE };
|
||||||
|
|
||||||
// Hand state (are we grabbing something or not)
|
// Hand state (are we grabbing something or not)
|
||||||
char _handState;
|
char _handState;
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Basic2DWindowOpenGLDisplayPlugin : public OpenGLDisplayPlugin {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
using Parent = OpenGLDisplayPlugin;
|
using Parent = OpenGLDisplayPlugin;
|
||||||
public:
|
public:
|
||||||
virtual const QString& getName() const override { return NAME; }
|
virtual const QString getName() const override { return NAME; }
|
||||||
|
|
||||||
virtual float getTargetFrameRate() const override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; }
|
virtual float getTargetFrameRate() const override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; }
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
class NullDisplayPlugin : public DisplayPlugin {
|
class NullDisplayPlugin : public DisplayPlugin {
|
||||||
public:
|
public:
|
||||||
~NullDisplayPlugin() final {}
|
~NullDisplayPlugin() final {}
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
grouping getGrouping() const override { return DEVELOPER; }
|
grouping getGrouping() const override { return DEVELOPER; }
|
||||||
|
|
||||||
glm::uvec2 getRecommendedRenderSize() const override;
|
glm::uvec2 getRecommendedRenderSize() const override;
|
||||||
|
|
|
@ -758,7 +758,6 @@ void OpenGLDisplayPlugin::render(std::function<void(gpu::Batch& batch)> f) {
|
||||||
|
|
||||||
|
|
||||||
OpenGLDisplayPlugin::~OpenGLDisplayPlugin() {
|
OpenGLDisplayPlugin::~OpenGLDisplayPlugin() {
|
||||||
qDebug() << "Destroying OpenGLDisplayPlugin";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::updateCompositeFramebuffer() {
|
void OpenGLDisplayPlugin::updateCompositeFramebuffer() {
|
||||||
|
|
|
@ -13,7 +13,7 @@ class DebugHmdDisplayPlugin : public HmdDisplayPlugin {
|
||||||
using Parent = HmdDisplayPlugin;
|
using Parent = HmdDisplayPlugin;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
grouping getGrouping() const override { return DEVELOPER; }
|
grouping getGrouping() const override { return DEVELOPER; }
|
||||||
|
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
|
|
|
@ -710,3 +710,7 @@ void HmdDisplayPlugin::compositeExtra() {
|
||||||
HmdDisplayPlugin::~HmdDisplayPlugin() {
|
HmdDisplayPlugin::~HmdDisplayPlugin() {
|
||||||
qDebug() << "Destroying HmdDisplayPlugin";
|
qDebug() << "Destroying HmdDisplayPlugin";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float HmdDisplayPlugin::stutterRate() const {
|
||||||
|
return _stutterRate.rate();
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float stutterRate() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void hmdPresent() = 0;
|
virtual void hmdPresent() = 0;
|
||||||
virtual bool isHmdMounted() const = 0;
|
virtual bool isHmdMounted() const = 0;
|
||||||
|
@ -108,6 +110,7 @@ protected:
|
||||||
QMap<uint32_t, FrameInfo> _frameInfos;
|
QMap<uint32_t, FrameInfo> _frameInfos;
|
||||||
FrameInfo _currentPresentFrameInfo;
|
FrameInfo _currentPresentFrameInfo;
|
||||||
FrameInfo _currentRenderFrameInfo;
|
FrameInfo _currentRenderFrameInfo;
|
||||||
|
RateCounter<> _stutterRate;
|
||||||
|
|
||||||
bool _disablePreview { true };
|
bool _disablePreview { true };
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -13,7 +13,7 @@ class InterleavedStereoDisplayPlugin : public StereoDisplayPlugin {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
using Parent = StereoDisplayPlugin;
|
using Parent = StereoDisplayPlugin;
|
||||||
public:
|
public:
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
grouping getGrouping() const override { return ADVANCED; }
|
grouping getGrouping() const override { return ADVANCED; }
|
||||||
glm::uvec2 getRecommendedRenderSize() const override;
|
glm::uvec2 getRecommendedRenderSize() const override;
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ class SideBySideStereoDisplayPlugin : public StereoDisplayPlugin {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
using Parent = StereoDisplayPlugin;
|
using Parent = StereoDisplayPlugin;
|
||||||
public:
|
public:
|
||||||
virtual const QString& getName() const override { return NAME; }
|
virtual const QString getName() const override { return NAME; }
|
||||||
virtual grouping getGrouping() const override { return ADVANCED; }
|
virtual grouping getGrouping() const override { return ADVANCED; }
|
||||||
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
||||||
_lastSimulated(0),
|
_lastSimulated(0),
|
||||||
_lastUpdated(0),
|
_lastUpdated(0),
|
||||||
_lastEdited(0),
|
_lastEdited(0),
|
||||||
|
_lastEditedBy(ENTITY_ITEM_DEFAULT_LAST_EDITED_BY),
|
||||||
_lastEditedFromRemote(0),
|
_lastEditedFromRemote(0),
|
||||||
_lastEditedFromRemoteInRemoteTime(0),
|
_lastEditedFromRemoteInRemoteTime(0),
|
||||||
_created(UNKNOWN_CREATED_TIME),
|
_created(UNKNOWN_CREATED_TIME),
|
||||||
|
@ -141,6 +142,8 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
||||||
requestedProperties += PROP_CLIENT_ONLY;
|
requestedProperties += PROP_CLIENT_ONLY;
|
||||||
requestedProperties += PROP_OWNING_AVATAR_ID;
|
requestedProperties += PROP_OWNING_AVATAR_ID;
|
||||||
|
|
||||||
|
requestedProperties += PROP_LAST_EDITED_BY;
|
||||||
|
|
||||||
return requestedProperties;
|
return requestedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +282,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
||||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, getParentID());
|
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, getParentID());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex());
|
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, getQueryAACube());
|
APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, getQueryAACube());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, getLastEditedBy());
|
||||||
|
|
||||||
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
|
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
|
||||||
requestedProperties,
|
requestedProperties,
|
||||||
|
@ -803,6 +807,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
}
|
}
|
||||||
|
|
||||||
READ_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, AACube, setQueryAACube);
|
READ_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, AACube, setQueryAACube);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy);
|
||||||
|
|
||||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||||
propertyFlags, overwriteLocalData, somethingChanged);
|
propertyFlags, overwriteLocalData, somethingChanged);
|
||||||
|
@ -1205,6 +1210,8 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(clientOnly, getClientOnly);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(clientOnly, getClientOnly);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(owningAvatarID, getOwningAvatarID);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(owningAvatarID, getOwningAvatarID);
|
||||||
|
|
||||||
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lastEditedBy, getLastEditedBy);
|
||||||
|
|
||||||
properties._defaultSettings = false;
|
properties._defaultSettings = false;
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
|
@ -1307,6 +1314,8 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(clientOnly, setClientOnly);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(clientOnly, setClientOnly);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(owningAvatarID, setOwningAvatarID);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(owningAvatarID, setOwningAvatarID);
|
||||||
|
|
||||||
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy);
|
||||||
|
|
||||||
AACube saveQueryAACube = _queryAACube;
|
AACube saveQueryAACube = _queryAACube;
|
||||||
checkAndAdjustQueryAACube();
|
checkAndAdjustQueryAACube();
|
||||||
if (saveQueryAACube != _queryAACube) {
|
if (saveQueryAACube != _queryAACube) {
|
||||||
|
|
|
@ -459,6 +459,9 @@ public:
|
||||||
|
|
||||||
virtual void emitScriptEvent(const QVariant& message) {}
|
virtual void emitScriptEvent(const QVariant& message) {}
|
||||||
|
|
||||||
|
QUuid getLastEditedBy() const { return _lastEditedBy; }
|
||||||
|
void setLastEditedBy(QUuid value) { _lastEditedBy = value; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void setSimulated(bool simulated) { _simulated = simulated; }
|
void setSimulated(bool simulated) { _simulated = simulated; }
|
||||||
|
@ -474,6 +477,7 @@ protected:
|
||||||
// and physics changes
|
// and physics changes
|
||||||
quint64 _lastUpdated; // last time this entity called update(), this includes animations and non-physics changes
|
quint64 _lastUpdated; // last time this entity called update(), this includes animations and non-physics changes
|
||||||
quint64 _lastEdited; // last official local or remote edit time
|
quint64 _lastEdited; // last official local or remote edit time
|
||||||
|
QUuid _lastEditedBy; // id of last editor
|
||||||
quint64 _lastBroadcast; // the last time we sent an edit packet about this entity
|
quint64 _lastBroadcast; // the last time we sent an edit packet about this entity
|
||||||
|
|
||||||
quint64 _lastEditedFromRemote; // last time we received and edit from the server
|
quint64 _lastEditedFromRemote; // last time we received and edit from the server
|
||||||
|
|
|
@ -227,6 +227,7 @@ void EntityItemProperties::setBackgroundModeFromString(const QString& background
|
||||||
EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
||||||
EntityPropertyFlags changedProperties;
|
EntityPropertyFlags changedProperties;
|
||||||
|
|
||||||
|
CHECK_PROPERTY_CHANGE(PROP_LAST_EDITED_BY, lastEditedBy);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_POSITION, position);
|
CHECK_PROPERTY_CHANGE(PROP_POSITION, position);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_DIMENSIONS, dimensions);
|
CHECK_PROPERTY_CHANGE(PROP_DIMENSIONS, dimensions);
|
||||||
CHECK_PROPERTY_CHANGE(PROP_ROTATION, rotation);
|
CHECK_PROPERTY_CHANGE(PROP_ROTATION, rotation);
|
||||||
|
@ -368,6 +369,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable
|
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LAST_EDITED_BY, lastEditedBy);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POSITION, position);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POSITION, position);
|
||||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DIMENSIONS, dimensions);
|
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DIMENSIONS, dimensions);
|
||||||
if (!skipDefaults) {
|
if (!skipDefaults) {
|
||||||
|
@ -611,6 +613,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
||||||
setType(typeScriptValue.toVariant().toString());
|
setType(typeScriptValue.toVariant().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(lastEditedBy, QUuid, setLastEditedBy);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(position, glmVec3, setPosition);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(position, glmVec3, setPosition);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(dimensions, glmVec3, setDimensions);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(dimensions, glmVec3, setDimensions);
|
||||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(rotation, glmQuat, setRotation);
|
COPY_PROPERTY_FROM_QSCRIPTVALUE(rotation, glmQuat, setRotation);
|
||||||
|
@ -750,6 +753,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItemProperties::merge(const EntityItemProperties& other) {
|
void EntityItemProperties::merge(const EntityItemProperties& other) {
|
||||||
|
COPY_PROPERTY_IF_CHANGED(lastEditedBy);
|
||||||
COPY_PROPERTY_IF_CHANGED(position);
|
COPY_PROPERTY_IF_CHANGED(position);
|
||||||
COPY_PROPERTY_IF_CHANGED(dimensions);
|
COPY_PROPERTY_IF_CHANGED(dimensions);
|
||||||
COPY_PROPERTY_IF_CHANGED(rotation);
|
COPY_PROPERTY_IF_CHANGED(rotation);
|
||||||
|
@ -1667,6 +1671,7 @@ bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityIt
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItemProperties::markAllChanged() {
|
void EntityItemProperties::markAllChanged() {
|
||||||
|
_lastEditedByChanged = true;
|
||||||
_simulationOwnerChanged = true;
|
_simulationOwnerChanged = true;
|
||||||
_positionChanged = true;
|
_positionChanged = true;
|
||||||
_dimensionsChanged = true;
|
_dimensionsChanged = true;
|
||||||
|
|
|
@ -83,6 +83,7 @@ public:
|
||||||
quint64 getLastEdited() const { return _lastEdited; }
|
quint64 getLastEdited() const { return _lastEdited; }
|
||||||
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
|
float getEditedAgo() const /// Elapsed seconds since this entity was last edited
|
||||||
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
|
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
|
||||||
|
|
||||||
EntityPropertyFlags getChangedProperties() const;
|
EntityPropertyFlags getChangedProperties() const;
|
||||||
|
|
||||||
bool parentDependentPropertyChanged() const; // was there a changed in a property that requires parent info to interpret?
|
bool parentDependentPropertyChanged() const; // was there a changed in a property that requires parent info to interpret?
|
||||||
|
@ -218,6 +219,8 @@ public:
|
||||||
|
|
||||||
DEFINE_PROPERTY_REF(PROP_DPI, DPI, dpi, uint16_t, ENTITY_ITEM_DEFAULT_DPI);
|
DEFINE_PROPERTY_REF(PROP_DPI, DPI, dpi, uint16_t, ENTITY_ITEM_DEFAULT_DPI);
|
||||||
|
|
||||||
|
DEFINE_PROPERTY_REF(PROP_LAST_EDITED_BY, LastEditedBy, lastEditedBy, QUuid, ENTITY_ITEM_DEFAULT_LAST_EDITED_BY);
|
||||||
|
|
||||||
static QString getBackgroundModeString(BackgroundMode mode);
|
static QString getBackgroundModeString(BackgroundMode mode);
|
||||||
|
|
||||||
|
|
||||||
|
@ -455,6 +458,8 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ClientOnly, clientOnly, "");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ClientOnly, clientOnly, "");
|
||||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, OwningAvatarID, owningAvatarID, "");
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, OwningAvatarID, owningAvatarID, "");
|
||||||
|
|
||||||
|
DEBUG_PROPERTY_IF_CHANGED(debug, properties, LastEditedBy, lastEditedBy, "");
|
||||||
|
|
||||||
properties.getAnimation().debugDump();
|
properties.getAnimation().debugDump();
|
||||||
properties.getSkybox().debugDump();
|
properties.getSkybox().debugDump();
|
||||||
properties.getStage().debugDump();
|
properties.getStage().debugDump();
|
||||||
|
|
|
@ -75,4 +75,6 @@ const QString ENTITY_ITEM_DEFAULT_NAME = QString("");
|
||||||
|
|
||||||
const uint16_t ENTITY_ITEM_DEFAULT_DPI = 30;
|
const uint16_t ENTITY_ITEM_DEFAULT_DPI = 30;
|
||||||
|
|
||||||
|
const QUuid ENTITY_ITEM_DEFAULT_LAST_EDITED_BY = QUuid();
|
||||||
|
|
||||||
#endif // hifi_EntityItemPropertiesDefaults_h
|
#endif // hifi_EntityItemPropertiesDefaults_h
|
||||||
|
|
|
@ -181,6 +181,8 @@ enum EntityPropertyList {
|
||||||
PROP_LOCAL_VELOCITY, // only used to convert values to and from scripts
|
PROP_LOCAL_VELOCITY, // only used to convert values to and from scripts
|
||||||
PROP_LOCAL_ANGULAR_VELOCITY, // only used to convert values to and from scripts
|
PROP_LOCAL_ANGULAR_VELOCITY, // only used to convert values to and from scripts
|
||||||
|
|
||||||
|
PROP_LAST_EDITED_BY,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||||
PROP_AFTER_LAST_ITEM,
|
PROP_AFTER_LAST_ITEM,
|
||||||
|
|
|
@ -1013,6 +1013,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
|
||||||
endLogging = usecTimestampNow();
|
endLogging = usecTimestampNow();
|
||||||
|
|
||||||
startUpdate = usecTimestampNow();
|
startUpdate = usecTimestampNow();
|
||||||
|
properties.setLastEditedBy(senderNode->getUUID());
|
||||||
updateEntity(entityItemID, properties, senderNode);
|
updateEntity(entityItemID, properties, senderNode);
|
||||||
existingEntity->markAsChangedOnServer();
|
existingEntity->markAsChangedOnServer();
|
||||||
endUpdate = usecTimestampNow();
|
endUpdate = usecTimestampNow();
|
||||||
|
@ -1021,6 +1022,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
|
||||||
if (senderNode->getCanRez() || senderNode->getCanRezTmp()) {
|
if (senderNode->getCanRez() || senderNode->getCanRezTmp()) {
|
||||||
// this is a new entity... assign a new entityID
|
// this is a new entity... assign a new entityID
|
||||||
properties.setCreated(properties.getLastEdited());
|
properties.setCreated(properties.getLastEdited());
|
||||||
|
properties.setLastEditedBy(senderNode->getUUID());
|
||||||
startCreate = usecTimestampNow();
|
startCreate = usecTimestampNow();
|
||||||
EntityItemPointer newEntity = addEntity(entityItemID, properties);
|
EntityItemPointer newEntity = addEntity(entityItemID, properties);
|
||||||
endCreate = usecTimestampNow();
|
endCreate = usecTimestampNow();
|
||||||
|
|
|
@ -285,10 +285,10 @@ GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture&
|
||||||
}
|
}
|
||||||
|
|
||||||
GL45Texture::~GL45Texture() {
|
GL45Texture::~GL45Texture() {
|
||||||
// External textures cycle very quickly, so don't spam the log with messages about them.
|
// // External textures cycle very quickly, so don't spam the log with messages about them.
|
||||||
if (!_gpuObject.getUsage().isExternal()) {
|
// if (!_gpuObject.getUsage().isExternal()) {
|
||||||
qCDebug(gpugl45logging) << "Destroying texture " << _id << " from source " << _source.c_str();
|
// qCDebug(gpugl45logging) << "Destroying texture " << _id << " from source " << _source.c_str();
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Remove this texture from the candidate list of derezzable textures
|
// Remove this texture from the candidate list of derezzable textures
|
||||||
if (_transferrable) {
|
if (_transferrable) {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
|
|
||||||
const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse";
|
const char* KeyboardMouseDevice::NAME = "Keyboard/Mouse";
|
||||||
bool KeyboardMouseDevice::_enableTouch = true;
|
bool KeyboardMouseDevice::_enableTouch = true;
|
||||||
|
|
||||||
void KeyboardMouseDevice::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
void KeyboardMouseDevice::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
||||||
|
|
|
@ -66,7 +66,7 @@ public:
|
||||||
|
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
bool isSupported() const override { return true; }
|
bool isSupported() const override { return true; }
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
|
|
||||||
bool isHandController() const override { return false; }
|
bool isHandController() const override { return false; }
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ public:
|
||||||
|
|
||||||
static void enableTouch(bool enableTouch) { _enableTouch = enableTouch; }
|
static void enableTouch(bool enableTouch) { _enableTouch = enableTouch; }
|
||||||
|
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
|
|
||||||
const QString TouchscreenDevice::NAME = "Touchscreen";
|
const char* TouchscreenDevice::NAME = "Touchscreen";
|
||||||
|
|
||||||
bool TouchscreenDevice::isSupported() const {
|
bool TouchscreenDevice::isSupported() const {
|
||||||
for (auto touchDevice : QTouchDevice::devices()) {
|
for (auto touchDevice : QTouchDevice::devices()) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
|
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
virtual const QString& getName() const override { return NAME; }
|
virtual const QString getName() const override { return NAME; }
|
||||||
|
|
||||||
bool isHandController() const override { return false; }
|
bool isHandController() const override { return false; }
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public:
|
||||||
void touchUpdateEvent(const QTouchEvent* event);
|
void touchUpdateEvent(const QTouchEvent* event);
|
||||||
void touchGestureEvent(const QGestureEvent* event);
|
void touchGestureEvent(const QGestureEvent* event);
|
||||||
|
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -272,15 +272,6 @@ void DomainHandler::setIsConnected(bool isConnected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainHandler::requestDomainSettings() {
|
void DomainHandler::requestDomainSettings() {
|
||||||
// TODO: the nodes basically lock if they don't get a response - add a timeout to this so that they at least restart
|
|
||||||
// if they can't get settings
|
|
||||||
|
|
||||||
NodeType_t owningNodeType = DependencyManager::get<NodeList>()->getOwnerType();
|
|
||||||
if (owningNodeType == NodeType::Agent) {
|
|
||||||
// for now the agent nodes don't need any domain settings
|
|
||||||
_settingsObject = QJsonObject();
|
|
||||||
emit settingsReceived(_settingsObject);
|
|
||||||
} else {
|
|
||||||
qCDebug(networking) << "Requesting settings from domain server";
|
qCDebug(networking) << "Requesting settings from domain server";
|
||||||
|
|
||||||
Assignment::Type assignmentType = Assignment::typeForNodeType(DependencyManager::get<NodeList>()->getOwnerType());
|
Assignment::Type assignmentType = Assignment::typeForNodeType(DependencyManager::get<NodeList>()->getOwnerType());
|
||||||
|
@ -293,7 +284,6 @@ void DomainHandler::requestDomainSettings() {
|
||||||
|
|
||||||
_settingsTimer.start();
|
_settingsTimer.start();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void DomainHandler::processSettingsPacketList(QSharedPointer<ReceivedMessage> packetList) {
|
void DomainHandler::processSettingsPacketList(QSharedPointer<ReceivedMessage> packetList) {
|
||||||
// stop our settings timer since we successfully requested the settings we need
|
// stop our settings timer since we successfully requested the settings we need
|
||||||
|
|
|
@ -815,3 +815,31 @@ void NodeList::kickNodeBySessionID(const QUuid& nodeID) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeList::muteNodeBySessionID(const QUuid& nodeID) {
|
||||||
|
// cannot mute yourself, or nobody
|
||||||
|
if (!nodeID.isNull() && _sessionUUID != nodeID ) {
|
||||||
|
if (getThisNodeCanKick()) {
|
||||||
|
auto audioMixer = soloNodeOfType(NodeType::AudioMixer);
|
||||||
|
if (audioMixer) {
|
||||||
|
// setup the packet
|
||||||
|
auto mutePacket = NLPacket::create(PacketType::NodeMuteRequest, NUM_BYTES_RFC4122_UUID, true);
|
||||||
|
|
||||||
|
// write the node ID to the packet
|
||||||
|
mutePacket->write(nodeID.toRfc4122());
|
||||||
|
|
||||||
|
qDebug() << "Sending packet to mute node" << uuidStringWithoutCurlyBraces(nodeID);
|
||||||
|
|
||||||
|
sendPacket(std::move(mutePacket), *audioMixer);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Couldn't find audio mixer to send node mute request";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qWarning() << "You do not have permissions to mute in this domain."
|
||||||
|
<< "Request to mute node" << uuidStringWithoutCurlyBraces(nodeID) << "will not be sent";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qWarning() << "NodeList::muteNodeBySessionID called with an invalid ID or an ID which matches the current session ID.";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ public:
|
||||||
bool isIgnoringNode(const QUuid& nodeID) const;
|
bool isIgnoringNode(const QUuid& nodeID) const;
|
||||||
|
|
||||||
void kickNodeBySessionID(const QUuid& nodeID);
|
void kickNodeBySessionID(const QUuid& nodeID);
|
||||||
|
void muteNodeBySessionID(const QUuid& nodeID);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
@ -26,7 +26,8 @@ const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
|
||||||
<< PacketType::NodeJsonStats << PacketType::EntityQuery
|
<< PacketType::NodeJsonStats << PacketType::EntityQuery
|
||||||
<< PacketType::OctreeDataNack << PacketType::EntityEditNack
|
<< PacketType::OctreeDataNack << PacketType::EntityEditNack
|
||||||
<< PacketType::DomainListRequest << PacketType::StopNode
|
<< PacketType::DomainListRequest << PacketType::StopNode
|
||||||
<< PacketType::DomainDisconnectRequest << PacketType::NodeKickRequest;
|
<< PacketType::DomainDisconnectRequest << PacketType::NodeKickRequest
|
||||||
|
<< PacketType::NodeMuteRequest;
|
||||||
|
|
||||||
const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
|
const QSet<PacketType> NON_SOURCED_PACKETS = QSet<PacketType>()
|
||||||
<< PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment
|
<< PacketType::StunResponse << PacketType::CreateAssignment << PacketType::RequestAssignment
|
||||||
|
@ -47,7 +48,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
case PacketType::EntityAdd:
|
case PacketType::EntityAdd:
|
||||||
case PacketType::EntityEdit:
|
case PacketType::EntityEdit:
|
||||||
case PacketType::EntityData:
|
case PacketType::EntityData:
|
||||||
return VERSION_ENTITIES_ARROW_ACTION;
|
return VERSION_ENTITIES_LAST_EDITED_BY;
|
||||||
case PacketType::AvatarIdentity:
|
case PacketType::AvatarIdentity:
|
||||||
case PacketType::AvatarData:
|
case PacketType::AvatarData:
|
||||||
case PacketType::BulkAvatarData:
|
case PacketType::BulkAvatarData:
|
||||||
|
|
|
@ -99,7 +99,8 @@ public:
|
||||||
SelectedAudioFormat,
|
SelectedAudioFormat,
|
||||||
MoreEntityShapes,
|
MoreEntityShapes,
|
||||||
NodeKickRequest,
|
NodeKickRequest,
|
||||||
LAST_PACKET_TYPE = NodeKickRequest
|
NodeMuteRequest,
|
||||||
|
LAST_PACKET_TYPE = NodeMuteRequest
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -188,6 +189,7 @@ const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_STATIC_MESH = 61;
|
||||||
const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SIMPLE_HULLS = 62;
|
const PacketVersion VERSION_MODEL_ENTITIES_SUPPORT_SIMPLE_HULLS = 62;
|
||||||
const PacketVersion VERSION_WEB_ENTITIES_SUPPORT_DPI = 63;
|
const PacketVersion VERSION_WEB_ENTITIES_SUPPORT_DPI = 63;
|
||||||
const PacketVersion VERSION_ENTITIES_ARROW_ACTION = 64;
|
const PacketVersion VERSION_ENTITIES_ARROW_ACTION = 64;
|
||||||
|
const PacketVersion VERSION_ENTITIES_LAST_EDITED_BY = 65;
|
||||||
|
|
||||||
enum class AssetServerPacketVersion: PacketVersion {
|
enum class AssetServerPacketVersion: PacketVersion {
|
||||||
VegasCongestionControl = 19
|
VegasCongestionControl = 19
|
||||||
|
|
|
@ -165,6 +165,12 @@ qint64 Socket::writePacketList(std::unique_ptr<PacketList> packetList, const Hif
|
||||||
// hand this packetList off to writeReliablePacketList
|
// hand this packetList off to writeReliablePacketList
|
||||||
// because Qt can't invoke with the unique_ptr we have to release it here and re-construct in writeReliablePacketList
|
// because Qt can't invoke with the unique_ptr we have to release it here and re-construct in writeReliablePacketList
|
||||||
|
|
||||||
|
if (packetList->getNumPackets() == 0) {
|
||||||
|
qCWarning(networking) << "Trying to send packet list with 0 packets, bailing.";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
auto ptr = packetList.release();
|
auto ptr = packetList.release();
|
||||||
QMetaObject::invokeMethod(this, "writeReliablePacketList", Qt::AutoConnection,
|
QMetaObject::invokeMethod(this, "writeReliablePacketList", Qt::AutoConnection,
|
||||||
|
|
|
@ -188,6 +188,8 @@ public:
|
||||||
virtual float renderRate() const { return -1.0f; }
|
virtual float renderRate() const { return -1.0f; }
|
||||||
// Rate at which we present to the display device
|
// Rate at which we present to the display device
|
||||||
virtual float presentRate() const { return -1.0f; }
|
virtual float presentRate() const { return -1.0f; }
|
||||||
|
// Rate at which old frames are presented to the device display
|
||||||
|
virtual float stutterRate() const { return -1.0f; }
|
||||||
// Rate at which new frames are being presented to the display device
|
// Rate at which new frames are being presented to the display device
|
||||||
virtual float newFramePresentRate() const { return -1.0f; }
|
virtual float newFramePresentRate() const { return -1.0f; }
|
||||||
// Rate at which rendered frames are being skipped
|
// Rate at which rendered frames are being skipped
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
//
|
//
|
||||||
#include "Plugin.h"
|
#include "Plugin.h"
|
||||||
|
|
||||||
QString Plugin::UNKNOWN_PLUGIN_ID("unknown");
|
const char* Plugin::UNKNOWN_PLUGIN_ID { "unknown" };
|
||||||
|
|
||||||
void Plugin::setContainer(PluginContainer* container) {
|
void Plugin::setContainer(PluginContainer* container) {
|
||||||
_container = container;
|
_container = container;
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Plugin : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
/// \return human-readable name
|
/// \return human-readable name
|
||||||
virtual const QString& getName() const = 0;
|
virtual const QString getName() const = 0;
|
||||||
|
|
||||||
typedef enum { STANDARD, ADVANCED, DEVELOPER } grouping;
|
typedef enum { STANDARD, ADVANCED, DEVELOPER } grouping;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ public:
|
||||||
virtual grouping getGrouping() const { return STANDARD; }
|
virtual grouping getGrouping() const { return STANDARD; }
|
||||||
|
|
||||||
/// \return string ID (not necessarily human-readable)
|
/// \return string ID (not necessarily human-readable)
|
||||||
virtual const QString& getID() const { assert(false); return UNKNOWN_PLUGIN_ID; }
|
virtual const QString getID() const { assert(false); return UNKNOWN_PLUGIN_ID; }
|
||||||
|
|
||||||
virtual bool isSupported() const;
|
virtual bool isSupported() const;
|
||||||
|
|
||||||
|
@ -74,6 +74,6 @@ signals:
|
||||||
protected:
|
protected:
|
||||||
bool _active { false };
|
bool _active { false };
|
||||||
PluginContainer* _container { nullptr };
|
PluginContainer* _container { nullptr };
|
||||||
static QString UNKNOWN_PLUGIN_ID;
|
static const char* UNKNOWN_PLUGIN_ID;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -162,9 +162,10 @@ static const uint32_t blue = toRGBA(0, 0, 255, 255);
|
||||||
|
|
||||||
const int NUM_CIRCLE_SLICES = 24;
|
const int NUM_CIRCLE_SLICES = 24;
|
||||||
|
|
||||||
static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius, AnimDebugDrawData::Vertex*& v) {
|
static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius, glm::vec4& vecColor, AnimDebugDrawData::Vertex*& v) {
|
||||||
|
|
||||||
const float XYZ_AXIS_LENGTH = radius * 4.0f;
|
const float XYZ_AXIS_LENGTH = radius * 4.0f;
|
||||||
|
const uint32_t color = toRGBA(vecColor);
|
||||||
|
|
||||||
AnimPose finalPose = rootPose * pose;
|
AnimPose finalPose = rootPose * pose;
|
||||||
glm::vec3 base = rootPose * pose.trans;
|
glm::vec3 base = rootPose * pose.trans;
|
||||||
|
@ -192,10 +193,10 @@ static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius
|
||||||
// x-ring
|
// x-ring
|
||||||
for (int i = 0; i < NUM_CIRCLE_SLICES; i++) {
|
for (int i = 0; i < NUM_CIRCLE_SLICES; i++) {
|
||||||
v->pos = xRing[i];
|
v->pos = xRing[i];
|
||||||
v->rgba = red;
|
v->rgba = color;
|
||||||
v++;
|
v++;
|
||||||
v->pos = xRing[i + 1];
|
v->pos = xRing[i + 1];
|
||||||
v->rgba = red;
|
v->rgba = color;
|
||||||
v++;
|
v++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,10 +211,10 @@ static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius
|
||||||
// y-ring
|
// y-ring
|
||||||
for (int i = 0; i < NUM_CIRCLE_SLICES; i++) {
|
for (int i = 0; i < NUM_CIRCLE_SLICES; i++) {
|
||||||
v->pos = yRing[i];
|
v->pos = yRing[i];
|
||||||
v->rgba = green;
|
v->rgba = color;
|
||||||
v++;
|
v++;
|
||||||
v->pos = yRing[i + 1];
|
v->pos = yRing[i + 1];
|
||||||
v->rgba = green;
|
v->rgba = color;
|
||||||
v++;
|
v++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,10 +229,10 @@ static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius
|
||||||
// z-ring
|
// z-ring
|
||||||
for (int i = 0; i < NUM_CIRCLE_SLICES; i++) {
|
for (int i = 0; i < NUM_CIRCLE_SLICES; i++) {
|
||||||
v->pos = zRing[i];
|
v->pos = zRing[i];
|
||||||
v->rgba = blue;
|
v->rgba = color;
|
||||||
v++;
|
v++;
|
||||||
v->pos = zRing[i + 1];
|
v->pos = zRing[i + 1];
|
||||||
v->rgba = blue;
|
v->rgba = color;
|
||||||
v++;
|
v++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,7 +368,7 @@ void AnimDebugDraw::update() {
|
||||||
const float radius = BONE_RADIUS / (absPoses[i].scale.x * rootPose.scale.x);
|
const float radius = BONE_RADIUS / (absPoses[i].scale.x * rootPose.scale.x);
|
||||||
|
|
||||||
// draw bone
|
// draw bone
|
||||||
addBone(rootPose, absPoses[i], radius, v);
|
addBone(rootPose, absPoses[i], radius, color, v);
|
||||||
|
|
||||||
// draw link to parent
|
// draw link to parent
|
||||||
auto parentIndex = skeleton->getParentIndex(i);
|
auto parentIndex = skeleton->getParentIndex(i);
|
||||||
|
@ -382,20 +383,18 @@ void AnimDebugDraw::update() {
|
||||||
for (auto& iter : markerMap) {
|
for (auto& iter : markerMap) {
|
||||||
glm::quat rot = std::get<0>(iter.second);
|
glm::quat rot = std::get<0>(iter.second);
|
||||||
glm::vec3 pos = std::get<1>(iter.second);
|
glm::vec3 pos = std::get<1>(iter.second);
|
||||||
glm::vec4 color = std::get<2>(iter.second); // TODO: currently ignored.
|
glm::vec4 color = std::get<2>(iter.second);
|
||||||
Q_UNUSED(color);
|
|
||||||
const float radius = POSE_RADIUS;
|
const float radius = POSE_RADIUS;
|
||||||
addBone(AnimPose::identity, AnimPose(glm::vec3(1), rot, pos), radius, v);
|
addBone(AnimPose::identity, AnimPose(glm::vec3(1), rot, pos), radius, color, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimPose myAvatarPose(glm::vec3(1), DebugDraw::getInstance().getMyAvatarRot(), DebugDraw::getInstance().getMyAvatarPos());
|
AnimPose myAvatarPose(glm::vec3(1), DebugDraw::getInstance().getMyAvatarRot(), DebugDraw::getInstance().getMyAvatarPos());
|
||||||
for (auto& iter : myAvatarMarkerMap) {
|
for (auto& iter : myAvatarMarkerMap) {
|
||||||
glm::quat rot = std::get<0>(iter.second);
|
glm::quat rot = std::get<0>(iter.second);
|
||||||
glm::vec3 pos = std::get<1>(iter.second);
|
glm::vec3 pos = std::get<1>(iter.second);
|
||||||
glm::vec4 color = std::get<2>(iter.second); // TODO: currently ignored.
|
glm::vec4 color = std::get<2>(iter.second);
|
||||||
Q_UNUSED(color);
|
|
||||||
const float radius = POSE_RADIUS;
|
const float radius = POSE_RADIUS;
|
||||||
addBone(myAvatarPose, AnimPose(glm::vec3(1), rot, pos), radius, v);
|
addBone(myAvatarPose, AnimPose(glm::vec3(1), rot, pos), radius, color, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw rays from shared DebugDraw singleton
|
// draw rays from shared DebugDraw singleton
|
||||||
|
|
|
@ -1172,7 +1172,8 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac
|
||||||
// Guard against meaningless query and fragment parts.
|
// Guard against meaningless query and fragment parts.
|
||||||
// Do NOT use PreferLocalFile as its behavior is unpredictable (e.g., on defaultScriptsLocation())
|
// Do NOT use PreferLocalFile as its behavior is unpredictable (e.g., on defaultScriptsLocation())
|
||||||
const auto strippingFlags = QUrl::RemoveFilename | QUrl::RemoveQuery | QUrl::RemoveFragment;
|
const auto strippingFlags = QUrl::RemoveFilename | QUrl::RemoveQuery | QUrl::RemoveFragment;
|
||||||
for (QString file : includeFiles) {
|
for (QString includeFile : includeFiles) {
|
||||||
|
QString file = ResourceManager::normalizeURL(includeFile);
|
||||||
QUrl thisURL;
|
QUrl thisURL;
|
||||||
bool isStandardLibrary = false;
|
bool isStandardLibrary = false;
|
||||||
if (file.startsWith("/~/")) {
|
if (file.startsWith("/~/")) {
|
||||||
|
|
|
@ -29,6 +29,11 @@ void UsersScriptingInterface::kick(const QUuid& nodeID) {
|
||||||
DependencyManager::get<NodeList>()->kickNodeBySessionID(nodeID);
|
DependencyManager::get<NodeList>()->kickNodeBySessionID(nodeID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UsersScriptingInterface::mute(const QUuid& nodeID) {
|
||||||
|
// ask the NodeList to mute the user with the given session ID
|
||||||
|
DependencyManager::get<NodeList>()->muteNodeBySessionID(nodeID);
|
||||||
|
}
|
||||||
|
|
||||||
bool UsersScriptingInterface::getCanKick() {
|
bool UsersScriptingInterface::getCanKick() {
|
||||||
// ask the NodeList to return our ability to kick
|
// ask the NodeList to return our ability to kick
|
||||||
return DependencyManager::get<NodeList>()->getThisNodeCanKick();
|
return DependencyManager::get<NodeList>()->getThisNodeCanKick();
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
void ignore(const QUuid& nodeID);
|
void ignore(const QUuid& nodeID);
|
||||||
void kick(const QUuid& nodeID);
|
void kick(const QUuid& nodeID);
|
||||||
|
void mute(const QUuid& nodeID);
|
||||||
|
|
||||||
bool getCanKick();
|
bool getCanKick();
|
||||||
|
|
||||||
|
|
|
@ -226,5 +226,5 @@ QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath, bool
|
||||||
shouldCreateIfMissing);
|
shouldCreateIfMissing);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,12 @@ namespace hifi {
|
||||||
using Builder = std::function<Pointer()>;
|
using Builder = std::function<Pointer()>;
|
||||||
using BuilderMap = std::map<Key, Builder>;
|
using BuilderMap = std::map<Key, Builder>;
|
||||||
|
|
||||||
void registerBuilder(const Key& name, Builder builder) {
|
void registerBuilder(const Key name, Builder builder) {
|
||||||
// FIXME don't allow name collisions
|
// FIXME don't allow name collisions
|
||||||
_builders[name] = builder;
|
_builders[name] = builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer create(const Key& name) const {
|
Pointer create(const Key name) const {
|
||||||
const auto& entryIt = _builders.find(name);
|
const auto& entryIt = _builders.find(name);
|
||||||
if (entryIt != _builders.end()) {
|
if (entryIt != _builders.end()) {
|
||||||
return (*entryIt).second();
|
return (*entryIt).second();
|
||||||
|
@ -39,7 +39,7 @@ namespace hifi {
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
class Registrar {
|
class Registrar {
|
||||||
public:
|
public:
|
||||||
Registrar(const Key& name, SimpleFactory& factory) {
|
Registrar(const Key name, SimpleFactory& factory) {
|
||||||
factory.registerBuilder(name, [] { return std::make_shared<Impl>(); });
|
factory.registerBuilder(name, [] { return std::make_shared<Impl>(); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include "HiFiCodec.h"
|
#include "HiFiCodec.h"
|
||||||
|
|
||||||
const QString HiFiCodec::NAME = "hifiAC";
|
const char* HiFiCodec::NAME { "hifiAC" };
|
||||||
|
|
||||||
void HiFiCodec::init() {
|
void HiFiCodec::init() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class HiFiCodec : public CodecPlugin {
|
||||||
public:
|
public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
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;
|
void init() override;
|
||||||
void deinit() override;
|
void deinit() override;
|
||||||
|
@ -36,7 +36,7 @@ public:
|
||||||
virtual void releaseDecoder(Decoder* decoder) override;
|
virtual void releaseDecoder(Decoder* decoder) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_HiFiCodec_h
|
#endif // hifi_HiFiCodec_h
|
||||||
|
|
|
@ -27,8 +27,8 @@ Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins")
|
||||||
|
|
||||||
#include <NeuronDataReader.h>
|
#include <NeuronDataReader.h>
|
||||||
|
|
||||||
const QString NeuronPlugin::NAME = "Neuron";
|
const char* NeuronPlugin::NAME = "Neuron";
|
||||||
const QString NeuronPlugin::NEURON_ID_STRING = "Perception Neuron";
|
const char* NeuronPlugin::NEURON_ID_STRING = "Perception Neuron";
|
||||||
|
|
||||||
// indices of joints of the Neuron standard skeleton.
|
// indices of joints of the Neuron standard skeleton.
|
||||||
// This is 'almost' the same as the High Fidelity standard skeleton.
|
// This is 'almost' the same as the High Fidelity standard skeleton.
|
||||||
|
|
|
@ -29,8 +29,8 @@ public:
|
||||||
|
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
virtual const QString& getName() const override { return NAME; }
|
virtual const QString getName() const override { return NAME; }
|
||||||
const QString& getID() const override { return NEURON_ID_STRING; }
|
const QString getID() const override { return NEURON_ID_STRING; }
|
||||||
|
|
||||||
virtual bool activate() override;
|
virtual bool activate() override;
|
||||||
virtual void deactivate() override;
|
virtual void deactivate() override;
|
||||||
|
@ -65,8 +65,8 @@ protected:
|
||||||
|
|
||||||
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>() };
|
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>() };
|
||||||
|
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
static const QString NEURON_ID_STRING;
|
static const char* NEURON_ID_STRING;
|
||||||
|
|
||||||
std::string _serverAddress;
|
std::string _serverAddress;
|
||||||
int _serverPort;
|
int _serverPort;
|
||||||
|
|
|
@ -29,7 +29,7 @@ class Joystick : public QObject, public controller::InputDevice {
|
||||||
public:
|
public:
|
||||||
using Pointer = std::shared_ptr<Joystick>;
|
using Pointer = std::shared_ptr<Joystick>;
|
||||||
|
|
||||||
const QString& getName() const { return _name; }
|
const QString getName() const { return _name; }
|
||||||
|
|
||||||
SDL_GameController* getGameController() { return _sdlGameController; }
|
SDL_GameController* getGameController() { return _sdlGameController; }
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ static_assert(
|
||||||
"SDL2 equvalence: Enums and values from StandardControls.h are assumed to match enums from SDL_gamecontroller.h");
|
"SDL2 equvalence: Enums and values from StandardControls.h are assumed to match enums from SDL_gamecontroller.h");
|
||||||
|
|
||||||
|
|
||||||
const QString SDL2Manager::NAME = "SDL2";
|
const char* SDL2Manager::NAME = "SDL2";
|
||||||
|
|
||||||
SDL_JoystickID SDL2Manager::getInstanceId(SDL_GameController* controller) {
|
SDL_JoystickID SDL2Manager::getInstanceId(SDL_GameController* controller) {
|
||||||
SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller);
|
SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller);
|
||||||
|
|
|
@ -24,7 +24,7 @@ class SDL2Manager : public InputPlugin {
|
||||||
public:
|
public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
|
|
||||||
QStringList getSubdeviceNames() override;
|
QStringList getSubdeviceNames() override;
|
||||||
bool isHandController() const override { return false; }
|
bool isHandController() const override { return false; }
|
||||||
|
@ -79,7 +79,7 @@ private:
|
||||||
|
|
||||||
QMap<SDL_JoystickID, Joystick::Pointer> _openJoysticks;
|
QMap<SDL_JoystickID, Joystick::Pointer> _openJoysticks;
|
||||||
bool _isInitialized { false } ;
|
bool _isInitialized { false } ;
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
QStringList _subdeviceNames;
|
QStringList _subdeviceNames;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -55,15 +55,15 @@ bool SixenseManager::_sixenseLoaded = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const QString SixenseManager::NAME = "Sixense";
|
const char* SixenseManager::NAME { "Sixense" };
|
||||||
const QString SixenseManager::HYDRA_ID_STRING = "Razer Hydra";
|
const char* SixenseManager::HYDRA_ID_STRING { "Razer Hydra" };
|
||||||
|
|
||||||
const QString MENU_PARENT = "Developer";
|
const char* MENU_PARENT { "Developer" };
|
||||||
const QString MENU_NAME = "Sixense";
|
const char* MENU_NAME { "Sixense" };
|
||||||
const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
const char* MENU_PATH { "Developer" ">" "Sixense" };
|
||||||
const QString TOGGLE_SMOOTH = "Smooth Sixense Movement";
|
const char* TOGGLE_SMOOTH { "Smooth Sixense Movement" };
|
||||||
const QString SHOW_DEBUG_RAW = "Debug Draw Raw Data";
|
const char* SHOW_DEBUG_RAW { "Debug Draw Raw Data" };
|
||||||
const QString SHOW_DEBUG_CALIBRATED = "Debug Draw Calibrated Data";
|
const char* SHOW_DEBUG_CALIBRATED { "Debug Draw Calibrated Data" };
|
||||||
|
|
||||||
bool SixenseManager::isSupported() const {
|
bool SixenseManager::isSupported() const {
|
||||||
#if defined(HAVE_SIXENSE) && !defined(Q_OS_OSX)
|
#if defined(HAVE_SIXENSE) && !defined(Q_OS_OSX)
|
||||||
|
|
|
@ -28,8 +28,8 @@ class SixenseManager : public InputPlugin {
|
||||||
public:
|
public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
virtual bool isSupported() const override;
|
virtual bool isSupported() const override;
|
||||||
virtual const QString& getName() const override { return NAME; }
|
virtual const QString getName() const override { return NAME; }
|
||||||
virtual const QString& getID() const override { return HYDRA_ID_STRING; }
|
virtual const QString getID() const override { return HYDRA_ID_STRING; }
|
||||||
|
|
||||||
// Sixense always seems to initialize even if the hydras are not present. Is there
|
// Sixense always seems to initialize even if the hydras are not present. Is there
|
||||||
// a way we can properly detect whether the hydras are present?
|
// a way we can properly detect whether the hydras are present?
|
||||||
|
@ -92,8 +92,8 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>() };
|
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>() };
|
||||||
|
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
static const QString HYDRA_ID_STRING;
|
static const char* HYDRA_ID_STRING;
|
||||||
|
|
||||||
static bool _sixenseLoaded;
|
static bool _sixenseLoaded;
|
||||||
};
|
};
|
||||||
|
|
|
@ -76,8 +76,8 @@ class SpacemouseManager : public InputPlugin, public QAbstractNativeEventFilter
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
const QString& getID() const override { return NAME; }
|
const QString getID() const override { return NAME; }
|
||||||
|
|
||||||
bool activate() override;
|
bool activate() override;
|
||||||
void deactivate() override;
|
void deactivate() override;
|
||||||
|
@ -127,7 +127,7 @@ private:
|
||||||
// use to calculate distance traveled since last event
|
// use to calculate distance traveled since last event
|
||||||
DWORD fLast3dmouseInputTime;
|
DWORD fLast3dmouseInputTime;
|
||||||
|
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
friend class SpacemouseDevice;
|
friend class SpacemouseDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,11 @@
|
||||||
Q_DECLARE_LOGGING_CATEGORY(oculus)
|
Q_DECLARE_LOGGING_CATEGORY(oculus)
|
||||||
|
|
||||||
|
|
||||||
static const QString MENU_PARENT = "Avatar";
|
static const char* MENU_PARENT = "Avatar";
|
||||||
static const QString MENU_NAME = "Oculus Touch Controllers";
|
static const char* MENU_NAME = "Oculus Touch Controllers";
|
||||||
static const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
static const char* MENU_PATH = "Avatar" ">" "Oculus Touch Controllers";
|
||||||
|
|
||||||
const QString OculusControllerManager::NAME = "Oculus";
|
const char* OculusControllerManager::NAME = "Oculus";
|
||||||
|
|
||||||
bool OculusControllerManager::isSupported() const {
|
bool OculusControllerManager::isSupported() const {
|
||||||
return oculusAvailable();
|
return oculusAvailable();
|
||||||
|
|
|
@ -24,7 +24,7 @@ class OculusControllerManager : public InputPlugin {
|
||||||
public:
|
public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
|
|
||||||
bool isHandController() const override { return _touch != nullptr; }
|
bool isHandController() const override { return _touch != nullptr; }
|
||||||
QStringList getSubdeviceNames() override;
|
QStringList getSubdeviceNames() override;
|
||||||
|
@ -95,7 +95,7 @@ private:
|
||||||
ovrInputState _inputState {};
|
ovrInputState _inputState {};
|
||||||
RemoteDevice::Pointer _remote;
|
RemoteDevice::Pointer _remote;
|
||||||
TouchDevice::Pointer _touch;
|
TouchDevice::Pointer _touch;
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi__OculusControllerManager
|
#endif // hifi__OculusControllerManager
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "OculusDebugDisplayPlugin.h"
|
#include "OculusDebugDisplayPlugin.h"
|
||||||
#include <QtCore/QProcessEnvironment>
|
#include <QtCore/QProcessEnvironment>
|
||||||
|
|
||||||
const QString OculusDebugDisplayPlugin::NAME("Oculus Rift (Simulator)");
|
const char* OculusDebugDisplayPlugin::NAME { "Oculus Rift (Simulator)" };
|
||||||
|
|
||||||
static const QString DEBUG_FLAG("HIFI_DEBUG_OCULUS");
|
static const QString DEBUG_FLAG("HIFI_DEBUG_OCULUS");
|
||||||
static bool enableDebugOculus = true || QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS");
|
static bool enableDebugOculus = true || QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS");
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
class OculusDebugDisplayPlugin : public OculusBaseDisplayPlugin {
|
class OculusDebugDisplayPlugin : public OculusBaseDisplayPlugin {
|
||||||
public:
|
public:
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
grouping getGrouping() const override { return DEVELOPER; }
|
grouping getGrouping() const override { return DEVELOPER; }
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
|
|
||||||
|
@ -20,6 +20,6 @@ protected:
|
||||||
bool isHmdMounted() const override { return true; }
|
bool isHmdMounted() const override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
const QString OculusDisplayPlugin::NAME("Oculus Rift");
|
const char* OculusDisplayPlugin::NAME { "Oculus Rift" };
|
||||||
static ovrPerfHudMode currentDebugMode = ovrPerfHud_Off;
|
static ovrPerfHudMode currentDebugMode = ovrPerfHud_Off;
|
||||||
|
|
||||||
bool OculusDisplayPlugin::internalActivate() {
|
bool OculusDisplayPlugin::internalActivate() {
|
||||||
|
@ -146,6 +146,16 @@ void OculusDisplayPlugin::hmdPresent() {
|
||||||
if (!OVR_SUCCESS(result)) {
|
if (!OVR_SUCCESS(result)) {
|
||||||
logWarning("Failed to present");
|
logWarning("Failed to present");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int droppedFrames = 0;
|
||||||
|
ovrPerfStats perfStats;
|
||||||
|
ovr_GetPerfStats(_session, &perfStats);
|
||||||
|
for (int i = 0; i < perfStats.FrameStatsCount; ++i) {
|
||||||
|
const auto& frameStats = perfStats.FrameStats[i];
|
||||||
|
int delta = frameStats.CompositorDroppedFrameCount - droppedFrames;
|
||||||
|
_stutterRate.increment(delta);
|
||||||
|
droppedFrames = frameStats.CompositorDroppedFrameCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_presentRate.increment();
|
_presentRate.increment();
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ class OculusDisplayPlugin : public OculusBaseDisplayPlugin {
|
||||||
using Parent = OculusBaseDisplayPlugin;
|
using Parent = OculusBaseDisplayPlugin;
|
||||||
public:
|
public:
|
||||||
~OculusDisplayPlugin();
|
~OculusDisplayPlugin();
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ protected:
|
||||||
void cycleDebugOutput() override;
|
void cycleDebugOutput() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
ovrTextureSwapChain _textureSwapChain;
|
ovrTextureSwapChain _textureSwapChain;
|
||||||
gpu::FramebufferPointer _outputFramebuffer;
|
gpu::FramebufferPointer _outputFramebuffer;
|
||||||
bool _customized { false };
|
bool _customized { false };
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift");
|
const char* OculusLegacyDisplayPlugin::NAME { "Oculus Rift" };
|
||||||
|
|
||||||
OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() {
|
OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class OculusLegacyDisplayPlugin : public HmdDisplayPlugin {
|
||||||
public:
|
public:
|
||||||
OculusLegacyDisplayPlugin();
|
OculusLegacyDisplayPlugin();
|
||||||
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;
|
void init() override;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ protected:
|
||||||
bool isHmdMounted() const override { return true; }
|
bool isHmdMounted() const override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
|
|
||||||
GLWindow* _hmdWindow{ nullptr };
|
GLWindow* _hmdWindow{ nullptr };
|
||||||
ovrHmd _hmd;
|
ovrHmd _hmd;
|
||||||
|
|
|
@ -33,9 +33,9 @@
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
||||||
|
|
||||||
const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)");
|
const char* OpenVrDisplayPlugin::NAME { "OpenVR (Vive)" };
|
||||||
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here
|
const char* StandingHMDSensorMode { "Standing HMD Sensor Mode" }; // this probably shouldn't be hardcoded here
|
||||||
const QString OpenVrThreadedSubmit = "OpenVR Threaded Submit"; // this probably shouldn't be hardcoded here
|
const char* OpenVrThreadedSubmit { "OpenVR Threaded Submit" }; // this probably shouldn't be hardcoded here
|
||||||
|
|
||||||
PoseData _nextRenderPoseData;
|
PoseData _nextRenderPoseData;
|
||||||
PoseData _nextSimPoseData;
|
PoseData _nextSimPoseData;
|
||||||
|
@ -641,6 +641,12 @@ void OpenVrDisplayPlugin::hmdPresent() {
|
||||||
vr::VRCompositor()->PostPresentHandoff();
|
vr::VRCompositor()->PostPresentHandoff();
|
||||||
_presentRate.increment();
|
_presentRate.increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vr::Compositor_FrameTiming frameTiming;
|
||||||
|
memset(&frameTiming, 0, sizeof(vr::Compositor_FrameTiming));
|
||||||
|
frameTiming.m_nSize = sizeof(vr::Compositor_FrameTiming);
|
||||||
|
vr::VRCompositor()->GetFrameTiming(&frameTiming);
|
||||||
|
_stutterRate.increment(frameTiming.m_nNumDroppedFrames);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::postPreview() {
|
void OpenVrDisplayPlugin::postPreview() {
|
||||||
|
|
|
@ -36,7 +36,7 @@ class OpenVrDisplayPlugin : public HmdDisplayPlugin {
|
||||||
using Parent = HmdDisplayPlugin;
|
using Parent = HmdDisplayPlugin;
|
||||||
public:
|
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;
|
void init() override;
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ private:
|
||||||
vr::IVRSystem* _system { nullptr };
|
vr::IVRSystem* _system { nullptr };
|
||||||
std::atomic<vr::EDeviceActivityLevel> _hmdActivityLevel { vr::k_EDeviceActivityLevel_Unknown };
|
std::atomic<vr::EDeviceActivityLevel> _hmdActivityLevel { vr::k_EDeviceActivityLevel_Unknown };
|
||||||
std::atomic<uint32_t> _keyboardSupressionCount{ 0 };
|
std::atomic<uint32_t> _keyboardSupressionCount{ 0 };
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
|
|
||||||
vr::HmdMatrix34_t _lastGoodHMDPose;
|
vr::HmdMatrix34_t _lastGoodHMDPose;
|
||||||
mat4 _sensorResetMat;
|
mat4 _sensorResetMat;
|
||||||
|
|
|
@ -331,7 +331,7 @@ controller::Pose openVrControllerPoseToHandPose(bool isLeftHand, const mat4& mat
|
||||||
#define FAILED_MIN_SPEC_OVERLAY_FRIENDLY_NAME "Minimum specifications for SteamVR not met"
|
#define FAILED_MIN_SPEC_OVERLAY_FRIENDLY_NAME "Minimum specifications for SteamVR not met"
|
||||||
#define FAILED_MIN_SPEC_UPDATE_INTERVAL_MS 10
|
#define FAILED_MIN_SPEC_UPDATE_INTERVAL_MS 10
|
||||||
#define FAILED_MIN_SPEC_AUTO_QUIT_INTERVAL_MS (MSECS_PER_SECOND * 30)
|
#define FAILED_MIN_SPEC_AUTO_QUIT_INTERVAL_MS (MSECS_PER_SECOND * 30)
|
||||||
#define MIN_CORES_SPEC 5
|
#define MIN_CORES_SPEC 3
|
||||||
|
|
||||||
void showMinSpecWarning() {
|
void showMinSpecWarning() {
|
||||||
auto vrSystem = acquireOpenVrSystem();
|
auto vrSystem = acquireOpenVrSystem();
|
||||||
|
|
|
@ -37,12 +37,12 @@ void releaseOpenVrSystem();
|
||||||
|
|
||||||
static const char* CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b";
|
static const char* CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b";
|
||||||
|
|
||||||
static const QString MENU_PARENT = "Avatar";
|
static const char* MENU_PARENT = "Avatar";
|
||||||
static const QString MENU_NAME = "Vive Controllers";
|
static const char* MENU_NAME = "Vive Controllers";
|
||||||
static const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
static const char* MENU_PATH = "Avatar" ">" "Vive Controllers";
|
||||||
static const QString RENDER_CONTROLLERS = "Render Hand Controllers";
|
static const char* RENDER_CONTROLLERS = "Render Hand Controllers";
|
||||||
|
|
||||||
const QString ViveControllerManager::NAME = "OpenVR";
|
const char* ViveControllerManager::NAME { "OpenVR" };
|
||||||
|
|
||||||
bool ViveControllerManager::isSupported() const {
|
bool ViveControllerManager::isSupported() const {
|
||||||
return openVrSupported();
|
return openVrSupported();
|
||||||
|
|
|
@ -33,7 +33,7 @@ class ViveControllerManager : public InputPlugin {
|
||||||
public:
|
public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
const QString& getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
|
|
||||||
bool isHandController() const override { return true; }
|
bool isHandController() const override { return true; }
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ private:
|
||||||
vr::IVRSystem* _system { nullptr };
|
vr::IVRSystem* _system { nullptr };
|
||||||
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>(_system) };
|
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>(_system) };
|
||||||
|
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi__ViveControllerManager
|
#endif // hifi__ViveControllerManager
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
#include "PCMCodecManager.h"
|
#include "PCMCodecManager.h"
|
||||||
|
|
||||||
const QString PCMCodec::NAME = "pcm";
|
const char* PCMCodec::NAME { "pcm" };
|
||||||
|
|
||||||
void PCMCodec::init() {
|
void PCMCodec::init() {
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ void PCMCodec::releaseDecoder(Decoder* decoder) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString zLibCodec::NAME = "zlib";
|
const char* zLibCodec::NAME { "zlib" };
|
||||||
|
|
||||||
void zLibCodec::init() {
|
void zLibCodec::init() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class PCMCodec : public CodecPlugin, public Encoder, public Decoder {
|
||||||
public:
|
public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
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;
|
void init() override;
|
||||||
void deinit() override;
|
void deinit() override;
|
||||||
|
@ -45,7 +45,7 @@ public:
|
||||||
virtual void trackLostFrames(int numFrames) override { }
|
virtual void trackLostFrames(int numFrames) override { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
};
|
};
|
||||||
|
|
||||||
class zLibCodec : public CodecPlugin, public Encoder, public Decoder {
|
class zLibCodec : public CodecPlugin, public Encoder, public Decoder {
|
||||||
|
@ -54,7 +54,7 @@ class zLibCodec : public CodecPlugin, public Encoder, public Decoder {
|
||||||
public:
|
public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
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;
|
void init() override;
|
||||||
void deinit() override;
|
void deinit() override;
|
||||||
|
@ -80,7 +80,7 @@ public:
|
||||||
virtual void trackLostFrames(int numFrames) override { }
|
virtual void trackLostFrames(int numFrames) override { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const char* NAME;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi__PCMCodecManager_h
|
#endif // hifi__PCMCodecManager_h
|
||||||
|
|
33
scripts/system/assets/images/mute-target.svg
Executable file
33
scripts/system/assets/images/mute-target.svg
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
<?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 293 101.9" style="enable-background:new 0 0 293 101.9;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#EF3B4E;}
|
||||||
|
.st1{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<path d="M16.2,23.2H283c3.9,0,7.1,3.2,7.1,7.1V88c0,3.9-3.2,7.1-7.1,7.1H16.2c-3.9,0-7.1-3.2-7.1-7.1V30.3
|
||||||
|
C9.1,26.4,12.3,23.2,16.2,23.2z"/>
|
||||||
|
<path class="st0" d="M13.9,20.3h266.8c3.9,0,7.1,3.2,7.1,7.1v57.7c0,3.9-3.2,7.1-7.1,7.1H13.9c-3.9,0-7.1-3.2-7.1-7.1V27.4
|
||||||
|
C6.8,23.5,10,20.3,13.9,20.3z"/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path d="M103.4,79.8V52.4L92.8,72.8h-4.4L77.7,52.4v27.4h-8.1V38.3h8.6l12.3,23.6l12.4-23.6h8.6v41.5H103.4z"/>
|
||||||
|
<path d="M137.6,73c1.9,0,3.5-0.4,4.8-1.2c1.3-0.8,2.4-1.8,3.2-3c0.8-1.2,1.4-2.7,1.7-4.3c0.3-1.6,0.5-3.3,0.5-5V38.3h8v21.1
|
||||||
|
c0,2.8-0.3,5.5-1,8c-0.7,2.5-1.8,4.7-3.2,6.5c-1.5,1.9-3.3,3.3-5.6,4.4c-2.3,1.1-5,1.6-8.2,1.6c-3.3,0-6.1-0.6-8.4-1.7
|
||||||
|
c-2.3-1.1-4.2-2.7-5.6-4.6c-1.4-1.9-2.5-4.1-3.1-6.6c-0.6-2.5-1-5.1-1-7.8V38.3h8.1v21.1c0,1.8,0.2,3.4,0.5,5.1
|
||||||
|
c0.3,1.6,0.9,3,1.7,4.3c0.8,1.2,1.8,2.2,3.1,3C134.2,72.6,135.7,73,137.6,73z"/>
|
||||||
|
<path d="M194.8,45.4h-13.2v34.4h-8.1V45.4h-13.3v-7.1h34.5V45.4z"/>
|
||||||
|
<path d="M228.8,72.7v7.1H200V38.3h28.3v7.1h-20.2v10h17.5v6.5h-17.5v10.8H228.8z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st1" d="M101.5,77.9V50.4L90.8,70.9h-4.4L75.7,50.4v27.4h-8.1V36.4h8.6L88.6,60L101,36.4h8.6v41.5H101.5z"/>
|
||||||
|
<path class="st1" d="M135.7,71c1.9,0,3.5-0.4,4.8-1.2c1.3-0.8,2.4-1.8,3.2-3c0.8-1.2,1.4-2.7,1.7-4.3c0.3-1.6,0.5-3.3,0.5-5V36.4
|
||||||
|
h8v21.1c0,2.8-0.3,5.5-1,8c-0.7,2.5-1.8,4.7-3.2,6.5c-1.5,1.9-3.3,3.3-5.6,4.4c-2.3,1.1-5,1.6-8.2,1.6c-3.3,0-6.1-0.6-8.4-1.7
|
||||||
|
c-2.3-1.1-4.2-2.7-5.6-4.6c-1.4-1.9-2.5-4.1-3.1-6.6c-0.6-2.5-1-5.1-1-7.8V36.4h8.1v21.1c0,1.8,0.2,3.4,0.5,5.1
|
||||||
|
c0.3,1.6,0.9,3,1.7,4.3c0.8,1.2,1.8,2.2,3.1,3C132.2,70.6,133.8,71,135.7,71z"/>
|
||||||
|
<path class="st1" d="M192.9,43.5h-13.2v34.4h-8.1V43.5h-13.3v-7.1h34.5V43.5z"/>
|
||||||
|
<path class="st1" d="M226.9,70.8v7.1h-28.8V36.4h28.3v7.1h-20.2v10h17.5V60h-17.5v10.8H226.9z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -203,6 +203,32 @@ function overlayFromWorldPoint(point) {
|
||||||
return { x: horizontalPixels, y: verticalPixels };
|
return { x: horizontalPixels, y: verticalPixels };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var gamePad = Controller.findDevice("GamePad");
|
||||||
|
function activeHudPoint2dGamePad() {
|
||||||
|
if (!HMD.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var headPosition = MyAvatar.getHeadPosition();
|
||||||
|
var headDirection = Quat.getUp(Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 })));
|
||||||
|
|
||||||
|
var hudPoint3d = calculateRayUICollisionPoint(headPosition, headDirection);
|
||||||
|
|
||||||
|
if (!hudPoint3d) {
|
||||||
|
if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here
|
||||||
|
print('Controller is parallel to HUD'); // so let us know that our assumptions are wrong.
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var hudPoint2d = overlayFromWorldPoint(hudPoint3d);
|
||||||
|
|
||||||
|
// We don't know yet if we'll want to make the cursor or laser visble, but we need to move it to see if
|
||||||
|
// it's pointing at a QML tool (aka system overlay).
|
||||||
|
setReticlePosition(hudPoint2d);
|
||||||
|
|
||||||
|
return hudPoint2d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function activeHudPoint2d(activeHand) { // if controller is valid, update reticle position and answer 2d point. Otherwise falsey.
|
function activeHudPoint2d(activeHand) { // if controller is valid, update reticle position and answer 2d point. Otherwise falsey.
|
||||||
var controllerPose = getControllerWorldLocation(activeHand, true); // note: this will return head pose if hand pose is invalid (third eye)
|
var controllerPose = getControllerWorldLocation(activeHand, true); // note: this will return head pose if hand pose is invalid (third eye)
|
||||||
if (!controllerPose.valid) {
|
if (!controllerPose.valid) {
|
||||||
|
@ -405,7 +431,7 @@ clickMapping.from(rightTrigger.full).when(isPointingAtOverlayStartedNonFullTrigg
|
||||||
clickMapping.from(leftTrigger.full).when(isPointingAtOverlayStartedNonFullTrigger(leftTrigger)).to(Controller.Actions.ReticleClick);
|
clickMapping.from(leftTrigger.full).when(isPointingAtOverlayStartedNonFullTrigger(leftTrigger)).to(Controller.Actions.ReticleClick);
|
||||||
// The following is essentially like Left and Right versions of
|
// The following is essentially like Left and Right versions of
|
||||||
// clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(Controller.Actions.ContextMenu);
|
// clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(Controller.Actions.ContextMenu);
|
||||||
// except that we first update the reticle position from the appropriate hand position, before invoking the ContextMenu.
|
// except that we first update the reticle position from the appropriate hand position, before invoking the .
|
||||||
var wantsMenu = 0;
|
var wantsMenu = 0;
|
||||||
clickMapping.from(function () { return wantsMenu; }).to(Controller.Actions.ContextMenu);
|
clickMapping.from(function () { return wantsMenu; }).to(Controller.Actions.ContextMenu);
|
||||||
clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(function (clicked) {
|
clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(function (clicked) {
|
||||||
|
@ -420,6 +446,13 @@ clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(function (cl
|
||||||
}
|
}
|
||||||
wantsMenu = clicked;
|
wantsMenu = clicked;
|
||||||
});
|
});
|
||||||
|
clickMapping.from(Controller.Standard.Start).peek().to(function (clicked) {
|
||||||
|
if (clicked) {
|
||||||
|
activeHudPoint2dGamePad();
|
||||||
|
}
|
||||||
|
|
||||||
|
wantsMenu = clicked;
|
||||||
|
});
|
||||||
clickMapping.from(Controller.Hardware.Keyboard.RightMouseClicked).peek().to(function () {
|
clickMapping.from(Controller.Hardware.Keyboard.RightMouseClicked).peek().to(function () {
|
||||||
// Allow the reticle depth to be set correctly:
|
// Allow the reticle depth to be set correctly:
|
||||||
// Wait a tick for the context menu to be displayed, and then simulate a (non-hand-controller) mouse move
|
// Wait a tick for the context menu to be displayed, and then simulate a (non-hand-controller) mouse move
|
||||||
|
@ -472,13 +505,16 @@ function update() {
|
||||||
expireMouseCursor();
|
expireMouseCursor();
|
||||||
clearSystemLaser();
|
clearSystemLaser();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSeeking(true);
|
updateSeeking(true);
|
||||||
if (!handControllerLockOut.expired(now)) {
|
if (!handControllerLockOut.expired(now)) {
|
||||||
return off(); // Let them use mouse in peace.
|
return off(); // Let them use mouse in peace.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Menu.isOptionChecked("First Person")) {
|
if (!Menu.isOptionChecked("First Person")) {
|
||||||
return off(); // What to do? menus can be behind hand!
|
return off(); // What to do? menus can be behind hand!
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!Window.hasFocus() && !HMD.active) || !Reticle.allowMouseCapture) {
|
if ((!Window.hasFocus() && !HMD.active) || !Reticle.allowMouseCapture) {
|
||||||
// In desktop it's pretty clear when another app is on top. In that case we bail, because
|
// In desktop it's pretty clear when another app is on top. In that case we bail, because
|
||||||
// hand controllers might be sputtering "valid" data and that will keep someone from deliberately
|
// hand controllers might be sputtering "valid" data and that will keep someone from deliberately
|
||||||
|
@ -487,14 +523,18 @@ function update() {
|
||||||
// other apps anyway. So in that case, we DO keep going even though we're not on top. (Fogbugz 1831.)
|
// other apps anyway. So in that case, we DO keep going even though we're not on top. (Fogbugz 1831.)
|
||||||
return off(); // Don't mess with other apps or paused mouse activity
|
return off(); // Don't mess with other apps or paused mouse activity
|
||||||
}
|
}
|
||||||
|
|
||||||
leftTrigger.update();
|
leftTrigger.update();
|
||||||
rightTrigger.update();
|
rightTrigger.update();
|
||||||
if (!activeTrigger.state) {
|
if (!activeTrigger.state) {
|
||||||
return off(); // No trigger
|
return off(); // No trigger
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getGrabCommunications()) {
|
if (getGrabCommunications()) {
|
||||||
return off();
|
return off();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var hudPoint2d = activeHudPoint2d(activeHand);
|
var hudPoint2d = activeHudPoint2d(activeHand);
|
||||||
if (!hudPoint2d) {
|
if (!hudPoint2d) {
|
||||||
return off();
|
return off();
|
||||||
|
|
|
@ -52,7 +52,9 @@ function removeOverlays() {
|
||||||
|
|
||||||
for (var i = 0; i < modOverlayKeys.length; ++i) {
|
for (var i = 0; i < modOverlayKeys.length; ++i) {
|
||||||
var avatarID = modOverlayKeys[i];
|
var avatarID = modOverlayKeys[i];
|
||||||
Overlays.deleteOverlay(modOverlays[avatarID]);
|
for (var j = 0; j < modOverlays[avatarID].length; ++j) {
|
||||||
|
Overlays.deleteOverlay(modOverlays[avatarID][j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modOverlays = {};
|
modOverlays = {};
|
||||||
|
@ -74,10 +76,14 @@ function buttonClicked(){
|
||||||
|
|
||||||
button.clicked.connect(buttonClicked);
|
button.clicked.connect(buttonClicked);
|
||||||
|
|
||||||
function overlayURL() {
|
function kickOverlayURL() {
|
||||||
return ASSETS_PATH + "/images/" + (Users.canKick ? "kick-target.svg" : "ignore-target.svg");
|
return ASSETS_PATH + "/images/" + (Users.canKick ? "kick-target.svg" : "ignore-target.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function muteOverlayURL() {
|
||||||
|
return ASSETS_PATH + "/images/" + "mute-target.svg";
|
||||||
|
}
|
||||||
|
|
||||||
function updateOverlays() {
|
function updateOverlays() {
|
||||||
if (isShowingOverlays) {
|
if (isShowingOverlays) {
|
||||||
|
|
||||||
|
@ -101,20 +107,28 @@ function updateOverlays() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup a position for the overlay that is just above this avatar's head
|
// setup a position for the overlay that is just above this avatar's head
|
||||||
var overlayPosition = avatar.getJointPosition("Head");
|
var kickOverlayPosition = avatar.getJointPosition("Head");
|
||||||
overlayPosition.y += 0.45;
|
kickOverlayPosition.y += 0.45;
|
||||||
|
var muteOverlayPosition = avatar.getJointPosition("Head");
|
||||||
|
muteOverlayPosition.y += 0.70;
|
||||||
|
|
||||||
if (avatarID in modOverlays) {
|
if (avatarID in modOverlays) {
|
||||||
// keep the overlay above the current position of this avatar
|
// keep the overlay above the current position of this avatar
|
||||||
Overlays.editOverlay(modOverlays[avatarID], {
|
Overlays.editOverlay(modOverlays[avatarID][0], {
|
||||||
position: overlayPosition,
|
position: kickOverlayPosition,
|
||||||
url: overlayURL()
|
url: kickOverlayURL()
|
||||||
});
|
});
|
||||||
|
if (Users.canKick) {
|
||||||
|
Overlays.editOverlay(modOverlays[avatarID][1], {
|
||||||
|
position: muteOverlayPosition,
|
||||||
|
url: muteOverlayURL()
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// add the overlay above this avatar
|
// add the overlay above this avatar
|
||||||
var newOverlay = Overlays.addOverlay("image3d", {
|
var newKickOverlay = Overlays.addOverlay("image3d", {
|
||||||
url: overlayURL(),
|
url: kickOverlayURL(),
|
||||||
position: overlayPosition,
|
position: kickOverlayPosition,
|
||||||
size: 1,
|
size: 1,
|
||||||
scale: 0.4,
|
scale: 0.4,
|
||||||
color: { red: 255, green: 255, blue: 255},
|
color: { red: 255, green: 255, blue: 255},
|
||||||
|
@ -124,8 +138,23 @@ function updateOverlays() {
|
||||||
drawInFront: true
|
drawInFront: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modOverlays[avatarID]=[newKickOverlay];
|
||||||
|
|
||||||
|
if (Users.canKick) {
|
||||||
|
var newMuteOverlay = Overlays.addOverlay("image3d", {
|
||||||
|
url: muteOverlayURL(),
|
||||||
|
position: muteOverlayPosition,
|
||||||
|
size: 1,
|
||||||
|
scale: 0.4,
|
||||||
|
color: { red: 255, green: 255, blue: 255},
|
||||||
|
alpha: 1,
|
||||||
|
solid: true,
|
||||||
|
isFacingAvatar: true,
|
||||||
|
drawInFront: true
|
||||||
|
});
|
||||||
// push this overlay to our array of overlays
|
// push this overlay to our array of overlays
|
||||||
modOverlays[avatarID] = newOverlay;
|
modOverlays[avatarID].push(newMuteOverlay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,8 +166,10 @@ AvatarList.avatarRemovedEvent.connect(function(avatarID){
|
||||||
if (isShowingOverlays) {
|
if (isShowingOverlays) {
|
||||||
// we are currently showing overlays and an avatar just went away
|
// we are currently showing overlays and an avatar just went away
|
||||||
|
|
||||||
// first remove the rendered overlay
|
// first remove the rendered overlays
|
||||||
Overlays.deleteOverlay(modOverlays[avatarID]);
|
for (var j = 0; j < modOverlays[avatarID].length; ++j) {
|
||||||
|
Overlays.deleteOverlay(modOverlays[avatarID][j]);
|
||||||
|
}
|
||||||
|
|
||||||
// delete the saved ID of the overlay from our mod overlays object
|
// delete the saved ID of the overlay from our mod overlays object
|
||||||
delete modOverlays[avatarID];
|
delete modOverlays[avatarID];
|
||||||
|
@ -151,7 +182,8 @@ function handleSelectedOverlay(clickedOverlay) {
|
||||||
var modOverlayKeys = Object.keys(modOverlays);
|
var modOverlayKeys = Object.keys(modOverlays);
|
||||||
for (var i = 0; i < modOverlayKeys.length; ++i) {
|
for (var i = 0; i < modOverlayKeys.length; ++i) {
|
||||||
var avatarID = modOverlayKeys[i];
|
var avatarID = modOverlayKeys[i];
|
||||||
var modOverlay = modOverlays[avatarID];
|
var modOverlay = modOverlays[avatarID][0];
|
||||||
|
var muteOverlay = modOverlays[avatarID][1];
|
||||||
|
|
||||||
if (clickedOverlay.overlayID == modOverlay) {
|
if (clickedOverlay.overlayID == modOverlay) {
|
||||||
// matched to an overlay, ask for the matching avatar to be kicked or ignored
|
// matched to an overlay, ask for the matching avatar to be kicked or ignored
|
||||||
|
@ -160,8 +192,10 @@ function handleSelectedOverlay(clickedOverlay) {
|
||||||
} else {
|
} else {
|
||||||
Users.ignore(avatarID);
|
Users.ignore(avatarID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanup of the overlay is handled by the connection to avatarRemovedEvent
|
// cleanup of the overlay is handled by the connection to avatarRemovedEvent
|
||||||
|
|
||||||
|
} else if (muteOverlay && clickedOverlay.overlayID == muteOverlay) {
|
||||||
|
Users.mute(avatarID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue