mirror of
https://github.com/JulianGro/overte.git
synced 2025-08-04 11:25:05 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into audio/parity
This commit is contained in:
commit
3093a73ce1
29 changed files with 251 additions and 47 deletions
|
@ -132,7 +132,7 @@ void AvatarMixer::start() {
|
||||||
auto start = usecTimestampNow();
|
auto start = usecTimestampNow();
|
||||||
nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) {
|
nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) {
|
||||||
std::for_each(cbegin, cend, [&](const SharedNodePointer& node) {
|
std::for_each(cbegin, cend, [&](const SharedNodePointer& node) {
|
||||||
manageDisplayName(node);
|
manageIdentityData(node);
|
||||||
++_sumListeners;
|
++_sumListeners;
|
||||||
});
|
});
|
||||||
}, &lockWait, &nodeTransform, &functor);
|
}, &lockWait, &nodeTransform, &functor);
|
||||||
|
@ -183,8 +183,9 @@ void AvatarMixer::start() {
|
||||||
|
|
||||||
// NOTE: nodeData->getAvatar() might be side effected, must be called when access to node/nodeData
|
// NOTE: nodeData->getAvatar() might be side effected, must be called when access to node/nodeData
|
||||||
// is guaranteed to not be accessed by other thread
|
// is guaranteed to not be accessed by other thread
|
||||||
void AvatarMixer::manageDisplayName(const SharedNodePointer& node) {
|
void AvatarMixer::manageIdentityData(const SharedNodePointer& node) {
|
||||||
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());
|
AvatarMixerClientData* nodeData = reinterpret_cast<AvatarMixerClientData*>(node->getLinkedData());
|
||||||
|
bool sendIdentity = false;
|
||||||
if (nodeData && nodeData->getAvatarSessionDisplayNameMustChange()) {
|
if (nodeData && nodeData->getAvatarSessionDisplayNameMustChange()) {
|
||||||
AvatarData& avatar = nodeData->getAvatar();
|
AvatarData& avatar = nodeData->getAvatar();
|
||||||
const QString& existingBaseDisplayName = nodeData->getBaseDisplayName();
|
const QString& existingBaseDisplayName = nodeData->getBaseDisplayName();
|
||||||
|
@ -210,9 +211,39 @@ void AvatarMixer::manageDisplayName(const SharedNodePointer& node) {
|
||||||
soFar.second++; // refcount
|
soFar.second++; // refcount
|
||||||
nodeData->flagIdentityChange();
|
nodeData->flagIdentityChange();
|
||||||
nodeData->setAvatarSessionDisplayNameMustChange(false);
|
nodeData->setAvatarSessionDisplayNameMustChange(false);
|
||||||
sendIdentityPacket(nodeData, node); // Tell node whose name changed about its new session display name.
|
sendIdentity = true;
|
||||||
qCDebug(avatars) << "Giving session display name" << sessionDisplayName << "to node with ID" << node->getUUID();
|
qCDebug(avatars) << "Giving session display name" << sessionDisplayName << "to node with ID" << node->getUUID();
|
||||||
}
|
}
|
||||||
|
if (nodeData && nodeData->getAvatarSkeletonModelUrlMustChange()) { // never true for an empty _avatarWhitelist
|
||||||
|
nodeData->setAvatarSkeletonModelUrlMustChange(false);
|
||||||
|
AvatarData& avatar = nodeData->getAvatar();
|
||||||
|
static const QUrl emptyURL("");
|
||||||
|
QUrl url = avatar.cannonicalSkeletonModelURL(emptyURL);
|
||||||
|
if (!isAvatarInWhitelist(url)) {
|
||||||
|
qCDebug(avatars) << "Forbidden avatar" << nodeData->getNodeID() << avatar.getSkeletonModelURL() << "replaced with" << (_replacementAvatar.isEmpty() ? "default" : _replacementAvatar);
|
||||||
|
avatar.setSkeletonModelURL(_replacementAvatar);
|
||||||
|
sendIdentity = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sendIdentity) {
|
||||||
|
sendIdentityPacket(nodeData, node); // Tell node whose name changed about its new session display name or avatar.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AvatarMixer::isAvatarInWhitelist(const QUrl& url) {
|
||||||
|
// The avatar is in the whitelist if:
|
||||||
|
// 1. The avatar's URL's host matches one of the hosts of the URLs in the whitelist AND
|
||||||
|
// 2. The avatar's URL's path starts with the path of that same URL in the whitelist
|
||||||
|
for (const auto& whiteListedPrefix : _avatarWhitelist) {
|
||||||
|
auto whiteListURL = QUrl::fromUserInput(whiteListedPrefix);
|
||||||
|
// check if this script URL matches the whitelist domain and, optionally, is beneath the path
|
||||||
|
if (url.host().compare(whiteListURL.host(), Qt::CaseInsensitive) == 0 &&
|
||||||
|
url.path().startsWith(whiteListURL.path(), Qt::CaseInsensitive)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarMixer::throttle(std::chrono::microseconds duration, int frame) {
|
void AvatarMixer::throttle(std::chrono::microseconds duration, int frame) {
|
||||||
|
@ -402,13 +433,17 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> mes
|
||||||
AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity);
|
AvatarData::parseAvatarIdentityPacket(message->getMessage(), identity);
|
||||||
bool identityChanged = false;
|
bool identityChanged = false;
|
||||||
bool displayNameChanged = false;
|
bool displayNameChanged = false;
|
||||||
avatar.processAvatarIdentity(identity, identityChanged, displayNameChanged);
|
bool skeletonModelUrlChanged = false;
|
||||||
|
avatar.processAvatarIdentity(identity, identityChanged, displayNameChanged, skeletonModelUrlChanged);
|
||||||
if (identityChanged) {
|
if (identityChanged) {
|
||||||
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
QMutexLocker nodeDataLocker(&nodeData->getMutex());
|
||||||
nodeData->flagIdentityChange();
|
nodeData->flagIdentityChange();
|
||||||
if (displayNameChanged) {
|
if (displayNameChanged) {
|
||||||
nodeData->setAvatarSessionDisplayNameMustChange(true);
|
nodeData->setAvatarSessionDisplayNameMustChange(true);
|
||||||
}
|
}
|
||||||
|
if (skeletonModelUrlChanged && !_avatarWhitelist.isEmpty()) {
|
||||||
|
nodeData->setAvatarSkeletonModelUrlMustChange(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,4 +799,19 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
|
||||||
qCDebug(avatars) << "This domain requires a minimum avatar scale of" << _domainMinimumScale
|
qCDebug(avatars) << "This domain requires a minimum avatar scale of" << _domainMinimumScale
|
||||||
<< "and a maximum avatar scale of" << _domainMaximumScale;
|
<< "and a maximum avatar scale of" << _domainMaximumScale;
|
||||||
|
|
||||||
|
const QString AVATAR_WHITELIST_DEFAULT{ "" };
|
||||||
|
static const QString AVATAR_WHITELIST_OPTION = "avatar_whitelist";
|
||||||
|
_avatarWhitelist = domainSettings[AVATARS_SETTINGS_KEY].toObject()[AVATAR_WHITELIST_OPTION].toString(AVATAR_WHITELIST_DEFAULT).split(',', QString::KeepEmptyParts);
|
||||||
|
|
||||||
|
static const QString REPLACEMENT_AVATAR_OPTION = "replacement_avatar";
|
||||||
|
_replacementAvatar = domainSettings[AVATARS_SETTINGS_KEY].toObject()[REPLACEMENT_AVATAR_OPTION].toString(REPLACEMENT_AVATAR_DEFAULT);
|
||||||
|
|
||||||
|
if ((_avatarWhitelist.count() == 1) && _avatarWhitelist[0].isEmpty()) {
|
||||||
|
_avatarWhitelist.clear(); // KeepEmptyParts above will parse "," as ["", ""] (which is ok), but "" as [""] (which is not ok).
|
||||||
|
}
|
||||||
|
if (_avatarWhitelist.isEmpty()) {
|
||||||
|
qCDebug(avatars) << "All avatars are allowed.";
|
||||||
|
} else {
|
||||||
|
qCDebug(avatars) << "Avatars other than" << _avatarWhitelist << "will be replaced by" << (_replacementAvatar.isEmpty() ? "default" : _replacementAvatar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,12 @@ private:
|
||||||
void parseDomainServerSettings(const QJsonObject& domainSettings);
|
void parseDomainServerSettings(const QJsonObject& domainSettings);
|
||||||
void sendIdentityPacket(AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
|
void sendIdentityPacket(AvatarMixerClientData* nodeData, const SharedNodePointer& destinationNode);
|
||||||
|
|
||||||
void manageDisplayName(const SharedNodePointer& node);
|
void manageIdentityData(const SharedNodePointer& node);
|
||||||
|
bool isAvatarInWhitelist(const QUrl& url);
|
||||||
|
|
||||||
|
const QString REPLACEMENT_AVATAR_DEFAULT{ "" };
|
||||||
|
QStringList _avatarWhitelist { };
|
||||||
|
QString _replacementAvatar { REPLACEMENT_AVATAR_DEFAULT };
|
||||||
|
|
||||||
p_high_resolution_clock::time_point _lastFrameTimestamp;
|
p_high_resolution_clock::time_point _lastFrameTimestamp;
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,8 @@ public:
|
||||||
void flagIdentityChange() { _identityChangeTimestamp = usecTimestampNow(); }
|
void flagIdentityChange() { _identityChangeTimestamp = usecTimestampNow(); }
|
||||||
bool getAvatarSessionDisplayNameMustChange() const { return _avatarSessionDisplayNameMustChange; }
|
bool getAvatarSessionDisplayNameMustChange() const { return _avatarSessionDisplayNameMustChange; }
|
||||||
void setAvatarSessionDisplayNameMustChange(bool set = true) { _avatarSessionDisplayNameMustChange = set; }
|
void setAvatarSessionDisplayNameMustChange(bool set = true) { _avatarSessionDisplayNameMustChange = set; }
|
||||||
|
bool getAvatarSkeletonModelUrlMustChange() const { return _avatarSkeletonModelUrlMustChange; }
|
||||||
|
void setAvatarSkeletonModelUrlMustChange(bool set = true) { _avatarSkeletonModelUrlMustChange = set; }
|
||||||
|
|
||||||
void resetNumAvatarsSentLastFrame() { _numAvatarsSentLastFrame = 0; }
|
void resetNumAvatarsSentLastFrame() { _numAvatarsSentLastFrame = 0; }
|
||||||
void incrementNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; }
|
void incrementNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; }
|
||||||
|
@ -146,6 +148,7 @@ private:
|
||||||
|
|
||||||
uint64_t _identityChangeTimestamp;
|
uint64_t _identityChangeTimestamp;
|
||||||
bool _avatarSessionDisplayNameMustChange{ true };
|
bool _avatarSessionDisplayNameMustChange{ true };
|
||||||
|
bool _avatarSkeletonModelUrlMustChange{ false };
|
||||||
|
|
||||||
int _numAvatarsSentLastFrame = 0;
|
int _numAvatarsSentLastFrame = 0;
|
||||||
int _numFramesSinceAdjustment = 0;
|
int _numFramesSinceAdjustment = 0;
|
||||||
|
|
|
@ -47,7 +47,7 @@ void OctreeInboundPacketProcessor::resetStats() {
|
||||||
_singleSenderStats.clear();
|
_singleSenderStats.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long OctreeInboundPacketProcessor::getMaxWait() const {
|
uint32_t OctreeInboundPacketProcessor::getMaxWait() const {
|
||||||
// calculate time until next sendNackPackets()
|
// calculate time until next sendNackPackets()
|
||||||
quint64 nextNackTime = _lastNackTime + TOO_LONG_SINCE_LAST_NACK;
|
quint64 nextNackTime = _lastNackTime + TOO_LONG_SINCE_LAST_NACK;
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
|
|
|
@ -80,7 +80,7 @@ protected:
|
||||||
|
|
||||||
virtual void processPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) override;
|
virtual void processPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode) override;
|
||||||
|
|
||||||
virtual unsigned long getMaxWait() const override;
|
virtual uint32_t getMaxWait() const override;
|
||||||
virtual void preProcess() override;
|
virtual void preProcess() override;
|
||||||
virtual void midProcess() override;
|
virtual void midProcess() override;
|
||||||
|
|
||||||
|
|
|
@ -866,6 +866,22 @@
|
||||||
"help": "Limits the scale of avatars in your domain. Cannot be greater than 1000.",
|
"help": "Limits the scale of avatars in your domain. Cannot be greater than 1000.",
|
||||||
"placeholder": 3.0,
|
"placeholder": 3.0,
|
||||||
"default": 3.0
|
"default": 3.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "avatar_whitelist",
|
||||||
|
"label": "Avatars Allowed from:",
|
||||||
|
"help": "Comma separated list of URLs (with optional paths) that avatar .fst files are allowed from. If someone attempts to use an avatar with a different domain, it will be rejected and the replacement avatar will be used. If left blank, any domain is allowed.",
|
||||||
|
"placeholder": "",
|
||||||
|
"default": "",
|
||||||
|
"advanced": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "replacement_avatar",
|
||||||
|
"label": "Replacement Avatar for disallowed avatars",
|
||||||
|
"help": "A URL for an avatar .fst to be used when someone tries to use an avatar that is not allowed. If left blank, the generic default avatar is used.",
|
||||||
|
"placeholder": "",
|
||||||
|
"default": "",
|
||||||
|
"advanced": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -223,6 +223,14 @@ $(document).ready(function(){
|
||||||
// set focus to the first input in the new row
|
// set focus to the first input in the new row
|
||||||
$target.closest('table').find('tr.inputs input:first').focus();
|
$target.closest('table').find('tr.inputs input:first').focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tableRows = sibling.parent();
|
||||||
|
var tableBody = tableRows.parent();
|
||||||
|
|
||||||
|
// if theres no more siblings, we should jump to a new row
|
||||||
|
if (sibling.next().length == 0 && tableRows.nextAll().length == 1) {
|
||||||
|
tableBody.find("." + Settings.ADD_ROW_BUTTON_CLASS).click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ($target.is('input')) {
|
} else if ($target.is('input')) {
|
||||||
|
|
|
@ -128,7 +128,7 @@ Rectangle {
|
||||||
pal.sendToScript({method: 'refreshNearby', params: params});
|
pal.sendToScript({method: 'refreshNearby', params: params});
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Rectangle {
|
||||||
id: palTabContainer;
|
id: palTabContainer;
|
||||||
// Anchors
|
// Anchors
|
||||||
anchors {
|
anchors {
|
||||||
|
@ -137,6 +137,7 @@ Rectangle {
|
||||||
left: parent.left;
|
left: parent.left;
|
||||||
right: parent.right;
|
right: parent.right;
|
||||||
}
|
}
|
||||||
|
color: "white";
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: tabSelectorContainer;
|
id: tabSelectorContainer;
|
||||||
// Anchors
|
// Anchors
|
||||||
|
|
|
@ -1723,6 +1723,10 @@ void Application::cleanupBeforeQuit() {
|
||||||
|
|
||||||
// Cleanup all overlays after the scripts, as scripts might add more
|
// Cleanup all overlays after the scripts, as scripts might add more
|
||||||
_overlays.cleanupAllOverlays();
|
_overlays.cleanupAllOverlays();
|
||||||
|
// The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual
|
||||||
|
// removal of the items.
|
||||||
|
// See https://highfidelity.fogbugz.com/f/cases/5328
|
||||||
|
_main3DScene->processTransactionQueue();
|
||||||
|
|
||||||
// first stop all timers directly or by invokeMethod
|
// first stop all timers directly or by invokeMethod
|
||||||
// depending on what thread they run in
|
// depending on what thread they run in
|
||||||
|
@ -5294,6 +5298,11 @@ void Application::nodeActivated(SharedNodePointer node) {
|
||||||
|
|
||||||
if (node->getType() == NodeType::AvatarMixer) {
|
if (node->getType() == NodeType::AvatarMixer) {
|
||||||
// new avatar mixer, send off our identity packet on next update loop
|
// new avatar mixer, send off our identity packet on next update loop
|
||||||
|
// Reset skeletonModelUrl if the last server modified our choice.
|
||||||
|
static const QUrl empty{};
|
||||||
|
if (getMyAvatar()->getFullAvatarURLFromPreferences() != getMyAvatar()->cannonicalSkeletonModelURL(empty)) {
|
||||||
|
getMyAvatar()->resetFullAvatarURL();
|
||||||
|
}
|
||||||
getMyAvatar()->markIdentityDataChanged();
|
getMyAvatar()->markIdentityDataChanged();
|
||||||
getMyAvatar()->resetLastSent();
|
getMyAvatar()->resetLastSent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1961,6 +1961,32 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
totalBodyYaw += (speedFactor * deltaAngle * (180.0f / PI));
|
totalBodyYaw += (speedFactor * deltaAngle * (180.0f / PI));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use head/HMD roll to turn while walking or flying.
|
||||||
|
if (qApp->isHMDMode() && _hmdRollControlEnabled) {
|
||||||
|
// Turn with head roll.
|
||||||
|
const float MIN_CONTROL_SPEED = 0.01f;
|
||||||
|
float speed = glm::length(getVelocity());
|
||||||
|
if (speed >= MIN_CONTROL_SPEED) {
|
||||||
|
// Feather turn when stopping moving.
|
||||||
|
float speedFactor;
|
||||||
|
if (getDriveKey(TRANSLATE_Z) != 0.0f || _lastDrivenSpeed == 0.0f) {
|
||||||
|
_lastDrivenSpeed = speed;
|
||||||
|
speedFactor = 1.0f;
|
||||||
|
} else {
|
||||||
|
speedFactor = glm::min(speed / _lastDrivenSpeed, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float direction = glm::dot(getVelocity(), getRotation() * Vectors::UNIT_NEG_Z) > 0.0f ? 1.0f : -1.0f;
|
||||||
|
|
||||||
|
float rollAngle = glm::degrees(asinf(glm::dot(IDENTITY_UP, _hmdSensorOrientation * IDENTITY_RIGHT)));
|
||||||
|
float rollSign = rollAngle < 0.0f ? -1.0f : 1.0f;
|
||||||
|
rollAngle = fabsf(rollAngle);
|
||||||
|
rollAngle = rollAngle > _hmdRollControlDeadZone ? rollSign * (rollAngle - _hmdRollControlDeadZone) : 0.0f;
|
||||||
|
|
||||||
|
totalBodyYaw += speedFactor * direction * rollAngle * deltaTime * _hmdRollControlRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// update body orientation by movement inputs
|
// update body orientation by movement inputs
|
||||||
glm::quat initialOrientation = getOrientationOutbound();
|
glm::quat initialOrientation = getOrientationOutbound();
|
||||||
setOrientation(getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))));
|
setOrientation(getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, totalBodyYaw, 0.0f))));
|
||||||
|
|
|
@ -132,6 +132,10 @@ class MyAvatar : public Avatar {
|
||||||
Q_PROPERTY(bool characterControllerEnabled READ getCharacterControllerEnabled WRITE setCharacterControllerEnabled)
|
Q_PROPERTY(bool characterControllerEnabled READ getCharacterControllerEnabled WRITE setCharacterControllerEnabled)
|
||||||
Q_PROPERTY(bool useAdvancedMovementControls READ useAdvancedMovementControls WRITE setUseAdvancedMovementControls)
|
Q_PROPERTY(bool useAdvancedMovementControls READ useAdvancedMovementControls WRITE setUseAdvancedMovementControls)
|
||||||
|
|
||||||
|
Q_PROPERTY(bool hmdRollControlEnabled READ getHMDRollControlEnabled WRITE setHMDRollControlEnabled)
|
||||||
|
Q_PROPERTY(float hmdRollControlDeadZone READ getHMDRollControlDeadZone WRITE setHMDRollControlDeadZone)
|
||||||
|
Q_PROPERTY(float hmdRollControlRate READ getHMDRollControlRate WRITE setHMDRollControlRate)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum DriveKeys {
|
enum DriveKeys {
|
||||||
TRANSLATE_X = 0,
|
TRANSLATE_X = 0,
|
||||||
|
@ -337,6 +341,13 @@ public:
|
||||||
void setUseAdvancedMovementControls(bool useAdvancedMovementControls)
|
void setUseAdvancedMovementControls(bool useAdvancedMovementControls)
|
||||||
{ _useAdvancedMovementControls.set(useAdvancedMovementControls); }
|
{ _useAdvancedMovementControls.set(useAdvancedMovementControls); }
|
||||||
|
|
||||||
|
void setHMDRollControlEnabled(bool value) { _hmdRollControlEnabled = value; }
|
||||||
|
bool getHMDRollControlEnabled() const { return _hmdRollControlEnabled; }
|
||||||
|
void setHMDRollControlDeadZone(float value) { _hmdRollControlDeadZone = value; }
|
||||||
|
float getHMDRollControlDeadZone() const { return _hmdRollControlDeadZone; }
|
||||||
|
void setHMDRollControlRate(float value) { _hmdRollControlRate = value; }
|
||||||
|
float getHMDRollControlRate() const { return _hmdRollControlRate; }
|
||||||
|
|
||||||
// get/set avatar data
|
// get/set avatar data
|
||||||
void saveData();
|
void saveData();
|
||||||
void loadData();
|
void loadData();
|
||||||
|
@ -687,6 +698,13 @@ private:
|
||||||
bool _useSnapTurn { true };
|
bool _useSnapTurn { true };
|
||||||
bool _clearOverlayWhenMoving { true };
|
bool _clearOverlayWhenMoving { true };
|
||||||
|
|
||||||
|
const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // deg
|
||||||
|
const float ROLL_CONTROL_RATE_DEFAULT = 2.5f; // deg/sec/deg
|
||||||
|
bool _hmdRollControlEnabled { true };
|
||||||
|
float _hmdRollControlDeadZone { ROLL_CONTROL_DEAD_ZONE_DEFAULT };
|
||||||
|
float _hmdRollControlRate { ROLL_CONTROL_RATE_DEFAULT };
|
||||||
|
float _lastDrivenSpeed { 0.0f };
|
||||||
|
|
||||||
// working copies -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access
|
// working copies -- see AvatarData for thread-safe _sensorToWorldMatrixCache, used for outward facing access
|
||||||
glm::mat4 _sensorToWorldMatrix { glm::mat4() };
|
glm::mat4 _sensorToWorldMatrix { glm::mat4() };
|
||||||
|
|
||||||
|
|
|
@ -432,6 +432,11 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
|
||||||
return (mode == QAudio::AudioInput) ? QAudioDeviceInfo::defaultInputDevice() : QAudioDeviceInfo::defaultOutputDevice();
|
return (mode == QAudio::AudioInput) ? QAudioDeviceInfo::defaultInputDevice() : QAudioDeviceInfo::defaultOutputDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AudioClient::getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName) {
|
||||||
|
return (getNamedAudioDeviceForMode(mode, deviceName).deviceName() == deviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// attempt to use the native sample rate and channel count
|
// attempt to use the native sample rate and channel count
|
||||||
bool nativeFormatForAudioDevice(const QAudioDeviceInfo& audioDevice,
|
bool nativeFormatForAudioDevice(const QAudioDeviceInfo& audioDevice,
|
||||||
QAudioFormat& audioFormat) {
|
QAudioFormat& audioFormat) {
|
||||||
|
|
|
@ -150,6 +150,8 @@ public:
|
||||||
|
|
||||||
static const float CALLBACK_ACCELERATOR_RATIO;
|
static const float CALLBACK_ACCELERATOR_RATIO;
|
||||||
|
|
||||||
|
bool getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
static QString getWinDeviceName(wchar_t* guid);
|
static QString getWinDeviceName(wchar_t* guid);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1504,7 +1504,7 @@ QUrl AvatarData::cannonicalSkeletonModelURL(const QUrl& emptyURL) const {
|
||||||
return _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL;
|
return _skeletonModelURL.scheme() == "file" ? emptyURL : _skeletonModelURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged) {
|
void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, bool& skeletonModelUrlChanged) {
|
||||||
|
|
||||||
if (identity.sequenceId < _identitySequenceId) {
|
if (identity.sequenceId < _identitySequenceId) {
|
||||||
qCDebug(avatars) << "Ignoring older identity packet for avatar" << getSessionUUID()
|
qCDebug(avatars) << "Ignoring older identity packet for avatar" << getSessionUUID()
|
||||||
|
@ -1517,6 +1517,7 @@ void AvatarData::processAvatarIdentity(const Identity& identity, bool& identityC
|
||||||
if (_firstSkeletonCheck || (identity.skeletonModelURL != cannonicalSkeletonModelURL(emptyURL))) {
|
if (_firstSkeletonCheck || (identity.skeletonModelURL != cannonicalSkeletonModelURL(emptyURL))) {
|
||||||
setSkeletonModelURL(identity.skeletonModelURL);
|
setSkeletonModelURL(identity.skeletonModelURL);
|
||||||
identityChanged = true;
|
identityChanged = true;
|
||||||
|
skeletonModelUrlChanged = true;
|
||||||
if (_firstSkeletonCheck) {
|
if (_firstSkeletonCheck) {
|
||||||
displayNameChanged = true;
|
displayNameChanged = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -368,6 +368,7 @@ public:
|
||||||
virtual ~AvatarData();
|
virtual ~AvatarData();
|
||||||
|
|
||||||
static const QUrl& defaultFullAvatarModelUrl();
|
static const QUrl& defaultFullAvatarModelUrl();
|
||||||
|
QUrl cannonicalSkeletonModelURL(const QUrl& empty) const;
|
||||||
|
|
||||||
virtual bool isMyAvatar() const { return false; }
|
virtual bool isMyAvatar() const { return false; }
|
||||||
|
|
||||||
|
@ -536,9 +537,8 @@ public:
|
||||||
|
|
||||||
static void parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut);
|
static void parseAvatarIdentityPacket(const QByteArray& data, Identity& identityOut);
|
||||||
|
|
||||||
// identityChanged returns true if identity has changed, false otherwise.
|
// identityChanged returns true if identity has changed, false otherwise. Similarly for displayNameChanged and skeletonModelUrlChange.
|
||||||
// displayNameChanged returns true if displayName has changed, false otherwise.
|
void processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged, bool& skeletonModelUrlChanged);
|
||||||
void processAvatarIdentity(const Identity& identity, bool& identityChanged, bool& displayNameChanged);
|
|
||||||
|
|
||||||
QByteArray identityByteArray() const;
|
QByteArray identityByteArray() const;
|
||||||
|
|
||||||
|
@ -697,7 +697,6 @@ protected:
|
||||||
QVector<AttachmentData> _attachmentData;
|
QVector<AttachmentData> _attachmentData;
|
||||||
QString _displayName;
|
QString _displayName;
|
||||||
QString _sessionDisplayName { };
|
QString _sessionDisplayName { };
|
||||||
QUrl cannonicalSkeletonModelURL(const QUrl& empty) const;
|
|
||||||
|
|
||||||
QHash<QString, int> _jointIndices; ///< 1-based, since zero is returned for missing keys
|
QHash<QString, int> _jointIndices; ///< 1-based, since zero is returned for missing keys
|
||||||
QStringList _jointNames; ///< in order of depth-first traversal
|
QStringList _jointNames; ///< in order of depth-first traversal
|
||||||
|
|
|
@ -148,8 +148,9 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer<ReceivedMessage>
|
||||||
auto avatar = newOrExistingAvatar(identity.uuid, sendingNode);
|
auto avatar = newOrExistingAvatar(identity.uuid, sendingNode);
|
||||||
bool identityChanged = false;
|
bool identityChanged = false;
|
||||||
bool displayNameChanged = false;
|
bool displayNameChanged = false;
|
||||||
|
bool skeletonModelUrlChanged = false;
|
||||||
// In this case, the "sendingNode" is the Avatar Mixer.
|
// In this case, the "sendingNode" is the Avatar Mixer.
|
||||||
avatar->processAvatarIdentity(identity, identityChanged, displayNameChanged);
|
avatar->processAvatarIdentity(identity, identityChanged, displayNameChanged, skeletonModelUrlChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -584,7 +584,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
|
||||||
return matchingNode;
|
return matchingNode;
|
||||||
} else {
|
} else {
|
||||||
// we didn't have this node, so add them
|
// we didn't have this node, so add them
|
||||||
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, permissions, connectionSecret, this);
|
Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket, permissions, connectionSecret);
|
||||||
|
|
||||||
if (nodeType == NodeType::AudioMixer) {
|
if (nodeType == NodeType::AudioMixer) {
|
||||||
LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer);
|
LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer);
|
||||||
|
@ -617,24 +617,28 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert the new node and release our read lock
|
// insert the new node and release our read lock
|
||||||
_nodeHash.insert(UUIDNodePair(newNode->getUUID(), newNodePointer));
|
_nodeHash.emplace(newNode->getUUID(), newNodePointer);
|
||||||
readLocker.unlock();
|
readLocker.unlock();
|
||||||
|
|
||||||
qCDebug(networking) << "Added" << *newNode;
|
qCDebug(networking) << "Added" << *newNode;
|
||||||
|
|
||||||
|
auto weakPtr = newNodePointer.toWeakRef(); // We don't want the lambdas to hold a strong ref
|
||||||
|
|
||||||
emit nodeAdded(newNodePointer);
|
emit nodeAdded(newNodePointer);
|
||||||
if (newNodePointer->getActiveSocket()) {
|
if (newNodePointer->getActiveSocket()) {
|
||||||
emit nodeActivated(newNodePointer);
|
emit nodeActivated(newNodePointer);
|
||||||
} else {
|
} else {
|
||||||
connect(newNodePointer.data(), &NetworkPeer::socketActivated, this, [=] {
|
connect(newNodePointer.data(), &NetworkPeer::socketActivated, this, [this, weakPtr] {
|
||||||
emit nodeActivated(newNodePointer);
|
auto sharedPtr = weakPtr.lock();
|
||||||
disconnect(newNodePointer.data(), &NetworkPeer::socketActivated, this, 0);
|
if (sharedPtr) {
|
||||||
|
emit nodeActivated(sharedPtr);
|
||||||
|
disconnect(sharedPtr.data(), &NetworkPeer::socketActivated, this, 0);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signal when a socket changes, so we can start the hole punch over.
|
// Signal when a socket changes, so we can start the hole punch over.
|
||||||
auto weakPtr = newNodePointer.toWeakRef(); // We don't want the lambda to hold a strong ref
|
connect(newNodePointer.data(), &NetworkPeer::socketUpdated, this, [this, weakPtr] {
|
||||||
connect(newNodePointer.data(), &NetworkPeer::socketUpdated, this, [=] {
|
|
||||||
emit nodeSocketUpdated(weakPtr);
|
emit nodeSocketUpdated(weakPtr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ public:
|
||||||
Node(const QUuid& uuid, NodeType_t type,
|
Node(const QUuid& uuid, NodeType_t type,
|
||||||
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
||||||
const NodePermissions& permissions, const QUuid& connectionSecret = QUuid(),
|
const NodePermissions& permissions, const QUuid& connectionSecret = QUuid(),
|
||||||
QObject* parent = 0);
|
QObject* parent = nullptr);
|
||||||
|
|
||||||
bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; }
|
bool operator==(const Node& otherNode) const { return _uuid == otherNode._uuid; }
|
||||||
bool operator!=(const Node& otherNode) const { return !(*this == otherNode); }
|
bool operator!=(const Node& otherNode) const { return !(*this == otherNode); }
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
class ReceivedPacketProcessor : public GenericThread {
|
class ReceivedPacketProcessor : public GenericThread {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
static const uint64_t MAX_WAIT_TIME { 100 }; // Max wait time in ms
|
||||||
|
|
||||||
ReceivedPacketProcessor();
|
ReceivedPacketProcessor();
|
||||||
|
|
||||||
/// Add packet from network receive thread to the processing queue.
|
/// Add packet from network receive thread to the processing queue.
|
||||||
|
@ -63,8 +65,8 @@ protected:
|
||||||
/// Implements generic processing behavior for this thread.
|
/// Implements generic processing behavior for this thread.
|
||||||
virtual bool process() override;
|
virtual bool process() override;
|
||||||
|
|
||||||
/// Determines the timeout of the wait when there are no packets to process. Default value means no timeout
|
/// Determines the timeout of the wait when there are no packets to process. Default value is 100ms to allow for regular event processing.
|
||||||
virtual unsigned long getMaxWait() const { return ULONG_MAX; }
|
virtual uint32_t getMaxWait() const { return MAX_WAIT_TIME; }
|
||||||
|
|
||||||
/// Override to do work before the packets processing loop. Default does nothing.
|
/// Override to do work before the packets processing loop. Default does nothing.
|
||||||
virtual void preProcess() { }
|
virtual void preProcess() { }
|
||||||
|
|
|
@ -35,14 +35,13 @@ void JurisdictionListener::nodeKilled(SharedNodePointer node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JurisdictionListener::queueJurisdictionRequest() {
|
bool JurisdictionListener::queueJurisdictionRequest() {
|
||||||
auto packet = NLPacket::create(PacketType::JurisdictionRequest, 0);
|
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
int nodeCount = 0;
|
int nodeCount = 0;
|
||||||
|
|
||||||
nodeList->eachNode([&](const SharedNodePointer& node) {
|
nodeList->eachNode([&](const SharedNodePointer& node) {
|
||||||
if (node->getType() == getNodeType() && node->getActiveSocket()) {
|
if (node->getType() == getNodeType() && node->getActiveSocket()) {
|
||||||
|
auto packet = NLPacket::create(PacketType::JurisdictionRequest, 0);
|
||||||
_packetSender.queuePacketForSending(node, std::move(packet));
|
_packetSender.queuePacketForSending(node, std::move(packet));
|
||||||
nodeCount++;
|
nodeCount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,6 @@ bool JurisdictionSender::process() {
|
||||||
|
|
||||||
// call our ReceivedPacketProcessor base class process so we'll get any pending packets
|
// call our ReceivedPacketProcessor base class process so we'll get any pending packets
|
||||||
if (continueProcessing && (continueProcessing = ReceivedPacketProcessor::process())) {
|
if (continueProcessing && (continueProcessing = ReceivedPacketProcessor::process())) {
|
||||||
auto packet = (_jurisdictionMap) ? _jurisdictionMap->packIntoPacket()
|
|
||||||
: JurisdictionMap::packEmptyJurisdictionIntoMessage(getNodeType());
|
|
||||||
int nodeCount = 0;
|
int nodeCount = 0;
|
||||||
|
|
||||||
lockRequestingNodes();
|
lockRequestingNodes();
|
||||||
|
@ -53,6 +51,8 @@ bool JurisdictionSender::process() {
|
||||||
SharedNodePointer node = DependencyManager::get<NodeList>()->nodeWithUUID(nodeUUID);
|
SharedNodePointer node = DependencyManager::get<NodeList>()->nodeWithUUID(nodeUUID);
|
||||||
|
|
||||||
if (node && node->getActiveSocket()) {
|
if (node && node->getActiveSocket()) {
|
||||||
|
auto packet = (_jurisdictionMap) ? _jurisdictionMap->packIntoPacket()
|
||||||
|
: JurisdictionMap::packEmptyJurisdictionIntoMessage(getNodeType());
|
||||||
_packetSender.queuePacketForSending(node, std::move(packet));
|
_packetSender.queuePacketForSending(node, std::move(packet));
|
||||||
nodeCount++;
|
nodeCount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "AntialiasingEffect.h"
|
#include "AntialiasingEffect.h"
|
||||||
#include "StencilMaskPass.h"
|
#include "StencilMaskPass.h"
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "FramebufferCache.h"
|
|
||||||
#include "DependencyManager.h"
|
#include "DependencyManager.h"
|
||||||
#include "ViewFrustum.h"
|
#include "ViewFrustum.h"
|
||||||
#include "GeometryCache.h"
|
#include "GeometryCache.h"
|
||||||
|
@ -40,9 +39,9 @@ Antialiasing::~Antialiasing() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() {
|
const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline(RenderArgs* args) {
|
||||||
int width = DependencyManager::get<FramebufferCache>()->getFrameBufferSize().width();
|
int width = args->_viewport.z;
|
||||||
int height = DependencyManager::get<FramebufferCache>()->getFrameBufferSize().height();
|
int height = args->_viewport.w;
|
||||||
|
|
||||||
if (_antialiasingBuffer && _antialiasingBuffer->getSize() != uvec2(width, height)) {
|
if (_antialiasingBuffer && _antialiasingBuffer->getSize() != uvec2(width, height)) {
|
||||||
_antialiasingBuffer.reset();
|
_antialiasingBuffer.reset();
|
||||||
|
@ -51,7 +50,7 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() {
|
||||||
if (!_antialiasingBuffer) {
|
if (!_antialiasingBuffer) {
|
||||||
// Link the antialiasing FBO to texture
|
// Link the antialiasing FBO to texture
|
||||||
_antialiasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing"));
|
_antialiasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("antialiasing"));
|
||||||
auto format = gpu::Element::COLOR_SRGBA_32; // DependencyManager::get<FramebufferCache>()->getLightingTexture()->getTexelFormat();
|
auto format = gpu::Element::COLOR_SRGBA_32;
|
||||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
||||||
_antialiasingTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler);
|
_antialiasingTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, defaultSampler);
|
||||||
_antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture);
|
_antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture);
|
||||||
|
@ -115,10 +114,8 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
|
||||||
batch.setViewportTransform(args->_viewport);
|
batch.setViewportTransform(args->_viewport);
|
||||||
|
|
||||||
// FIXME: NEED to simplify that code to avoid all the GeometryCahce call, this is purely pixel manipulation
|
// FIXME: NEED to simplify that code to avoid all the GeometryCahce call, this is purely pixel manipulation
|
||||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
float fbWidth = renderContext->args->_viewport.z;
|
||||||
QSize framebufferSize = framebufferCache->getFrameBufferSize();
|
float fbHeight = renderContext->args->_viewport.w;
|
||||||
float fbWidth = framebufferSize.width();
|
|
||||||
float fbHeight = framebufferSize.height();
|
|
||||||
// float sMin = args->_viewport.x / fbWidth;
|
// float sMin = args->_viewport.x / fbWidth;
|
||||||
// float sWidth = args->_viewport.z / fbWidth;
|
// float sWidth = args->_viewport.z / fbWidth;
|
||||||
// float tMin = args->_viewport.y / fbHeight;
|
// float tMin = args->_viewport.y / fbHeight;
|
||||||
|
@ -133,10 +130,10 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
|
||||||
batch.setModelTransform(Transform());
|
batch.setModelTransform(Transform());
|
||||||
|
|
||||||
// FXAA step
|
// FXAA step
|
||||||
getAntialiasingPipeline();
|
auto pipeline = getAntialiasingPipeline(renderContext->args);
|
||||||
batch.setResourceTexture(0, sourceBuffer->getRenderBuffer(0));
|
batch.setResourceTexture(0, sourceBuffer->getRenderBuffer(0));
|
||||||
batch.setFramebuffer(_antialiasingBuffer);
|
batch.setFramebuffer(_antialiasingBuffer);
|
||||||
batch.setPipeline(getAntialiasingPipeline());
|
batch.setPipeline(pipeline);
|
||||||
|
|
||||||
// initialize the view-space unpacking uniforms using frustum data
|
// initialize the view-space unpacking uniforms using frustum data
|
||||||
float left, right, bottom, top, nearVal, farVal;
|
float left, right, bottom, top, nearVal, farVal;
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
void configure(const Config& config) {}
|
void configure(const Config& config) {}
|
||||||
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& sourceBuffer);
|
void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& sourceBuffer);
|
||||||
|
|
||||||
const gpu::PipelinePointer& getAntialiasingPipeline();
|
const gpu::PipelinePointer& getAntialiasingPipeline(RenderArgs* args);
|
||||||
const gpu::PipelinePointer& getBlendPipeline();
|
const gpu::PipelinePointer& getBlendPipeline();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include <ViewFrustum.h>
|
#include <ViewFrustum.h>
|
||||||
|
|
||||||
#include "GeometryCache.h"
|
#include "GeometryCache.h"
|
||||||
#include "FramebufferCache.h"
|
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "DeferredLightingEffect.h"
|
#include "DeferredLightingEffect.h"
|
||||||
|
|
||||||
|
@ -410,7 +409,6 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I
|
||||||
batch.setViewportTransform(args->_viewport);
|
batch.setViewportTransform(args->_viewport);
|
||||||
|
|
||||||
const auto geometryBuffer = DependencyManager::get<GeometryCache>();
|
const auto geometryBuffer = DependencyManager::get<GeometryCache>();
|
||||||
const auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
|
||||||
const auto textureCache = DependencyManager::get<TextureCache>();
|
const auto textureCache = DependencyManager::get<TextureCache>();
|
||||||
|
|
||||||
glm::mat4 projMat;
|
glm::mat4 projMat;
|
||||||
|
|
|
@ -418,10 +418,7 @@ model::MeshPointer DeferredLightingEffect::getSpotLightMesh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& primaryFramebuffer) {
|
void PreparePrimaryFramebuffer::run(const RenderContextPointer& renderContext, gpu::FramebufferPointer& primaryFramebuffer) {
|
||||||
|
glm::uvec2 frameSize(renderContext->args->_viewport.z, renderContext->args->_viewport.w);
|
||||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
|
||||||
auto framebufferSize = framebufferCache->getFrameBufferSize();
|
|
||||||
glm::uvec2 frameSize(framebufferSize.width(), framebufferSize.height());
|
|
||||||
|
|
||||||
// Resizing framebuffers instead of re-building them seems to cause issues with threaded
|
// Resizing framebuffers instead of re-building them seems to cause issues with threaded
|
||||||
// rendering
|
// rendering
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QtCore/QCoreApplication>
|
||||||
|
|
||||||
#include "GenericThread.h"
|
#include "GenericThread.h"
|
||||||
|
|
||||||
|
@ -73,6 +74,7 @@ void GenericThread::threadRoutine() {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!_stopThread) {
|
while (!_stopThread) {
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
// override this function to do whatever your class actually does, return false to exit thread early
|
// override this function to do whatever your class actually does, return false to exit thread early
|
||||||
if (!process()) {
|
if (!process()) {
|
||||||
|
|
17
scripts/developer/hmdRollControlDisable.js
Normal file
17
scripts/developer/hmdRollControlDisable.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
//
|
||||||
|
// hmdRollControlDisable.js
|
||||||
|
//
|
||||||
|
// Created by David Rowe on 4 Jun 2017.
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var hmdRollControlEnabled = false;
|
||||||
|
|
||||||
|
//print("HMD roll control: " + hmdRollControlEnabled);
|
||||||
|
|
||||||
|
MyAvatar.hmdRollControlEnabled = hmdRollControlEnabled;
|
||||||
|
|
||||||
|
Script.stop();
|
21
scripts/developer/hmdRollControlEnable.js
Normal file
21
scripts/developer/hmdRollControlEnable.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//
|
||||||
|
// hmdRollControlEnable.js
|
||||||
|
//
|
||||||
|
// Created by David Rowe on 4 Jun 2017.
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var hmdRollControlEnabled = true;
|
||||||
|
var hmdRollControlDeadZone = 8.0; // deg
|
||||||
|
var hmdRollControlRate = 2.5; // deg/sec/deg
|
||||||
|
|
||||||
|
//print("HMD roll control: " + hmdRollControlEnabled + ", " + hmdRollControlDeadZone + ", " + hmdRollControlRate);
|
||||||
|
|
||||||
|
MyAvatar.hmdRollControlEnabled = hmdRollControlEnabled;
|
||||||
|
MyAvatar.hmdRollControlDeadZone = hmdRollControlDeadZone;
|
||||||
|
MyAvatar.hmdRollControlRate = hmdRollControlRate;
|
||||||
|
|
||||||
|
Script.stop();
|
|
@ -101,6 +101,10 @@ function getApplicationDataDirectory() {
|
||||||
return path.join(getRootHifiDataDirectory(), '/Server Console');
|
return path.join(getRootHifiDataDirectory(), '/Server Console');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update lock filepath
|
||||||
|
const UPDATER_LOCK_FILENAME = ".updating";
|
||||||
|
const UPDATER_LOCK_FULL_PATH = getRootHifiDataDirectory() + "/" + UPDATER_LOCK_FILENAME;
|
||||||
|
|
||||||
// Configure log
|
// Configure log
|
||||||
global.log = require('electron-log');
|
global.log = require('electron-log');
|
||||||
const logFile = getApplicationDataDirectory() + '/log.txt';
|
const logFile = getApplicationDataDirectory() + '/log.txt';
|
||||||
|
@ -630,11 +634,22 @@ function checkNewContent() {
|
||||||
userConfig.save(configPath);
|
userConfig.save(configPath);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else if (fs.existsSync(UPDATER_LOCK_FULL_PATH)) {
|
||||||
|
backupResourceDirectoriesAndRestart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function removeIncompleteUpdate(acResourceDirectory, dsResourceDirectory) {
|
||||||
|
if (fs.existsSync(UPDATER_LOCK_FULL_PATH)) {
|
||||||
|
log.debug('Removing incomplete content update files before copying new update');
|
||||||
|
fs.emptyDirSync(dsResourceDirectory);
|
||||||
|
fs.emptyDirSync(acResourceDirectory);
|
||||||
|
} else {
|
||||||
|
fs.ensureFileSync(UPDATER_LOCK_FULL_PATH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function maybeInstallDefaultContentSet(onComplete) {
|
function maybeInstallDefaultContentSet(onComplete) {
|
||||||
// Check for existing data
|
// Check for existing data
|
||||||
|
@ -673,7 +688,11 @@ function maybeInstallDefaultContentSet(onComplete) {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("Found contentPath:" + argv.contentPath);
|
log.debug("Found contentPath:" + argv.contentPath);
|
||||||
|
|
||||||
if (argv.contentPath) {
|
if (argv.contentPath) {
|
||||||
|
// check if we're updating a data folder whose update is incomplete
|
||||||
|
removeIncompleteUpdate(acResourceDirectory, dsResourceDirectory);
|
||||||
|
|
||||||
fs.copy(argv.contentPath, getRootHifiDataDirectory(), function (err) {
|
fs.copy(argv.contentPath, getRootHifiDataDirectory(), function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('Could not copy home content: ' + err);
|
log.debug('Could not copy home content: ' + err);
|
||||||
|
@ -682,12 +701,12 @@ function maybeInstallDefaultContentSet(onComplete) {
|
||||||
log.debug('Copied home content over to: ' + getRootHifiDataDirectory());
|
log.debug('Copied home content over to: ' + getRootHifiDataDirectory());
|
||||||
userConfig.set('homeContentLastModified', new Date());
|
userConfig.set('homeContentLastModified', new Date());
|
||||||
userConfig.save(configPath);
|
userConfig.save(configPath);
|
||||||
|
fs.removeSync(UPDATER_LOCK_FULL_PATH);
|
||||||
onComplete();
|
onComplete();
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Show popup
|
// Show popup
|
||||||
var window = new BrowserWindow({
|
var window = new BrowserWindow({
|
||||||
icon: appIcon,
|
icon: appIcon,
|
||||||
|
@ -718,6 +737,9 @@ function maybeInstallDefaultContentSet(onComplete) {
|
||||||
|
|
||||||
var aborted = false;
|
var aborted = false;
|
||||||
|
|
||||||
|
// check if we're updating a data folder whose update is incomplete
|
||||||
|
removeIncompleteUpdate(acResourceDirectory, dsResourceDirectory);
|
||||||
|
|
||||||
// Start downloading content set
|
// Start downloading content set
|
||||||
var req = progress(request.get({
|
var req = progress(request.get({
|
||||||
url: HOME_CONTENT_URL
|
url: HOME_CONTENT_URL
|
||||||
|
@ -763,6 +785,7 @@ function maybeInstallDefaultContentSet(onComplete) {
|
||||||
log.debug("Finished unarchiving home content set");
|
log.debug("Finished unarchiving home content set");
|
||||||
userConfig.set('homeContentLastModified', new Date());
|
userConfig.set('homeContentLastModified', new Date());
|
||||||
userConfig.save(configPath);
|
userConfig.save(configPath);
|
||||||
|
fs.removeSync(UPDATER_LOCK_FULL_PATH);
|
||||||
sendStateUpdate('complete');
|
sendStateUpdate('complete');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue