Merge remote-tracking branch 'upstream/master' into police
|
@ -66,7 +66,7 @@ if (ANDROID)
|
||||||
set(GLES_OPTION ON)
|
set(GLES_OPTION ON)
|
||||||
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
|
set(PLATFORM_QT_COMPONENTS AndroidExtras WebView)
|
||||||
else ()
|
else ()
|
||||||
set(PLATFORM_QT_COMPONENTS WebEngine WebEngineWidgets)
|
set(PLATFORM_QT_COMPONENTS WebEngine)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (USE_GLES AND (NOT ANDROID))
|
if (USE_GLES AND (NOT ANDROID))
|
||||||
|
|
2
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2013-2016, High Fidelity, Inc.
|
Copyright (c) 2013-2018, High Fidelity, Inc.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
licensing@highfidelity.io
|
licensing@highfidelity.io
|
||||||
|
|
||||||
|
|
|
@ -216,13 +216,14 @@ void Agent::requestScript() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure this is not a script request for the file scheme
|
// make sure this is not a script request for the file scheme
|
||||||
if (scriptURL.scheme() == URL_SCHEME_FILE) {
|
if (scriptURL.scheme() == HIFI_URL_SCHEME_FILE) {
|
||||||
qWarning() << "Cannot load script for Agent from local filesystem.";
|
qWarning() << "Cannot load script for Agent from local filesystem.";
|
||||||
scriptRequestFinished();
|
scriptRequestFinished();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(this, scriptURL);
|
auto request = DependencyManager::get<ResourceManager>()->createResourceRequest(
|
||||||
|
this, scriptURL, true, -1, "Agent::requestScript");
|
||||||
|
|
||||||
if (!request) {
|
if (!request) {
|
||||||
qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString();
|
qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString();
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
#include <ClientTraitsHandler.h>
|
|
||||||
#include <EntityEditPacketSender.h>
|
#include <EntityEditPacketSender.h>
|
||||||
#include <EntityTree.h>
|
#include <EntityTree.h>
|
||||||
#include <ScriptEngine.h>
|
#include <ScriptEngine.h>
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include "AssignmentClientLogging.h"
|
#include "AssignmentClientLogging.h"
|
||||||
#include "AssignmentFactory.h"
|
#include "AssignmentFactory.h"
|
||||||
|
#include "ResourceRequestObserver.h"
|
||||||
|
|
||||||
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
|
||||||
const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
|
const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
|
||||||
|
@ -49,6 +50,7 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri
|
||||||
DependencyManager::set<tracing::Tracer>();
|
DependencyManager::set<tracing::Tracer>();
|
||||||
DependencyManager::set<StatTracker>();
|
DependencyManager::set<StatTracker>();
|
||||||
DependencyManager::set<AccountManager>();
|
DependencyManager::set<AccountManager>();
|
||||||
|
DependencyManager::set<ResourceRequestObserver>();
|
||||||
|
|
||||||
auto addressManager = DependencyManager::set<AddressManager>();
|
auto addressManager = DependencyManager::set<AddressManager>();
|
||||||
|
|
||||||
|
|
|
@ -202,7 +202,7 @@ void AudioMixerClientData::parsePerAvatarGainSet(ReceivedMessage& message, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioMixerClientData::setGainForAvatar(QUuid nodeID, uint8_t gain) {
|
void AudioMixerClientData::setGainForAvatar(QUuid nodeID, float gain) {
|
||||||
auto it = std::find_if(_streams.active.cbegin(), _streams.active.cend(), [nodeID](const MixableStream& mixableStream){
|
auto it = std::find_if(_streams.active.cbegin(), _streams.active.cend(), [nodeID](const MixableStream& mixableStream){
|
||||||
return mixableStream.nodeStreamID.nodeID == nodeID && mixableStream.nodeStreamID.streamID.isNull();
|
return mixableStream.nodeStreamID.nodeID == nodeID && mixableStream.nodeStreamID.streamID.isNull();
|
||||||
});
|
});
|
||||||
|
|
|
@ -172,7 +172,7 @@ private:
|
||||||
|
|
||||||
void optionallyReplicatePacket(ReceivedMessage& packet, const Node& node);
|
void optionallyReplicatePacket(ReceivedMessage& packet, const Node& node);
|
||||||
|
|
||||||
void setGainForAvatar(QUuid nodeID, uint8_t gain);
|
void setGainForAvatar(QUuid nodeID, float gain);
|
||||||
|
|
||||||
bool containsValidPosition(ReceivedMessage& message) const;
|
bool containsValidPosition(ReceivedMessage& message) const;
|
||||||
|
|
||||||
|
|
|
@ -541,7 +541,7 @@ void AvatarMixer::handleRequestsDomainListDataPacket(QSharedPointer<ReceivedMess
|
||||||
// ...For those nodes, reset the lastBroadcastTime to 0
|
// ...For those nodes, reset the lastBroadcastTime to 0
|
||||||
// so that the AvatarMixer will send Identity data to us
|
// so that the AvatarMixer will send Identity data to us
|
||||||
[&](const SharedNodePointer& node) {
|
[&](const SharedNodePointer& node) {
|
||||||
nodeData->setLastBroadcastTime(node->getUUID(), 0);
|
nodeData->setLastBroadcastTime(node->getLocalID(), 0);
|
||||||
nodeData->resetSentTraitData(node->getLocalID());
|
nodeData->resetSentTraitData(node->getLocalID());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -565,7 +565,8 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
|
||||||
// parse the identity packet and update the change timestamp if appropriate
|
// parse the identity packet and update the change timestamp if appropriate
|
||||||
bool identityChanged = false;
|
bool identityChanged = false;
|
||||||
bool displayNameChanged = false;
|
bool displayNameChanged = false;
|
||||||
avatar.processAvatarIdentity(message->getMessage(), identityChanged, displayNameChanged);
|
QDataStream avatarIdentityStream(message->getMessage());
|
||||||
|
avatar.processAvatarIdentity(avatarIdentityStream, identityChanged, displayNameChanged);
|
||||||
|
|
||||||
if (identityChanged) {
|
if (identityChanged) {
|
||||||
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
||||||
|
@ -637,7 +638,7 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage>
|
||||||
// Reset the lastBroadcastTime for the ignored avatar to 0
|
// Reset the lastBroadcastTime for the ignored avatar to 0
|
||||||
// so the AvatarMixer knows it'll have to send identity data about the ignored avatar
|
// so the AvatarMixer knows it'll have to send identity data about the ignored avatar
|
||||||
// to the ignorer if the ignorer unignores.
|
// to the ignorer if the ignorer unignores.
|
||||||
nodeData->setLastBroadcastTime(ignoredUUID, 0);
|
nodeData->setLastBroadcastTime(ignoredNode->getLocalID(), 0);
|
||||||
nodeData->resetSentTraitData(ignoredNode->getLocalID());
|
nodeData->resetSentTraitData(ignoredNode->getLocalID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,7 +648,7 @@ void AvatarMixer::handleNodeIgnoreRequestPacket(QSharedPointer<ReceivedMessage>
|
||||||
// to the ignored if the ignorer unignores.
|
// to the ignored if the ignorer unignores.
|
||||||
AvatarMixerClientData* ignoredNodeData = reinterpret_cast<AvatarMixerClientData*>(ignoredNode->getLinkedData());
|
AvatarMixerClientData* ignoredNodeData = reinterpret_cast<AvatarMixerClientData*>(ignoredNode->getLinkedData());
|
||||||
if (ignoredNodeData) {
|
if (ignoredNodeData) {
|
||||||
ignoredNodeData->setLastBroadcastTime(senderNode->getUUID(), 0);
|
ignoredNodeData->setLastBroadcastTime(senderNode->getLocalID(), 0);
|
||||||
ignoredNodeData->resetSentTraitData(senderNode->getLocalID());
|
ignoredNodeData->resetSentTraitData(senderNode->getLocalID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,20 +26,20 @@ AvatarMixerClientData::AvatarMixerClientData(const QUuid& nodeID, Node::LocalID
|
||||||
_avatar->setID(nodeID);
|
_avatar->setID(nodeID);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t AvatarMixerClientData::getLastOtherAvatarEncodeTime(QUuid otherAvatar) const {
|
uint64_t AvatarMixerClientData::getLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar) const {
|
||||||
std::unordered_map<QUuid, uint64_t>::const_iterator itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
|
const auto itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
|
||||||
if (itr != _lastOtherAvatarEncodeTime.end()) {
|
if (itr != _lastOtherAvatarEncodeTime.end()) {
|
||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time) {
|
void AvatarMixerClientData::setLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar, uint64_t time) {
|
||||||
std::unordered_map<QUuid, uint64_t>::iterator itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
|
auto itr = _lastOtherAvatarEncodeTime.find(otherAvatar);
|
||||||
if (itr != _lastOtherAvatarEncodeTime.end()) {
|
if (itr != _lastOtherAvatarEncodeTime.end()) {
|
||||||
itr->second = time;
|
itr->second = time;
|
||||||
} else {
|
} else {
|
||||||
_lastOtherAvatarEncodeTime.emplace(std::pair<QUuid, uint64_t>(otherAvatar, time));
|
_lastOtherAvatarEncodeTime.emplace(std::pair<NLPacket::LocalID, uint64_t>(otherAvatar, time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ void AvatarMixerClientData::checkSkeletonURLAgainstWhitelist(const SlaveSharedDa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t AvatarMixerClientData::getLastBroadcastTime(const QUuid& nodeUUID) const {
|
uint64_t AvatarMixerClientData::getLastBroadcastTime(NLPacket::LocalID nodeUUID) const {
|
||||||
// return the matching PacketSequenceNumber, or the default if we don't have it
|
// return the matching PacketSequenceNumber, or the default if we don't have it
|
||||||
auto nodeMatch = _lastBroadcastTimes.find(nodeUUID);
|
auto nodeMatch = _lastBroadcastTimes.find(nodeUUID);
|
||||||
if (nodeMatch != _lastBroadcastTimes.end()) {
|
if (nodeMatch != _lastBroadcastTimes.end()) {
|
||||||
|
@ -229,9 +229,9 @@ uint64_t AvatarMixerClientData::getLastBroadcastTime(const QUuid& nodeUUID) cons
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t AvatarMixerClientData::getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const {
|
uint16_t AvatarMixerClientData::getLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) const {
|
||||||
// return the matching PacketSequenceNumber, or the default if we don't have it
|
// return the matching PacketSequenceNumber, or the default if we don't have it
|
||||||
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeUUID);
|
auto nodeMatch = _lastBroadcastSequenceNumbers.find(nodeID);
|
||||||
if (nodeMatch != _lastBroadcastSequenceNumbers.end()) {
|
if (nodeMatch != _lastBroadcastSequenceNumbers.end()) {
|
||||||
return nodeMatch->second;
|
return nodeMatch->second;
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ void AvatarMixerClientData::ignoreOther(const Node* self, const Node* other) {
|
||||||
} else {
|
} else {
|
||||||
killPacket->writePrimitive(KillAvatarReason::YourAvatarEnteredTheirBubble);
|
killPacket->writePrimitive(KillAvatarReason::YourAvatarEnteredTheirBubble);
|
||||||
}
|
}
|
||||||
setLastBroadcastTime(other->getUUID(), 0);
|
setLastBroadcastTime(other->getLocalID(), 0);
|
||||||
|
|
||||||
resetSentTraitData(other->getLocalID());
|
resetSentTraitData(other->getLocalID());
|
||||||
|
|
||||||
|
@ -331,9 +331,9 @@ AvatarMixerClientData::TraitsCheckTimestamp AvatarMixerClientData::getLastOtherA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarMixerClientData::cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID) {
|
void AvatarMixerClientData::cleanupKilledNode(const QUuid&, Node::LocalID nodeLocalID) {
|
||||||
removeLastBroadcastSequenceNumber(nodeUUID);
|
removeLastBroadcastSequenceNumber(nodeLocalID);
|
||||||
removeLastBroadcastTime(nodeUUID);
|
removeLastBroadcastTime(nodeLocalID);
|
||||||
_lastSentTraitsTimestamps.erase(nodeLocalID);
|
_lastSentTraitsTimestamps.erase(nodeLocalID);
|
||||||
_sentTraitVersions.erase(nodeLocalID);
|
_sentTraitVersions.erase(nodeLocalID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,17 +49,16 @@ public:
|
||||||
const AvatarData* getConstAvatarData() const { return _avatar.get(); }
|
const AvatarData* getConstAvatarData() const { return _avatar.get(); }
|
||||||
AvatarSharedPointer getAvatarSharedPointer() const { return _avatar; }
|
AvatarSharedPointer getAvatarSharedPointer() const { return _avatar; }
|
||||||
|
|
||||||
|
uint16_t getLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) const;
|
||||||
|
void setLastBroadcastSequenceNumber(NLPacket::LocalID nodeID, uint16_t sequenceNumber)
|
||||||
|
{ _lastBroadcastSequenceNumbers[nodeID] = sequenceNumber; }
|
||||||
|
Q_INVOKABLE void removeLastBroadcastSequenceNumber(NLPacket::LocalID nodeID) { _lastBroadcastSequenceNumbers.erase(nodeID); }
|
||||||
bool isIgnoreRadiusEnabled() const { return _isIgnoreRadiusEnabled; }
|
bool isIgnoreRadiusEnabled() const { return _isIgnoreRadiusEnabled; }
|
||||||
void setIsIgnoreRadiusEnabled(bool enabled) { _isIgnoreRadiusEnabled = enabled; }
|
void setIsIgnoreRadiusEnabled(bool enabled) { _isIgnoreRadiusEnabled = enabled; }
|
||||||
|
|
||||||
uint16_t getLastBroadcastSequenceNumber(const QUuid& nodeUUID) const;
|
uint64_t getLastBroadcastTime(NLPacket::LocalID nodeUUID) const;
|
||||||
void setLastBroadcastSequenceNumber(const QUuid& nodeUUID, uint16_t sequenceNumber)
|
void setLastBroadcastTime(NLPacket::LocalID nodeUUID, uint64_t broadcastTime) { _lastBroadcastTimes[nodeUUID] = broadcastTime; }
|
||||||
{ _lastBroadcastSequenceNumbers[nodeUUID] = sequenceNumber; }
|
Q_INVOKABLE void removeLastBroadcastTime(NLPacket::LocalID nodeUUID) { _lastBroadcastTimes.erase(nodeUUID); }
|
||||||
Q_INVOKABLE void removeLastBroadcastSequenceNumber(const QUuid& nodeUUID) { _lastBroadcastSequenceNumbers.erase(nodeUUID); }
|
|
||||||
|
|
||||||
uint64_t getLastBroadcastTime(const QUuid& nodeUUID) const;
|
|
||||||
void setLastBroadcastTime(const QUuid& nodeUUID, uint64_t broadcastTime) { _lastBroadcastTimes[nodeUUID] = broadcastTime; }
|
|
||||||
Q_INVOKABLE void removeLastBroadcastTime(const QUuid& nodeUUID) { _lastBroadcastTimes.erase(nodeUUID); }
|
|
||||||
|
|
||||||
Q_INVOKABLE void cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID);
|
Q_INVOKABLE void cleanupKilledNode(const QUuid& nodeUUID, Node::LocalID nodeLocalID);
|
||||||
|
|
||||||
|
@ -93,7 +92,7 @@ public:
|
||||||
|
|
||||||
void loadJSONStats(QJsonObject& jsonObject) const;
|
void loadJSONStats(QJsonObject& jsonObject) const;
|
||||||
|
|
||||||
glm::vec3 getPosition() const { return _avatar ? _avatar->getWorldPosition() : glm::vec3(0); }
|
glm::vec3 getPosition() const { return _avatar ? _avatar->getClientGlobalPosition() : glm::vec3(0); }
|
||||||
bool isRadiusIgnoring(const QUuid& other) const;
|
bool isRadiusIgnoring(const QUuid& other) const;
|
||||||
void addToRadiusIgnoringSet(const QUuid& other);
|
void addToRadiusIgnoringSet(const QUuid& other);
|
||||||
void removeFromRadiusIgnoringSet(const QUuid& other);
|
void removeFromRadiusIgnoringSet(const QUuid& other);
|
||||||
|
@ -114,10 +113,10 @@ public:
|
||||||
|
|
||||||
const ConicalViewFrustums& getViewFrustums() const { return _currentViewFrustums; }
|
const ConicalViewFrustums& getViewFrustums() const { return _currentViewFrustums; }
|
||||||
|
|
||||||
uint64_t getLastOtherAvatarEncodeTime(QUuid otherAvatar) const;
|
uint64_t getLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar) const;
|
||||||
void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, uint64_t time);
|
void setLastOtherAvatarEncodeTime(NLPacket::LocalID otherAvatar, uint64_t time);
|
||||||
|
|
||||||
QVector<JointData>& getLastOtherAvatarSentJoints(QUuid otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; }
|
QVector<JointData>& getLastOtherAvatarSentJoints(NLPacket::LocalID otherAvatar) { return _lastOtherAvatarSentJoints[otherAvatar]; }
|
||||||
|
|
||||||
void queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
|
void queuePacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer node);
|
||||||
int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed
|
int processPackets(const SlaveSharedData& slaveSharedData); // returns number of packets processed
|
||||||
|
@ -150,13 +149,13 @@ private:
|
||||||
AvatarSharedPointer _avatar { new AvatarData() };
|
AvatarSharedPointer _avatar { new AvatarData() };
|
||||||
|
|
||||||
uint16_t _lastReceivedSequenceNumber { 0 };
|
uint16_t _lastReceivedSequenceNumber { 0 };
|
||||||
std::unordered_map<QUuid, uint16_t> _lastBroadcastSequenceNumbers;
|
std::unordered_map<NLPacket::LocalID, uint16_t> _lastBroadcastSequenceNumbers;
|
||||||
std::unordered_map<QUuid, uint64_t> _lastBroadcastTimes;
|
std::unordered_map<NLPacket::LocalID, uint64_t> _lastBroadcastTimes;
|
||||||
|
|
||||||
// this is a map of the last time we encoded an "other" avatar for
|
// this is a map of the last time we encoded an "other" avatar for
|
||||||
// sending to "this" node
|
// sending to "this" node
|
||||||
std::unordered_map<QUuid, uint64_t> _lastOtherAvatarEncodeTime;
|
std::unordered_map<NLPacket::LocalID, uint64_t> _lastOtherAvatarEncodeTime;
|
||||||
std::unordered_map<QUuid, QVector<JointData>> _lastOtherAvatarSentJoints;
|
std::unordered_map<NLPacket::LocalID, QVector<JointData>> _lastOtherAvatarSentJoints;
|
||||||
|
|
||||||
uint64_t _identityChangeTimestamp;
|
uint64_t _identityChangeTimestamp;
|
||||||
bool _avatarSessionDisplayNameMustChange{ true };
|
bool _avatarSessionDisplayNameMustChange{ true };
|
||||||
|
|
|
@ -68,13 +68,11 @@ void AvatarMixerSlave::processIncomingPackets(const SharedNodePointer& node) {
|
||||||
_stats.processIncomingPacketsElapsedTime += (end - start);
|
_stats.processIncomingPacketsElapsedTime += (end - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AvatarMixerSlave::sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode) {
|
int AvatarMixerSlave::sendIdentityPacket(NLPacketList& packetList, const AvatarMixerClientData* nodeData, const Node& destinationNode) {
|
||||||
if (destinationNode->getType() == NodeType::Agent && !destinationNode->isUpstream()) {
|
if (destinationNode.getType() == NodeType::Agent && !destinationNode.isUpstream()) {
|
||||||
QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray();
|
QByteArray individualData = nodeData->getConstAvatarData()->identityByteArray();
|
||||||
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
|
individualData.replace(0, NUM_BYTES_RFC4122_UUID, nodeData->getNodeID().toRfc4122()); // FIXME, this looks suspicious
|
||||||
auto identityPackets = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
|
packetList.write(individualData);
|
||||||
identityPackets->write(individualData);
|
|
||||||
DependencyManager::get<NodeList>()->sendPacketList(std::move(identityPackets), *destinationNode);
|
|
||||||
_stats.numIdentityPackets++;
|
_stats.numIdentityPackets++;
|
||||||
return individualData.size();
|
return individualData.size();
|
||||||
} else {
|
} else {
|
||||||
|
@ -247,12 +245,12 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
// reset the internal state for correct random number distribution
|
// reset the internal state for correct random number distribution
|
||||||
distribution.reset();
|
distribution.reset();
|
||||||
|
|
||||||
|
// Estimate number to sort on number sent last frame (with min. of 20).
|
||||||
|
const int numToSendEst = std::max(int(nodeData->getNumAvatarsSentLastFrame() * 2.5f), 20);
|
||||||
|
|
||||||
// reset the number of sent avatars
|
// reset the number of sent avatars
|
||||||
nodeData->resetNumAvatarsSentLastFrame();
|
nodeData->resetNumAvatarsSentLastFrame();
|
||||||
|
|
||||||
// keep a counter of the number of considered avatars
|
|
||||||
int numOtherAvatars = 0;
|
|
||||||
|
|
||||||
// keep track of outbound data rate specifically for avatar data
|
// keep track of outbound data rate specifically for avatar data
|
||||||
int numAvatarDataBytes = 0;
|
int numAvatarDataBytes = 0;
|
||||||
int identityBytesSent = 0;
|
int identityBytesSent = 0;
|
||||||
|
@ -261,7 +259,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
// max number of avatarBytes per frame
|
// max number of avatarBytes per frame
|
||||||
int maxAvatarBytesPerFrame = int(_maxKbpsPerNode * BYTES_PER_KILOBIT / AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND);
|
int maxAvatarBytesPerFrame = int(_maxKbpsPerNode * BYTES_PER_KILOBIT / AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND);
|
||||||
|
|
||||||
|
|
||||||
// keep track of the number of other avatars held back in this frame
|
// keep track of the number of other avatars held back in this frame
|
||||||
int numAvatarsHeldBack = 0;
|
int numAvatarsHeldBack = 0;
|
||||||
|
|
||||||
|
@ -279,10 +276,6 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
int minimumBytesPerAvatar = PALIsOpen ? AvatarDataPacket::AVATAR_HAS_FLAGS_SIZE + NUM_BYTES_RFC4122_UUID +
|
int minimumBytesPerAvatar = PALIsOpen ? AvatarDataPacket::AVATAR_HAS_FLAGS_SIZE + NUM_BYTES_RFC4122_UUID +
|
||||||
sizeof(AvatarDataPacket::AvatarGlobalPosition) + sizeof(AvatarDataPacket::AudioLoudness) : 0;
|
sizeof(AvatarDataPacket::AvatarGlobalPosition) + sizeof(AvatarDataPacket::AudioLoudness) : 0;
|
||||||
|
|
||||||
// setup a PacketList for the avatarPackets
|
|
||||||
auto avatarPacketList = NLPacketList::create(PacketType::BulkAvatarData);
|
|
||||||
static auto maxAvatarDataBytes = avatarPacketList->getMaxSegmentSize() - NUM_BYTES_RFC4122_UUID;
|
|
||||||
|
|
||||||
// compute node bounding box
|
// compute node bounding box
|
||||||
const float MY_AVATAR_BUBBLE_EXPANSION_FACTOR = 4.0f; // magic number determined emperically
|
const float MY_AVATAR_BUBBLE_EXPANSION_FACTOR = 4.0f; // magic number determined emperically
|
||||||
AABox nodeBox = computeBubbleBox(avatar, MY_AVATAR_BUBBLE_EXPANSION_FACTOR);
|
AABox nodeBox = computeBubbleBox(avatar, MY_AVATAR_BUBBLE_EXPANSION_FACTOR);
|
||||||
|
@ -350,8 +343,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
// Don't bother with these checks if the other avatar has their bubble enabled and we're gettingAnyIgnored
|
// Don't bother with these checks if the other avatar has their bubble enabled and we're gettingAnyIgnored
|
||||||
if (nodeData->isIgnoreRadiusEnabled() || (avatarClientNodeData->isIgnoreRadiusEnabled() && !getsAnyIgnored)) {
|
if (nodeData->isIgnoreRadiusEnabled() || (avatarClientNodeData->isIgnoreRadiusEnabled() && !getsAnyIgnored)) {
|
||||||
// Perform the collision check between the two bounding boxes
|
// Perform the collision check between the two bounding boxes
|
||||||
const float OTHER_AVATAR_BUBBLE_EXPANSION_FACTOR = 2.4f; // magic number determined empirically
|
AABox otherNodeBox = avatarClientNodeData->getAvatar().getDefaultBubbleBox();
|
||||||
AABox otherNodeBox = computeBubbleBox(avatarClientNodeData->getAvatar(), OTHER_AVATAR_BUBBLE_EXPANSION_FACTOR);
|
|
||||||
if (nodeBox.touches(otherNodeBox)) {
|
if (nodeBox.touches(otherNodeBox)) {
|
||||||
nodeData->ignoreOther(destinationNode, avatarNode);
|
nodeData->ignoreOther(destinationNode, avatarNode);
|
||||||
shouldIgnore = !getsAnyIgnored;
|
shouldIgnore = !getsAnyIgnored;
|
||||||
|
@ -364,7 +356,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldIgnore) {
|
if (!shouldIgnore) {
|
||||||
AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(avatarNode->getUUID());
|
AvatarDataSequenceNumber lastSeqToReceiver = nodeData->getLastBroadcastSequenceNumber(avatarNode->getLocalID());
|
||||||
AvatarDataSequenceNumber lastSeqFromSender = avatarClientNodeData->getLastReceivedSequenceNumber();
|
AvatarDataSequenceNumber lastSeqFromSender = avatarClientNodeData->getLastReceivedSequenceNumber();
|
||||||
|
|
||||||
// FIXME - This code does appear to be working. But it seems brittle.
|
// FIXME - This code does appear to be working. But it seems brittle.
|
||||||
|
@ -396,7 +388,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
if (!shouldIgnore) {
|
if (!shouldIgnore) {
|
||||||
// sort this one for later
|
// sort this one for later
|
||||||
const AvatarData* avatarNodeData = avatarClientNodeData->getConstAvatarData();
|
const AvatarData* avatarNodeData = avatarClientNodeData->getConstAvatarData();
|
||||||
auto lastEncodeTime = nodeData->getLastOtherAvatarEncodeTime(avatarNodeData->getSessionUUID());
|
auto lastEncodeTime = nodeData->getLastOtherAvatarEncodeTime(avatarNode->getLocalID());
|
||||||
|
|
||||||
sortedAvatars.push(SortableAvatar(avatarNodeData, avatarNode, lastEncodeTime));
|
sortedAvatars.push(SortableAvatar(avatarNodeData, avatarNode, lastEncodeTime));
|
||||||
}
|
}
|
||||||
|
@ -406,8 +398,13 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
|
|
||||||
int remainingAvatars = (int)sortedAvatars.size();
|
int remainingAvatars = (int)sortedAvatars.size();
|
||||||
auto traitsPacketList = NLPacketList::create(PacketType::BulkAvatarTraits, QByteArray(), true, true);
|
auto traitsPacketList = NLPacketList::create(PacketType::BulkAvatarTraits, QByteArray(), true, true);
|
||||||
|
auto avatarPacket = NLPacket::create(PacketType::BulkAvatarData);
|
||||||
|
const int avatarPacketCapacity = avatarPacket->getPayloadCapacity();
|
||||||
|
int avatarSpaceAvailable = avatarPacketCapacity;
|
||||||
|
int numPacketsSent = 0;
|
||||||
|
auto identityPacketList = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
|
||||||
|
|
||||||
const auto& sortedAvatarVector = sortedAvatars.getSortedVector();
|
const auto& sortedAvatarVector = sortedAvatars.getSortedVector(numToSendEst);
|
||||||
for (const auto& sortedAvatar : sortedAvatarVector) {
|
for (const auto& sortedAvatar : sortedAvatarVector) {
|
||||||
const Node* otherNode = sortedAvatar.getNode();
|
const Node* otherNode = sortedAvatar.getNode();
|
||||||
auto lastEncodeForOther = sortedAvatar.getTimestamp();
|
auto lastEncodeForOther = sortedAvatar.getTimestamp();
|
||||||
|
@ -432,21 +429,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
|
|
||||||
auto startAvatarDataPacking = chrono::high_resolution_clock::now();
|
auto startAvatarDataPacking = chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
++numOtherAvatars;
|
|
||||||
|
|
||||||
const AvatarMixerClientData* otherNodeData = reinterpret_cast<const AvatarMixerClientData*>(otherNode->getLinkedData());
|
const AvatarMixerClientData* otherNodeData = reinterpret_cast<const AvatarMixerClientData*>(otherNode->getLinkedData());
|
||||||
const AvatarData* otherAvatar = otherNodeData->getConstAvatarData();
|
const AvatarData* otherAvatar = otherNodeData->getConstAvatarData();
|
||||||
|
|
||||||
// If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO
|
|
||||||
// the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A.
|
|
||||||
if (otherAvatar->hasProcessedFirstIdentity()
|
|
||||||
&& nodeData->getLastBroadcastTime(otherNode->getUUID()) <= otherNodeData->getIdentityChangeTimestamp()) {
|
|
||||||
identityBytesSent += sendIdentityPacket(otherNodeData, node);
|
|
||||||
|
|
||||||
// remember the last time we sent identity details about this other node to the receiver
|
|
||||||
nodeData->setLastBroadcastTime(otherNode->getUUID(), usecTimestampNow());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Typically all out-of-view avatars but such avatars' priorities will rise with time:
|
// Typically all out-of-view avatars but such avatars' priorities will rise with time:
|
||||||
bool isLowerPriority = sortedAvatar.getPriority() <= OUT_OF_VIEW_THRESHOLD;
|
bool isLowerPriority = sortedAvatar.getPriority() <= OUT_OF_VIEW_THRESHOLD;
|
||||||
|
|
||||||
|
@ -456,71 +441,56 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
} else if (!overBudget) {
|
} else if (!overBudget) {
|
||||||
detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO ? AvatarData::SendAllData : AvatarData::CullSmallData;
|
detail = distribution(generator) < AVATAR_SEND_FULL_UPDATE_RATIO ? AvatarData::SendAllData : AvatarData::CullSmallData;
|
||||||
nodeData->incrementAvatarInView();
|
nodeData->incrementAvatarInView();
|
||||||
}
|
|
||||||
|
|
||||||
bool includeThisAvatar = true;
|
// If the time that the mixer sent AVATAR DATA about Avatar B to Avatar A is BEFORE OR EQUAL TO
|
||||||
QVector<JointData>& lastSentJointsForOther = nodeData->getLastOtherAvatarSentJoints(otherNode->getUUID());
|
// the time that Avatar B flagged an IDENTITY DATA change, send IDENTITY DATA about Avatar B to Avatar A.
|
||||||
|
if (otherAvatar->hasProcessedFirstIdentity()
|
||||||
|
&& nodeData->getLastBroadcastTime(otherNode->getLocalID()) <= otherNodeData->getIdentityChangeTimestamp()) {
|
||||||
|
identityBytesSent += sendIdentityPacket(*identityPacketList, otherNodeData, *destinationNode);
|
||||||
|
|
||||||
lastSentJointsForOther.resize(otherAvatar->getJointCount());
|
// remember the last time we sent identity details about this other node to the receiver
|
||||||
|
nodeData->setLastBroadcastTime(otherNode->getLocalID(), usecTimestampNow());
|
||||||
bool distanceAdjust = true;
|
|
||||||
glm::vec3 viewerPosition = myPosition;
|
|
||||||
AvatarDataPacket::HasFlags hasFlagsOut; // the result of the toByteArray
|
|
||||||
bool dropFaceTracking = false;
|
|
||||||
|
|
||||||
auto startSerialize = chrono::high_resolution_clock::now();
|
|
||||||
QByteArray bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
|
|
||||||
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition,
|
|
||||||
&lastSentJointsForOther);
|
|
||||||
auto endSerialize = chrono::high_resolution_clock::now();
|
|
||||||
_stats.toByteArrayElapsedTime +=
|
|
||||||
(quint64) chrono::duration_cast<chrono::microseconds>(endSerialize - startSerialize).count();
|
|
||||||
|
|
||||||
if (bytes.size() > maxAvatarDataBytes) {
|
|
||||||
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
|
|
||||||
<< "resulted in very large buffer of" << bytes.size() << "bytes - dropping facial data";
|
|
||||||
|
|
||||||
dropFaceTracking = true; // first try dropping the facial data
|
|
||||||
bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
|
|
||||||
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition, &lastSentJointsForOther);
|
|
||||||
|
|
||||||
if (bytes.size() > maxAvatarDataBytes) {
|
|
||||||
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
|
|
||||||
<< "without facial data resulted in very large buffer of" << bytes.size()
|
|
||||||
<< "bytes - reducing to MinimumData";
|
|
||||||
bytes = otherAvatar->toByteArray(AvatarData::MinimumData, lastEncodeForOther, lastSentJointsForOther,
|
|
||||||
hasFlagsOut, dropFaceTracking, distanceAdjust, viewerPosition, &lastSentJointsForOther);
|
|
||||||
|
|
||||||
if (bytes.size() > maxAvatarDataBytes) {
|
|
||||||
qCWarning(avatars) << "otherAvatar.toByteArray() for" << otherNode->getUUID()
|
|
||||||
<< "MinimumData resulted in very large buffer of" << bytes.size()
|
|
||||||
<< "bytes - refusing to send avatar";
|
|
||||||
includeThisAvatar = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeThisAvatar) {
|
QVector<JointData>& lastSentJointsForOther = nodeData->getLastOtherAvatarSentJoints(otherNode->getLocalID());
|
||||||
// start a new segment in the PacketList for this avatar
|
|
||||||
avatarPacketList->startSegment();
|
|
||||||
numAvatarDataBytes += avatarPacketList->write(otherNode->getUUID().toRfc4122());
|
|
||||||
numAvatarDataBytes += avatarPacketList->write(bytes);
|
|
||||||
avatarPacketList->endSegment();
|
|
||||||
|
|
||||||
if (detail != AvatarData::NoData) {
|
const bool distanceAdjust = true;
|
||||||
_stats.numOthersIncluded++;
|
const bool dropFaceTracking = false;
|
||||||
|
AvatarDataPacket::SendStatus sendStatus;
|
||||||
|
sendStatus.sendUUID = true;
|
||||||
|
|
||||||
// increment the number of avatars sent to this reciever
|
do {
|
||||||
nodeData->incrementNumAvatarsSentLastFrame();
|
auto startSerialize = chrono::high_resolution_clock::now();
|
||||||
|
QByteArray bytes = otherAvatar->toByteArray(detail, lastEncodeForOther, lastSentJointsForOther,
|
||||||
|
sendStatus, dropFaceTracking, distanceAdjust, myPosition,
|
||||||
|
&lastSentJointsForOther, avatarSpaceAvailable);
|
||||||
|
auto endSerialize = chrono::high_resolution_clock::now();
|
||||||
|
_stats.toByteArrayElapsedTime +=
|
||||||
|
(quint64)chrono::duration_cast<chrono::microseconds>(endSerialize - startSerialize).count();
|
||||||
|
|
||||||
// set the last sent sequence number for this sender on the receiver
|
avatarPacket->write(bytes);
|
||||||
nodeData->setLastBroadcastSequenceNumber(otherNode->getUUID(),
|
avatarSpaceAvailable -= bytes.size();
|
||||||
otherNodeData->getLastReceivedSequenceNumber());
|
numAvatarDataBytes += bytes.size();
|
||||||
nodeData->setLastOtherAvatarEncodeTime(otherNode->getUUID(), usecTimestampNow());
|
if (!sendStatus || avatarSpaceAvailable < (int)AvatarDataPacket::MIN_BULK_PACKET_SIZE) {
|
||||||
|
// Weren't able to fit everything.
|
||||||
|
nodeList->sendPacket(std::move(avatarPacket), *destinationNode);
|
||||||
|
++numPacketsSent;
|
||||||
|
avatarPacket = NLPacket::create(PacketType::BulkAvatarData);
|
||||||
|
avatarSpaceAvailable = avatarPacketCapacity;
|
||||||
}
|
}
|
||||||
} else {
|
} while (!sendStatus);
|
||||||
// TODO? this avatar is not included now, and will probably not be included next frame.
|
|
||||||
// It would be nice if we could tweak its future sort priority to put it at the back of the list.
|
if (detail != AvatarData::NoData) {
|
||||||
|
_stats.numOthersIncluded++;
|
||||||
|
|
||||||
|
// increment the number of avatars sent to this receiver
|
||||||
|
nodeData->incrementNumAvatarsSentLastFrame();
|
||||||
|
|
||||||
|
// set the last sent sequence number for this sender on the receiver
|
||||||
|
nodeData->setLastBroadcastSequenceNumber(otherNode->getLocalID(),
|
||||||
|
otherNodeData->getLastReceivedSequenceNumber());
|
||||||
|
nodeData->setLastOtherAvatarEncodeTime(otherNode->getLocalID(), usecTimestampNow());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto endAvatarDataPacking = chrono::high_resolution_clock::now();
|
auto endAvatarDataPacking = chrono::high_resolution_clock::now();
|
||||||
|
@ -532,17 +502,21 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
remainingAvatars--;
|
remainingAvatars--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nodeData->getNumAvatarsSentLastFrame() > numToSendEst) {
|
||||||
|
qCWarning(avatars) << "More avatars sent than upper estimate" << nodeData->getNumAvatarsSentLastFrame()
|
||||||
|
<< " / " << numToSendEst;
|
||||||
|
}
|
||||||
|
|
||||||
quint64 startPacketSending = usecTimestampNow();
|
quint64 startPacketSending = usecTimestampNow();
|
||||||
|
|
||||||
// close the current packet so that we're always sending something
|
if (avatarPacket->getPayloadSize() != 0) {
|
||||||
avatarPacketList->closeCurrentPacket(true);
|
nodeList->sendPacket(std::move(avatarPacket), *destinationNode);
|
||||||
|
++numPacketsSent;
|
||||||
|
}
|
||||||
|
|
||||||
_stats.numPacketsSent += (int)avatarPacketList->getNumPackets();
|
_stats.numPacketsSent += numPacketsSent;
|
||||||
_stats.numBytesSent += numAvatarDataBytes;
|
_stats.numBytesSent += numAvatarDataBytes;
|
||||||
|
|
||||||
// send the avatar data PacketList
|
|
||||||
nodeList->sendPacketList(std::move(avatarPacketList), *destinationNode);
|
|
||||||
|
|
||||||
// record the bytes sent for other avatar data in the AvatarMixerClientData
|
// record the bytes sent for other avatar data in the AvatarMixerClientData
|
||||||
nodeData->recordSentAvatarData(numAvatarDataBytes);
|
nodeData->recordSentAvatarData(numAvatarDataBytes);
|
||||||
|
|
||||||
|
@ -554,6 +528,12 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
nodeList->sendPacketList(std::move(traitsPacketList), *destinationNode);
|
nodeList->sendPacketList(std::move(traitsPacketList), *destinationNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send any AvatarIdentity packets:
|
||||||
|
identityPacketList->closeCurrentPacket();
|
||||||
|
if (identityBytesSent > 0) {
|
||||||
|
nodeList->sendPacketList(std::move(identityPacketList), *destinationNode);
|
||||||
|
}
|
||||||
|
|
||||||
// record the number of avatars held back this frame
|
// record the number of avatars held back this frame
|
||||||
nodeData->recordNumOtherAvatarStarves(numAvatarsHeldBack);
|
nodeData->recordNumOtherAvatarStarves(numAvatarsHeldBack);
|
||||||
nodeData->recordNumOtherAvatarSkips(numAvatarsWithSkippedFrames);
|
nodeData->recordNumOtherAvatarSkips(numAvatarsWithSkippedFrames);
|
||||||
|
@ -599,20 +579,20 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
|
||||||
// so we always send a full update for this avatar
|
// so we always send a full update for this avatar
|
||||||
|
|
||||||
quint64 start = usecTimestampNow();
|
quint64 start = usecTimestampNow();
|
||||||
AvatarDataPacket::HasFlags flagsOut;
|
AvatarDataPacket::SendStatus sendStatus;
|
||||||
|
|
||||||
QVector<JointData> emptyLastJointSendData { otherAvatar->getJointCount() };
|
QVector<JointData> emptyLastJointSendData { otherAvatar->getJointCount() };
|
||||||
|
|
||||||
QByteArray avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
|
QByteArray avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
|
||||||
flagsOut, false, false, glm::vec3(0), nullptr);
|
sendStatus, false, false, glm::vec3(0), nullptr, 0);
|
||||||
quint64 end = usecTimestampNow();
|
quint64 end = usecTimestampNow();
|
||||||
_stats.toByteArrayElapsedTime += (end - start);
|
_stats.toByteArrayElapsedTime += (end - start);
|
||||||
|
|
||||||
auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getUUID());
|
auto lastBroadcastTime = nodeData->getLastBroadcastTime(agentNode->getLocalID());
|
||||||
if (lastBroadcastTime <= agentNodeData->getIdentityChangeTimestamp()
|
if (lastBroadcastTime <= agentNodeData->getIdentityChangeTimestamp()
|
||||||
|| (start - lastBroadcastTime) >= REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US) {
|
|| (start - lastBroadcastTime) >= REBROADCAST_IDENTITY_TO_DOWNSTREAM_EVERY_US) {
|
||||||
sendReplicatedIdentityPacket(*agentNode, agentNodeData, *node);
|
sendReplicatedIdentityPacket(*agentNode, agentNodeData, *node);
|
||||||
nodeData->setLastBroadcastTime(agentNode->getUUID(), start);
|
nodeData->setLastBroadcastTime(agentNode->getLocalID(), start);
|
||||||
}
|
}
|
||||||
|
|
||||||
// figure out how large our avatar byte array can be to fit in the packet list
|
// figure out how large our avatar byte array can be to fit in the packet list
|
||||||
|
@ -630,14 +610,14 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
|
||||||
<< "-" << avatarByteArray.size() << "bytes";
|
<< "-" << avatarByteArray.size() << "bytes";
|
||||||
|
|
||||||
avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
|
avatarByteArray = otherAvatar->toByteArray(AvatarData::SendAllData, 0, emptyLastJointSendData,
|
||||||
flagsOut, true, false, glm::vec3(0), nullptr);
|
sendStatus, true, false, glm::vec3(0), nullptr, 0);
|
||||||
|
|
||||||
if (avatarByteArray.size() > maxAvatarByteArraySize) {
|
if (avatarByteArray.size() > maxAvatarByteArraySize) {
|
||||||
qCWarning(avatars) << "Replicated avatar data without facial data still too large for"
|
qCWarning(avatars) << "Replicated avatar data without facial data still too large for"
|
||||||
<< otherAvatar->getSessionUUID() << "-" << avatarByteArray.size() << "bytes";
|
<< otherAvatar->getSessionUUID() << "-" << avatarByteArray.size() << "bytes";
|
||||||
|
|
||||||
avatarByteArray = otherAvatar->toByteArray(AvatarData::MinimumData, 0, emptyLastJointSendData,
|
avatarByteArray = otherAvatar->toByteArray(AvatarData::MinimumData, 0, emptyLastJointSendData,
|
||||||
flagsOut, true, false, glm::vec3(0), nullptr);
|
sendStatus, true, false, glm::vec3(0), nullptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +626,7 @@ void AvatarMixerSlave::broadcastAvatarDataToDownstreamMixer(const SharedNodePoin
|
||||||
nodeData->incrementNumAvatarsSentLastFrame();
|
nodeData->incrementNumAvatarsSentLastFrame();
|
||||||
|
|
||||||
// set the last sent sequence number for this sender on the receiver
|
// set the last sent sequence number for this sender on the receiver
|
||||||
nodeData->setLastBroadcastSequenceNumber(agentNode->getUUID(),
|
nodeData->setLastBroadcastSequenceNumber(agentNode->getLocalID(),
|
||||||
agentNodeData->getLastReceivedSequenceNumber());
|
agentNodeData->getLastReceivedSequenceNumber());
|
||||||
|
|
||||||
// increment the number of avatars sent to this reciever
|
// increment the number of avatars sent to this reciever
|
||||||
|
|
|
@ -101,7 +101,7 @@ public:
|
||||||
void harvestStats(AvatarMixerSlaveStats& stats);
|
void harvestStats(AvatarMixerSlaveStats& stats);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int sendIdentityPacket(const AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
|
int sendIdentityPacket(NLPacketList& packet, const AvatarMixerClientData* nodeData, const Node& destinationNode);
|
||||||
int sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode);
|
int sendReplicatedIdentityPacket(const Node& agentNode, const AvatarMixerClientData* nodeData, const Node& destinationNode);
|
||||||
|
|
||||||
qint64 addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData,
|
qint64 addChangedTraitsToBulkPacket(AvatarMixerClientData* listeningNodeData,
|
||||||
|
|
|
@ -69,10 +69,10 @@ void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static AnimPose composeAnimPose(const FBXJoint& fbxJoint, const glm::quat rotation, const glm::vec3 translation) {
|
static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, const glm::vec3 translation) {
|
||||||
glm::mat4 translationMat = glm::translate(translation);
|
glm::mat4 translationMat = glm::translate(translation);
|
||||||
glm::mat4 rotationMat = glm::mat4_cast(fbxJoint.preRotation * rotation * fbxJoint.postRotation);
|
glm::mat4 rotationMat = glm::mat4_cast(joint.preRotation * rotation * joint.postRotation);
|
||||||
glm::mat4 finalMat = translationMat * fbxJoint.preTransform * rotationMat * fbxJoint.postTransform;
|
glm::mat4 finalMat = translationMat * joint.preTransform * rotationMat * joint.postTransform;
|
||||||
return AnimPose(finalMat);
|
return AnimPose(finalMat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
// Run animation
|
// Run animation
|
||||||
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) {
|
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) {
|
||||||
if (!_animSkeleton) {
|
if (!_animSkeleton) {
|
||||||
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getGeometry());
|
_animSkeleton = std::make_shared<AnimSkeleton>(_bind->getHFMModel());
|
||||||
}
|
}
|
||||||
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
|
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
|
||||||
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
|
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
|
||||||
|
@ -93,7 +93,7 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
}
|
}
|
||||||
_animationDetails.currentFrame = currentFrame;
|
_animationDetails.currentFrame = currentFrame;
|
||||||
|
|
||||||
const QVector<FBXJoint>& modelJoints = _bind->getGeometry().joints;
|
const QVector<HFMJoint>& modelJoints = _bind->getHFMModel().joints;
|
||||||
QStringList animationJointNames = _animation->getJointNames();
|
QStringList animationJointNames = _animation->getJointNames();
|
||||||
|
|
||||||
const int nJoints = modelJoints.size();
|
const int nJoints = modelJoints.size();
|
||||||
|
@ -102,8 +102,8 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const int frameCount = _animation->getFrames().size();
|
const int frameCount = _animation->getFrames().size();
|
||||||
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
|
const HFMAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
|
||||||
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
const HFMAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
||||||
const float frameFraction = glm::fract(currentFrame);
|
const float frameFraction = glm::fract(currentFrame);
|
||||||
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();
|
std::vector<AnimPose> poses = _animSkeleton->getRelativeDefaultPoses();
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ void ScriptableAvatar::update(float deltatime) {
|
||||||
const QString& name = animationJointNames[i];
|
const QString& name = animationJointNames[i];
|
||||||
// As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than
|
// As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than
|
||||||
// trusting the .fst (which is sometimes not updated to match changes to .fbx).
|
// trusting the .fst (which is sometimes not updated to match changes to .fbx).
|
||||||
int mapping = _bind->getGeometry().getJointIndex(name);
|
int mapping = _bind->getHFMModel().getJointIndex(name);
|
||||||
if (mapping != -1 && !_maskedJoints.contains(name)) {
|
if (mapping != -1 && !_maskedJoints.contains(name)) {
|
||||||
|
|
||||||
AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE);
|
AnimPose floorPose = composeAnimPose(modelJoints[mapping], floorFrame.rotations[i], floorFrame.translations[i] * UNIT_SCALE);
|
||||||
|
|
|
@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC73.zip
|
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC75.zip
|
||||||
URL_MD5 0c5edfb63cafb042311d3cf25261fbf2
|
URL_MD5 b4225d058952e17976ac228330ce8d51
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
|
|
|
@ -28,6 +28,78 @@
|
||||||
|
|
||||||
!include "WinVer.nsh"
|
!include "WinVer.nsh"
|
||||||
|
|
||||||
|
;--------------------------------
|
||||||
|
;Include Installer Logging
|
||||||
|
; taken from http://nsis.sourceforge.net/Logging:_Simple_Text_File_Logging_Functions_and_Macros
|
||||||
|
; TextLog.nsh v1.1 - 2005-12-26
|
||||||
|
; Written by Mike Schinkel [http://www.mikeschinkel.com/blog/]
|
||||||
|
|
||||||
|
Var /GLOBAL __TextLog_FileHandle
|
||||||
|
Var /GLOBAL __TextLog_FileName
|
||||||
|
Var /GLOBAL __TextLog_State
|
||||||
|
|
||||||
|
!define LogMsg '!insertmacro LogMsgCall'
|
||||||
|
!macro LogMsgCall _text
|
||||||
|
Call LogSetOn
|
||||||
|
Push "${_text}"
|
||||||
|
Call LogText
|
||||||
|
Call LogSetOff
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
|
||||||
|
!define LogText '!insertmacro LogTextCall'
|
||||||
|
!macro LogTextCall _text
|
||||||
|
Push "${_text}"
|
||||||
|
Call LogText
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
Function LogText
|
||||||
|
Exch $0 ; pABC -> 0ABC
|
||||||
|
FileWrite $__TextLog_FileHandle "$0$\r$\n"
|
||||||
|
Pop $0 ; 0ABC -> ABC
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
!define LogSetFileName '!insertmacro LogSetFileNameCall'
|
||||||
|
!macro LogSetFileNameCall _filename
|
||||||
|
Push "${_filename}"
|
||||||
|
Call LogSetFileName
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
Function LogSetFileName
|
||||||
|
Exch $0 ; pABC -> 0ABC
|
||||||
|
StrCpy $__TextLog_FileName "$0"
|
||||||
|
StrCmp $__TextLog_State "open" +1 +3
|
||||||
|
Call LogSetOff
|
||||||
|
Call LogSetOn
|
||||||
|
Pop $0 ; 0ABC -> ABC
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
!define LogSetOn '!insertmacro LogSetOnCall'
|
||||||
|
!macro LogSetOnCall
|
||||||
|
Call LogSetOn
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
Function LogSetOn
|
||||||
|
StrCmp $__TextLog_FileName "" +1 AlreadySet
|
||||||
|
StrCpy $__TextLog_FileName "$INSTDIR\install.log"
|
||||||
|
AlreadySet:
|
||||||
|
StrCmp $__TextLog_State "open" +2
|
||||||
|
FileOpen $__TextLog_FileHandle "$__TextLog_FileName" a
|
||||||
|
FileSeek $__TextLog_FileHandle 0 END
|
||||||
|
StrCpy $__TextLog_State "open"
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
!define LogSetOff '!insertmacro LogSetOffCall'
|
||||||
|
!macro LogSetOffCall
|
||||||
|
Call LogSetOff
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
Function LogSetOff
|
||||||
|
StrCmp $__TextLog_State "open" +1 +2
|
||||||
|
FileClose $__TextLog_FileHandle
|
||||||
|
StrCpy $__TextLog_State ""
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
; Utilities and Functions
|
; Utilities and Functions
|
||||||
;--------------------------------
|
;--------------------------------
|
||||||
|
@ -375,6 +447,10 @@ Var GAClientID
|
||||||
!insertmacro CreateGUID $GAClientID
|
!insertmacro CreateGUID $GAClientID
|
||||||
!macroend
|
!macroend
|
||||||
|
|
||||||
|
!macro LogStep Category Action Label Value
|
||||||
|
${LogText} "Step: ${Category} ${Action} ${Label} ${Value}"
|
||||||
|
!macroend
|
||||||
|
|
||||||
!macro GoogleAnalytics Category Action Label Value
|
!macro GoogleAnalytics Category Action Label Value
|
||||||
${If} "@GA_TRACKING_ID@" != ""
|
${If} "@GA_TRACKING_ID@" != ""
|
||||||
Push $0
|
Push $0
|
||||||
|
@ -557,11 +633,13 @@ Var Express
|
||||||
!macro MaybeSkipPage
|
!macro MaybeSkipPage
|
||||||
; Check if Express is set, if so, abort the post install options page
|
; Check if Express is set, if so, abort the post install options page
|
||||||
${If} $Express == "1"
|
${If} $Express == "1"
|
||||||
|
${LogText} "Express Install: Skipping Post Install Options Page"
|
||||||
Abort
|
Abort
|
||||||
${EndIf}
|
${EndIf}
|
||||||
!macroend
|
!macroend
|
||||||
|
|
||||||
!macro DownloadSlideshowImages
|
!macro DownloadSlideshowImages
|
||||||
|
${LogText} "Download Slideshow Images"
|
||||||
InitPluginsDir
|
InitPluginsDir
|
||||||
|
|
||||||
Push $0
|
Push $0
|
||||||
|
@ -583,32 +661,40 @@ Var Express
|
||||||
!macroend
|
!macroend
|
||||||
|
|
||||||
Function OnUserAbort
|
Function OnUserAbort
|
||||||
|
!insertmacro LogStep "Installer" "Abort" "User Abort" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "Abort" "User Abort" ""
|
!insertmacro GoogleAnalytics "Installer" "Abort" "User Abort" ""
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
Function PageWelcomePre
|
Function PageWelcomePre
|
||||||
|
!insertmacro LogStep "Installer" "Welcome" "" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "Welcome" "" ""
|
!insertmacro GoogleAnalytics "Installer" "Welcome" "" ""
|
||||||
!insertmacro DownloadSlideshowImages
|
!insertmacro DownloadSlideshowImages
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
Function PageLicensePre
|
Function PageLicensePre
|
||||||
|
!insertmacro LogStep "Installer" "License" "" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "License" "" ""
|
!insertmacro GoogleAnalytics "Installer" "License" "" ""
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
Function PageDirectoryPre
|
Function PageDirectoryPre
|
||||||
!insertmacro MaybeSkipPage
|
!insertmacro MaybeSkipPage
|
||||||
|
!insertmacro LogStep "Installer" "Directory" "" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "Directory" "" ""
|
!insertmacro GoogleAnalytics "Installer" "Directory" "" ""
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
Function PageStartMenuPre
|
Function PageStartMenuPre
|
||||||
!insertmacro MaybeSkipPage
|
!insertmacro MaybeSkipPage
|
||||||
|
!insertmacro LogStep "Installer" "StartMenu" "" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "StartMenu" "" ""
|
!insertmacro GoogleAnalytics "Installer" "StartMenu" "" ""
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
Function PageComponentsPre
|
Function PageComponentsPre
|
||||||
!insertmacro MaybeSkipPage
|
!insertmacro MaybeSkipPage
|
||||||
|
!insertmacro LogStep "Installer" "Components" "" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "Components" "" ""
|
!insertmacro GoogleAnalytics "Installer" "Components" "" ""
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
Function PageInstallFilesPre
|
Function PageInstallFilesPre
|
||||||
|
!insertmacro LogStep "Installer" "Install" "" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "Install" "" ""
|
!insertmacro GoogleAnalytics "Installer" "Install" "" ""
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
!macro SetInstallOption Checkbox OptionName Default
|
!macro SetInstallOption Checkbox OptionName Default
|
||||||
|
${LogText} "SetInstallOption ${OptionName} ${Default}"
|
||||||
; reads the value for the given install option to the registry
|
; reads the value for the given install option to the registry
|
||||||
ReadRegStr $0 HKLM "@REGISTRY_HKLM_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\@POST_INSTALL_OPTIONS_REG_GROUP@" "${OptionName}"
|
ReadRegStr $0 HKLM "@REGISTRY_HKLM_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\@POST_INSTALL_OPTIONS_REG_GROUP@" "${OptionName}"
|
||||||
|
|
||||||
|
@ -625,6 +711,7 @@ FunctionEnd
|
||||||
!macroend
|
!macroend
|
||||||
|
|
||||||
Function InstallTypesPage
|
Function InstallTypesPage
|
||||||
|
!insertmacro LogStep "Installer" "Install Types" "" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "Install Types" "" ""
|
!insertmacro GoogleAnalytics "Installer" "Install Types" "" ""
|
||||||
|
|
||||||
!insertmacro MUI_HEADER_TEXT "Choose Installation Type" "Express or Custom Install"
|
!insertmacro MUI_HEADER_TEXT "Choose Installation Type" "Express or Custom Install"
|
||||||
|
@ -688,6 +775,7 @@ FunctionEnd
|
||||||
|
|
||||||
Function StartInstallSlideshow
|
Function StartInstallSlideshow
|
||||||
; create a slideshow file based on what files we have available
|
; create a slideshow file based on what files we have available
|
||||||
|
${LogText} "Start Installs Slideshow"
|
||||||
|
|
||||||
; stash $0 and $1
|
; stash $0 and $1
|
||||||
Push $0
|
Push $0
|
||||||
|
@ -730,7 +818,11 @@ Function StartInstallSlideshow
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
Function PostInstallOptionsPage
|
Function PostInstallOptionsPage
|
||||||
|
|
||||||
|
${LogText} "Install Directory: $INSTDIR"
|
||||||
|
|
||||||
!insertmacro MaybeSkipPage
|
!insertmacro MaybeSkipPage
|
||||||
|
!insertmacro LogStep "Installer" "Post Install Options" "" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "Post Install Options" "" ""
|
!insertmacro GoogleAnalytics "Installer" "Post Install Options" "" ""
|
||||||
|
|
||||||
!insertmacro MUI_HEADER_TEXT "Setup Options" ""
|
!insertmacro MUI_HEADER_TEXT "Setup Options" ""
|
||||||
|
@ -876,30 +968,43 @@ Function ReadPostInstallOptions
|
||||||
|
|
||||||
; check if the user asked for a desktop shortcut to console
|
; check if the user asked for a desktop shortcut to console
|
||||||
${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState
|
${NSD_GetState} $DesktopConsoleCheckbox $DesktopConsoleState
|
||||||
|
${LogText} "Option: Start Desktop Console: $DesktopConsoleState"
|
||||||
|
|
||||||
; check if the user asked to have console launched every startup
|
; check if the user asked to have console launched every startup
|
||||||
${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState
|
${NSD_GetState} $ConsoleStartupCheckbox $ConsoleStartupState
|
||||||
|
${LogText} "Option: Start Desktop Console On Startup: $ConsoleStartupState"
|
||||||
|
|
||||||
|
${If} @SERVER_COMPONENT_CONDITIONAL@
|
||||||
|
${LogText} "Option: Install Server"
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
|
${LogText} "Option: Install Client"
|
||||||
; check if the user asked for a desktop shortcut to High Fidelity
|
; check if the user asked for a desktop shortcut to High Fidelity
|
||||||
${NSD_GetState} $DesktopClientCheckbox $DesktopClientState
|
${NSD_GetState} $DesktopClientCheckbox $DesktopClientState
|
||||||
|
${LogText} "Option: Create Client Desktop Shortcut: $DesktopClientState"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${If} @PR_BUILD@ == 1
|
${If} @PR_BUILD@ == 1
|
||||||
|
${LogText} "Option: PR Build"
|
||||||
; check if we need to copy settings/content from production for this PR build
|
; check if we need to copy settings/content from production for this PR build
|
||||||
${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState
|
${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState
|
||||||
|
${LogText} "Option: Copy Settings From Production: $CopyFromProductionState"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; check if we need to launch the console post-install
|
; check if we need to launch the console post-install
|
||||||
${NSD_GetState} $LaunchConsoleNowCheckbox $LaunchConsoleNowState
|
${NSD_GetState} $LaunchConsoleNowCheckbox $LaunchConsoleNowState
|
||||||
|
${LogText} "Option: Launch Console Now: $LaunchConsoleNowState"
|
||||||
|
|
||||||
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
${If} @CLIENT_COMPONENT_CONDITIONAL@
|
||||||
; check if we need to launch the client post-install
|
; check if we need to launch the client post-install
|
||||||
${NSD_GetState} $LaunchClientNowCheckbox $LaunchClientNowState
|
${NSD_GetState} $LaunchClientNowCheckbox $LaunchClientNowState
|
||||||
|
${LogText} "Option: Launch Client Now: $LaunchClientNowState"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
; check if the user asked for a clean install
|
; check if the user asked for a clean install
|
||||||
${NSD_GetState} $CleanInstallCheckbox $CleanInstallState
|
${NSD_GetState} $CleanInstallCheckbox $CleanInstallState
|
||||||
|
${LogText} "Option: Clean Install: $CleanInstallState"
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
|
||||||
Function HandlePostInstallOptions
|
Function HandlePostInstallOptions
|
||||||
|
@ -1225,6 +1330,7 @@ Section "-Core installation"
|
||||||
; Handle whichever post install options were set
|
; Handle whichever post install options were set
|
||||||
Call HandlePostInstallOptions
|
Call HandlePostInstallOptions
|
||||||
|
|
||||||
|
!insertmacro LogStep "Installer" "Done" "" ""
|
||||||
!insertmacro GoogleAnalytics "Installer" "Done" "" ""
|
!insertmacro GoogleAnalytics "Installer" "Done" "" ""
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
|
@ -1232,7 +1338,6 @@ SectionEnd
|
||||||
|
|
||||||
!macro PromptForRunningApplication applicationName displayName action prompter
|
!macro PromptForRunningApplication applicationName displayName action prompter
|
||||||
!define UniqueID ${__LINE__}
|
!define UniqueID ${__LINE__}
|
||||||
|
|
||||||
Prompt_${UniqueID}:
|
Prompt_${UniqueID}:
|
||||||
|
|
||||||
${nsProcess::FindProcess} ${applicationName} $R0
|
${nsProcess::FindProcess} ${applicationName} $R0
|
||||||
|
@ -1478,6 +1583,11 @@ InstallDirRegKey HKLM "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_RE
|
||||||
|
|
||||||
Function .onInit
|
Function .onInit
|
||||||
|
|
||||||
|
Delete "$TEMP\hifi_install.log"
|
||||||
|
${LogSetFileName} "$TEMP\hifi_install.log"
|
||||||
|
${LogSetOn}
|
||||||
|
${LogText} "In .onInit"
|
||||||
|
|
||||||
!ifdef INNER
|
!ifdef INNER
|
||||||
; If INNER is defined, then we aren't supposed to do anything except write out
|
; If INNER is defined, then we aren't supposed to do anything except write out
|
||||||
; the installer. This is better than processing a command line option as it means
|
; the installer. This is better than processing a command line option as it means
|
||||||
|
@ -1495,6 +1605,7 @@ Function .onInit
|
||||||
!insertmacro GoogleAnalytics "Installer" "Start" "$CampaignName" ""
|
!insertmacro GoogleAnalytics "Installer" "Start" "$CampaignName" ""
|
||||||
|
|
||||||
; make sure none of the installed applications are still running
|
; make sure none of the installed applications are still running
|
||||||
|
${LogText} "Checking For Running Applications"
|
||||||
!insertmacro CheckForRunningApplications "installed" "Installer"
|
!insertmacro CheckForRunningApplications "installed" "Installer"
|
||||||
${nsProcess::Unload}
|
${nsProcess::Unload}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
|
|
||||||
import "../../qml/controls-uit"
|
import controlsUit 1.0
|
||||||
import "../../qml/styles-uit"
|
import stylesUit 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: menu
|
id: menu
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
|
|
||||||
import "../../qml/controls-uit"
|
import controlsUit 1.0
|
||||||
import "../../qml/styles-uit"
|
import stylesUit 1.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
|
|
||||||
import "../../qml/controls-uit"
|
import controlsUit 1.0
|
||||||
import "../../qml/styles-uit"
|
import stylesUit 1.0
|
||||||
import "../../qml/dialogs"
|
import "../../qml/dialogs"
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
|
|
140
interface/resources/avatar/network-animation.json
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
{
|
||||||
|
"version": "1.1",
|
||||||
|
"root": {
|
||||||
|
"id": "userAnimStateMachine",
|
||||||
|
"type": "stateMachine",
|
||||||
|
"data": {
|
||||||
|
"currentState": "idleAnim",
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"id": "idleAnim",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "postTransitAnim", "state": "postTransitAnim" },
|
||||||
|
{ "var": "preTransitAnim", "state": "preTransitAnim" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "preTransitAnim",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "idleAnim", "state": "idleAnim" },
|
||||||
|
{ "var": "transitAnim", "state": "transitAnim" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "transitAnim",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "preTransitAnim", "state": "preTransitAnim" },
|
||||||
|
{ "var": "postTransitAnim", "state": "postTransitAnim" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "postTransitAnim",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "transitAnim", "state": "transitAnim" },
|
||||||
|
{ "var": "idleAnim", "state": "idleAnim" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userAnimA",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "idleAnim", "state": "idleAnim" },
|
||||||
|
{ "var": "userAnimB", "state": "userAnimB" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userAnimB",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "idleAnim", "state": "idleAnim" },
|
||||||
|
{ "var": "userAnimA", "state": "userAnimA" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "idleAnim",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "qrc:///avatar/animations/idle.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 90.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "preTransitAnim",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 10.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "transitAnim",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx",
|
||||||
|
"startFrame": 11.0,
|
||||||
|
"endFrame": 11.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "postTransitAnim",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "https://hifi-content.s3.amazonaws.com/luis/test_scripts/transitApp/animations/teleport01_warp.fbx",
|
||||||
|
"startFrame": 22.0,
|
||||||
|
"endFrame": 49.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": false
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userAnimA",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "qrc:///avatar/animations/idle.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 90.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userAnimB",
|
||||||
|
"type": "clip",
|
||||||
|
"data": {
|
||||||
|
"url": "qrc:///avatar/animations/idle.fbx",
|
||||||
|
"startFrame": 0.0,
|
||||||
|
"endFrame": 90.0,
|
||||||
|
"timeScale": 1.0,
|
||||||
|
"loopFlag": true
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
2476
interface/resources/config/keyboard.json
Normal file
|
@ -51,32 +51,34 @@
|
||||||
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
|
{ "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" },
|
||||||
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
|
{ "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" },
|
||||||
|
|
||||||
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand"},
|
{ "from": "Vive.LeftHand", "to": "Standard.LeftHand" },
|
||||||
{ "from": "Vive.RightHand", "to": "Standard.RightHand"},
|
{ "from": "Vive.RightHand", "to": "Standard.RightHand" },
|
||||||
|
{ "from": "Vive.Head", "to" : "Standard.Head" },
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
"from": "Vive.LeftFoot", "to" : "Standard.LeftFoot",
|
||||||
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
|
"from": "Vive.RightFoot", "to" : "Standard.RightFoot",
|
||||||
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.Hips", "to" : "Standard.Hips",
|
"from": "Vive.Hips", "to" : "Standard.Hips",
|
||||||
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"from": "Vive.Spine2", "to" : "Standard.Spine2",
|
"from": "Vive.Spine2", "to" : "Standard.Spine2",
|
||||||
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.3}]
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "Vive.RightArm", "to" : "Standard.RightArm",
|
||||||
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "Vive.LeftArm", "to" : "Standard.LeftArm",
|
||||||
|
"filters" : [{"type" : "exponentialSmoothing", "rotation" : 0.15, "translation": 0.15}]
|
||||||
},
|
},
|
||||||
|
|
||||||
{ "from": "Vive.Head", "to" : "Standard.Head"},
|
|
||||||
{ "from": "Vive.RightArm", "to" : "Standard.RightArm" },
|
|
||||||
{ "from": "Vive.LeftArm", "to" : "Standard.LeftArm" },
|
|
||||||
|
|
||||||
{ "from": "Vive.TrackedObject00", "to" : "Standard.TrackedObject00" },
|
{ "from": "Vive.TrackedObject00", "to" : "Standard.TrackedObject00" },
|
||||||
{ "from": "Vive.TrackedObject01", "to" : "Standard.TrackedObject01" },
|
{ "from": "Vive.TrackedObject01", "to" : "Standard.TrackedObject01" },
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="22" height="26" fill="none" version="1.1" viewBox="0 0 22 26" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="#000" stroke-linejoin="round" stroke-width="2"/>
|
||||||
|
<circle class="st1" cx="19.407" cy="2.5881" r="2.5846" fill="#ef3b4e" stroke-width=".24043"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 356 B |
3
interface/resources/icons/tablet-icons/inventory-a.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="black" stroke-width="2" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 243 B |
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="22" height="26" fill="none" version="1.1" viewBox="0 0 22 26" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="#fff" stroke-linejoin="round" stroke-width="2"/>
|
||||||
|
<circle class="st1" cx="19.41" cy="2.5828" r="2.5846" fill="#ef3b4e" stroke-width=".24043"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 355 B |
3
interface/resources/icons/tablet-icons/inventory-i.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1 7L11 1L21 7M1 7L11 13M1 7V19L11 25M11 13L21 7M11 13V25M21 7V19L11 25" stroke="white" stroke-width="2" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 243 B |
|
@ -1,6 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st1{fill:#EF3B4E;}
|
|
||||||
</style>
|
|
||||||
<circle class="st1" cx="84.6" cy="11.5" r="10.75"/>
|
|
||||||
<g><path d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9V25.5 c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11V70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5v-1.5c0-2.8,2.2-5,5-5h13.3 c1.1,0,2,0.9,2,2V51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81 v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"></path></g></svg>
|
|
Before Width: | Height: | Size: 755 B |
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve"><g><path d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9V25.5 c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11V70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5v-1.5c0-2.8,2.2-5,5-5h13.3 c1.1,0,2,0.9,2,2V51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81 v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"></path></g></svg>
|
|
Before Width: | Height: | Size: 643 B |
|
@ -1,16 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 21.1.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 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#FFFFFF;}
|
|
||||||
.st1{fill:#EF3B4E;}
|
|
||||||
</style>
|
|
||||||
<circle class="st1" cx="84.6" cy="11.5" r="10.75"/>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9
|
|
||||||
V25.5c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11C2.4,25.5,2.4,70.5,2.4,70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5
|
|
||||||
v-1.5c0-2.8,2.2-5,5-5h13.3c1.1,0,2,0.9,2,2L87.6,51.8L87.6,51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7
|
|
||||||
c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 984 B |
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 21.1.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 96 96" style="enable-background:new 0 0 96 96;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#FFFFFF;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M2.4,70.5c0,6.1,4.9,11,11,11H76c6.1,0,11-4.9,11-11V59.6c3.7-0.7,6.6-3.9,6.6-7.9v-7.5c0-3.9-2.8-7.2-6.6-7.9
|
|
||||||
V25.5c0-6.1-4.9-11-11-11H13.4c-6.1,0-11,4.9-11,11C2.4,25.5,2.4,70.5,2.4,70.5z M87.6,51.8c0,1.1-0.9,2-2,2H72.2c-2.8,0-5-2.2-5-5
|
|
||||||
v-1.5c0-2.8,2.2-5,5-5h13.3c1.1,0,2,0.9,2,2L87.6,51.8L87.6,51.8z M8.4,25.5c0-2.8,2.2-5,5-5H76c2.8,0,5,2.2,5,5v10.7h-8.7
|
|
||||||
c-6.1,0-11,4.9-11,11v1.5c0,6.1,4.9,11,11,11H81v10.7c0,2.8-2.2,5-5,5H13.4c-2.8,0-5-2.2-5-5V25.5z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 909 B |
BIN
interface/resources/meshes/drumstick.fbx
Normal file
BIN
interface/resources/meshes/keyboard/SM_enter.fbx
Normal file
BIN
interface/resources/meshes/keyboard/SM_key.fbx
Normal file
BIN
interface/resources/meshes/keyboard/SM_space.fbx
Normal file
BIN
interface/resources/meshes/keyboard/keyCap_F.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_a.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_b.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_c.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_d.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_e.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_g.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_h.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_i.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_j.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_k.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_l.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_m.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_n.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_o.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_p.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_q.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_r.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_s.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_t.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_u.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_v.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_w.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_x.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_y.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
interface/resources/meshes/keyboard/keyCap_z.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
interface/resources/meshes/keyboard/key_0.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
interface/resources/meshes/keyboard/key_1.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
interface/resources/meshes/keyboard/key_123.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
interface/resources/meshes/keyboard/key_2.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
interface/resources/meshes/keyboard/key_3.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
interface/resources/meshes/keyboard/key_4.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
interface/resources/meshes/keyboard/key_5.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
interface/resources/meshes/keyboard/key_6.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
interface/resources/meshes/keyboard/key_7.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
interface/resources/meshes/keyboard/key_8.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
interface/resources/meshes/keyboard/key_9.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
interface/resources/meshes/keyboard/key_a.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
interface/resources/meshes/keyboard/key_abc.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
interface/resources/meshes/keyboard/key_ampersand.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
interface/resources/meshes/keyboard/key_ast.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
interface/resources/meshes/keyboard/key_at.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
interface/resources/meshes/keyboard/key_b.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
interface/resources/meshes/keyboard/key_backspace.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
interface/resources/meshes/keyboard/key_c.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
interface/resources/meshes/keyboard/key_cap.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
interface/resources/meshes/keyboard/key_caret.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
interface/resources/meshes/keyboard/key_close_paren.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
interface/resources/meshes/keyboard/key_colon.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
interface/resources/meshes/keyboard/key_comma.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
interface/resources/meshes/keyboard/key_d.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
interface/resources/meshes/keyboard/key_dollar.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
interface/resources/meshes/keyboard/key_dquote.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
interface/resources/meshes/keyboard/key_e.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
interface/resources/meshes/keyboard/key_enter.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
interface/resources/meshes/keyboard/key_exclam.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
interface/resources/meshes/keyboard/key_exit.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
interface/resources/meshes/keyboard/key_f.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
interface/resources/meshes/keyboard/key_g.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
interface/resources/meshes/keyboard/key_h.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
interface/resources/meshes/keyboard/key_hashtag.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
interface/resources/meshes/keyboard/key_i.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
interface/resources/meshes/keyboard/key_j.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
interface/resources/meshes/keyboard/key_k.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
interface/resources/meshes/keyboard/key_l.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
interface/resources/meshes/keyboard/key_m.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
interface/resources/meshes/keyboard/key_min.png
Normal file
After Width: | Height: | Size: 1.5 KiB |