From 172fab6789d6caba4d8ae1c8e080d8897f3e7435 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 30 Mar 2017 17:53:54 -0700 Subject: [PATCH 01/46] Thread safety for property getter/setters on entities --- libraries/entities/src/EntityItem.cpp | 543 ++++++++++++++++++++-- libraries/entities/src/EntityItem.h | 139 +++--- libraries/entities/src/TextEntityItem.cpp | 95 ++++ libraries/entities/src/TextEntityItem.h | 38 +- 4 files changed, 682 insertions(+), 133 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 0bb085459e..9ba740728b 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -909,19 +909,23 @@ void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSk float EntityItem::computeMass() const { glm::vec3 dimensions = getDimensions(); - return _density * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z; + return getDensity() * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z; } void EntityItem::setDensity(float density) { - _density = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY); + withWriteLock([&] { + _density = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY); + }); } void EntityItem::updateDensity(float density) { float clampedDensity = glm::max(glm::min(density, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY); - if (_density != clampedDensity) { - _density = clampedDensity; - _dirtyFlags |= Simulation::DIRTY_MASS; - } + withWriteLock([&] { + if (_density != clampedDensity) { + _density = clampedDensity; + _dirtyFlags |= Simulation::DIRTY_MASS; + } + }); } void EntityItem::setMass(float mass) { @@ -941,10 +945,12 @@ void EntityItem::setMass(float mass) { } else { newDensity = glm::max(glm::min(mass / volume, ENTITY_ITEM_MAX_DENSITY), ENTITY_ITEM_MIN_DENSITY); } - if (_density != newDensity) { - _density = newDensity; - _dirtyFlags |= Simulation::DIRTY_MASS; - } + withWriteLock([&] { + if (_density != newDensity) { + _density = newDensity; + _dirtyFlags |= Simulation::DIRTY_MASS; + } + }); } void EntityItem::setHref(QString value) { @@ -952,32 +958,47 @@ void EntityItem::setHref(QString value) { if (! (value.toLower().startsWith("hifi://")) ) { return; } - _href = value; + withWriteLock([&] { + _href = value; + }); } void EntityItem::setCollisionSoundURL(const QString& value) { - if (_collisionSoundURL != value) { - _collisionSoundURL = value; - + bool modified = false; + withWriteLock([&] { + if (_collisionSoundURL != value) { + _collisionSoundURL = value; + modified = true; + } + }); + if (modified) { if (auto myTree = getTree()) { - myTree->notifyNewCollisionSoundURL(_collisionSoundURL, getEntityItemID()); + myTree->notifyNewCollisionSoundURL(value, getEntityItemID()); } } } SharedSoundPointer EntityItem::getCollisionSound() { - if (!_collisionSound) { - _collisionSound = DependencyManager::get()->getSound(_collisionSoundURL); + SharedSoundPointer result; + withReadLock([&] { + result = _collisionSound; + }); + + if (!result) { + result = DependencyManager::get()->getSound(_collisionSoundURL); + withWriteLock([&] { + _collisionSound = result; + }); } - return _collisionSound; + return result; } void EntityItem::simulate(const quint64& now) { - if (_lastSimulated == 0) { - _lastSimulated = now; + if (0 == getLastSimulated()) { + setLastSimulated(now); } - float timeElapsed = (float)(now - _lastSimulated) / (float)(USECS_PER_SECOND); + float timeElapsed = (float)(now - getLastSimulated()) / (float)(USECS_PER_SECOND); #ifdef WANT_DEBUG qCDebug(entities) << "********** EntityItem::simulate()"; @@ -1024,7 +1045,7 @@ void EntityItem::simulate(const quint64& now) { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; setAcceleration(Vectors::ZERO); } - _lastSimulated = now; + setLastSimulated(now); } bool EntityItem::stepKinematicMotion(float timeElapsed) { @@ -1056,9 +1077,10 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) { timeElapsed = glm::min(timeElapsed, MAX_TIME_ELAPSED); if (isSpinning) { + float angularDamping = getAngularDamping(); // angular damping - if (_angularDamping > 0.0f) { - angularVelocity *= powf(1.0f - _angularDamping, timeElapsed); + if (angularDamping > 0.0f) { + angularVelocity *= powf(1.0f - angularDamping, timeElapsed); } const float MIN_KINEMATIC_ANGULAR_SPEED_SQUARED = @@ -1086,15 +1108,17 @@ bool EntityItem::stepKinematicMotion(float timeElapsed) { glm::vec3 deltaVelocity = Vectors::ZERO; // linear damping - if (_damping > 0.0f) { - deltaVelocity = (powf(1.0f - _damping, timeElapsed) - 1.0f) * linearVelocity; + float damping = getDamping(); + if (damping > 0.0f) { + deltaVelocity = (powf(1.0f - damping, timeElapsed) - 1.0f) * linearVelocity; } const float MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED = 1.0e-4f; // 0.01 m/sec^2 - if (glm::length2(_acceleration) > MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED) { + vec3 acceleration = getAcceleration(); + if (glm::length2(acceleration) > MIN_KINEMATIC_LINEAR_ACCELERATION_SQUARED) { // yes acceleration // acceleration is in world-frame but we need it in local-frame - glm::vec3 linearAcceleration = _acceleration; + glm::vec3 linearAcceleration = acceleration; bool success; Transform parentTransform = getParentTransform(success); if (success) { @@ -1180,7 +1204,7 @@ bool EntityItem::lifetimeHasExpired() const { } quint64 EntityItem::getExpiry() const { - return _created + (quint64)(_lifetime * (float)USECS_PER_SECOND); + return getCreated() + (quint64)(getLifetime() * (float)USECS_PER_SECOND); } EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProperties) const { @@ -1189,10 +1213,10 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper EntityItemProperties properties(propertyFlags); properties._id = getID(); properties._idSet = true; - properties._created = _created; - properties._lastEdited = _lastEdited; - properties.setClientOnly(_clientOnly); - properties.setOwningAvatarID(_owningAvatarID); + properties._created = getCreated(); + properties._lastEdited = getLastEdited(); + properties.setClientOnly(getClientOnly()); + properties.setOwningAvatarID(getOwningAvatarID()); properties._type = getType(); @@ -1259,7 +1283,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c properties._angularVelocity = getLocalAngularVelocity(); } if (!properties._accelerationChanged) { - properties._acceleration = _acceleration; + properties._acceleration = getAcceleration(); } properties._positionChanged = true; @@ -1777,20 +1801,26 @@ void EntityItem::updateRestitution(float value) { void EntityItem::updateFriction(float value) { float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION); - if (_friction != clampedValue) { - _friction = clampedValue; - _dirtyFlags |= Simulation::DIRTY_MATERIAL; - } + withWriteLock([&] { + if (_friction != clampedValue) { + _friction = clampedValue; + _dirtyFlags |= Simulation::DIRTY_MATERIAL; + } + }); } void EntityItem::setRestitution(float value) { float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_RESTITUTION, value), ENTITY_ITEM_MIN_RESTITUTION); - _restitution = clampedValue; + withWriteLock([&] { + _restitution = clampedValue; + }); } void EntityItem::setFriction(float value) { float clampedValue = glm::max(glm::min(ENTITY_ITEM_MAX_FRICTION, value), ENTITY_ITEM_MIN_FRICTION); - _friction = clampedValue; + withWriteLock([&] { + _friction = clampedValue; + }); } void EntityItem::updateLifetime(float value) { @@ -2327,3 +2357,436 @@ bool EntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const { // the json filter syntax did not match what we expected, return a match return true; } + +quint64 EntityItem::getLastSimulated() const { + quint64 result; + withReadLock([&] { + result = _lastSimulated; + }); + return result; +} + +void EntityItem::setLastSimulated(quint64 now) { + withWriteLock([&] { + _lastSimulated = now; + }); +} + +quint64 EntityItem::getLastEdited() const { + quint64 result; + withReadLock([&] { + result = _lastEdited; + }); + return result; +} + +void EntityItem::setLastEdited(quint64 lastEdited) { + withWriteLock([&] { + _lastEdited = _lastUpdated = lastEdited; + _changedOnServer = glm::max(lastEdited, _changedOnServer); + }); +} + +quint64 EntityItem::getLastBroadcast() const { + quint64 result; + withReadLock([&] { + result = _lastBroadcast; + }); + return result; +} + +void EntityItem::setLastBroadcast(quint64 lastBroadcast) { + withWriteLock([&] { + _lastBroadcast = lastBroadcast; + }); +} + +void EntityItem::markAsChangedOnServer() { + withWriteLock([&] { + _changedOnServer = usecTimestampNow(); + }); +} + +quint64 EntityItem::getLastChangedOnServer() const { + quint64 result; + withReadLock([&] { + result = _changedOnServer; + }); + return result; +} + +void EntityItem::update(const quint64& now) { + withWriteLock([&] { + _lastUpdated = now; + }); +} + +quint64 EntityItem::getLastUpdated() const { + quint64 result; + withReadLock([&] { + result = _lastUpdated; + }); + return result; +} + +void EntityItem::requiresRecalcBoxes() { + withWriteLock([&] { + _recalcAABox = true; + _recalcMinAACube = true; + _recalcMaxAACube = true; + }); +} + +QString EntityItem::getHref() const { + QString result; + withReadLock([&] { + result = _href; + }); + return result; +} + +QString EntityItem::getDescription() const { + QString result; + withReadLock([&] { + result = _description; + }); + return result; +} + +void EntityItem::setDescription(const QString& value) { + withWriteLock([&] { + _description = value; + }); +} + +float EntityItem::getLocalRenderAlpha() const { + float result; + withReadLock([&] { + result = _localRenderAlpha; + }); + return result; +} + +void EntityItem::setLocalRenderAlpha(float localRenderAlpha) { + withWriteLock([&] { + _localRenderAlpha = localRenderAlpha; + }); +} + +glm::vec3 EntityItem::getGravity() const { + glm::vec3 result; + withReadLock([&] { + result = _gravity; + }); + return result; +} + +void EntityItem::setGravity(const glm::vec3& value) { + withWriteLock([&] { + _gravity = value; + }); +} + +glm::vec3 EntityItem::getAcceleration() const { + glm::vec3 result; + withReadLock([&] { + result = _acceleration; + }); + return result; +} + +void EntityItem::setAcceleration(const glm::vec3& value) { + withWriteLock([&] { + _acceleration = value; + }); +} + +float EntityItem::getDamping() const { + float result; + withReadLock([&] { + result = _damping; + }); + return result; +} +void EntityItem::setDamping(float value) { + withWriteLock([&] { + _damping = value; + }); +} + +float EntityItem::getRestitution() const { + float result; + withReadLock([&] { + result = _restitution; + }); + return result; +} + +float EntityItem::getFriction() const { + float result; + withReadLock([&] { + result = _friction; + }); + return result; +} + +// lifetime related properties. +float EntityItem::getLifetime() const { + float result; + withReadLock([&] { + result = _lifetime; + }); + return result; +} + +void EntityItem::setLifetime(float value) { + withWriteLock([&] { + _lifetime = value; + }); +} + +quint64 EntityItem::getCreated() const { + quint64 result; + withReadLock([&] { + result = _created; + }); + return result; +} + +void EntityItem::setCreated(quint64 value) { + withWriteLock([&] { + _created = value; + }); +} + +QString EntityItem::getScript() const { + QString result; + withReadLock([&] { + result = _script; + }); + return result; +} + +void EntityItem::setScript(const QString& value) { + withWriteLock([&] { + _script = value; + }); +} + +quint64 EntityItem::getScriptTimestamp() const { + quint64 result; + withReadLock([&] { + result = _scriptTimestamp; + }); + return result; +} + +void EntityItem::setScriptTimestamp(const quint64 value) { + withWriteLock([&] { + _scriptTimestamp = value; + }); +} + +QString EntityItem::getServerScripts() const { + QString result; + withReadLock([&] { + result = _serverScripts; + }); + return result; +} + +void EntityItem::setServerScripts(const QString& serverScripts) { + withWriteLock([&] { + _serverScripts = serverScripts; + _serverScriptsChangedTimestamp = usecTimestampNow(); + }); +} + +QString EntityItem::getCollisionSoundURL() const { + QString result; + withReadLock([&] { + result = _collisionSoundURL; + }); + return result; +} + +void EntityItem::setCollisionSound(SharedSoundPointer sound) { + withWriteLock([&] { + _collisionSound = sound; + }); +} + +glm::vec3 EntityItem::getRegistrationPoint() const { + glm::vec3 result; + withReadLock([&] { + result = _registrationPoint; + }); + return result; +} + +void EntityItem::setRegistrationPoint(const glm::vec3& value) { + withWriteLock([&] { + _registrationPoint = glm::clamp(value, 0.0f, 1.0f); + }); + dimensionsChanged(); // Registration Point affects the bounding box +} + +float EntityItem::getAngularDamping() const { + float result; + withReadLock([&] { + result = _angularDamping; + }); + return result; +} + +void EntityItem::setAngularDamping(float value) { + withWriteLock([&] { + _angularDamping = value; + }); +} + +QString EntityItem::getName() const { + QString result; + withReadLock([&] { + result = _name; + }); + return result; +} + +void EntityItem::setName(const QString& value) { + withWriteLock([&] { + _name = value; + }); +} + +QString EntityItem::getDebugName() { + QString result = getName(); + if (result.isEmpty()) { + result = getID().toString(); + } + return result; +} + +bool EntityItem::getVisible() const { + bool result; + withReadLock([&] { + result = _visible; + }); + return result; +} + +void EntityItem::setVisible(bool value) { + withWriteLock([&] { + _visible = value; + }); +} + +bool EntityItem::getCollisionless() const { + bool result; + withReadLock([&] { + result = _collisionless; + }); + return result; +} + +void EntityItem::setCollisionless(bool value) { + withWriteLock([&] { + _collisionless = value; + }); +} + +uint8_t EntityItem::getCollisionMask() const { + uint8_t result; + withReadLock([&] { + result = _collisionMask; + }); + return result; +} + +void EntityItem::setCollisionMask(uint8_t value) { + withWriteLock([&] { + _collisionMask = value; + }); +} + +bool EntityItem::getDynamic() const { + if (SHAPE_TYPE_STATIC_MESH == getShapeType()) { + return false; + } + bool result; + withReadLock([&] { + result = _dynamic; + }); + return result; +} + +void EntityItem::setDynamic(bool value) { + withWriteLock([&] { + _dynamic = value; + }); +} + +bool EntityItem::getLocked() const { + bool result; + withReadLock([&] { + result = _locked; + }); + return result; +} + +void EntityItem::setLocked(bool value) { + withWriteLock([&] { + _locked = value; + }); +} + +QString EntityItem::getUserData() const { + QString result; + withReadLock([&] { + result = _userData; + }); + return result; +} + +void EntityItem::setUserData(const QString& value) { + withWriteLock([&] { + _userData = value; + }); +} + +QString EntityItem::getMarketplaceID() const { + QString result; + withReadLock([&] { + result = _marketplaceID; + }); + return result; +} + +void EntityItem::setMarketplaceID(const QString& value) { + withWriteLock([&] { + _marketplaceID = value; + }); +} + +uint32_t EntityItem::getDirtyFlags() const { + uint32_t result; + withReadLock([&] { + result = _dirtyFlags; + }); + return result; +} + +void EntityItem::clearDirtyFlags(uint32_t mask) { + withWriteLock([&] { + _dirtyFlags &= ~mask; + }); +} + +float EntityItem::getDensity() const { + float result; + withReadLock([&] { + result = _density; + }); + return result; +} + diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b973d916e6..929fe8a698 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -110,22 +110,21 @@ public: virtual void somethingChangedNotification() { } void recordCreationTime(); // set _created to 'now' - quint64 getLastSimulated() const { return _lastSimulated; } /// Last simulated time of this entity universal usecs - void setLastSimulated(quint64 now) { _lastSimulated = now; } + quint64 getLastSimulated() const; /// Last simulated time of this entity universal usecs + void setLastSimulated(quint64 now); /// Last edited time of this entity universal usecs - quint64 getLastEdited() const { return _lastEdited; } - void setLastEdited(quint64 lastEdited) - { _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); } + quint64 getLastEdited() const; + void setLastEdited(quint64 lastEdited); float getEditedAgo() const /// Elapsed seconds since this entity was last edited { return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; } /// Last time we sent out an edit packet for this entity - quint64 getLastBroadcast() const { return _lastBroadcast; } - void setLastBroadcast(quint64 lastBroadcast) { _lastBroadcast = lastBroadcast; } + quint64 getLastBroadcast() const; + void setLastBroadcast(quint64 lastBroadcast); - void markAsChangedOnServer() { _changedOnServer = usecTimestampNow(); } - quint64 getLastChangedOnServer() const { return _changedOnServer; } + void markAsChangedOnServer(); + quint64 getLastChangedOnServer() const; // TODO: eventually only include properties changed since the params.lastQuerySent time virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; @@ -163,8 +162,8 @@ public: static void adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSkew); // perform update - virtual void update(const quint64& now) { _lastUpdated = now; } - quint64 getLastUpdated() const { return _lastUpdated; } + virtual void update(const quint64& now); + quint64 getLastUpdated() const; // perform linear extrapolation for SimpleEntitySimulation void simulate(const quint64& now); @@ -188,63 +187,63 @@ public: const Transform getTransformToCenter(bool& success) const; - inline void requiresRecalcBoxes() { _recalcAABox = true; _recalcMinAACube = true; _recalcMaxAACube = true; } + inline void requiresRecalcBoxes(); // Hyperlink related getters and setters - QString getHref() const { return _href; } + QString getHref() const; void setHref(QString value); - QString getDescription() const { return _description; } - void setDescription(QString value) { _description = value; } + QString getDescription() const; + void setDescription(const QString& value); /// Dimensions in meters (0.0 - TREE_SCALE) inline const glm::vec3 getDimensions() const { return getScale(); } virtual void setDimensions(const glm::vec3& value); - float getLocalRenderAlpha() const { return _localRenderAlpha; } - void setLocalRenderAlpha(float localRenderAlpha) { _localRenderAlpha = localRenderAlpha; } + float getLocalRenderAlpha() const; + void setLocalRenderAlpha(float localRenderAlpha); void setDensity(float density); float computeMass() const; void setMass(float mass); - float getDensity() const { return _density; } + float getDensity() const; bool hasVelocity() const { return getVelocity() != ENTITY_ITEM_ZERO_VEC3; } bool hasLocalVelocity() const { return getLocalVelocity() != ENTITY_ITEM_ZERO_VEC3; } - const glm::vec3& getGravity() const { return _gravity; } /// get gravity in meters - void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in meters - bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; } + glm::vec3 getGravity() const; /// get gravity in meters + void setGravity(const glm::vec3& value); /// gravity in meters + bool hasGravity() const { return getGravity() != ENTITY_ITEM_ZERO_VEC3; } - const glm::vec3& getAcceleration() const { return _acceleration; } /// get acceleration in meters/second/second - void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second/second - bool hasAcceleration() const { return _acceleration != ENTITY_ITEM_ZERO_VEC3; } + glm::vec3 getAcceleration() const; /// get acceleration in meters/second/second + void setAcceleration(const glm::vec3& value); /// acceleration in meters/second/second + bool hasAcceleration() const { return getAcceleration() != ENTITY_ITEM_ZERO_VEC3; } - float getDamping() const { return _damping; } - void setDamping(float value) { _damping = value; } + float getDamping() const; + void setDamping(float value); - float getRestitution() const { return _restitution; } + float getRestitution() const; void setRestitution(float value); - float getFriction() const { return _friction; } + float getFriction() const; void setFriction(float value); // lifetime related properties. - float getLifetime() const { return _lifetime; } /// get the lifetime in seconds for the entity - void setLifetime(float value) { _lifetime = value; } /// set the lifetime in seconds for the entity + float getLifetime() const; /// get the lifetime in seconds for the entity + void setLifetime(float value); /// set the lifetime in seconds for the entity - quint64 getCreated() const { return _created; } /// get the created-time in useconds for the entity - void setCreated(quint64 value) { _created = value; } /// set the created-time in useconds for the entity + quint64 getCreated() const; /// get the created-time in useconds for the entity + void setCreated(quint64 value); /// set the created-time in useconds for the entity /// is this entity immortal, in that it has no lifetime set, and will exist until manually deleted - bool isImmortal() const { return _lifetime == ENTITY_ITEM_IMMORTAL_LIFETIME; } + bool isImmortal() const { return getLifetime() == ENTITY_ITEM_IMMORTAL_LIFETIME; } /// is this entity mortal, in that it has a lifetime set, and will automatically be deleted when that lifetime expires - bool isMortal() const { return _lifetime != ENTITY_ITEM_IMMORTAL_LIFETIME; } + bool isMortal() const { return getLifetime() != ENTITY_ITEM_IMMORTAL_LIFETIME; } /// age of this entity in seconds - float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } + float getAge() const { return (float)(usecTimestampNow() - getCreated()) / (float)USECS_PER_SECOND; } bool lifetimeHasExpired() const; quint64 getExpiry() const; @@ -256,63 +255,61 @@ public: using SpatiallyNestable::getQueryAACube; virtual AACube getQueryAACube(bool& success) const override; - QString getScript() const { return _script; } - void setScript(const QString& value) { _script = value; } + QString getScript() const; + void setScript(const QString& value); - quint64 getScriptTimestamp() const { return _scriptTimestamp; } - void setScriptTimestamp(const quint64 value) { _scriptTimestamp = value; } + quint64 getScriptTimestamp() const; + void setScriptTimestamp(const quint64 value); - QString getServerScripts() const { return _serverScripts; } - void setServerScripts(const QString& serverScripts) - { _serverScripts = serverScripts; _serverScriptsChangedTimestamp = usecTimestampNow(); } + QString getServerScripts() const; + void setServerScripts(const QString& serverScripts); - const QString& getCollisionSoundURL() const { return _collisionSoundURL; } + QString getCollisionSoundURL() const; void setCollisionSoundURL(const QString& value); SharedSoundPointer getCollisionSound(); - void setCollisionSound(SharedSoundPointer sound) { _collisionSound = sound; } + void setCollisionSound(SharedSoundPointer sound); - const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity + glm::vec3 getRegistrationPoint() const; /// registration point as ratio of entity /// registration point as ratio of entity - void setRegistrationPoint(const glm::vec3& value) { - _registrationPoint = glm::clamp(value, 0.0f, 1.0f); dimensionsChanged(); // Registration Point affects the bounding box - } + void setRegistrationPoint(const glm::vec3& value); bool hasAngularVelocity() const { return getAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; } bool hasLocalAngularVelocity() const { return getLocalAngularVelocity() != ENTITY_ITEM_ZERO_VEC3; } - float getAngularDamping() const { return _angularDamping; } - void setAngularDamping(float value) { _angularDamping = value; } + float getAngularDamping() const; + void setAngularDamping(float value); - QString getName() const { return _name; } - void setName(const QString& value) { _name = value; } - QString getDebugName() { return _name != "" ? _name : getID().toString(); } + QString getName() const; + void setName(const QString& value); + QString getDebugName(); - bool getVisible() const { return _visible; } - void setVisible(bool value) { _visible = value; } - bool isVisible() const { return _visible; } - bool isInvisible() const { return !_visible; } + bool getVisible() const; + void setVisible(bool value); + inline bool isVisible() const { return getVisible(); } + inline bool isInvisible() const { return !getVisible(); } - bool getCollisionless() const { return _collisionless; } - void setCollisionless(bool value) { _collisionless = value; } + bool getCollisionless() const; + void setCollisionless(bool value); - uint8_t getCollisionMask() const { return _collisionMask; } - void setCollisionMask(uint8_t value) { _collisionMask = value; } + uint8_t getCollisionMask() const; + void setCollisionMask(uint8_t value); void computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const; - bool getDynamic() const { return SHAPE_TYPE_STATIC_MESH == getShapeType() ? false : _dynamic; } - void setDynamic(bool value) { _dynamic = value; } + bool getDynamic() const; + void setDynamic(bool value); virtual bool shouldBePhysical() const { return false; } - bool getLocked() const { return _locked; } - void setLocked(bool value) { _locked = value; } + bool getLocked() const; + void setLocked(bool value); - const QString& getUserData() const { return _userData; } - virtual void setUserData(const QString& value) { _userData = value; } + QString getUserData() const; + virtual void setUserData(const QString& value); + // FIXME not thread safe? const SimulationOwner& getSimulationOwner() const { return _simulationOwner; } void setSimulationOwner(const QUuid& id, quint8 priority); void setSimulationOwner(const SimulationOwner& owner); @@ -325,8 +322,8 @@ public: void setPendingOwnershipPriority(quint8 priority, const quint64& timestamp); void rememberHasSimulationOwnershipBid() const; - const QString& getMarketplaceID() const { return _marketplaceID; } - void setMarketplaceID(const QString& value) { _marketplaceID = value; } + QString getMarketplaceID() const; + void setMarketplaceID(const QString& value); // TODO: get rid of users of getRadius()... float getRadius() const; @@ -369,8 +366,8 @@ public: void updateCreated(uint64_t value); virtual void setShapeType(ShapeType type) { /* do nothing */ } - uint32_t getDirtyFlags() const { return _dirtyFlags; } - void clearDirtyFlags(uint32_t mask = 0xffffffff) { _dirtyFlags &= ~mask; } + uint32_t getDirtyFlags() const; + void clearDirtyFlags(uint32_t mask = 0xffffffff); bool isMoving() const; bool isMovingRelativeToParent() const; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index fbb0bdc9cf..c6b857f6e7 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -141,3 +141,98 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const // FIXME - should set face and surfaceNormal return findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance); } + +void TextEntityItem::setText(const QString& value) { + withWriteLock([&] { + _text = value; + }); +} + +QString TextEntityItem::getText() const { + QString result; + withReadLock([&] { + result = _text; + }); + return result; +} + +void TextEntityItem::setLineHeight(float value) { + withWriteLock([&] { + _lineHeight = value; + }); +} + +float TextEntityItem::getLineHeight() const { + float result; + withReadLock([&] { + result = _lineHeight; + }); + return result; +} + +const rgbColor& TextEntityItem::getTextColor() const { + return _textColor; +} + +const rgbColor& TextEntityItem::getBackgroundColor() const { + return _backgroundColor; +} + +xColor TextEntityItem::getTextColorX() const { + xColor result; + withReadLock([&] { + result = { _textColor[RED_INDEX], _textColor[GREEN_INDEX], _textColor[BLUE_INDEX] }; + }); + return result; +} + +void TextEntityItem::setTextColor(const rgbColor& value) { + withWriteLock([&] { + memcpy(_textColor, value, sizeof(_textColor)); + }); +} + +void TextEntityItem::setTextColor(const xColor& value) { + withWriteLock([&] { + _textColor[RED_INDEX] = value.red; + _textColor[GREEN_INDEX] = value.green; + _textColor[BLUE_INDEX] = value.blue; + }); +} + +xColor TextEntityItem::getBackgroundColorX() const { + xColor result; + withReadLock([&] { + result = { _backgroundColor[RED_INDEX], _backgroundColor[GREEN_INDEX], _backgroundColor[BLUE_INDEX] }; + }); + return result; +} + +void TextEntityItem::setBackgroundColor(const rgbColor& value) { + withWriteLock([&] { + memcpy(_backgroundColor, value, sizeof(_backgroundColor)); + }); +} + +void TextEntityItem::setBackgroundColor(const xColor& value) { + withWriteLock([&] { + _backgroundColor[RED_INDEX] = value.red; + _backgroundColor[GREEN_INDEX] = value.green; + _backgroundColor[BLUE_INDEX] = value.blue; + }); +} + +bool TextEntityItem::getFaceCamera() const { + bool result; + withReadLock([&] { + result = _faceCamera; + }); + return result; +} + +void TextEntityItem::setFaceCamera(bool value) { + withWriteLock([&] { + _faceCamera = value; + }); +} + diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 633aa96bfa..4e49bb8ef0 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -53,38 +53,32 @@ public: void** intersectedObject, bool precisionPicking) const override; static const QString DEFAULT_TEXT; - void setText(const QString& value) { _text = value; } - const QString& getText() const { return _text; } + void setText(const QString& value); + QString getText() const; static const float DEFAULT_LINE_HEIGHT; - void setLineHeight(float value) { _lineHeight = value; } - float getLineHeight() const { return _lineHeight; } + void setLineHeight(float value); + float getLineHeight() const; static const xColor DEFAULT_TEXT_COLOR; - const rgbColor& getTextColor() const { return _textColor; } - xColor getTextColorX() const { xColor color = { _textColor[RED_INDEX], _textColor[GREEN_INDEX], _textColor[BLUE_INDEX] }; return color; } + // FIXME should not return a reference because of thread safety, but can't return an array + const rgbColor& getTextColor() const; + xColor getTextColorX() const; - void setTextColor(const rgbColor& value) { memcpy(_textColor, value, sizeof(_textColor)); } - void setTextColor(const xColor& value) { - _textColor[RED_INDEX] = value.red; - _textColor[GREEN_INDEX] = value.green; - _textColor[BLUE_INDEX] = value.blue; - } + void setTextColor(const rgbColor& value); + void setTextColor(const xColor& value); static const xColor DEFAULT_BACKGROUND_COLOR; - const rgbColor& getBackgroundColor() const { return _backgroundColor; } - xColor getBackgroundColorX() const { xColor color = { _backgroundColor[RED_INDEX], _backgroundColor[GREEN_INDEX], _backgroundColor[BLUE_INDEX] }; return color; } + // FIXME should not return a reference because of thread safety, but can't return an array + const rgbColor& getBackgroundColor() const; + xColor getBackgroundColorX() const; - void setBackgroundColor(const rgbColor& value) { memcpy(_backgroundColor, value, sizeof(_backgroundColor)); } - void setBackgroundColor(const xColor& value) { - _backgroundColor[RED_INDEX] = value.red; - _backgroundColor[GREEN_INDEX] = value.green; - _backgroundColor[BLUE_INDEX] = value.blue; - } + void setBackgroundColor(const rgbColor& value); + void setBackgroundColor(const xColor& value); static const bool DEFAULT_FACE_CAMERA; - bool getFaceCamera() const { return _faceCamera; } - void setFaceCamera(bool value) { _faceCamera = value; } + bool getFaceCamera() const; + void setFaceCamera(bool value); protected: QString _text; From 03c6275268fa32e2806afad7f8356d035a61b241 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 3 Apr 2017 08:44:27 -0700 Subject: [PATCH 02/46] more thread safety --- libraries/entities/src/EntityItem.cpp | 43 ++++--- libraries/entities/src/EntityItem.h | 3 +- libraries/entities/src/LightEntityItem.cpp | 140 ++++++++++++++++++--- libraries/entities/src/LightEntityItem.h | 2 +- libraries/entities/src/LineEntityItem.cpp | 61 ++++++++- libraries/entities/src/LineEntityItem.h | 20 ++- libraries/entities/src/ModelEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.h | 2 +- 8 files changed, 216 insertions(+), 57 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 9ba740728b..891196862a 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -683,7 +683,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // However, for now, when the server uses a newer time than what we sent, listen to what we're told. if (overwriteLocalData) weOwnSimulation = false; } else if (_simulationOwner.set(newSimOwner)) { - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); somethingChanged = true; // recompute weOwnSimulation for later weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); @@ -695,19 +695,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef weOwnSimulation = true; if (!_simulationOwner.isNull()) { // someone else really did own it - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); somethingChanged = true; _simulationOwner.clearCurrentOwner(); } } else if (newSimOwner.matchesValidID(myNodeID) && !_hasBidOnSimulation) { // entity-server tells us that we have simulation ownership while we never requested this for this EntityItem, // this could happen when the user reloads the cache and entity tree. - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); somethingChanged = true; _simulationOwner.clearCurrentOwner(); weOwnSimulation = false; } else if (_simulationOwner.set(newSimOwner)) { - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); somethingChanged = true; // recompute weOwnSimulation for later weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); @@ -994,7 +994,7 @@ SharedSoundPointer EntityItem::getCollisionSound() { } void EntityItem::simulate(const quint64& now) { - if (0 == getLastSimulated()) { + if (getLastSimulated() == 0) { setLastSimulated(now); } @@ -1042,7 +1042,7 @@ void EntityItem::simulate(const quint64& now) { if (!stepKinematicMotion(timeElapsed)) { // this entity is no longer moving // flag it to transition from KINEMATIC to STATIC - _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; + markDirtyFlags(Simulation::DIRTY_MOTION_TYPE); setAcceleration(Vectors::ZERO); } setLastSimulated(now); @@ -1294,7 +1294,7 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c } void EntityItem::pokeSimulationOwnership() { - _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE; + markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_POKE); auto nodeList = DependencyManager::get(); if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { // we already own it @@ -1306,7 +1306,7 @@ void EntityItem::pokeSimulationOwnership() { } void EntityItem::grabSimulationOwnership() { - _dirtyFlags |= Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB; + markDirtyFlags(Simulation::DIRTY_SIMULATION_OWNERSHIP_FOR_GRAB); auto nodeList = DependencyManager::get(); if (_simulationOwner.matchesValidID(nodeList->getSessionUUID())) { // we already own it @@ -1599,18 +1599,18 @@ float EntityItem::getVolumeEstimate() const { void EntityItem::updateRegistrationPoint(const glm::vec3& value) { if (value != _registrationPoint) { setRegistrationPoint(value); - _dirtyFlags |= Simulation::DIRTY_SHAPE; + markDirtyFlags(Simulation::DIRTY_SHAPE); } } void EntityItem::updatePosition(const glm::vec3& value) { if (getLocalPosition() != value) { setLocalPosition(value); - _dirtyFlags |= Simulation::DIRTY_POSITION; + markDirtyFlags(Simulation::DIRTY_POSITION); forEachDescendant([&](SpatiallyNestablePointer object) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); - entity->_dirtyFlags |= Simulation::DIRTY_POSITION; + entity->markDirtyFlags(Simulation::DIRTY_POSITION); } }); } @@ -1619,8 +1619,9 @@ void EntityItem::updatePosition(const glm::vec3& value) { void EntityItem::updateParentID(const QUuid& value) { if (getParentID() != value) { setParentID(value); - _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; // children are forced to be kinematic - _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar + // children are forced to be kinematic + // may need to not collide with own avatar + markDirtyFlags(Simulation::DIRTY_MOTION_TYPE | Simulation::DIRTY_COLLISION_GROUP); } } @@ -1634,7 +1635,7 @@ void EntityItem::updatePositionFromNetwork(const glm::vec3& value) { void EntityItem::updateDimensions(const glm::vec3& value) { if (getDimensions() != value) { setDimensions(value); - _dirtyFlags |= (Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); + markDirtyFlags(Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS); } } @@ -1645,8 +1646,7 @@ void EntityItem::updateRotation(const glm::quat& rotation) { forEachDescendant([&](SpatiallyNestablePointer object) { if (object->getNestableType() == NestableType::Entity) { EntityItemPointer entity = std::static_pointer_cast(object); - entity->_dirtyFlags |= Simulation::DIRTY_ROTATION; - entity->_dirtyFlags |= Simulation::DIRTY_POSITION; + entity->markDirtyFlags(Simulation::DIRTY_ROTATION | Simulation::DIRTY_POSITION); } }); } @@ -1913,7 +1913,7 @@ void EntityItem::updateSimulationOwner(const SimulationOwner& owner) { } if (_simulationOwner.set(owner)) { - _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); } } @@ -1926,7 +1926,7 @@ void EntityItem::clearSimulationOwnership() { // don't bother setting the DIRTY_SIMULATOR_ID flag because: // (a) when entity-server calls clearSimulationOwnership() the dirty-flags are meaningless (only used by interface) // (b) the interface only calls clearSimulationOwnership() in a context that already knows best about dirty flags - //_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; + //markDirtyFlags(Simulation::DIRTY_SIMULATOR_ID); } @@ -2776,6 +2776,13 @@ uint32_t EntityItem::getDirtyFlags() const { return result; } + +void EntityItem::markDirtyFlags(uint32_t mask) { + withWriteLock([&] { + _dirtyFlags |= mask; + }); +} + void EntityItem::clearDirtyFlags(uint32_t mask) { withWriteLock([&] { _dirtyFlags &= ~mask; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 929fe8a698..e705fcbe2a 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -367,6 +367,7 @@ public: virtual void setShapeType(ShapeType type) { /* do nothing */ } uint32_t getDirtyFlags() const; + void markDirtyFlags(uint32_t mask); void clearDirtyFlags(uint32_t mask = 0xffffffff); bool isMoving() const; @@ -509,7 +510,7 @@ protected: // NOTE: _volumeMultiplier is used to allow some mass properties code exist in the EntityItem base class // rather than in all of the derived classes. If we ever collapse these classes to one we could do it a // different way. - float _volumeMultiplier { 1.0f }; + const float _volumeMultiplier { 1.0f }; glm::vec3 _gravity; glm::vec3 _acceleration; float _damping; diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index e09822f028..753ff1d3c8 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -69,38 +69,59 @@ EntityItemProperties LightEntityItem::getProperties(EntityPropertyFlags desiredP } void LightEntityItem::setFalloffRadius(float value) { - _falloffRadius = glm::max(value, 0.0f); - _lightPropertiesChanged = true; + value = glm::max(value, 0.0f); + if (value == getFalloffRadius()) { + return; + } + withWriteLock([&] { + _falloffRadius = value; + _lightPropertiesChanged = true; + }); } void LightEntityItem::setIsSpotlight(bool value) { - if (value != _isSpotlight) { - _isSpotlight = value; - - glm::vec3 dimensions = getDimensions(); - if (_isSpotlight) { - const float length = dimensions.z; - const float width = length * glm::sin(glm::radians(_cutoff)); - setDimensions(glm::vec3(width, width, length)); - } else { - float maxDimension = glm::compMax(dimensions); - setDimensions(glm::vec3(maxDimension, maxDimension, maxDimension)); - } - _lightPropertiesChanged = true; + if (value == getIsSpotlight()) { + return; } + + glm::vec3 dimensions = getDimensions(); + glm::vec3 newDimensions; + if (value) { + const float length = dimensions.z; + const float width = length * glm::sin(glm::radians(getCutoff())); + newDimensions = glm::vec3(width, width, length); + } else { + newDimensions = glm::vec3(glm::compMax(dimensions)); + } + + withWriteLock([&] { + _isSpotlight = value; + _lightPropertiesChanged = true; + }); + setDimensions(newDimensions); } void LightEntityItem::setCutoff(float value) { - _cutoff = glm::clamp(value, 0.0f, 90.0f); + value = glm::clamp(value, 0.0f, 90.0f); + if (value == getCutoff()) { + return; + } - if (_isSpotlight) { + withWriteLock([&] { + _cutoff = value; + }); + + if (getIsSpotlight()) { // If we are a spotlight, adjusting the cutoff will affect the area we encapsulate, // so update the dimensions to reflect this. const float length = getDimensions().z; const float width = length * glm::sin(glm::radians(_cutoff)); setDimensions(glm::vec3(width, width, length)); } - _lightPropertiesChanged = true; + + withWriteLock([&] { + _lightPropertiesChanged = true; + }); } bool LightEntityItem::setProperties(const EntityItemProperties& properties) { @@ -205,5 +226,86 @@ void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit void LightEntityItem::somethingChangedNotification() { EntityItem::somethingChangedNotification(); - _lightPropertiesChanged = false; + withWriteLock([&] { + _lightPropertiesChanged = false; + }); } + +const rgbColor& LightEntityItem::getColor() const { + return _color; +} + +xColor LightEntityItem::getXColor() const { + xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; +} + +void LightEntityItem::setColor(const rgbColor& value) { + withWriteLock([&] { + memcpy(_color, value, sizeof(_color)); + _lightPropertiesChanged = true; + }); +} + +void LightEntityItem::setColor(const xColor& value) { + withWriteLock([&] { + _color[RED_INDEX] = value.red; + _color[GREEN_INDEX] = value.green; + _color[BLUE_INDEX] = value.blue; + _lightPropertiesChanged = true; + }); +} + +bool LightEntityItem::getIsSpotlight() const { + bool result; + withReadLock([&] { + result = _isSpotlight; + }); + return result; +} + +float LightEntityItem::getIntensity() const { + float result; + withReadLock([&] { + result = _intensity; + }); + return result; +} + +void LightEntityItem::setIntensity(float value) { + withWriteLock([&] { + _intensity = value; + _lightPropertiesChanged = true; + }); +} + +float LightEntityItem::getFalloffRadius() const { + float result; + withReadLock([&] { + result = _falloffRadius; + }); + return result; +} + +float LightEntityItem::getExponent() const { + float result; + withReadLock([&] { + result = _exponent; + }); + return result; +} + +void LightEntityItem::setExponent(float value) { + withWriteLock([&] { + _exponent = value; + _lightPropertiesChanged = true; + }); +} + +float LightEntityItem::getCutoff() const { + float result; + withReadLock([&] { + result = _cutoff; + }); + return result; +} + diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 3444b11cae..f0ed58f47a 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -97,7 +97,7 @@ public: static bool getLightsArePickable() { return _lightsArePickable; } static void setLightsArePickable(bool value) { _lightsArePickable = value; } -protected: +private: // properties of a light diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 8ace665616..fe2c803f43 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -88,8 +88,10 @@ bool LineEntityItem::appendPoint(const glm::vec3& point) { qCDebug(entities) << "Point is outside entity's bounding box"; return false; } - _points << point; - _pointsChanged = true; + withWriteLock([&] { + _points << point; + _pointsChanged = true; + }); return true; } @@ -105,8 +107,11 @@ bool LineEntityItem::setLinePoints(const QVector& points) { return false; } } - _points = points; - _pointsChanged = true; + + withWriteLock([&] { + _points = points; + _pointsChanged = true; + }); return true; } @@ -159,3 +164,51 @@ void LineEntityItem::debugDump() const { qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } + +const rgbColor& LineEntityItem::getColor() const { + return _color; +} + +xColor LineEntityItem::getXColor() const { + xColor result; + withReadLock([&] { + result = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; + }); + return result; +} + +void LineEntityItem::setColor(const rgbColor& value) { + withWriteLock([&] { + memcpy(_color, value, sizeof(_color)); + }); +} + +void LineEntityItem::setColor(const xColor& value) { + withWriteLock([&] { + _color[RED_INDEX] = value.red; + _color[GREEN_INDEX] = value.green; + _color[BLUE_INDEX] = value.blue; + }); +} + +void LineEntityItem::setLineWidth(float lineWidth) { + withWriteLock([&] { + _lineWidth = lineWidth; + }); +} + +float LineEntityItem::getLineWidth() const { + float result; + withReadLock([&] { + result = _lineWidth; + }); + return result; +} + +QVector LineEntityItem::getLinePoints() const { + QVector result; + withReadLock([&] { + result = _points; + }); + return result; +} diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 8629c94eb4..7a882f6b9d 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -42,23 +42,19 @@ class LineEntityItem : public EntityItem { EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - const rgbColor& getColor() const { return _color; } - xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } + const rgbColor& getColor() const; + xColor getXColor() const; - void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } - void setColor(const xColor& value) { - _color[RED_INDEX] = value.red; - _color[GREEN_INDEX] = value.green; - _color[BLUE_INDEX] = value.blue; - } + void setColor(const rgbColor& value); + void setColor(const xColor& value); - void setLineWidth(float lineWidth){ _lineWidth = lineWidth; } - float getLineWidth() const{ return _lineWidth; } + void setLineWidth(float lineWidth); + float getLineWidth() const; bool setLinePoints(const QVector& points); bool appendPoint(const glm::vec3& point); - const QVector& getLinePoints() const{ return _points; } + QVector getLinePoints() const; virtual ShapeType getShapeType() const override { return SHAPE_TYPE_NONE; } @@ -74,7 +70,7 @@ class LineEntityItem : public EntityItem { static const float DEFAULT_LINE_WIDTH; static const int MAX_POINTS_PER_LINE; - protected: + private: rgbColor _color; float _lineWidth; bool _pointsChanged; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index e1cb5cd92c..972bf1e18d 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -130,7 +130,7 @@ private: void setAnimationSettings(const QString& value); // only called for old bitstream format ShapeType computeTrueShapeType() const; -protected: +private: // these are used: // - to bounce joint data from an animation into the model/rig. // - to relay changes from scripts to model/rig. diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 4e49bb8ef0..ee421d567a 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -80,7 +80,7 @@ public: bool getFaceCamera() const; void setFaceCamera(bool value); -protected: +private: QString _text; float _lineHeight; rgbColor _textColor; From d89104f69ca3f68ae44236f81f1ea126a0b5dfe4 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 3 Apr 2017 14:22:00 -0700 Subject: [PATCH 03/46] Use getters instead of direct member access --- .../src/RenderableModelEntityItem.cpp | 27 ++++++++++--------- .../src/RenderableTextEntityItem.cpp | 8 +++--- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 487a3e1e56..06b79bb6a2 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -277,10 +277,11 @@ bool RenderableModelEntityItem::getAnimationFrame() { return false; } - if (_animation && _animation->isLoaded()) { + auto animation = getAnimation(); + if (animation && animation->isLoaded()) { - const QVector& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy - auto& fbxJoints = _animation->getGeometry().joints; + const QVector& frames = animation->getFramesReference(); // NOTE: getFrames() is too heavy + auto& fbxJoints = animation->getGeometry().joints; int frameCount = frames.size(); if (frameCount > 0) { @@ -566,7 +567,7 @@ void RenderableModelEntityItem::update(const quint64& now) { } // make a copy of the animation properites - _renderAnimationProperties = _animationProperties; + _renderAnimationProperties = getAnimationProperties(); ModelEntityItem::update(now); } @@ -608,11 +609,11 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori void RenderableModelEntityItem::setShapeType(ShapeType type) { ModelEntityItem::setShapeType(type); - if (_shapeType == SHAPE_TYPE_COMPOUND) { - if (!_compoundShapeResource && !_compoundShapeURL.isEmpty()) { + if (getShapeType() == SHAPE_TYPE_COMPOUND) { + if (!_compoundShapeResource && !getCompoundShapeURL().isEmpty()) { _compoundShapeResource = DependencyManager::get()->getGeometryResource(getCompoundShapeURL()); } - } else if (_compoundShapeResource && !_compoundShapeURL.isEmpty()) { + } else if (_compoundShapeResource && !getCompoundShapeURL().isEmpty()) { // the compoundURL has been set but the shapeType does not agree _compoundShapeResource.reset(); } @@ -627,7 +628,7 @@ void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) { if (tree) { QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); } - if (_shapeType == SHAPE_TYPE_COMPOUND) { + if (getShapeType() == SHAPE_TYPE_COMPOUND) { _compoundShapeResource = DependencyManager::get()->getGeometryResource(url); } } @@ -637,7 +638,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { ShapeType type = getShapeType(); if (type == SHAPE_TYPE_COMPOUND) { - if (!_model || _compoundShapeURL.isEmpty()) { + if (!_model || getCompoundShapeURL().isEmpty()) { EntityTreePointer tree = getTree(); if (tree) { QMetaObject::invokeMethod(tree.get(), "callLoader", Qt::QueuedConnection, Q_ARG(EntityItemID, getID())); @@ -659,8 +660,8 @@ bool RenderableModelEntityItem::isReadyToComputeShape() { doInitialModelSimulation(); } return true; - } else if (!_compoundShapeURL.isEmpty()) { - _compoundShapeResource = DependencyManager::get()->getGeometryResource(_compoundShapeURL); + } else if (!getCompoundShapeURL().isEmpty()) { + _compoundShapeResource = DependencyManager::get()->getGeometryResource(getCompoundShapeURL()); } } @@ -775,7 +776,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { pointCollection[i][j] = scaleToFit * (pointCollection[i][j] + _model->getOffset()) - registrationOffset; } } - shapeInfo.setParams(type, dimensions, _compoundShapeURL); + shapeInfo.setParams(type, dimensions, getCompoundShapeURL()); } else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) { // should never fall in here when model not fully loaded assert(_model && _model->isLoaded()); @@ -1001,7 +1002,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { } } - shapeInfo.setParams(type, 0.5f * dimensions, _modelURL); + shapeInfo.setParams(type, 0.5f * dimensions, getModelURL()); } else { ModelEntityItem::computeShapeInfo(shapeInfo); shapeInfo.setParams(type, 0.5f * dimensions); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 9c98e699f1..a58ed8bbff 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -77,14 +77,16 @@ void RenderableTextEntityItem::render(RenderArgs* args) { geometryCache->bindSimpleProgram(batch, false, transparent, false, false, true); geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID); - float scale = _lineHeight / _textRenderer->getFontSize(); + float lineheight = getLineHeight(); + float scale = lineheight / _textRenderer->getFontSize(); transformToTopLeft.setScale(scale); // Scale to have the correct line height batch.setModelTransform(transformToTopLeft); - float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight; + float leftMargin = 0.1f * lineheight, topMargin = 0.1f * lineheight; glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin, dimensions.y - 2.0f * topMargin); - _textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, _text, textColor, bounds / scale); + auto text = getText(); + _textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, text, textColor, bounds / scale); } From fe84232ab459765041b141b7f458862b0bfd9dac Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 3 Apr 2017 14:22:37 -0700 Subject: [PATCH 04/46] More work on thread safety --- libraries/entities/src/EntityItem.h | 2 +- libraries/entities/src/LightEntityItem.h | 37 ++++++++---------------- libraries/entities/src/LineEntityItem.h | 3 +- libraries/entities/src/ModelEntityItem.h | 2 +- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index e705fcbe2a..a751fd88b2 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -510,7 +510,7 @@ protected: // NOTE: _volumeMultiplier is used to allow some mass properties code exist in the EntityItem base class // rather than in all of the derived classes. If we ever collapse these classes to one we could do it a // different way. - const float _volumeMultiplier { 1.0f }; + float _volumeMultiplier { 1.0f }; glm::vec3 _gravity; glm::vec3 _acceleration; float _damping; diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index f0ed58f47a..b3cadcf0c7 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -57,41 +57,27 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - const rgbColor& getColor() const { return _color; } - xColor getXColor() const { - xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; - } + const rgbColor& getColor() const; + xColor getXColor() const; - void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } - void setColor(const xColor& value) { - _color[RED_INDEX] = value.red; - _color[GREEN_INDEX] = value.green; - _color[BLUE_INDEX] = value.blue; - _lightPropertiesChanged = true; - } + void setColor(const rgbColor& value); + void setColor(const xColor& value); - bool getIsSpotlight() const { return _isSpotlight; } + bool getIsSpotlight() const; void setIsSpotlight(bool value); void setIgnoredColor(const rgbColor& value) { } void setIgnoredAttenuation(float value) { } - float getIntensity() const { return _intensity; } - void setIntensity(float value) { - _intensity = value; - _lightPropertiesChanged = true; - } - - float getFalloffRadius() const { return _falloffRadius; } + float getIntensity() const; + void setIntensity(float value); + float getFalloffRadius() const; void setFalloffRadius(float value); - float getExponent() const { return _exponent; } - void setExponent(float value) { - _exponent = value; - _lightPropertiesChanged = true; - } + float getExponent() const; + void setExponent(float value); - float getCutoff() const { return _cutoff; } + float getCutoff() const; void setCutoff(float value); static bool getLightsArePickable() { return _lightsArePickable; } @@ -108,6 +94,7 @@ private: float _exponent { DEFAULT_EXPONENT }; float _cutoff { DEFAULT_CUTOFF }; +protected: // Dirty flag turn true when either light properties is changing values. // This gets back to false in the somethingChangedNotification() call // Which is called after a setProperties() or a readEntitySubClassFromBUfferCall on the entity. diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 7a882f6b9d..bb8ae8a21a 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -73,8 +73,9 @@ class LineEntityItem : public EntityItem { private: rgbColor _color; float _lineWidth; - bool _pointsChanged; QVector _points; +protected: + bool _pointsChanged; }; #endif // hifi_LineEntityItem_h diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 972bf1e18d..e1cb5cd92c 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -130,7 +130,7 @@ private: void setAnimationSettings(const QString& value); // only called for old bitstream format ShapeType computeTrueShapeType() const; -private: +protected: // these are used: // - to bounce joint data from an animation into the model/rig. // - to relay changes from scripts to model/rig. From a0f0879087a8799cb619b36c2dd9032d991016e6 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 10 Mar 2017 18:16:38 -0800 Subject: [PATCH 05/46] added file type filter and interceptor --- interface/resources/qml/controls/WebView.qml | 4 +- interface/resources/qml/hifi/Desktop.qml | 4 +- interface/src/Application.cpp | 2 + interface/src/networking/FileTypeProfile.cpp | 26 +++++++++ interface/src/networking/FileTypeProfile.h | 25 ++++++++ .../networking/FileTypeRequestInterceptor.cpp | 22 +++++++ .../networking/FileTypeRequestInterceptor.h | 26 +++++++++ .../HFWebEngineRequestInterceptor.cpp | 27 +-------- interface/src/networking/RequestFilters.cpp | 58 +++++++++++++++++++ interface/src/networking/RequestFilters.h | 28 +++++++++ 10 files changed, 194 insertions(+), 28 deletions(-) create mode 100644 interface/src/networking/FileTypeProfile.cpp create mode 100644 interface/src/networking/FileTypeProfile.h create mode 100644 interface/src/networking/FileTypeRequestInterceptor.cpp create mode 100644 interface/src/networking/FileTypeRequestInterceptor.h create mode 100644 interface/src/networking/RequestFilters.cpp create mode 100644 interface/src/networking/RequestFilters.h diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index a3badd7e1f..d3e1d97d1a 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -2,7 +2,7 @@ import QtQuick 2.5 import QtWebEngine 1.1 import QtWebChannel 1.0 import "../controls-uit" as HiFiControls -import HFWebEngineProfile 1.0 +import FileTypeProfile 1.0 Item { property alias url: root.url @@ -36,7 +36,7 @@ Item { width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - profile: HFWebEngineProfile { + profile: FileTypeProfile { id: webviewProfile storageName: "qmlWebEngine" } diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index 7857eda3c2..cd66b014a4 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -2,7 +2,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtWebEngine 1.1; import Qt.labs.settings 1.0 -import HFWebEngineProfile 1.0 +import FileTypeProfile 1.0 import "../desktop" as OriginalDesktop import ".." @@ -27,7 +27,7 @@ OriginalDesktop.Desktop { property alias toolWindow: toolWindow ToolWindow { id: toolWindow } - property var browserProfile: HFWebEngineProfile { + property var browserProfile: FileTypeProfile { id: webviewProfile storageName: "qmlWebEngine" } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e19eea0a2e..aa33b66962 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -142,6 +142,7 @@ #include "ModelPackager.h" #include "networking/HFWebEngineProfile.h" #include "networking/HFTabletWebEngineProfile.h" +#include "networking/FileTypeProfile.h" #include "scripting/TestScriptingInterface.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AssetMappingsScriptingInterface.h" @@ -1934,6 +1935,7 @@ void Application::initializeUi() { qmlRegisterType("HFWebEngineProfile", 1, 0, "HFWebEngineProfile"); qmlRegisterType("HFTabletWebEngineProfile", 1, 0, "HFTabletWebEngineProfile"); + qmlRegisterType("FileTypeProfile", 1, 0, "FileTypeProfile"); auto offscreenUi = DependencyManager::get(); offscreenUi->create(_glWidget->qglContext()); diff --git a/interface/src/networking/FileTypeProfile.cpp b/interface/src/networking/FileTypeProfile.cpp new file mode 100644 index 0000000000..2048751e5d --- /dev/null +++ b/interface/src/networking/FileTypeProfile.cpp @@ -0,0 +1,26 @@ +// +// FileTypeProfile.cpp +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#include "FileTypeProfile.h" + +#include "FileTypeRequestInterceptor.h" + +static const QString QML_WEB_ENGINE_STORAGE_NAME = "qmlWebEngine"; + +FileTypeProfile::FileTypeProfile(QObject* parent) : + QQuickWebEngineProfile(parent) +{ + static const QString WEB_ENGINE_USER_AGENT = "Chrome/48.0 (HighFidelityInterface)"; + setHttpUserAgent(WEB_ENGINE_USER_AGENT); + + auto requestInterceptor = new FileTypeRequestInterceptor(this); + setRequestInterceptor(requestInterceptor); +} \ No newline at end of file diff --git a/interface/src/networking/FileTypeProfile.h b/interface/src/networking/FileTypeProfile.h new file mode 100644 index 0000000000..99ed5d4b79 --- /dev/null +++ b/interface/src/networking/FileTypeProfile.h @@ -0,0 +1,25 @@ +// +// FileTypeProfile.h +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#pragma once + +#ifndef hifi_FileTypeProfile_h +#define hifi_FileTypeProfile_h + +#include + +class FileTypeProfile : public QQuickWebEngineProfile { +public: + FileTypeProfile(QObject* parent = Q_NULLPTR); +}; + + +#endif // hifi_FileTypeProfile_h \ No newline at end of file diff --git a/interface/src/networking/FileTypeRequestInterceptor.cpp b/interface/src/networking/FileTypeRequestInterceptor.cpp new file mode 100644 index 0000000000..2dac5db194 --- /dev/null +++ b/interface/src/networking/FileTypeRequestInterceptor.cpp @@ -0,0 +1,22 @@ +// +// FileTypeRequestInterceptor.cpp +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#include "FileTypeRequestInterceptor.h" + +#include + +#include "RequestFilters.h" + +void FileTypeRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { + RequestFilters* filter = new RequestFilters; + filter->interceptHFWebEngineRequest(info); + filter->interceptFileType(info); +} diff --git a/interface/src/networking/FileTypeRequestInterceptor.h b/interface/src/networking/FileTypeRequestInterceptor.h new file mode 100644 index 0000000000..c39c860b7c --- /dev/null +++ b/interface/src/networking/FileTypeRequestInterceptor.h @@ -0,0 +1,26 @@ +// +// FileTypeRequestInterceptor.h +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#pragma once + +#ifndef hifi_FileTypeRequestInterceptor_h +#define hifi_FileTypeRequestInterceptor_h + +#include + +class FileTypeRequestInterceptor : public QWebEngineUrlRequestInterceptor { +public: + FileTypeRequestInterceptor(QObject* parent) : QWebEngineUrlRequestInterceptor(parent) {}; + + virtual void interceptRequest(QWebEngineUrlRequestInfo& info) override; +}; + +#endif // hifi_FileTypeRequestInterceptor_h \ No newline at end of file diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.cpp b/interface/src/networking/HFWebEngineRequestInterceptor.cpp index f6b0914f08..400d547d92 100644 --- a/interface/src/networking/HFWebEngineRequestInterceptor.cpp +++ b/interface/src/networking/HFWebEngineRequestInterceptor.cpp @@ -15,30 +15,9 @@ #include #include - -bool isAuthableHighFidelityURL(const QUrl& url) { - static const QStringList HF_HOSTS = { - "highfidelity.com", "highfidelity.io", - "metaverse.highfidelity.com", "metaverse.highfidelity.io" - }; - const auto& scheme = url.scheme(); - const auto& host = url.host(); - - return (scheme == "https" && HF_HOSTS.contains(host)) || - ((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host())); -} +#include "RequestFilters.h" void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - // check if this is a request to a highfidelity URL - if (isAuthableHighFidelityURL(info.requestUrl())) { - // if we have an access token, add it to the right HTTP header for authorization - auto accountManager = DependencyManager::get(); - - if (accountManager->hasValidAccessToken()) { - static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization"; - - QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token; - info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit()); - } - } + RequestFilters* filter = new RequestFilters; + filter->interceptHFWebEngineRequest(info); } diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp new file mode 100644 index 0000000000..65845504c0 --- /dev/null +++ b/interface/src/networking/RequestFilters.cpp @@ -0,0 +1,58 @@ +// +// RequestFilters.cpp +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#include "RequestFilters.h" + +#include + +#include + +bool isAuthableHighFidelityURL(const QUrl& url) { + static const QStringList HF_HOSTS = { + "highfidelity.com", "highfidelity.io", + "metaverse.highfidelity.com", "metaverse.highfidelity.io" + }; + + return url.scheme() == "https" && HF_HOSTS.contains(url.host()); +} + +bool isJavaScriptFile(const QString filename) { + return filename.contains(".js", Qt::CaseInsensitive); +} + +bool isEntityFile(const QString filename) { + return filename.contains(".svo.json", Qt::CaseInsensitive); +} + +void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) { + // check if this is a request to a highfidelity URL + if (isAuthableHighFidelityURL(info.requestUrl())) { + // if we have an access token, add it to the right HTTP header for authorization + auto accountManager = DependencyManager::get(); + + if (accountManager->hasValidAccessToken()) { + static const QString OAUTH_AUTHORIZATION_HEADER = "Authorization"; + + QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token; + info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit()); + } + } +} + +void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { + QString filename = info.requestUrl().fileName(); + + if (isJavaScriptFile(filename) || isEntityFile(filename)) { + static const QString CONTENT_HEADER = "Content-Type"; + static const QString HEADER_VALUE = "text/plain"; + info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), HEADER_VALUE.toLocal8Bit()); + } +} \ No newline at end of file diff --git a/interface/src/networking/RequestFilters.h b/interface/src/networking/RequestFilters.h new file mode 100644 index 0000000000..ab20a267e0 --- /dev/null +++ b/interface/src/networking/RequestFilters.h @@ -0,0 +1,28 @@ +// +// RequestFilters.h +// interface/src/networking +// +// Created by Kunal Gosar on 2017-03-10. +// 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 +// + +#pragma once + +#ifndef hifi_RequestFilters_h +#define hifi_RequestFilters_h + +#include +#include + +class RequestFilters : public QObject { + Q_OBJECT + +public: + void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info); + void interceptFileType(QWebEngineUrlRequestInfo& info); +}; + +#endif // hifi_RequestFilters_h \ No newline at end of file From 9b758dbdba32d31e1ecda5f08b202c37b2463d84 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 10 Mar 2017 18:45:25 -0800 Subject: [PATCH 06/46] updated headers --- interface/src/networking/RequestFilters.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 65845504c0..5a29b58da9 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -51,8 +51,11 @@ void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { QString filename = info.requestUrl().fileName(); if (isJavaScriptFile(filename) || isEntityFile(filename)) { - static const QString CONTENT_HEADER = "Content-Type"; - static const QString HEADER_VALUE = "text/plain"; - info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), HEADER_VALUE.toLocal8Bit()); + static const QString CONTENT_HEADER = "Accept"; + static const QString TYPE_VALUE = "text/html"; + info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit()); + static const QString CONTENT_DISPOSITION = "Content-Disposition"; + static const QString DISPOSITION_VALUE = "inline"; + info.setHttpHeader(CONTENT_DISPOSITION.toLocal8Bit(), DISPOSITION_VALUE.toLocal8Bit()); } } \ No newline at end of file From 19ab7526d35f9863e84d8602d9141779986c8030 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Thu, 16 Mar 2017 17:54:42 -0700 Subject: [PATCH 07/46] apply profile to relevant entities --- interface/resources/qml/Browser.qml | 6 ++++++ .../resources/qml/controls/WebEntityView.qml | 20 +++++++++++++++++++ interface/resources/qml/controls/WebView.qml | 6 ++++-- interface/resources/qml/hifi/Desktop.qml | 4 ++-- interface/src/networking/FileTypeProfile.cpp | 2 +- interface/src/networking/FileTypeProfile.h | 2 +- .../networking/FileTypeRequestInterceptor.h | 2 +- interface/src/networking/RequestFilters.cpp | 8 ++------ interface/src/networking/RequestFilters.h | 2 +- .../src/RenderableWebEntityItem.cpp | 2 +- 10 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 interface/resources/qml/controls/WebEntityView.qml diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index c4e0c85642..47fb610469 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -2,6 +2,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.2 import QtWebChannel 1.0 import QtWebEngine 1.2 +import FileTypeProfile 1.0 import "controls-uit" import "styles" as HifiStyles @@ -216,6 +217,11 @@ ScrollingWindow { WebChannel.id: "eventBridgeWrapper" property var eventBridge; } + + profile: FileTypeProfile { + id: webviewProfile + storageName: "qmlWebEngine" + } webChannel.registeredObjects: [eventBridgeWrapper] diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml new file mode 100644 index 0000000000..961ebffb38 --- /dev/null +++ b/interface/resources/qml/controls/WebEntityView.qml @@ -0,0 +1,20 @@ +// +// WebEntityView.qml +// +// Created by Kunal Gosar on 16 March 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 +// + +import QtQuick 2.5 +import "." +import FileTypeProfile 1.0 + +WebView { + viewProfile: FileTypeProfile { + id: webviewProfile + storageName: "qmlWebEngine" + } +} diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index d3e1d97d1a..8c73eddcc2 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -2,7 +2,7 @@ import QtQuick 2.5 import QtWebEngine 1.1 import QtWebChannel 1.0 import "../controls-uit" as HiFiControls -import FileTypeProfile 1.0 +import HFWebEngineProfile 1.0 Item { property alias url: root.url @@ -27,6 +27,8 @@ Item { WebChannel.id: "eventBridgeWrapper" property var eventBridge; } + + property alias viewProfile: root.profile WebEngineView { id: root @@ -36,7 +38,7 @@ Item { width: parent.width height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height : parent.height - profile: FileTypeProfile { + profile: HFWebEngineProfile { id: webviewProfile storageName: "qmlWebEngine" } diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index cd66b014a4..7857eda3c2 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -2,7 +2,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtWebEngine 1.1; import Qt.labs.settings 1.0 -import FileTypeProfile 1.0 +import HFWebEngineProfile 1.0 import "../desktop" as OriginalDesktop import ".." @@ -27,7 +27,7 @@ OriginalDesktop.Desktop { property alias toolWindow: toolWindow ToolWindow { id: toolWindow } - property var browserProfile: FileTypeProfile { + property var browserProfile: HFWebEngineProfile { id: webviewProfile storageName: "qmlWebEngine" } diff --git a/interface/src/networking/FileTypeProfile.cpp b/interface/src/networking/FileTypeProfile.cpp index 2048751e5d..6fcd8df669 100644 --- a/interface/src/networking/FileTypeProfile.cpp +++ b/interface/src/networking/FileTypeProfile.cpp @@ -23,4 +23,4 @@ FileTypeProfile::FileTypeProfile(QObject* parent) : auto requestInterceptor = new FileTypeRequestInterceptor(this); setRequestInterceptor(requestInterceptor); -} \ No newline at end of file +} diff --git a/interface/src/networking/FileTypeProfile.h b/interface/src/networking/FileTypeProfile.h index 99ed5d4b79..f922fd66de 100644 --- a/interface/src/networking/FileTypeProfile.h +++ b/interface/src/networking/FileTypeProfile.h @@ -22,4 +22,4 @@ public: }; -#endif // hifi_FileTypeProfile_h \ No newline at end of file +#endif // hifi_FileTypeProfile_h diff --git a/interface/src/networking/FileTypeRequestInterceptor.h b/interface/src/networking/FileTypeRequestInterceptor.h index c39c860b7c..be971daf7a 100644 --- a/interface/src/networking/FileTypeRequestInterceptor.h +++ b/interface/src/networking/FileTypeRequestInterceptor.h @@ -23,4 +23,4 @@ public: virtual void interceptRequest(QWebEngineUrlRequestInfo& info) override; }; -#endif // hifi_FileTypeRequestInterceptor_h \ No newline at end of file +#endif // hifi_FileTypeRequestInterceptor_h diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 5a29b58da9..0f59258b66 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -49,13 +49,9 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { QString filename = info.requestUrl().fileName(); - if (isJavaScriptFile(filename) || isEntityFile(filename)) { static const QString CONTENT_HEADER = "Accept"; - static const QString TYPE_VALUE = "text/html"; + static const QString TYPE_VALUE = "text/plain"; info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit()); - static const QString CONTENT_DISPOSITION = "Content-Disposition"; - static const QString DISPOSITION_VALUE = "inline"; - info.setHttpHeader(CONTENT_DISPOSITION.toLocal8Bit(), DISPOSITION_VALUE.toLocal8Bit()); } -} \ No newline at end of file +} diff --git a/interface/src/networking/RequestFilters.h b/interface/src/networking/RequestFilters.h index ab20a267e0..d61208a22d 100644 --- a/interface/src/networking/RequestFilters.h +++ b/interface/src/networking/RequestFilters.h @@ -25,4 +25,4 @@ public: void interceptFileType(QWebEngineUrlRequestInfo& info); }; -#endif // hifi_RequestFilters_h \ No newline at end of file +#endif // hifi_RequestFilters_h diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index c4ae0db1aa..109c4cbfe9 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -266,7 +266,7 @@ void RenderableWebEntityItem::loadSourceURL() { _webSurface->setMaxFps(DEFAULT_MAX_FPS); } - _webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) { + _webSurface->load("WebEntityView.qml", [&](QQmlContext* context, QObject* obj) { context->setContextProperty("eventBridgeJavaScriptToInject", QVariant(_javaScriptToInject)); }); From 9d0667cb3150a99e636cc5706f9dc9cca434c8a4 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 17 Mar 2017 15:22:36 -0700 Subject: [PATCH 08/46] add url tag to web entities --- interface/resources/qml/controls/WebEntityView.qml | 2 ++ interface/resources/qml/controls/WebView.qml | 5 ++++- interface/src/Application.cpp | 5 ++++- interface/src/networking/FileTypeRequestInterceptor.cpp | 5 ++--- interface/src/networking/HFWebEngineRequestInterceptor.cpp | 3 +-- interface/src/networking/RequestFilters.cpp | 6 +++--- interface/src/networking/RequestFilters.h | 4 ++-- 7 files changed, 18 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml index 961ebffb38..821954bf7b 100644 --- a/interface/resources/qml/controls/WebEntityView.qml +++ b/interface/resources/qml/controls/WebEntityView.qml @@ -17,4 +17,6 @@ WebView { id: webviewProfile storageName: "qmlWebEngine" } + + urlTag: "?noDowload=true"; } diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index 8c73eddcc2..dc62721ace 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -10,6 +10,7 @@ Item { property alias eventBridge: eventBridgeWrapper.eventBridge property alias canGoBack: root.canGoBack; property var goBack: root.goBack; + property alias urlTag: root.urlTag property bool keyboardEnabled: true // FIXME - Keyboard HMD only: Default to false property bool keyboardRaised: false property bool punctuationMode: false @@ -68,6 +69,8 @@ Item { injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished. worldId: WebEngineScript.MainWorld } + + property string urlTag: "?noDowload=false"; userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] @@ -95,7 +98,7 @@ Item { // Required to support clicking on "hifi://" links if (WebEngineView.LoadStartedStatus == loadRequest.status) { - var url = loadRequest.url.toString(); + var url = loadRequest.url.toString() + urlTag; if (urlHandler.canHandleUrl(url)) { if (urlHandler.handleUrl(url)) { root.stop(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index aa33b66962..eee9253c76 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -219,6 +219,7 @@ static const QString FST_EXTENSION = ".fst"; static const QString FBX_EXTENSION = ".fbx"; static const QString OBJ_EXTENSION = ".obj"; static const QString AVA_JSON_EXTENSION = ".ava.json"; +static const QString WEB_VIEW_TAG = "?noDowload=true"; static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; @@ -2607,7 +2608,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); QUrl url = fileEvent->url(); - + if (!url.isEmpty()) { QString urlString = url.toString(); @@ -5549,6 +5550,8 @@ bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); if (urlString.startsWith(HIFI_URL_SCHEME)) { return true; + } else if (urlString.endsWith(WEB_VIEW_TAG)) { + return false; } QHashIterator i(_acceptedExtensions); QString lowerPath = url.path().toLower(); diff --git a/interface/src/networking/FileTypeRequestInterceptor.cpp b/interface/src/networking/FileTypeRequestInterceptor.cpp index 2dac5db194..91bacd46a6 100644 --- a/interface/src/networking/FileTypeRequestInterceptor.cpp +++ b/interface/src/networking/FileTypeRequestInterceptor.cpp @@ -16,7 +16,6 @@ #include "RequestFilters.h" void FileTypeRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - RequestFilters* filter = new RequestFilters; - filter->interceptHFWebEngineRequest(info); - filter->interceptFileType(info); + RequestFilters::interceptHFWebEngineRequest(info); + RequestFilters::interceptFileType(info); } diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.cpp b/interface/src/networking/HFWebEngineRequestInterceptor.cpp index 400d547d92..546edcf95c 100644 --- a/interface/src/networking/HFWebEngineRequestInterceptor.cpp +++ b/interface/src/networking/HFWebEngineRequestInterceptor.cpp @@ -18,6 +18,5 @@ #include "RequestFilters.h" void HFWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - RequestFilters* filter = new RequestFilters; - filter->interceptHFWebEngineRequest(info); + RequestFilters::interceptHFWebEngineRequest(info); } diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 0f59258b66..39ed5117ac 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -15,7 +15,7 @@ #include -bool isAuthableHighFidelityURL(const QUrl& url) { +bool static isAuthableHighFidelityURL(const QUrl& url) { static const QStringList HF_HOSTS = { "highfidelity.com", "highfidelity.io", "metaverse.highfidelity.com", "metaverse.highfidelity.io" @@ -24,11 +24,11 @@ bool isAuthableHighFidelityURL(const QUrl& url) { return url.scheme() == "https" && HF_HOSTS.contains(url.host()); } -bool isJavaScriptFile(const QString filename) { +bool static isJavaScriptFile(const QString filename) { return filename.contains(".js", Qt::CaseInsensitive); } -bool isEntityFile(const QString filename) { +bool static isEntityFile(const QString filename) { return filename.contains(".svo.json", Qt::CaseInsensitive); } diff --git a/interface/src/networking/RequestFilters.h b/interface/src/networking/RequestFilters.h index d61208a22d..0d7d66e155 100644 --- a/interface/src/networking/RequestFilters.h +++ b/interface/src/networking/RequestFilters.h @@ -21,8 +21,8 @@ class RequestFilters : public QObject { Q_OBJECT public: - void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info); - void interceptFileType(QWebEngineUrlRequestInfo& info); + static void interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info); + static void interceptFileType(QWebEngineUrlRequestInfo& info); }; #endif // hifi_RequestFilters_h From 3b88553699e62d33ed4eb3a5a4dd97b4ab623dc1 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 17 Mar 2017 15:33:42 -0700 Subject: [PATCH 09/46] check scripts --- interface/src/networking/RequestFilters.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 39ed5117ac..894ed9fdd2 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -24,14 +24,10 @@ bool static isAuthableHighFidelityURL(const QUrl& url) { return url.scheme() == "https" && HF_HOSTS.contains(url.host()); } -bool static isJavaScriptFile(const QString filename) { +bool static isScript(const QString filename) { return filename.contains(".js", Qt::CaseInsensitive); } -bool static isEntityFile(const QString filename) { - return filename.contains(".svo.json", Qt::CaseInsensitive); -} - void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) { // check if this is a request to a highfidelity URL if (isAuthableHighFidelityURL(info.requestUrl())) { @@ -49,9 +45,9 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { QString filename = info.requestUrl().fileName(); - if (isJavaScriptFile(filename) || isEntityFile(filename)) { + if (isScript(filename)) { static const QString CONTENT_HEADER = "Accept"; - static const QString TYPE_VALUE = "text/plain"; + static const QString TYPE_VALUE = "text/plain,text/html"; info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit()); } } From 8e4229b2119dc789c1c90f91fe9e4ac56512634a Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Fri, 17 Mar 2017 15:44:46 -0700 Subject: [PATCH 10/46] dont redirect people from webentity --- interface/src/Application.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index eee9253c76..2901de23b3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5548,10 +5548,10 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); - if (urlString.startsWith(HIFI_URL_SCHEME)) { - return true; - } else if (urlString.endsWith(WEB_VIEW_TAG)) { + if (urlString.endsWith(WEB_VIEW_TAG)) { return false; + } else if (urlString.startsWith(HIFI_URL_SCHEME)) { + return true; } QHashIterator i(_acceptedExtensions); QString lowerPath = url.path().toLower(); From e5c075f107b95000b1cca4a5e0d7163b7e5e6271 Mon Sep 17 00:00:00 2001 From: Kunal Gosar Date: Fri, 24 Mar 2017 00:10:53 -0700 Subject: [PATCH 11/46] fix typo and namespace --- .../resources/qml/controls/WebEntityView.qml | 2 +- interface/resources/qml/controls/WebView.qml | 2 +- interface/src/Application.cpp | 2 +- interface/src/networking/RequestFilters.cpp | 22 +++++++++++-------- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml index 821954bf7b..4b4c8fe46f 100644 --- a/interface/resources/qml/controls/WebEntityView.qml +++ b/interface/resources/qml/controls/WebEntityView.qml @@ -18,5 +18,5 @@ WebView { storageName: "qmlWebEngine" } - urlTag: "?noDowload=true"; + urlTag: "?noDownload=true"; } diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index dc62721ace..b904dd5d55 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -70,7 +70,7 @@ Item { worldId: WebEngineScript.MainWorld } - property string urlTag: "?noDowload=false"; + property string urlTag: "?noDownload=false"; userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2901de23b3..f0897176af 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -219,7 +219,7 @@ static const QString FST_EXTENSION = ".fst"; static const QString FBX_EXTENSION = ".fbx"; static const QString OBJ_EXTENSION = ".obj"; static const QString AVA_JSON_EXTENSION = ".ava.json"; -static const QString WEB_VIEW_TAG = "?noDowload=true"; +static const QString WEB_VIEW_TAG = "?noDownload=true"; static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 894ed9fdd2..abf9575bdc 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -15,17 +15,21 @@ #include -bool static isAuthableHighFidelityURL(const QUrl& url) { - static const QStringList HF_HOSTS = { - "highfidelity.com", "highfidelity.io", - "metaverse.highfidelity.com", "metaverse.highfidelity.io" - }; +namespace { - return url.scheme() == "https" && HF_HOSTS.contains(url.host()); -} + bool isAuthableHighFidelityURL(const QUrl& url) { + static const QStringList HF_HOSTS = { + "highfidelity.com", "highfidelity.io", + "metaverse.highfidelity.com", "metaverse.highfidelity.io" + }; + + return url.scheme() == "https" && HF_HOSTS.contains(url.host()); + } + + bool isScript(const QString filename) { + return filename.contains(".js", Qt::CaseInsensitive); + } -bool static isScript(const QString filename) { - return filename.contains(".js", Qt::CaseInsensitive); } void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) { From cc81bcab663dcc3698da8a0cd036afb98047b756 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Tue, 4 Apr 2017 11:58:38 -0700 Subject: [PATCH 12/46] updating url check from hifi master --- .../HFWebEngineRequestInterceptor.cpp | 1 - interface/src/networking/RequestFilters.cpp | 18 +++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/interface/src/networking/HFWebEngineRequestInterceptor.cpp b/interface/src/networking/HFWebEngineRequestInterceptor.cpp index 546edcf95c..59897d427f 100644 --- a/interface/src/networking/HFWebEngineRequestInterceptor.cpp +++ b/interface/src/networking/HFWebEngineRequestInterceptor.cpp @@ -10,7 +10,6 @@ // #include "HFWebEngineRequestInterceptor.h" -#include "NetworkingConstants.h" #include diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index abf9575bdc..4e08080df0 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -10,6 +10,7 @@ // #include "RequestFilters.h" +#include "NetworkingConstants.h" #include @@ -17,14 +18,17 @@ namespace { - bool isAuthableHighFidelityURL(const QUrl& url) { - static const QStringList HF_HOSTS = { - "highfidelity.com", "highfidelity.io", - "metaverse.highfidelity.com", "metaverse.highfidelity.io" - }; + bool isAuthableHighFidelityURL(const QUrl& url) { + static const QStringList HF_HOSTS = { + "highfidelity.com", "highfidelity.io", + "metaverse.highfidelity.com", "metaverse.highfidelity.io" + }; + const auto& scheme = url.scheme(); + const auto& host = url.host(); - return url.scheme() == "https" && HF_HOSTS.contains(url.host()); - } + return (scheme == "https" && HF_HOSTS.contains(host)) || + ((scheme == NetworkingConstants::METAVERSE_SERVER_URL.scheme()) && (host == NetworkingConstants::METAVERSE_SERVER_URL.host())); + } bool isScript(const QString filename) { return filename.contains(".js", Qt::CaseInsensitive); From 8749428ede5203c5f7e383a2d339b646a061dbf3 Mon Sep 17 00:00:00 2001 From: kunalgosar Date: Tue, 4 Apr 2017 13:51:34 -0700 Subject: [PATCH 13/46] dont assume no query tags --- interface/resources/qml/controls/WebEntityView.qml | 2 +- interface/resources/qml/controls/WebView.qml | 5 +++-- interface/src/Application.cpp | 10 ++++++---- interface/src/networking/RequestFilters.cpp | 8 ++++++-- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/controls/WebEntityView.qml b/interface/resources/qml/controls/WebEntityView.qml index 4b4c8fe46f..a3d5fe903b 100644 --- a/interface/resources/qml/controls/WebEntityView.qml +++ b/interface/resources/qml/controls/WebEntityView.qml @@ -18,5 +18,5 @@ WebView { storageName: "qmlWebEngine" } - urlTag: "?noDownload=true"; + urlTag: "noDownload=true"; } diff --git a/interface/resources/qml/controls/WebView.qml b/interface/resources/qml/controls/WebView.qml index b904dd5d55..52f277520f 100644 --- a/interface/resources/qml/controls/WebView.qml +++ b/interface/resources/qml/controls/WebView.qml @@ -70,7 +70,7 @@ Item { worldId: WebEngineScript.MainWorld } - property string urlTag: "?noDownload=false"; + property string urlTag: "noDownload=false"; userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ] @@ -98,7 +98,8 @@ Item { // Required to support clicking on "hifi://" links if (WebEngineView.LoadStartedStatus == loadRequest.status) { - var url = loadRequest.url.toString() + urlTag; + var url = loadRequest.url.toString(); + url = (url.indexOf("?") >= 0) ? url + urlTag : url + "?" + urlTag; if (urlHandler.canHandleUrl(url)) { if (urlHandler.handleUrl(url)) { root.stop(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f0897176af..dec6850497 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -219,7 +219,7 @@ static const QString FST_EXTENSION = ".fst"; static const QString FBX_EXTENSION = ".fbx"; static const QString OBJ_EXTENSION = ".obj"; static const QString AVA_JSON_EXTENSION = ".ava.json"; -static const QString WEB_VIEW_TAG = "?noDownload=true"; +static const QString WEB_VIEW_TAG = "noDownload=true"; static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; @@ -2608,7 +2608,7 @@ bool Application::event(QEvent* event) { QFileOpenEvent* fileEvent = static_cast(event); QUrl url = fileEvent->url(); - + if (!url.isEmpty()) { QString urlString = url.toString(); @@ -5548,7 +5548,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri bool Application::canAcceptURL(const QString& urlString) const { QUrl url(urlString); - if (urlString.endsWith(WEB_VIEW_TAG)) { + if (url.query().contains(WEB_VIEW_TAG)) { return false; } else if (urlString.startsWith(HIFI_URL_SCHEME)) { return true; @@ -5658,7 +5658,9 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) { QUrl scriptURL { scriptFilenameOrURL }; if (scriptURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) { - shortName = shortName.mid(shortName.lastIndexOf('/') + 1); + int startIndex = shortName.lastIndexOf('/') + 1; + int endIndex = shortName.lastIndexOf('?'); + shortName = shortName.mid(startIndex, endIndex - startIndex); } QString message = "Would you like to run this script:\n" + shortName; diff --git a/interface/src/networking/RequestFilters.cpp b/interface/src/networking/RequestFilters.cpp index 4e08080df0..fedde94f15 100644 --- a/interface/src/networking/RequestFilters.cpp +++ b/interface/src/networking/RequestFilters.cpp @@ -31,7 +31,11 @@ namespace { } bool isScript(const QString filename) { - return filename.contains(".js", Qt::CaseInsensitive); + return filename.endsWith(".js", Qt::CaseInsensitive); + } + + bool isJSON(const QString filename) { + return filename.endsWith(".json", Qt::CaseInsensitive); } } @@ -53,7 +57,7 @@ void RequestFilters::interceptHFWebEngineRequest(QWebEngineUrlRequestInfo& info) void RequestFilters::interceptFileType(QWebEngineUrlRequestInfo& info) { QString filename = info.requestUrl().fileName(); - if (isScript(filename)) { + if (isScript(filename) || isJSON(filename)) { static const QString CONTENT_HEADER = "Accept"; static const QString TYPE_VALUE = "text/plain,text/html"; info.setHttpHeader(CONTENT_HEADER.toLocal8Bit(), TYPE_VALUE.toLocal8Bit()); From 54200c03a73fee13bbbe07e48ce80170c8aafc26 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 4 Apr 2017 13:53:49 -0700 Subject: [PATCH 14/46] Fixing deadlock --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 891196862a..3f732e26cb 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2133,7 +2133,7 @@ void EntityItem::deserializeActionsInternal() { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex(".*action creation failed for.*"); qCDebug(entities) << "EntityItem::deserializeActionsInternal -- action creation failed for" - << getID() << getName(); + << getID() << _name; // getName(); removeActionInternal(actionID, nullptr); } } From cd7c1643a3492c8ed4c2824d98ed2cee8d67207e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 4 Apr 2017 14:03:30 -0700 Subject: [PATCH 15/46] More thread safety --- libraries/entities/src/LineEntityItem.cpp | 4 +- .../entities/src/ParticleEffectEntityItem.cpp | 17 +++ .../entities/src/ParticleEffectEntityItem.h | 9 +- libraries/entities/src/PolyLineEntityItem.cpp | 110 +++++++++++++----- libraries/entities/src/PolyLineEntityItem.h | 15 +-- 5 files changed, 106 insertions(+), 49 deletions(-) diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index fe2c803f43..58cdb1cd7b 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -34,8 +34,8 @@ EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const En LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID), _lineWidth(DEFAULT_LINE_WIDTH), - _pointsChanged(true), - _points(QVector(0)) + _points(QVector(0)), + _pointsChanged(true) { _type = EntityTypes::Line; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 140522b00e..80f7f3b6b8 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -733,3 +733,20 @@ void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { _timeUntilNextEmit = 0.0f; } } + +QString ParticleEffectEntityItem::getTextures() const { + QString result; + withReadLock([&] { + result = _textures; + }); + return result; +} + +void ParticleEffectEntityItem::setTextures(const QString& textures) { + withWriteLock([&] { + if (_textures != textures) { + _textures = textures; + _texturesChangedFlag = true; + } + }); +} diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 6c6596e7a2..4d053e5a45 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -205,13 +205,8 @@ public: void computeAndUpdateDimensions(); static const QString DEFAULT_TEXTURES; - const QString& getTextures() const { return _textures; } - void setTextures(const QString& textures) { - if (_textures != textures) { - _textures = textures; - _texturesChangedFlag = true; - } - } + QString getTextures() const; + void setTextures(const QString& textures); static const bool DEFAULT_EMITTER_SHOULD_TRAIL; bool getEmitterShouldTrail() const { return _emitterShouldTrail; } diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 7abafad627..9fe8ac0c8f 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -104,14 +104,18 @@ bool PolyLineEntityItem::appendPoint(const glm::vec3& point) { bool PolyLineEntityItem::setStrokeWidths(const QVector& strokeWidths) { - _strokeWidths = strokeWidths; - _strokeWidthsChanged = true; + withWriteLock([&] { + _strokeWidths = strokeWidths; + _strokeWidthsChanged = true; + }); return true; } bool PolyLineEntityItem::setNormals(const QVector& normals) { - _normals = normals; - _normalsChanged = true; + withWriteLock([&] { + _normals = normals; + _normalsChanged = true; + }); return true; } @@ -119,35 +123,39 @@ bool PolyLineEntityItem::setLinePoints(const QVector& points) { if (points.size() > MAX_POINTS_PER_LINE) { return false; } - if (points.size() != _points.size()) { - _pointsChanged = true; - } - //Check to see if points actually changed. If they haven't, return before doing anything else - else if (points.size() == _points.size()) { - //same number of points, so now compare every point - for (int i = 0; i < points.size(); i++) { - if (points.at(i) != _points.at(i)){ - _pointsChanged = true; - break; + bool result = false; + withWriteLock([&] { + //Check to see if points actually changed. If they haven't, return before doing anything else + if (points.size() != _points.size()) { + _pointsChanged = true; + } else if (points.size() == _points.size()) { + //same number of points, so now compare every point + for (int i = 0; i < points.size(); i++) { + if (points.at(i) != _points.at(i)) { + _pointsChanged = true; + break; + } } } - } - if (!_pointsChanged) { - return false; - } - - for (int i = 0; i < points.size(); i++) { - glm::vec3 point = points.at(i); - glm::vec3 halfBox = getDimensions() * 0.5f; - if ((point.x < -halfBox.x || point.x > halfBox.x) || - (point.y < -halfBox.y || point.y > halfBox.y) || - (point.z < -halfBox.z || point.z > halfBox.z)) { - qCDebug(entities) << "Point is outside entity's bounding box"; - return false; + if (!_pointsChanged) { + return; } - } - _points = points; - return true; + + for (int i = 0; i < points.size(); i++) { + glm::vec3 point = points.at(i); + glm::vec3 halfBox = getDimensions() * 0.5f; + if ((point.x < -halfBox.x || point.x > halfBox.x) || + (point.y < -halfBox.y || point.y > halfBox.y) || + (point.z < -halfBox.z || point.z > halfBox.z)) { + qCDebug(entities) << "Point is outside entity's bounding box"; + return; + } + } + _points = points; + result = true; + }); + + return result; } int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -210,3 +218,45 @@ void PolyLineEntityItem::debugDump() const { qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } + + +QVector PolyLineEntityItem::getLinePoints() const { + QVector result; + withReadLock([&] { + result = _points; + }); + return result; +} + +QVector PolyLineEntityItem::getNormals() const { + QVector result; + withReadLock([&] { + result = _normals; + }); + return result; +} + +QVector PolyLineEntityItem::getStrokeWidths() const { + QVector result; + withReadLock([&] { + result = _strokeWidths; + }); + return result; +} + +QString PolyLineEntityItem::getTextures() const { + QString result; + withReadLock([&] { + result = _textures; + }); + return result; +} + +void PolyLineEntityItem::setTextures(const QString& textures) { + withWriteLock([&] { + if (_textures != textures) { + _textures = textures; + _texturesChangedFlag = true; + } + }); +} diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 5f9f9124cf..0ee9a638de 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -59,21 +59,16 @@ class PolyLineEntityItem : public EntityItem { bool setLinePoints(const QVector& points); bool appendPoint(const glm::vec3& point); - const QVector& getLinePoints() const{ return _points; } + QVector getLinePoints() const; bool setNormals(const QVector& normals); - const QVector& getNormals() const{ return _normals; } + QVector getNormals() const; bool setStrokeWidths(const QVector& strokeWidths); - const QVector& getStrokeWidths() const{ return _strokeWidths; } + QVector getStrokeWidths() const; - const QString& getTextures() const { return _textures; } - void setTextures(const QString& textures) { - if (_textures != textures) { - _textures = textures; - _texturesChangedFlag = true; - } - } + QString getTextures() const; + void setTextures(const QString& textures); virtual bool needsToCallUpdate() const override { return true; } From 15f7e895aafb0243cdb903eaa637e146985d704e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 4 Apr 2017 15:09:21 -0700 Subject: [PATCH 16/46] More thread safety --- .../src/RenderablePolyVoxEntityItem.cpp | 12 +- .../src/RenderablePolyVoxEntityItem.h | 6 +- libraries/entities/src/PolyVoxEntityItem.cpp | 126 ++++++++++++++++++ libraries/entities/src/PolyVoxEntityItem.h | 48 +++---- libraries/entities/src/WebEntityItem.cpp | 24 ++-- libraries/entities/src/WebEntityItem.h | 2 +- libraries/entities/src/ZoneEntityItem.cpp | 33 ++++- libraries/entities/src/ZoneEntityItem.h | 6 +- 8 files changed, 207 insertions(+), 50 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 419f32f897..a8e422be0f 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -660,22 +660,22 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { }); } -void RenderablePolyVoxEntityItem::setXTextureURL(QString xTextureURL) { - if (xTextureURL != _xTextureURL) { +void RenderablePolyVoxEntityItem::setXTextureURL(const QString& xTextureURL) { + if (xTextureURL != getXTextureURL()) { _xTexture.clear(); PolyVoxEntityItem::setXTextureURL(xTextureURL); } } -void RenderablePolyVoxEntityItem::setYTextureURL(QString yTextureURL) { - if (yTextureURL != _yTextureURL) { +void RenderablePolyVoxEntityItem::setYTextureURL(const QString& yTextureURL) { + if (yTextureURL != getYTextureURL()) { _yTexture.clear(); PolyVoxEntityItem::setYTextureURL(yTextureURL); } } -void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) { - if (zTextureURL != _zTextureURL) { +void RenderablePolyVoxEntityItem::setZTextureURL(const QString& zTextureURL) { + if (zTextureURL != getZTextureURL()) { _zTexture.clear(); PolyVoxEntityItem::setZTextureURL(zTextureURL); } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index cdfe2e38fe..e416f59858 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -101,9 +101,9 @@ public: virtual bool setAll(uint8_t toValue) override; virtual bool setCuboid(const glm::vec3& lowPosition, const glm::vec3& cuboidSize, int toValue) override; - virtual void setXTextureURL(QString xTextureURL) override; - virtual void setYTextureURL(QString yTextureURL) override; - virtual void setZTextureURL(QString zTextureURL) override; + virtual void setXTextureURL(const QString& xTextureURL) override; + virtual void setYTextureURL(const QString& yTextureURL) override; + virtual void setZTextureURL(const QString& zTextureURL) override; virtual bool addToScene(EntityItemPointer self, std::shared_ptr scene, diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index 2a374c1d17..711c3b5625 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -242,3 +242,129 @@ const QByteArray PolyVoxEntityItem::getVoxelData() const { }); return voxelDataCopy; } + + +void PolyVoxEntityItem::setXTextureURL(const QString& xTextureURL) { + withWriteLock([&] { + _xTextureURL = xTextureURL; + }); +} + +QString PolyVoxEntityItem::getXTextureURL() const { + QString result; + withReadLock([&] { + result = _xTextureURL; + }); + return result; +} + +void PolyVoxEntityItem::setYTextureURL(const QString& yTextureURL) { + withWriteLock([&] { + _yTextureURL = yTextureURL; + }); +} + +QString PolyVoxEntityItem::getYTextureURL() const { + QString result; + withReadLock([&] { + result = _yTextureURL; + }); + return result; +} + +void PolyVoxEntityItem::setZTextureURL(const QString& zTextureURL) { + withWriteLock([&] { + _zTextureURL = zTextureURL; + }); +} +QString PolyVoxEntityItem::getZTextureURL() const { + QString result; + withReadLock([&] { + result = _zTextureURL; + }); + return result; +} + +void PolyVoxEntityItem::setXNNeighborID(const EntityItemID& xNNeighborID) { + withWriteLock([&] { + _xNNeighborID = xNNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getXNNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _xNNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setYNNeighborID(const EntityItemID& yNNeighborID) { + withWriteLock([&] { + _yNNeighborID = yNNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getYNNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _yNNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setZNNeighborID(const EntityItemID& zNNeighborID) { + withWriteLock([&] { + _zNNeighborID = zNNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getZNNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _zNNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setXPNeighborID(const EntityItemID& xPNeighborID) { + withWriteLock([&] { + _xPNeighborID = xPNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getXPNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _xPNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setYPNeighborID(const EntityItemID& yPNeighborID) { + withWriteLock([&] { + _yPNeighborID = yPNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getYPNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _yPNeighborID; + }); + return result; +} + +void PolyVoxEntityItem::setZPNeighborID(const EntityItemID& zPNeighborID) { + withWriteLock([&] { + _zPNeighborID = zPNeighborID; + }); +} + +EntityItemID PolyVoxEntityItem::getZPNeighborID() const { + EntityItemID result; + withReadLock([&] { + result = _zPNeighborID; + }); + return result; +} diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index cf7531fc9e..05b5cb33a6 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -99,36 +99,36 @@ class PolyVoxEntityItem : public EntityItem { static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16); static const QString DEFAULT_X_TEXTURE_URL; - virtual void setXTextureURL(QString xTextureURL) { _xTextureURL = xTextureURL; } - virtual const QString& getXTextureURL() const { return _xTextureURL; } + virtual void setXTextureURL(const QString& xTextureURL); + QString getXTextureURL() const; static const QString DEFAULT_Y_TEXTURE_URL; - virtual void setYTextureURL(QString yTextureURL) { _yTextureURL = yTextureURL; } - virtual const QString& getYTextureURL() const { return _yTextureURL; } + virtual void setYTextureURL(const QString& yTextureURL); + QString getYTextureURL() const; static const QString DEFAULT_Z_TEXTURE_URL; - virtual void setZTextureURL(QString zTextureURL) { _zTextureURL = zTextureURL; } - virtual const QString& getZTextureURL() const { return _zTextureURL; } + virtual void setZTextureURL(const QString& zTextureURL); + QString getZTextureURL() const; - virtual void setXNNeighborID(const EntityItemID& xNNeighborID) { _xNNeighborID = xNNeighborID; } - void setXNNeighborID(const QString& xNNeighborID) { setXNNeighborID(QUuid(xNNeighborID)); } - virtual const EntityItemID& getXNNeighborID() const { return _xNNeighborID; } - virtual void setYNNeighborID(const EntityItemID& yNNeighborID) { _yNNeighborID = yNNeighborID; } - void setYNNeighborID(const QString& yNNeighborID) { setYNNeighborID(QUuid(yNNeighborID)); } - virtual const EntityItemID& getYNNeighborID() const { return _yNNeighborID; } - virtual void setZNNeighborID(const EntityItemID& zNNeighborID) { _zNNeighborID = zNNeighborID; } - void setZNNeighborID(const QString& zNNeighborID) { setZNNeighborID(QUuid(zNNeighborID)); } - virtual const EntityItemID& getZNNeighborID() const { return _zNNeighborID; } + virtual void setXNNeighborID(const EntityItemID& xNNeighborID); + void setXNNeighborID(const QString& xNNeighborID); + virtual EntityItemID getXNNeighborID() const; + virtual void setYNNeighborID(const EntityItemID& yNNeighborID); + void setYNNeighborID(const QString& yNNeighborID); + virtual EntityItemID getYNNeighborID() const; + virtual void setZNNeighborID(const EntityItemID& zNNeighborID); + void setZNNeighborID(const QString& zNNeighborID); + virtual EntityItemID getZNNeighborID() const; - virtual void setXPNeighborID(const EntityItemID& xPNeighborID) { _xPNeighborID = xPNeighborID; } - void setXPNeighborID(const QString& xPNeighborID) { setXPNeighborID(QUuid(xPNeighborID)); } - virtual const EntityItemID& getXPNeighborID() const { return _xPNeighborID; } - virtual void setYPNeighborID(const EntityItemID& yPNeighborID) { _yPNeighborID = yPNeighborID; } - void setYPNeighborID(const QString& yPNeighborID) { setYPNeighborID(QUuid(yPNeighborID)); } - virtual const EntityItemID& getYPNeighborID() const { return _yPNeighborID; } - virtual void setZPNeighborID(const EntityItemID& zPNeighborID) { _zPNeighborID = zPNeighborID; } - void setZPNeighborID(const QString& zPNeighborID) { setZPNeighborID(QUuid(zPNeighborID)); } - virtual const EntityItemID& getZPNeighborID() const { return _zPNeighborID; } + virtual void setXPNeighborID(const EntityItemID& xPNeighborID); + void setXPNeighborID(const QString& xPNeighborID); + virtual EntityItemID getXPNeighborID() const; + virtual void setYPNeighborID(const EntityItemID& yPNeighborID); + void setYPNeighborID(const QString& yPNeighborID); + virtual EntityItemID getYPNeighborID() const; + virtual void setZPNeighborID(const EntityItemID& zPNeighborID); + void setZPNeighborID(const QString& zPNeighborID); + virtual EntityItemID getZPNeighborID() const; virtual void rebakeMesh() {}; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 182d58ba36..5b060cc702 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -124,18 +124,26 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g } void WebEntityItem::setSourceUrl(const QString& value) { - if (_sourceUrl != value) { - auto newURL = QUrl::fromUserInput(value); + withWriteLock([&] { + if (_sourceUrl != value) { + auto newURL = QUrl::fromUserInput(value); - if (newURL.isValid()) { - _sourceUrl = newURL.toDisplayString(); - } else { - qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL."; + if (newURL.isValid()) { + _sourceUrl = newURL.toDisplayString(); + } else { + qCDebug(entities) << "Clearing web entity source URL since" << value << "cannot be parsed to a valid URL."; + } } - } + }); } -const QString& WebEntityItem::getSourceUrl() const { return _sourceUrl; } +QString WebEntityItem::getSourceUrl() const { + QString result; + withReadLock([&] { + result = _sourceUrl; + }); + return result; +} void WebEntityItem::setDPI(uint16_t value) { _dpi = value; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 19a7b577fe..5cd081687f 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -52,7 +52,7 @@ public: void** intersectedObject, bool precisionPicking) const override; virtual void setSourceUrl(const QString& value); - const QString& getSourceUrl() const; + QString getSourceUrl() const; virtual bool wantsHandControllerPointerEvents() const override { return true; } diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 37b3be99a3..26d566a795 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -208,10 +208,12 @@ ShapeType ZoneEntityItem::getShapeType() const { } void ZoneEntityItem::setCompoundShapeURL(const QString& url) { - _compoundShapeURL = url; - if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) { - _shapeType = DEFAULT_SHAPE_TYPE; - } + withWriteLock([&] { + _compoundShapeURL = url; + if (_compoundShapeURL.isEmpty() && _shapeType == SHAPE_TYPE_COMPOUND) { + _shapeType = DEFAULT_SHAPE_TYPE; + } + }); } bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, @@ -223,7 +225,9 @@ bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const } void ZoneEntityItem::setFilterURL(QString url) { - _filterURL = url; + withWriteLock([&] { + _filterURL = url; + }); if (DependencyManager::isSet()) { auto entityEditFilters = DependencyManager::get(); qCDebug(entities) << "adding filter " << url << "for zone" << getEntityItemID(); @@ -231,3 +235,22 @@ void ZoneEntityItem::setFilterURL(QString url) { } } +QString ZoneEntityItem::getFilterURL() const { + QString result; + withReadLock([&] { + result = _filterURL; + }); + return result; +} + +bool ZoneEntityItem::hasCompoundShapeURL() const { + return !getCompoundShapeURL().isEmpty(); +} + +QString ZoneEntityItem::getCompoundShapeURL() const { + QString result; + withReadLock([&] { + result = _compoundShapeURL; + }); + return result; +} diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index 2bef95e452..dfc18aff80 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -58,8 +58,8 @@ public: void setShapeType(ShapeType type) override { _shapeType = type; } virtual ShapeType getShapeType() const override; - virtual bool hasCompoundShapeURL() const { return !_compoundShapeURL.isEmpty(); } - const QString getCompoundShapeURL() const { return _compoundShapeURL; } + virtual bool hasCompoundShapeURL() const; + QString getCompoundShapeURL() const; virtual void setCompoundShapeURL(const QString& url); const KeyLightPropertyGroup& getKeyLightProperties() const { return _keyLightProperties; } @@ -74,7 +74,7 @@ public: void setFlyingAllowed(bool value) { _flyingAllowed = value; } bool getGhostingAllowed() const { return _ghostingAllowed; } void setGhostingAllowed(bool value) { _ghostingAllowed = value; } - QString getFilterURL() const { return _filterURL; } + QString getFilterURL() const; void setFilterURL(const QString url); virtual bool supportsDetailedRayIntersection() const override { return true; } From 2e4e10759f3753445eab30971dbe52e1c10a264d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 5 Apr 2017 13:17:03 -0700 Subject: [PATCH 17/46] teleport raypick now ignores equipped or grabbed entities --- .../system/controllers/handControllerGrab.js | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index e1b432d09f..d1c00a9d81 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1094,7 +1094,6 @@ function MyController(hand) { this.grabbedOverlay = null; this.state = STATE_OFF; this.pointer = null; // entity-id of line object - this.entityActivated = false; this.triggerValue = 0; // rolling average of trigger value this.triggerClicked = false; @@ -2826,12 +2825,6 @@ function MyController(hand) { Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - if (this.entityActivated) { - var saveGrabbedID = this.grabbedThingID; - this.release(); - this.grabbedThingID = saveGrabbedID; - } - var grabbedProperties; if (this.grabbedIsOverlay) { grabbedProperties = { @@ -3007,22 +3000,25 @@ function MyController(hand) { * is called correctly, as these just freshly created entity may not have completely initialized. */ var grabEquipCheck = function () { - if (_this.state == STATE_NEAR_GRABBING) { - _this.callEntityMethodOnGrabbed("startNearGrab"); + if (_this.state == STATE_NEAR_GRABBING) { + _this.callEntityMethodOnGrabbed("startNearGrab"); } else { // this.state == STATE_HOLD - _this.callEntityMethodOnGrabbed("startEquip"); + _this.callEntityMethodOnGrabbed("startEquip"); } - _this.currentHandControllerTipPosition = - (_this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition; - _this.currentObjectTime = Date.now(); + // don't block teleport raypick with equipped entity + Messages.sendMessage('Hifi-Teleport-Ignore-Add', _this.grabbedThingID); - _this.currentObjectPosition = grabbedProperties.position; - _this.currentObjectRotation = grabbedProperties.rotation; - _this.currentVelocity = ZERO_VEC; - _this.currentAngularVelocity = ZERO_VEC; + _this.currentHandControllerTipPosition = + (_this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition; + _this.currentObjectTime = Date.now(); - _this.prevDropDetected = false; + _this.currentObjectPosition = grabbedProperties.position; + _this.currentObjectRotation = grabbedProperties.rotation; + _this.currentVelocity = ZERO_VEC; + _this.currentAngularVelocity = ZERO_VEC; + + _this.prevDropDetected = false; } if (isClone) { @@ -3654,6 +3650,9 @@ function MyController(hand) { this.turnOffVisualizations(); if (this.grabbedThingID !== null) { + + Messages.sendMessage('Hifi-Teleport-Ignore-Remove', this.grabbedThingID); + if (this.state === STATE_HOLD) { this.callEntityMethodOnGrabbed("releaseEquip"); } From e9934ac696b7d70466ca962d97b18a2272592719 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 5 Apr 2017 14:59:19 -0700 Subject: [PATCH 18/46] selfie stick script --- script-archive/selfieStick.js | 104 ++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 script-archive/selfieStick.js diff --git a/script-archive/selfieStick.js b/script-archive/selfieStick.js new file mode 100644 index 0000000000..767cf55144 --- /dev/null +++ b/script-archive/selfieStick.js @@ -0,0 +1,104 @@ +// selfieStick.js +// +// Created by Faye Li on March 23, 2016 +// +// Usage instruction: Spacebar toggles camera control - WASD first person free movement or no movement but allowing others to grab the selfie stick +// and control your camera. +// For best result, turn off avatar collisions(Developer > Avatar > Uncheck Enable Avatar Collisions) +// + +(function() { // BEGIN LOCAL_SCOPE + var MODEL_URL = "https://hifi-content.s3.amazonaws.com/faye/twitch-stream/selfie_stick.json"; + var AVATAR_URL = "https://hifi-content.s3.amazonaws.com/jimi/avatar/camera/fst/camera.fst"; + var originalAvatar = null; + var importedEntityIDs = []; + var selfieStickEntityID = null; + var lensEntityID = null; + var freeMovementMode = true; + + changeAvatar(); + importModel(); + processImportedEntities(); + parentEntityToAvatar(); + setupSpaceBarControl(); + + function changeAvatar() { + originalAvatar = MyAvatar.skeletonModelURL; + MyAvatar.skeletonModelURL = AVATAR_URL; + } + + function importModel() { + var success = Clipboard.importEntities(MODEL_URL); + var spawnLocation = MyAvatar.position; + if (success) { + importedEntityIDs = Clipboard.pasteEntities(spawnLocation); + } + } + + function processImportedEntities() { + importedEntityIDs.forEach(function(id){ + var props = Entities.getEntityProperties(id); + if (props.name === "Selfie Stick") { + selfieStickEntityID = id; + } else if (props.name === "Lens") { + lensEntityID = id; + } + }); + } + + function parentEntityToAvatar() { + var props = { + "parentID" : MyAvatar.sessionUUID + }; + Entities.editEntity(selfieStickEntityID, props); + } + + function unparentEntityFromAvatar() { + var props = { + "parentID" : 0 + }; + Entities.editEntity(selfieStickEntityID, props); + } + + function parentAvatarToEntity() { + MyAvatar.setParentID(selfieStickEntityID); + } + + function unparentAvatarFromEntity() { + MyAvatar.setParentID(0); + } + + function setupSpaceBarControl() { + var mappingName = "Handheld-Cam-Space-Bar"; + var myMapping = Controller.newMapping(mappingName); + myMapping.from(Controller.Hardware.Keyboard.Space).to(function(value){ + if ( value === 0 ) { + return; + } + if (freeMovementMode) { + freeMovementMode = false; + // Camera.mode = "entity"; + // Camera.cameraEntity = lensEntityID; + unparentEntityFromAvatar(); + parentAvatarToEntity(); + } else { + freeMovementMode = true; + // Camera.mode = "first person"; + unparentAvatarFromEntity(); + parentEntityToAvatar(); + } + }); + Controller.enableMapping(mappingName); + } + + // Removes all entities we imported and reset settings we've changed + function cleanup() { + importedEntityIDs.forEach(function(id) { + Entities.deleteEntity(id); + }); + Camera.mode = "first person"; + Controller.disableMapping("Handheld-Cam-Space-Bar"); + MyAvatar.skeletonModelURL = originalAvatar; + } + Script.scriptEnding.connect(cleanup); +}()); // END LOCAL_SCOPE \ No newline at end of file From 97d75e654e22cf732d104334e66357bb99b43054 Mon Sep 17 00:00:00 2001 From: Faye Li Date: Wed, 5 Apr 2017 15:04:21 -0700 Subject: [PATCH 19/46] mannually bind avatar and entity --- script-archive/selfieStick.js | 68 +++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/script-archive/selfieStick.js b/script-archive/selfieStick.js index 767cf55144..c6fb9c5349 100644 --- a/script-archive/selfieStick.js +++ b/script-archive/selfieStick.js @@ -7,6 +7,15 @@ // For best result, turn off avatar collisions(Developer > Avatar > Uncheck Enable Avatar Collisions) // +// selfieStick.js +// +// Created by Faye Li on March 23, 2016 +// +// Usage instruction: Spacebar toggles camera control - WASD first person free movement or no movement but allowing others to grab the selfie stick +// and control your camera. +// For best result, turn off avatar collisions(Developer > Avatar > Uncheck Enable Avatar Collisions) +// + (function() { // BEGIN LOCAL_SCOPE var MODEL_URL = "https://hifi-content.s3.amazonaws.com/faye/twitch-stream/selfie_stick.json"; var AVATAR_URL = "https://hifi-content.s3.amazonaws.com/jimi/avatar/camera/fst/camera.fst"; @@ -19,8 +28,8 @@ changeAvatar(); importModel(); processImportedEntities(); - parentEntityToAvatar(); setupSpaceBarControl(); + Script.update.connect(update); function changeAvatar() { originalAvatar = MyAvatar.skeletonModelURL; @@ -46,28 +55,6 @@ }); } - function parentEntityToAvatar() { - var props = { - "parentID" : MyAvatar.sessionUUID - }; - Entities.editEntity(selfieStickEntityID, props); - } - - function unparentEntityFromAvatar() { - var props = { - "parentID" : 0 - }; - Entities.editEntity(selfieStickEntityID, props); - } - - function parentAvatarToEntity() { - MyAvatar.setParentID(selfieStickEntityID); - } - - function unparentAvatarFromEntity() { - MyAvatar.setParentID(0); - } - function setupSpaceBarControl() { var mappingName = "Handheld-Cam-Space-Bar"; var myMapping = Controller.newMapping(mappingName); @@ -77,20 +64,41 @@ } if (freeMovementMode) { freeMovementMode = false; - // Camera.mode = "entity"; - // Camera.cameraEntity = lensEntityID; - unparentEntityFromAvatar(); - parentAvatarToEntity(); + Camera.mode = "entity"; + Camera.cameraEntity = lensEntityID; } else { freeMovementMode = true; - // Camera.mode = "first person"; - unparentAvatarFromEntity(); - parentEntityToAvatar(); + Camera.mode = "first person"; } }); Controller.enableMapping(mappingName); } + function update(deltaTime) { + if (freeMovementMode) { + var upFactor = 0.1; + var upUnitVec = Vec3.normalize(Quat.getUp(MyAvatar.orientation)); + var upOffset = Vec3.multiply(upUnitVec, upFactor); + var forwardFactor = -0.1; + var forwardUnitVec = Vec3.normalize(Quat.getFront(MyAvatar.orientation)); + var forwardOffset = Vec3.multiply(forwardUnitVec, forwardFactor); + var newPos = Vec3.sum(Vec3.sum(MyAvatar.position, upOffset), forwardOffset); + var newRot = MyAvatar.orientation; + Entities.editEntity(selfieStickEntityID, {position: newPos, rotation: newRot}); + } else { + var props = Entities.getEntityProperties(selfieStickEntityID); + var upFactor = 0.1; + var upUnitVec = Vec3.normalize(Quat.getUp(props.rotation)); + var upOffset = Vec3.multiply(upUnitVec, -upFactor); + var forwardFactor = -0.1; + var forwardUnitVec = Vec3.normalize(Quat.getFront(props.rotation)); + var forwardOffset = Vec3.multiply(forwardUnitVec, -forwardFactor); + var newPos = Vec3.sum(Vec3.sum(props.position, upOffset), forwardOffset); + MyAvatar.position = newPos; + MyAvatar.orientation = props.rotation; + } + } + // Removes all entities we imported and reset settings we've changed function cleanup() { importedEntityIDs.forEach(function(id) { From 90f5d02c990db8f79b25002da949d4947423fbc6 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Apr 2017 00:13:53 +0100 Subject: [PATCH 20/46] goto toggle option --- interface/src/ui/DialogsManager.cpp | 43 +++++++++++++++++-- interface/src/ui/DialogsManager.h | 1 + .../src/TabletScriptingInterface.cpp | 8 ++++ .../src/TabletScriptingInterface.h | 3 ++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 402e27e256..a95ac8d91f 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -31,6 +31,7 @@ #include "TabletScriptingInterface.h" #include "scripting/HMDScriptingInterface.h" +static const QVariant TABLET_ADDRESS_DIALOG = "TabletAddressDialog.qml"; template void DialogsManager::maybeCreateDialog(QPointer& member) { if (!member) { @@ -46,12 +47,48 @@ void DialogsManager::maybeCreateDialog(QPointer& member) { } void DialogsManager::toggleAddressBar() { - AddressBarDialog::toggle(); - emit addressBarToggled(); + auto hmd = DependencyManager::get(); + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); + if (tablet->getToolbarMode()) { + if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG)) { + tablet->gotoHomeScreen(); + emit addressBarToggled(); + } else { + tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + emit addressBarToggled(); + } + } else { + if (hmd->getShouldShowTablet()) { + if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG) && _closeAddressBar) { + tablet->gotoHomeScreen(); + hmd->closeTablet(); + _closeAddressBar = false; + emit addressBarToggled(); + } else { + tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + _closeAddressBar = true; + emit addressBarToggled(); + } + } else { + tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + hmd->openTablet(); + _closeAddressBar = true; + emit addressBarToggled(); + } + + } } void DialogsManager::showAddressBar() { - AddressBarDialog::show(); + auto hmd = DependencyManager::get(); + auto tabletScriptingInterface = DependencyManager::get(); + auto tablet = dynamic_cast(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system")); + tablet->loadQMLSource(TABLET_ADDRESS_DIALOG); + + if (!hmd->getShouldShowTablet()) { + hmd->openTablet(); + } } void DialogsManager::showFeed() { diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 608195aca7..24b9078baf 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -79,6 +79,7 @@ private: QPointer _octreeStatsDialog; QPointer _testingDialog; QPointer _domainConnectionDialog; + bool _closeAddressBar { false }; }; #endif // hifi_DialogsManager_h diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index b4d8977b6d..7747e1b6dc 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -275,6 +275,9 @@ void TabletProxy::emitWebEvent(QVariant msg) { emit webEventReceived(msg); } +bool TabletProxy::isPathLoaded(QVariant path) { + return path.toString() == _currentPathLoaded.toString(); +} void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) { std::lock_guard guard(_mutex); _qmlOffscreenSurface = qmlOffscreenSurface; @@ -322,6 +325,7 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr removeButtonsFromHomeScreen(); _state = State::Uninitialized; emit screenChanged(QVariant("Closed"), QVariant("")); + _currentPathLoaded = ""; } } @@ -345,6 +349,7 @@ void TabletProxy::gotoMenuScreen(const QString& submenu) { QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL))); _state = State::Menu; emit screenChanged(QVariant("Menu"), QVariant(VRMENU_SOURCE_URL)); + _currentPathLoaded = VRMENU_SOURCE_URL; QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); } } @@ -364,6 +369,7 @@ void TabletProxy::loadQMLSource(const QVariant& path) { QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path)); _state = State::QML; emit screenChanged(QVariant("QML"), path); + _currentPathLoaded = path; QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true))); } } else { @@ -426,6 +432,7 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) { } _state = State::Home; emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL)); + _currentPathLoaded = TABLET_SOURCE_URL; } } @@ -450,6 +457,7 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS } _state = State::Web; emit screenChanged(QVariant("Web"), QVariant(url)); + _currentPathLoaded = QVariant(url); } QObject* TabletProxy::addButton(const QVariant& properties) { diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index e9ae60fee1..195db02789 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -183,6 +183,8 @@ public: Q_INVOKABLE void setLandscape(bool landscape) { _landscape = landscape; } Q_INVOKABLE bool getLandscape() { return _landscape; } + Q_INVOKABLE bool isPathLoaded(QVariant path); + QQuickItem* getTabletRoot() const { return _qmlTabletRoot; } QObject* getTabletSurface(); @@ -235,6 +237,7 @@ protected: bool _initialScreen { false }; QVariant _initialPath { "" }; + QVariant _currentPathLoaded { "" }; QString _name; std::mutex _mutex; std::vector> _tabletButtonProxies; From f588612fc30b9d457668456aa622a65394e17a42 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Thu, 6 Apr 2017 16:04:14 +0100 Subject: [PATCH 21/46] add audioPacketLoss % display in stats --- interface/resources/qml/Stats.qml | 2 +- interface/src/ui/Stats.cpp | 2 ++ interface/src/ui/Stats.h | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 17e6578e4d..9eb5ba44e0 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -130,7 +130,7 @@ Item { id: pingCol spacing: 4; x: 4; y: 4; StatText { - text: "Audio ping: " + root.audioPing + text: "Audio ping/loss: " + root.audioPing + " / " + root.audioPacketLoss + "%" } StatText { text: "Avatar ping: " + root.avatarPing diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index cedcb923d9..bcb56fc7aa 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -164,7 +164,9 @@ void Stats::updateStats(bool force) { SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer); SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer); SharedNodePointer messageMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer); + auto mixerStream = _audioStats->data()->getMixerStream(); STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1); + STAT_UPDATE(audioPacketLoss, mixerStream ? roundf(mixerStream->lossRateWindow() * 100.0f) : -1); STAT_UPDATE(avatarPing, avatarMixerNode ? avatarMixerNode->getPingMs() : -1); STAT_UPDATE(assetPing, assetServerNode ? assetServerNode->getPingMs() : -1); STAT_UPDATE(messagePing, messageMixerNode ? messageMixerNode->getPingMs() : -1); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index a93a255a06..85cf2caab9 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -81,6 +81,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, audioSilentOutboundPPS, 0) STATS_PROPERTY(int, audioAudioInboundPPS, 0) STATS_PROPERTY(int, audioSilentInboundPPS, 0) + STATS_PROPERTY(int, audioPacketLoss, 0) STATS_PROPERTY(QString, audioCodec, QString()) STATS_PROPERTY(QString, audioNoiseGate, QString()) @@ -204,6 +205,7 @@ signals: void audioSilentOutboundPPSChanged(); void audioAudioInboundPPSChanged(); void audioSilentInboundPPSChanged(); + void audioPacketLossChanged(); void audioCodecChanged(); void audioNoiseGateChanged(); @@ -263,4 +265,3 @@ private: }; #endif // hifi_Stats_h - From 52fd446d4d5bc965acd6d60b11a2d05236206df3 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Apr 2017 22:27:37 +0100 Subject: [PATCH 22/46] toggle goto in tablet --- interface/resources/qml/hifi/Card.qml | 7 +----- .../qml/hifi/tablet/TabletAddressDialog.qml | 25 ++++++++++++++----- interface/src/Application.cpp | 1 + .../src/TabletScriptingInterface.cpp | 2 +- scripts/system/tablet-goto.js | 13 +++++++--- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/interface/resources/qml/hifi/Card.qml b/interface/resources/qml/hifi/Card.qml index 217cfec707..b72901fbdf 100644 --- a/interface/resources/qml/hifi/Card.qml +++ b/interface/resources/qml/hifi/Card.qml @@ -243,12 +243,7 @@ Rectangle { } } } - DropShadow { - anchors.fill: actionIcon - radius: 8.0 - color: "#80000000" - source: actionIcon - } + MouseArea { id: messageArea; width: rectIcon.width; diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index b0b8c68789..fbb78d2694 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -25,22 +25,31 @@ StackView { HifiConstants { id: hifi } HifiStyles.HifiConstants { id: hifiStyleConstants } initialItem: addressBarDialog - width: parent.width - height: parent.height property var eventBridge; property var allStories: []; property int cardWidth: 460; property int cardHeight: 320; property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/"; + property var tablet: null; + property bool isDesktop: false; + Component { id: tabletStoryCard; TabletStoryCard {} } Component.onCompleted: { root.currentItem.focus = true; root.currentItem.forceActiveFocus(); + addressLine.focus = true; + addressLine.forceActiveFocus(); fillDestinations(); updateLocationText(false); root.parentChanged.connect(center); center(); + isDesktop = (typeof desktop !== "undefined"); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + + if (desktop) { + root.title = "GOTO"; + } } Component.onDestruction: { root.parentChanged.disconnect(center); @@ -107,7 +116,6 @@ StackView { imageURL: "../../../images/home.svg" onClicked: { addressBarDialog.loadHome(); - root.shown = false; } anchors { left: parent.left @@ -291,9 +299,8 @@ StackView { left: parent.left right: parent.right leftMargin: 10 - verticalCenter: parent.verticalCenter; - horizontalCenter: parent.horizontalCenter; } + model: suggestions orientation: ListView.Vertical @@ -547,7 +554,13 @@ StackView { if (addressLine.text !== "") { addressBarDialog.loadAddress(addressLine.text, fromSuggestions) } - root.shown = false; + + if (root.desktop) { + tablet.gotoHomeScreen(); + } else { + HMD.closeTablet(); + } + } Keys.onPressed: { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e19eea0a2e..feba5a74a7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2010,6 +2010,7 @@ void Application::initializeUi() { rootContext->setContextProperty("SoundCache", DependencyManager::get().data()); rootContext->setContextProperty("Account", AccountScriptingInterface::getInstance()); + rootContext->setContextProperty("Tablet", DependencyManager::get().data()); rootContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface); rootContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); rootContext->setContextProperty("FaceTracker", DependencyManager::get().data()); diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index 7747e1b6dc..3aa0cc99e7 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -83,7 +83,7 @@ QQuickWindow* TabletScriptingInterface::getTabletWindow() { QObject* qmlSurface = tablet->getTabletSurface(); OffscreenQmlSurface* surface = dynamic_cast(qmlSurface); - if (!surface) { + if (!surface) { return nullptr; } QQuickWindow* window = surface->getWindow(); diff --git a/scripts/system/tablet-goto.js b/scripts/system/tablet-goto.js index eb95d9d8a3..84f7357b1a 100644 --- a/scripts/system/tablet-goto.js +++ b/scripts/system/tablet-goto.js @@ -29,10 +29,15 @@ } function onScreenChanged(type, url) { - // for toolbar mode: change button to active when window is first openend, false otherwise. - button.editProperties({isActive: shouldActivateButton}); - shouldActivateButton = false; - onGotoScreen = false; + if (url === gotoQmlSource) { + onGotoScreen = true; + shouldActivateButton = true; + button.editProperties({isActive: shouldActivateButton}); + } else { + shouldActivateButton = false; + onGotoScreen = false; + button.editProperties({isActive: shouldActivateButton}); + } } var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); From 179a445f597e25feec658b35eb1f2d132c41223c Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 6 Apr 2017 15:21:10 -0700 Subject: [PATCH 23/46] updated connection instructions --- interface/resources/qml/hifi/Pal.qml | 31 +++++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index d627fb54f9..b378ee3c61 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -916,17 +916,28 @@ Rectangle { color: hifi.colors.darkGray wrapMode: Text.WordWrap textFormat: Text.StyledText; + property string hmdMountedInstructions: + "1. Put your hand out onto their hand and squeeze your controller's grip button on its side.
" + + "2. Once the other person puts their hand onto yours, you'll see your connection form.
" + + "3. After about 3 seconds, you're connected!" + property string hmdNotMountedInstructions: + "1. Press and hold the 'x' key to extend your arm.
" + + "2. Once the other person puts their hand onto yours, you'll see your connection form.
" + + "3. After about 3 seconds, you're connected!"; + property string notLoggedInInstructions: "You must be logged into your High Fidelity account to make connections.
" + property string instructions: + "When you meet someone you want to remember later, you can connect with a handshake:

" + // Text - text: HMD.isMounted ? - "When you meet someone you want to remember later, you can connect with a handshake:

" + - "1. Put your hand out onto their hand and squeeze your controller's grip button on its side.
" + - "2. Once the other person puts their hand onto yours, you'll see your connection form.
" + - "3. After about 3 seconds, you're connected!" - : - "When you meet someone you want to remember later, you can connect with a handshake:

" + - "1. Press and hold the 'x' key to extend your arm.
" + - "2. Once the other person puts their hand onto yours, you'll see your connection form.
" + - "3. After about 3 seconds, you're connected!"; + text: + Account.isLoggedIn() ? + HMD.isMounted ? + instructions + hmdMountedInstructions + : instructions + hmdNotMountedInstructions + : + HMD.isMounted ? + notLoggedInInstructions + instructions + hmdMountedInstructions + : notLoggedInInstructions + instructions + hmdNotMountedInstructions } } From 22521526ece9f2b4af843169906c87500911323c Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Apr 2017 23:41:30 +0100 Subject: [PATCH 24/46] removed stray space --- libraries/script-engine/src/TabletScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index 3aa0cc99e7..7747e1b6dc 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -83,7 +83,7 @@ QQuickWindow* TabletScriptingInterface::getTabletWindow() { QObject* qmlSurface = tablet->getTabletSurface(); OffscreenQmlSurface* surface = dynamic_cast(qmlSurface); - if (!surface) { + if (!surface) { return nullptr; } QQuickWindow* window = surface->getWindow(); From f88ba7bc5756d24775ec8960d891d015e40ff20a Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 7 Apr 2017 15:45:33 +0200 Subject: [PATCH 25/46] Yahoo, Reddit etc now works correctly --- interface/resources/qml/TabletBrowser.qml | 7 +------ interface/resources/qml/controls/TabletWebView.qml | 14 +++++++++++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/TabletBrowser.qml b/interface/resources/qml/TabletBrowser.qml index 2650102b27..74318a165e 100644 --- a/interface/resources/qml/TabletBrowser.qml +++ b/interface/resources/qml/TabletBrowser.qml @@ -104,6 +104,7 @@ Item { // Required to support clicking on "hifi://" links if (WebEngineView.LoadStartedStatus == loadRequest.status) { + urlAppend(loadRequest.url.toString()) var url = loadRequest.url.toString(); if (urlHandler.canHandleUrl(url)) { if (urlHandler.handleUrl(url)) { @@ -113,12 +114,6 @@ Item { } } - onNavigationRequested: { - if (request.navigationType == WebEngineNavigationRequest.LinkClickedNavigation) { - pagesModel.append({webUrl: request.url.toString()}) - } - } - onNewViewRequested: { request.openIn(webView); } diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index 50d6e1c504..e5b891777f 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -117,7 +117,7 @@ Item { } function gotoPage(url) { - pagesModel.append({webUrl: url}) + urlAppend(url) } function reloadPage() { @@ -126,9 +126,20 @@ Item { view.setEnabled(true); } + function urlAppend(url) { + var _url = decodeURIComponent(url) + if (_url[_url.length - 1] !== "/") + _url = _url + "/" + if (currentPage === -1 || pagesModel.get(currentPage).webUrl !== _url) { + pagesModel.append({webUrl: _url}) + } + } + onCurrentPageChanged: { if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) { loader.item.url = pagesModel.get(currentPage).webUrl + web.url = loader.item.url + web.address = loader.item.url } } @@ -160,6 +171,7 @@ Item { if (currentPage >= 0) { //we got something to load already item.url = pagesModel.get(currentPage).webUrl + web.address = loader.item.url } } } From fcfd206e9c52601506c3ab3fe73657c18271e07a Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Fri, 7 Apr 2017 17:47:04 +0100 Subject: [PATCH 26/46] change implict conversions --- interface/resources/qml/Stats.qml | 2 +- interface/src/ui/Stats.cpp | 48 +++++++++++++++---------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 9eb5ba44e0..d6459afd08 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -130,7 +130,7 @@ Item { id: pingCol spacing: 4; x: 4; y: 4; StatText { - text: "Audio ping/loss: " + root.audioPing + " / " + root.audioPacketLoss + "%" + text: "Audio ping/loss: " + root.audioPing + "/" + root.audioPacketLoss + "%" } StatText { text: "Avatar ping: " + root.avatarPing diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index bcb56fc7aa..5be29e6391 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -126,7 +126,7 @@ void Stats::updateStats(bool force) { STAT_UPDATE(updatedAvatarCount, avatarManager->getNumAvatarsUpdated()); STAT_UPDATE(notUpdatedAvatarCount, avatarManager->getNumAvatarsNotUpdated()); STAT_UPDATE(serverCount, (int)nodeList->size()); - STAT_UPDATE(framerate, qApp->getFps()); + STAT_UPDATE_FLOAT(framerate, qApp->getFps(), 0.1f); if (qApp->getActiveDisplayPlugin()) { auto displayPlugin = qApp->getActiveDisplayPlugin(); auto stats = displayPlugin->getHardwareStats(); @@ -134,11 +134,11 @@ void Stats::updateStats(bool force) { STAT_UPDATE(longrenders, stats["long_render_count"].toInt()); STAT_UPDATE(longsubmits, stats["long_submit_count"].toInt()); STAT_UPDATE(longframes, stats["long_frame_count"].toInt()); - STAT_UPDATE(renderrate, displayPlugin->renderRate()); - STAT_UPDATE(presentrate, displayPlugin->presentRate()); - STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate()); - STAT_UPDATE(presentdroprate, displayPlugin->droppedFrameRate()); - STAT_UPDATE(stutterrate, displayPlugin->stutterRate()); + STAT_UPDATE_FLOAT(renderrate, displayPlugin->renderRate(), 0.1f); + STAT_UPDATE_FLOAT(presentrate, displayPlugin->presentRate(), 0.1f); + STAT_UPDATE_FLOAT(presentnewrate, displayPlugin->newFramePresentRate(), 0.1f); + STAT_UPDATE_FLOAT(presentdroprate, displayPlugin->droppedFrameRate(), 0.1f); + STAT_UPDATE_FLOAT(stutterrate, displayPlugin->stutterRate(), 0.1f); } else { STAT_UPDATE(appdropped, -1); STAT_UPDATE(longrenders, -1); @@ -151,8 +151,8 @@ void Stats::updateStats(bool force) { STAT_UPDATE(avatarSimrate, (int)qApp->getAvatarSimrate()); auto bandwidthRecorder = DependencyManager::get(); - STAT_UPDATE(packetInCount, bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond()); - STAT_UPDATE(packetOutCount, bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond()); + STAT_UPDATE(packetInCount, (int)bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond()); + STAT_UPDATE(packetOutCount, (int)bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond()); STAT_UPDATE_FLOAT(mbpsIn, (float)bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond() / 1000.0f, 0.01f); STAT_UPDATE_FLOAT(mbpsOut, (float)bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond() / 1000.0f, 0.01f); @@ -166,7 +166,7 @@ void Stats::updateStats(bool force) { SharedNodePointer messageMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer); auto mixerStream = _audioStats->data()->getMixerStream(); STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1); - STAT_UPDATE(audioPacketLoss, mixerStream ? roundf(mixerStream->lossRateWindow() * 100.0f) : -1); + STAT_UPDATE(audioPacketLoss, mixerStream ? (int)roundf(mixerStream->lossRateWindow() * 100.0f) : -1); STAT_UPDATE(avatarPing, avatarMixerNode ? avatarMixerNode->getPingMs() : -1); STAT_UPDATE(assetPing, assetServerNode ? assetServerNode->getPingMs() : -1); STAT_UPDATE(messagePing, messageMixerNode ? messageMixerNode->getPingMs() : -1); @@ -198,36 +198,36 @@ void Stats::updateStats(bool force) { if (_expanded || force) { SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer); if (avatarMixer) { - STAT_UPDATE(avatarMixerInKbps, roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer))); - STAT_UPDATE(avatarMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer))); - STAT_UPDATE(avatarMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer))); - STAT_UPDATE(avatarMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer))); + STAT_UPDATE(avatarMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer))); + STAT_UPDATE(avatarMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer))); + STAT_UPDATE(avatarMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer))); + STAT_UPDATE(avatarMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer))); } else { STAT_UPDATE(avatarMixerInKbps, -1); STAT_UPDATE(avatarMixerInPps, -1); STAT_UPDATE(avatarMixerOutKbps, -1); STAT_UPDATE(avatarMixerOutPps, -1); } - STAT_UPDATE(myAvatarSendRate, avatarManager->getMyAvatarSendRate()); + STAT_UPDATE_FLOAT(myAvatarSendRate, avatarManager->getMyAvatarSendRate(), 0.1f); SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); auto audioClient = DependencyManager::get(); if (audioMixerNode || force) { - STAT_UPDATE(audioMixerKbps, roundf( + STAT_UPDATE(audioMixerKbps, (int)roundf( bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) + bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer))); - STAT_UPDATE(audioMixerPps, roundf( + STAT_UPDATE(audioMixerPps, (int)roundf( bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer) + bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer))); - STAT_UPDATE(audioMixerInKbps, roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer))); - STAT_UPDATE(audioMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer))); - STAT_UPDATE(audioMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer))); - STAT_UPDATE(audioMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer))); - STAT_UPDATE(audioAudioInboundPPS, audioClient->getAudioInboundPPS()); - STAT_UPDATE(audioSilentInboundPPS, audioClient->getSilentInboundPPS()); - STAT_UPDATE(audioOutboundPPS, audioClient->getAudioOutboundPPS()); - STAT_UPDATE(audioSilentOutboundPPS, audioClient->getSilentOutboundPPS()); + STAT_UPDATE(audioMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer))); + STAT_UPDATE(audioMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer))); + STAT_UPDATE(audioMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer))); + STAT_UPDATE(audioMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer))); + STAT_UPDATE(audioAudioInboundPPS, (int)audioClient->getAudioInboundPPS()); + STAT_UPDATE(audioSilentInboundPPS, (int)audioClient->getSilentInboundPPS()); + STAT_UPDATE(audioOutboundPPS, (int)audioClient->getAudioOutboundPPS()); + STAT_UPDATE(audioSilentOutboundPPS, (int)audioClient->getSilentOutboundPPS()); } else { STAT_UPDATE(audioMixerKbps, -1); STAT_UPDATE(audioMixerPps, -1); From 3caea886413f63e6835ece7c3f3858d4f05c3f0e Mon Sep 17 00:00:00 2001 From: Faye Li Date: Fri, 7 Apr 2017 10:02:30 -0700 Subject: [PATCH 27/46] use JS method to enable/disable avatar collisions --- script-archive/selfieStick.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/script-archive/selfieStick.js b/script-archive/selfieStick.js index c6fb9c5349..fd3bb82145 100644 --- a/script-archive/selfieStick.js +++ b/script-archive/selfieStick.js @@ -13,7 +13,6 @@ // // Usage instruction: Spacebar toggles camera control - WASD first person free movement or no movement but allowing others to grab the selfie stick // and control your camera. -// For best result, turn off avatar collisions(Developer > Avatar > Uncheck Enable Avatar Collisions) // (function() { // BEGIN LOCAL_SCOPE @@ -25,12 +24,21 @@ var lensEntityID = null; var freeMovementMode = true; + turnOffAvatarCollisions(); changeAvatar(); importModel(); processImportedEntities(); setupSpaceBarControl(); Script.update.connect(update); + function turnOffAvatarCollisions() { + Menu.setIsOptionChecked("Enable avatar collisions", 0); + } + + function turnOnAvatarCollisions() { + Menu.setIsOptionChecked("Enable avatar collisions", 1); + } + function changeAvatar() { originalAvatar = MyAvatar.skeletonModelURL; MyAvatar.skeletonModelURL = AVATAR_URL; @@ -107,6 +115,7 @@ Camera.mode = "first person"; Controller.disableMapping("Handheld-Cam-Space-Bar"); MyAvatar.skeletonModelURL = originalAvatar; + turnOnAvatarCollisions(); } Script.scriptEnding.connect(cleanup); }()); // END LOCAL_SCOPE \ No newline at end of file From 9a563ba02fc76e06ce100c278c444190ebd95aad Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 7 Apr 2017 19:17:09 +0200 Subject: [PATCH 28/46] Check if offset outside image, set to last image --- interface/resources/qml/hifi/toolbars/StateImage.qml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/toolbars/StateImage.qml b/interface/resources/qml/hifi/toolbars/StateImage.qml index e0389c5e02..ebf1544f2b 100644 --- a/interface/resources/qml/hifi/toolbars/StateImage.qml +++ b/interface/resources/qml/hifi/toolbars/StateImage.qml @@ -12,7 +12,10 @@ Item { property bool pinned: false clip: true - function updateYOffset() { yOffset = size * buttonState; } + function updateYOffset() { + //make sure offset not set outside image + yOffset = (size * buttonState >= image.height) ? image.height - size : size * buttonState + } onButtonStateChanged: updateYOffset(); Component.onCompleted: { From ee9bc0bfa4e6a4a97c05826403e81e2f936375d6 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 7 Apr 2017 10:25:37 -0700 Subject: [PATCH 29/46] updated availability combo dialog --- interface/resources/qml/hifi/ComboDialog.qml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/ComboDialog.qml b/interface/resources/qml/hifi/ComboDialog.qml index 8905ed9c17..e9d32aa7f8 100644 --- a/interface/resources/qml/hifi/ComboDialog.qml +++ b/interface/resources/qml/hifi/ComboDialog.qml @@ -92,8 +92,7 @@ Item { color: selectedOptionIndex === index ? '#cee6ff' : 'white'; Rectangle { id: comboOptionSelected; - visible: selectedOptionIndex === index ? true : false; - color: hifi.colors.blueAccent; + color: selectedOptionIndex == index ? hifi.colors.blueAccent : 'white'; anchors.left: parent.left; anchors.leftMargin: 20; anchors.top: parent.top; @@ -102,7 +101,7 @@ Item { height: width; radius: width; border.width: 3; - border.color: hifi.colors.blueHighlight; + border.color: selectedOptionIndex === index ? hifi.colors.blueHighlight: hifi.colors.lightGrayText; } From a1892b351ff2680ed9786f4ed29b7550eb62e0fc Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Fri, 7 Apr 2017 19:40:46 +0200 Subject: [PATCH 30/46] Cant use underscores outside class internals --- interface/resources/qml/controls/TabletWebView.qml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/controls/TabletWebView.qml b/interface/resources/qml/controls/TabletWebView.qml index e5b891777f..ee26a32a85 100644 --- a/interface/resources/qml/controls/TabletWebView.qml +++ b/interface/resources/qml/controls/TabletWebView.qml @@ -127,11 +127,11 @@ Item { } function urlAppend(url) { - var _url = decodeURIComponent(url) - if (_url[_url.length - 1] !== "/") - _url = _url + "/" - if (currentPage === -1 || pagesModel.get(currentPage).webUrl !== _url) { - pagesModel.append({webUrl: _url}) + var lurl = decodeURIComponent(url) + if (lurl[lurl.length - 1] !== "/") + lurl = lurl + "/" + if (currentPage === -1 || pagesModel.get(currentPage).webUrl !== lurl) { + pagesModel.append({webUrl: lurl}) } } From 870e00331178e253b1863a824473b529764c4090 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 7 Apr 2017 11:12:54 -0700 Subject: [PATCH 31/46] Scattered X glyphs around the letterbox and combo dialogs --- interface/resources/qml/hifi/ComboDialog.qml | 24 +++++++++++++++++++ .../resources/qml/hifi/LetterboxMessage.qml | 22 +++++++++++++++++ interface/resources/qml/hifi/Pal.qml | 4 ++-- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/ComboDialog.qml b/interface/resources/qml/hifi/ComboDialog.qml index e9d32aa7f8..e328805d74 100644 --- a/interface/resources/qml/hifi/ComboDialog.qml +++ b/interface/resources/qml/hifi/ComboDialog.qml @@ -12,6 +12,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "../styles-uit" +import "../controls-uit" Item { property var dialogTitleText : ""; @@ -67,6 +68,29 @@ Item { verticalAlignment: Text.AlignTop; } + HiFiGlyphs { + id: closeGlyphButton; + text: hifi.glyphs.close; + size: 32; + anchors.verticalCenter: dialogTitle.verticalCenter; + anchors.right: parent.right; + anchors.rightMargin: 20; + MouseArea { + anchors.fill: closeGlyphButton; + hoverEnabled: true; + onEntered: { + parent.text = hifi.glyphs.closeInverted; + } + onExited: { + parent.text = hifi.glyphs.close; + } + onClicked: { + combo.visible = false; + } + } + } + + ListModel { id: comboListViewModel; } diff --git a/interface/resources/qml/hifi/LetterboxMessage.qml b/interface/resources/qml/hifi/LetterboxMessage.qml index e50d1de547..754876b2c1 100644 --- a/interface/resources/qml/hifi/LetterboxMessage.qml +++ b/interface/resources/qml/hifi/LetterboxMessage.qml @@ -85,6 +85,28 @@ Item { wrapMode: Text.WordWrap textFormat: Text.StyledText } + HiFiGlyphs { + id: closeGlyphButton + text: hifi.glyphs.close + size: headerTextPixelSize + anchors.top: parent.top + anchors.topMargin: -20 + anchors.right: parent.right + anchors.rightMargin: -25 + MouseArea { + anchors.fill: closeGlyphButton + hoverEnabled: true + onEntered: { + parent.text = hifi.glyphs.closeInverted; + } + onExited: { + parent.text = hifi.glyphs.close; + } + onClicked: { + letterbox.visible = false; + } + } + } } // Popup Text Text { diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 809ff24b62..f97d034db9 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -311,9 +311,9 @@ Rectangle { enabled: activeTab === "connectionsTab"; onClicked: letterbox(hifi.glyphs.question, "Connections and Friends", - "Purple borders around profile pictures are Connections.
" + + "Purple borders around profile pictures represent Connections.
" + "When your availability is set to Everyone, Connections can see your username and location.

" + - "Green borders around profile pictures are Friends.
" + + "Green borders around profile pictures represent Friends.
" + "When your availability is set to Friends, only Friends can see your username and location."); onEntered: connectionsHelpText.color = hifi.colors.blueHighlight; onExited: connectionsHelpText.color = hifi.colors.blueAccent; From 909fda98a48ec9bd6ab57b5fa77f5870e74c66e6 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 7 Apr 2017 21:01:53 +0100 Subject: [PATCH 32/46] git goto button toggle hightlight --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 396f03a1c9..e4f6aa3407 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -560,7 +560,7 @@ StackView { addressBarDialog.loadAddress(addressLine.text, fromSuggestions) } - if (root.desktop) { + if (isDesktop) { tablet.gotoHomeScreen(); } else { HMD.closeTablet(); From cde9310f3e1c56ae6afb8b74012acd3f5ba2b7ba Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 7 Apr 2017 21:35:28 +0100 Subject: [PATCH 33/46] goto home button fix --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index e4f6aa3407..39892f27a4 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -119,6 +119,8 @@ StackView { onClicked: { addressBarDialog.loadHome(); tabletRoot.shown = false; + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet.gotoHomeScreen(); } anchors { left: parent.left From 174b2978e37d08321e292d89db21b88610b8a87a Mon Sep 17 00:00:00 2001 From: David Kelly Date: Fri, 7 Apr 2017 14:01:36 -0700 Subject: [PATCH 34/46] username stays around now when tabbing to connections --- interface/resources/qml/hifi/NameCard.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 3343cec26f..6be85f2ea6 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -302,7 +302,7 @@ Item { height: usernameTextPixelSize + 4 // Anchors anchors.top: isMyCard ? myDisplayName.bottom : pal.activeTab == "nearbyTab" ? displayNameContainer.bottom : undefined //(parent.height - displayNameTextPixelSize/2)); - anchors.verticalCenter: pal.activeTab == "connectionsTab" ? avatarImage.verticalCenter : undefined + anchors.verticalCenter: pal.activeTab == "connectionsTab" && !isMyCard ? avatarImage.verticalCenter : undefined anchors.left: avatarImage.right; anchors.leftMargin: avatarImage.visible ? 5 : 0; anchors.rightMargin: 5; From 40844d2a49a8376bc2ee4cbfa9e48f5584b3f851 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 7 Apr 2017 14:03:31 -0700 Subject: [PATCH 35/46] Added getAbsoluteDefaultJoint*InOjbectFrame to Avatar API. --- interface/src/avatar/Avatar.cpp | 15 +++++++++++++++ interface/src/avatar/Avatar.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ade98c63d8..b9b9a7b912 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -933,6 +933,21 @@ glm::vec3 Avatar::getDefaultJointTranslation(int index) const { return translation; } +glm::quat Avatar::getAbsoluteDefaultJointRotationInObjectFrame(int index) const { + glm::quat rotation; + auto rig = _skeletonModel->getRig(); + glm::quat rot = rig->getAnimSkeleton()->getAbsoluteDefaultPose(index).rot(); + return Quaternions::Y_180 * rot; +} + +glm::vec3 Avatar::getAbsoluteDefaultJointTranslationInObjectFrame(int index) const { + glm::vec3 translation; + auto rig = _skeletonModel->getRig(); + glm::vec3 trans = rig->getAnimSkeleton()->getAbsoluteDefaultPose(index).trans(); + glm::mat4 y180Mat = createMatFromQuatAndPos(Quaternions::Y_180, glm::vec3()); + return transformPoint(y180Mat * rig->getGeometryToRigTransform(), trans); +} + glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const { if (index < 0) { index += numeric_limits::max() + 1; // 65536 diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ba7e1c617e..c81ff95f10 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -121,6 +121,10 @@ public: Q_INVOKABLE virtual glm::quat getDefaultJointRotation(int index) const; Q_INVOKABLE virtual glm::vec3 getDefaultJointTranslation(int index) const; + // in avatar coordinates + Q_INVOKABLE virtual glm::quat getAbsoluteDefaultJointRotationInObjectFrame(int index) const; + Q_INVOKABLE virtual glm::vec3 getAbsoluteDefaultJointTranslationInObjectFrame(int index) const; + virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } From e065c1bac499b432a93dd33a86c20b81d4d2735f Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 7 Apr 2017 14:12:03 -0700 Subject: [PATCH 36/46] Added jsdoc for new Avatar.getAbsoluteDefaultJoint*InObjectFrame API --- interface/src/avatar/Avatar.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index c81ff95f10..fae4cd08be 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -121,8 +121,24 @@ public: Q_INVOKABLE virtual glm::quat getDefaultJointRotation(int index) const; Q_INVOKABLE virtual glm::vec3 getDefaultJointTranslation(int index) const; - // in avatar coordinates + /**jsdoc + * Provides read only access to the default joint rotations in avatar coordinates. + * The default pose of the avatar is defined by the position and orientation of all bones + * in the avatar's model file. Typically this is a t-pose. + * @function Avatar.getAbsoluteDefaultJointRotationInObjectFrame + * @param index {number} index number + * @returns {Quat} The rotation of this joint in avatar coordinates. + */ Q_INVOKABLE virtual glm::quat getAbsoluteDefaultJointRotationInObjectFrame(int index) const; + + /**jsdoc + * Provides read only access to the default joint translations in avatar coordinates. + * The default pose of the avatar is defined by the position and orientation of all bones + * in the avatar's model file. Typically this is a t-pose. + * @function Avatar.getAbsoluteDefaultJointTranslationInObjectFrame + * @param index {number} index number + * @returns {Vec3} The position of this joint in avatar coordinates. + */ Q_INVOKABLE virtual glm::vec3 getAbsoluteDefaultJointTranslationInObjectFrame(int index) const; virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; From a06df1a400686a62a3db7801286a4516bbb79d2f Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 7 Apr 2017 14:13:00 -0700 Subject: [PATCH 37/46] Bug fix for passing quats from script to C++ via the animationStateHandler --- libraries/animation/src/AnimVariant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/AnimVariant.cpp b/libraries/animation/src/AnimVariant.cpp index 911899f5a9..832ab8678c 100644 --- a/libraries/animation/src/AnimVariant.cpp +++ b/libraries/animation/src/AnimVariant.cpp @@ -109,7 +109,7 @@ void AnimVariantMap::animVariantMapFromScriptValue(const QScriptValue& source) { if (z.isNumber()) { QScriptValue w = value.property("w"); if (w.isNumber()) { - set(property.name(), glm::quat(x.toNumber(), y.toNumber(), z.toNumber(), w.toNumber())); + set(property.name(), glm::quat(w.toNumber(), x.toNumber(), y.toNumber(), z.toNumber())); } else { set(property.name(), glm::vec3(x.toNumber(), y.toNumber(), z.toNumber())); } From c32879d807d573fa78a2ac23ccc7081b37fdf588 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Sat, 8 Apr 2017 15:41:11 -0700 Subject: [PATCH 38/46] fix multi-line sessionDisplayName --- assignment-client/src/avatars/AvatarMixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index f09caac4b6..810de73a5e 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -200,7 +200,7 @@ void AvatarMixer::manageDisplayName(const SharedNodePointer& node) { QString baseName = avatar.getDisplayName().trimmed(); const QRegularExpression curses { "fuck|shit|damn|cock|cunt" }; // POC. We may eventually want something much more elaborate (subscription?). baseName = baseName.replace(curses, "*"); // Replace rather than remove, so that people have a clue that the person's a jerk. - const QRegularExpression trailingDigits { "\\s*_\\d+$" }; // whitespace "_123" + const QRegularExpression trailingDigits { "\\s*_\\d+(\\n[^$]*)?$" }; // trailing whitespace "_123" and any subsequent lines baseName = baseName.remove(trailingDigits); if (baseName.isEmpty()) { baseName = "anonymous"; From ec6885a2fbf04f6fa01e2bbae3b54bc6f7c738ec Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sun, 9 Apr 2017 09:49:41 +0100 Subject: [PATCH 39/46] change audioPacketLoss stat to display largest of upstream/downstream loss --- interface/src/ui/Stats.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 5be29e6391..86a3b7af40 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -164,9 +164,11 @@ void Stats::updateStats(bool force) { SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer); SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer); SharedNodePointer messageMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer); - auto mixerStream = _audioStats->data()->getMixerStream(); - STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1); - STAT_UPDATE(audioPacketLoss, mixerStream ? (int)roundf(mixerStream->lossRateWindow() * 100.0f) : -1); + STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1); + int mixerLossRate = (int)roundf(_audioStats->data()->getMixerStream()->lossRateWindow() * 100.0f); + int clientLossRate = (int)roundf(_audioStats->data()->getClientStream()->lossRateWindow() * 100.0f); + int largestLossRate = mixerLossRate > clientLossRate ? mixerLossRate : clientLossRate; + STAT_UPDATE(audioPacketLoss, audioMixerNode ? largestLossRate : -1); STAT_UPDATE(avatarPing, avatarMixerNode ? avatarMixerNode->getPingMs() : -1); STAT_UPDATE(assetPing, assetServerNode ? assetServerNode->getPingMs() : -1); STAT_UPDATE(messagePing, messageMixerNode ? messageMixerNode->getPingMs() : -1); From 54eb7c10c6f59ba794a792a2e43f9a61a1894c31 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sun, 9 Apr 2017 10:50:22 +0100 Subject: [PATCH 40/46] distracted --- interface/src/ui/Stats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 86a3b7af40..6d60969db8 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -165,8 +165,8 @@ void Stats::updateStats(bool force) { SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer); SharedNodePointer messageMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer); STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1); - int mixerLossRate = (int)roundf(_audioStats->data()->getMixerStream()->lossRateWindow() * 100.0f); - int clientLossRate = (int)roundf(_audioStats->data()->getClientStream()->lossRateWindow() * 100.0f); + const int mixerLossRate = (int)roundf(_audioStats->data()->getMixerStream()->lossRateWindow() * 100.0f); + const int clientLossRate = (int)roundf(_audioStats->data()->getClientStream()->lossRateWindow() * 100.0f); int largestLossRate = mixerLossRate > clientLossRate ? mixerLossRate : clientLossRate; STAT_UPDATE(audioPacketLoss, audioMixerNode ? largestLossRate : -1); STAT_UPDATE(avatarPing, avatarMixerNode ? avatarMixerNode->getPingMs() : -1); From 7936637e9c43d8f6b2b89bd4608fa1a75b58552e Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Sun, 9 Apr 2017 11:02:35 +0100 Subject: [PATCH 41/46] and tired.. --- interface/src/ui/Stats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 6d60969db8..dc612b0129 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -167,7 +167,7 @@ void Stats::updateStats(bool force) { STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1); const int mixerLossRate = (int)roundf(_audioStats->data()->getMixerStream()->lossRateWindow() * 100.0f); const int clientLossRate = (int)roundf(_audioStats->data()->getClientStream()->lossRateWindow() * 100.0f); - int largestLossRate = mixerLossRate > clientLossRate ? mixerLossRate : clientLossRate; + const int largestLossRate = mixerLossRate > clientLossRate ? mixerLossRate : clientLossRate; STAT_UPDATE(audioPacketLoss, audioMixerNode ? largestLossRate : -1); STAT_UPDATE(avatarPing, avatarMixerNode ? avatarMixerNode->getPingMs() : -1); STAT_UPDATE(assetPing, assetServerNode ? assetServerNode->getPingMs() : -1); From 3ea6cac45aac79ee125ead7dc5702c11eb02634e Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 10 Apr 2017 08:05:01 -0700 Subject: [PATCH 42/46] HMD.mounted instead of HMD.isMounted --- interface/resources/qml/hifi/Pal.qml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 8814342f02..6f815e79f9 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -921,17 +921,10 @@ Rectangle { property string notLoggedInInstructions: "You must be logged into your High Fidelity account to make connections.
" property string instructions: "When you meet someone you want to remember later, you can connect with a handshake:

" - // Text text: - Account.isLoggedIn() ? - HMD.isMounted ? - instructions + hmdMountedInstructions - : instructions + hmdNotMountedInstructions - : - HMD.isMounted ? - notLoggedInInstructions + instructions + hmdMountedInstructions - : notLoggedInInstructions + instructions + hmdNotMountedInstructions + Account.isLoggedIn() ? ( HMD.mounted ? instructions + hmdMountedInstructions : instructions + hmdNotMountedInstructions) + : ( HMD.mounted ? notLoggedInInstructions + instructions + hmdMountedInstructions : notLoggedInInstructions + instructions + hmdNotMountedInstructions } } From 54888f85bec049e0ffb35439af39de7cae42fd83 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 10 Apr 2017 08:41:50 -0700 Subject: [PATCH 43/46] strip more --- assignment-client/src/avatars/AvatarMixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 810de73a5e..f3da74ce5e 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -200,7 +200,7 @@ void AvatarMixer::manageDisplayName(const SharedNodePointer& node) { QString baseName = avatar.getDisplayName().trimmed(); const QRegularExpression curses { "fuck|shit|damn|cock|cunt" }; // POC. We may eventually want something much more elaborate (subscription?). baseName = baseName.replace(curses, "*"); // Replace rather than remove, so that people have a clue that the person's a jerk. - const QRegularExpression trailingDigits { "\\s*_\\d+(\\n[^$]*)?$" }; // trailing whitespace "_123" and any subsequent lines + const QRegularExpression trailingDigits { "\\s*(_\\d+\\s*)?(\\s*\\n[^$]*)?$" }; // trailing whitespace "_123" and any subsequent lines baseName = baseName.remove(trailingDigits); if (baseName.isEmpty()) { baseName = "anonymous"; From 36940b4dfe1fabcbc4e00932b76271795653b3a7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 10 Apr 2017 09:11:23 -0700 Subject: [PATCH 44/46] revert commit that broke sendToScript --- libraries/gl/src/gl/OffscreenGLCanvas.cpp | 2 -- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 6 +----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/libraries/gl/src/gl/OffscreenGLCanvas.cpp b/libraries/gl/src/gl/OffscreenGLCanvas.cpp index e5c630d97e..3f1d629638 100644 --- a/libraries/gl/src/gl/OffscreenGLCanvas.cpp +++ b/libraries/gl/src/gl/OffscreenGLCanvas.cpp @@ -59,8 +59,6 @@ bool OffscreenGLCanvas::create(QOpenGLContext* sharedContext) { bool OffscreenGLCanvas::makeCurrent() { bool result = _context->makeCurrent(_offscreenSurface); - Q_ASSERT(result); - std::call_once(_reportOnce, [this]{ qCDebug(glLogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION)); qCDebug(glLogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION)); diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 16e32ab42e..3bbd26e010 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -612,11 +612,7 @@ QObject* OffscreenQmlSurface::finishQmlLoad(std::functionmetaObject()->indexOfSignal("sendToScript"); - if (sendToScriptIndex != -1) { - connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant))); - } + connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant))); // The root item is ready. Associate it with the window. _rootItem = newItem; From 0ca0874c524ab9c7a91f9bac623d76769e4e85a1 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 7 Dec 2016 14:36:53 -0800 Subject: [PATCH 45/46] Creating new avatar rendering library, prepping for crowd rendering project --- interface/CMakeLists.txt | 2 +- libraries/avatars-renderer/CMakeLists.txt | 6 ++++++ .../src/AvatarsRendererLogging.cpp | 11 +++++++++++ .../src/AvatarsRendererLogging.h | 16 ++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 libraries/avatars-renderer/CMakeLists.txt create mode 100644 libraries/avatars-renderer/src/AvatarsRendererLogging.cpp create mode 100644 libraries/avatars-renderer/src/AvatarsRendererLogging.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 726aa7ef84..ac44be18f2 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -192,7 +192,7 @@ link_hifi_libraries( shared octree ktx gpu gl gpu-gl procedural model render recording fbx networking model-networking entities avatars audio audio-client animation script-engine physics - render-utils entities-renderer ui auto-updater + render-utils entities-renderer avatars-renderer ui auto-updater controllers plugins ui-plugins display-plugins input-plugins ${NON_ANDROID_LIBRARIES} diff --git a/libraries/avatars-renderer/CMakeLists.txt b/libraries/avatars-renderer/CMakeLists.txt new file mode 100644 index 0000000000..bee2cb31d6 --- /dev/null +++ b/libraries/avatars-renderer/CMakeLists.txt @@ -0,0 +1,6 @@ +set(TARGET_NAME avatars-renderer) +AUTOSCRIBE_SHADER_LIB(gpu model render render-utils) +setup_hifi_library(Widgets Network Script) +link_hifi_libraries(shared gpu model animation physics model-networking script-engine render render-utils) + +target_bullet() diff --git a/libraries/avatars-renderer/src/AvatarsRendererLogging.cpp b/libraries/avatars-renderer/src/AvatarsRendererLogging.cpp new file mode 100644 index 0000000000..2804df1b7a --- /dev/null +++ b/libraries/avatars-renderer/src/AvatarsRendererLogging.cpp @@ -0,0 +1,11 @@ +// +// Created by Bradley Austin Davis on 2016/12/06 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AvatarsRendererLogging.h" + +Q_LOGGING_CATEGORY(avatars_renderer, "hifi.avatars.rendering") diff --git a/libraries/avatars-renderer/src/AvatarsRendererLogging.h b/libraries/avatars-renderer/src/AvatarsRendererLogging.h new file mode 100644 index 0000000000..a1cfd8d9e4 --- /dev/null +++ b/libraries/avatars-renderer/src/AvatarsRendererLogging.h @@ -0,0 +1,16 @@ +// +// Created by Bradley Austin Davis on 2016/12/06 +// Copyright 2013-2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AvatarsRendererLogging_h +#define hifi_AvatarsRendererLogging_h + +#include + +Q_DECLARE_LOGGING_CATEGORY(avatars_renderer) + +#endif // hifi_AvatarsRendererLogging_h From 082d0964d26859c77140205527557ff9c7cf3835 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Mon, 10 Apr 2017 11:08:45 -0700 Subject: [PATCH 46/46] oops --- interface/resources/qml/hifi/Pal.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 6f815e79f9..1e72d71b18 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -924,7 +924,7 @@ Rectangle { // Text text: Account.isLoggedIn() ? ( HMD.mounted ? instructions + hmdMountedInstructions : instructions + hmdNotMountedInstructions) - : ( HMD.mounted ? notLoggedInInstructions + instructions + hmdMountedInstructions : notLoggedInInstructions + instructions + hmdNotMountedInstructions + : ( HMD.mounted ? notLoggedInInstructions + instructions + hmdMountedInstructions : notLoggedInInstructions + instructions + hmdNotMountedInstructions) } }