From 460eaa515bf0a4fbcd166206d456bb5d2c9506dc Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 10 Aug 2015 14:19:25 -0700 Subject: [PATCH 01/57] adding direction spread --- libraries/entities/src/ParticleEffectEntityItem.cpp | 5 +++++ libraries/entities/src/ParticleEffectEntityItem.h | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index dc5bbb85ed..7909606f8d 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -50,6 +50,7 @@ const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION(0.0f, 1.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_DIRECTION_SPREAD(0.0f, 0.0f, 0.0f); const float ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH = 25.0f; const float ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY = -9.8f; const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; @@ -107,6 +108,10 @@ void ParticleEffectEntityItem::setEmitDirection(glm::vec3 emitDirection) { computeAndUpdateDimensions(); } +void ParticleEffectEntityItem::setDirectionSpread(glm::vec3 directionSpread) { + _directionSpread = directionSpread; +} + void ParticleEffectEntityItem::setEmitStrength(float emitStrength) { _emitStrength = emitStrength; computeAndUpdateDimensions(); diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 994c609f0f..651dc55616 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -103,6 +103,11 @@ public: static const glm::vec3 DEFAULT_EMIT_DIRECTION; void setEmitDirection(glm::vec3 emitDirection); const glm::vec3& getEmitDirection() const { return _emitDirection; } + + + static const glm::vec3 DEFAULT_DIRECTION_SPREAD; + void setDirectionSpread(glm::vec3 directionSpread); + const glm::vec3& getDirectionSpread() const { return _directionSpread; } static const float DEFAULT_EMIT_STRENGTH; void setEmitStrength(float emitStrength); @@ -146,6 +151,7 @@ protected: float _lifespan; float _emitRate; glm::vec3 _emitDirection; + glm::vec3 _directionSpread; float _emitStrength; float _localGravity; float _particleRadius; From 23dcc647c4deb5f7271b25f2d12245da2d226389 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 10 Aug 2015 15:00:21 -0700 Subject: [PATCH 02/57] adding more for direction spread --- libraries/entities/src/EntityItemProperties.cpp | 1 + libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityPropertyFlags.h | 3 +++ libraries/entities/src/ParticleEffectEntityItem.cpp | 5 +++++ 4 files changed, 10 insertions(+) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4e7228e573..cd470dcee2 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -84,6 +84,7 @@ CONSTRUCT_PROPERTY(maxParticles, ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), CONSTRUCT_PROPERTY(emitDirection, ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION), +CONSTRUCT_PROPERTY(directionSpread, ParticleEffectEntityItem::DEFAULT_DIRECTION_SPREAD), CONSTRUCT_PROPERTY(emitStrength, ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH), CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 3ce6040d19..8236f3bb67 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -131,6 +131,7 @@ public: DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float); DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); DEFINE_PROPERTY_REF(PROP_EMIT_DIRECTION, EmitDirection, emitDirection, glm::vec3); + DEFINE_PROPERTY_REF(PROP_DIRECTION_SPREAD, DirectionSpread, directionSpread, glm::vec3); DEFINE_PROPERTY(PROP_EMIT_STRENGTH, EmitStrength, emitStrength, float); DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float); DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index be16683f39..99aa30327b 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -125,6 +125,9 @@ enum EntityPropertyList { PROP_FACE_CAMERA, PROP_SCRIPT_TIMESTAMP, PROP_ACTION_DATA, + + // used by particles + PROP_DIRECTION_SPREAD, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 7909606f8d..5ecc1384cd 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -207,6 +207,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(localGravity, setLocalGravity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(directionSpread, setDirectionSpread); if (somethingChanged) { bool wantDebug = false; @@ -262,6 +263,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, setLocalGravity); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); + READ_ENTITY_PROPERTY(PROP_DIRECTION_SPREAD, glm::vec3, setDirectionSpread); return bytesRead; } @@ -285,6 +287,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_LOCAL_GRAVITY; requestedProperties += PROP_PARTICLE_RADIUS; requestedProperties += PROP_TEXTURES; + requestedProperties += PROP_DIRECTION_SPREAD; return requestedProperties; } @@ -312,6 +315,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, getLocalGravity()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, getParticleRadius()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures()); + APPEND_ENTITY_PROPERTY(PROP_DIRECTION_SPREAD, getDirectionSpread()); } bool ParticleEffectEntityItem::isAnimatingSomething() const { @@ -532,6 +536,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // jitter the _emitDirection by a random offset glm::vec3 randOffset; + qDebug() << "direction spread " << _directionSpread.x; randOffset.x = (randFloat() - 0.5f) * 0.25f * _emitStrength; randOffset.y = (randFloat() - 0.5f) * 0.25f * _emitStrength; randOffset.z = (randFloat() - 0.5f) * 0.25f * _emitStrength; From d568e20e147d02c05160f125be68ab22da1e7170 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 10 Aug 2015 15:06:08 -0700 Subject: [PATCH 03/57] spread going accross wire --- libraries/entities/src/EntityItemProperties.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index cd470dcee2..d554bea415 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -345,6 +345,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_LIFESPAN, lifespan); CHECK_PROPERTY_CHANGE(PROP_EMIT_RATE, emitRate); CHECK_PROPERTY_CHANGE(PROP_EMIT_DIRECTION, emitDirection); + CHECK_PROPERTY_CHANGE(PROP_DIRECTION_SPREAD, directionSpread); CHECK_PROPERTY_CHANGE(PROP_EMIT_STRENGTH, emitStrength); CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); @@ -442,6 +443,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(lifespan); COPY_PROPERTY_TO_QSCRIPTVALUE(emitRate); COPY_PROPERTY_TO_QSCRIPTVALUE(emitDirection); + COPY_PROPERTY_TO_QSCRIPTVALUE(directionSpread); COPY_PROPERTY_TO_QSCRIPTVALUE(emitStrength); COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity); COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); @@ -556,6 +558,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(lifespan, float, setLifespan); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitDirection, glmVec3, setEmitDirection); + COPY_PROPERTY_FROM_QSCRIPTVALUE(directionSpread, glmVec3, setDirectionSpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitStrength, float, setEmitStrength); COPY_PROPERTY_FROM_QSCRIPTVALUE(localGravity, float, setLocalGravity); COPY_PROPERTY_FROM_QSCRIPTVALUE(particleRadius, float, setParticleRadius); @@ -789,9 +792,11 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, properties.getLifespan()); APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, properties.getEmitRate()); APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, properties.getEmitDirection()); + APPEND_ENTITY_PROPERTY(PROP_DIRECTION_SPREAD, properties.getDirectionSpread()); APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, properties.getEmitStrength()); APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, properties.getLocalGravity()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius()); + } if (properties.getType() == EntityTypes::Zone) { @@ -1046,6 +1051,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DIRECTION_SPREAD, glm::vec3, setDirectionSpread); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_STRENGTH, float, setEmitStrength); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); @@ -1166,6 +1172,7 @@ void EntityItemProperties::markAllChanged() { _lifespanChanged = true; _emitRateChanged = true; _emitDirectionChanged = true; + _directionSpreadChanged = true; _emitStrengthChanged = true; _localGravityChanged = true; _particleRadiusChanged = true; From d341dc337de9e99e469a5d5d594d94c85b3ea71a Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 10 Aug 2015 15:48:28 -0700 Subject: [PATCH 04/57] added direction spread property to particle entity to enable users to create more varied effects (such as falling snow --- libraries/entities/src/ParticleEffectEntityItem.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 5ecc1384cd..c626b88735 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -536,10 +536,10 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // jitter the _emitDirection by a random offset glm::vec3 randOffset; - qDebug() << "direction spread " << _directionSpread.x; - randOffset.x = (randFloat() - 0.5f) * 0.25f * _emitStrength; - randOffset.y = (randFloat() - 0.5f) * 0.25f * _emitStrength; - randOffset.z = (randFloat() - 0.5f) * 0.25f * _emitStrength; + randOffset.x = -_directionSpread.x + randFloat() * (_directionSpread.x * 2.0f); + randOffset.y = -_directionSpread.y + randFloat() * (_directionSpread.y * 2.0f); + randOffset.z = -_directionSpread.z + randFloat() * (_directionSpread.z * 2.0f); + // set initial conditions _particlePositions[i] = glm::vec3(0.0f, 0.0f, 0.0f); From ddaba19a4e07a7419a6daf25adc63e7335b673b6 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 11 Aug 2015 14:43:05 -0700 Subject: [PATCH 05/57] chaning to velocity from direction --- .../entities/src/EntityItemProperties.cpp | 7 --- libraries/entities/src/EntityItemProperties.h | 2 - .../entities/src/ParticleEffectEntityItem.cpp | 59 +------------------ .../entities/src/ParticleEffectEntityItem.h | 7 --- 4 files changed, 2 insertions(+), 73 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 9302ed5049..c4364858e8 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -86,7 +86,6 @@ CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), CONSTRUCT_PROPERTY(emitDirection, ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION), CONSTRUCT_PROPERTY(directionSpread, ParticleEffectEntityItem::DEFAULT_DIRECTION_SPREAD), -CONSTRUCT_PROPERTY(emitStrength, ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH), CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), @@ -352,7 +351,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_EMIT_RATE, emitRate); CHECK_PROPERTY_CHANGE(PROP_EMIT_DIRECTION, emitDirection); CHECK_PROPERTY_CHANGE(PROP_DIRECTION_SPREAD, directionSpread); - CHECK_PROPERTY_CHANGE(PROP_EMIT_STRENGTH, emitStrength); CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID); @@ -455,7 +453,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(emitRate); COPY_PROPERTY_TO_QSCRIPTVALUE(emitDirection); COPY_PROPERTY_TO_QSCRIPTVALUE(directionSpread); - COPY_PROPERTY_TO_QSCRIPTVALUE(emitStrength); COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity); COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID); @@ -576,7 +573,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitDirection, glmVec3, setEmitDirection); COPY_PROPERTY_FROM_QSCRIPTVALUE(directionSpread, glmVec3, setDirectionSpread); - COPY_PROPERTY_FROM_QSCRIPTVALUE(emitStrength, float, setEmitStrength); COPY_PROPERTY_FROM_QSCRIPTVALUE(localGravity, float, setLocalGravity); COPY_PROPERTY_FROM_QSCRIPTVALUE(particleRadius, float, setParticleRadius); COPY_PROPERTY_FROM_QSCRIPTVALUE(marketplaceID, QString, setMarketplaceID); @@ -818,7 +814,6 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, properties.getEmitRate()); APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, properties.getEmitDirection()); APPEND_ENTITY_PROPERTY(PROP_DIRECTION_SPREAD, properties.getDirectionSpread()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, properties.getEmitStrength()); APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, properties.getLocalGravity()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius()); @@ -1088,7 +1083,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DIRECTION_SPREAD, glm::vec3, setDirectionSpread); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_STRENGTH, float, setEmitStrength); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); } @@ -1220,7 +1214,6 @@ void EntityItemProperties::markAllChanged() { _emitRateChanged = true; _emitDirectionChanged = true; _directionSpreadChanged = true; - _emitStrengthChanged = true; _localGravityChanged = true; _particleRadiusChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index a3f512b36e..4ebe29eda9 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -133,7 +133,6 @@ public: DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); DEFINE_PROPERTY_REF(PROP_EMIT_DIRECTION, EmitDirection, emitDirection, glm::vec3); DEFINE_PROPERTY_REF(PROP_DIRECTION_SPREAD, DirectionSpread, directionSpread, glm::vec3); - DEFINE_PROPERTY(PROP_EMIT_STRENGTH, EmitStrength, emitStrength, float); DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float); DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); @@ -313,7 +312,6 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifespan, lifespan, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRate, emitRate, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitDirection, emitDirection, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitStrength, emitStrength, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, ""); diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index e1019efba5..403d9e4df5 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -52,7 +52,6 @@ const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION(0.0f, 1.0f, 0.0f); const glm::vec3 ParticleEffectEntityItem::DEFAULT_DIRECTION_SPREAD(0.0f, 0.0f, 0.0f); -const float ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH = 25.0f; const float ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY = -9.8f; const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = ""; @@ -69,7 +68,6 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte _lifespan(DEFAULT_LIFESPAN), _emitRate(DEFAULT_EMIT_RATE), _emitDirection(DEFAULT_EMIT_DIRECTION), - _emitStrength(DEFAULT_EMIT_STRENGTH), _localGravity(DEFAULT_LOCAL_GRAVITY), _particleRadius(DEFAULT_PARTICLE_RADIUS), _lastAnimated(usecTimestampNow()), @@ -95,78 +93,29 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte ParticleEffectEntityItem::~ParticleEffectEntityItem() { } -void ParticleEffectEntityItem::setDimensions(const glm::vec3& value) { - computeAndUpdateDimensions(); -} void ParticleEffectEntityItem::setLifespan(float lifespan) { _lifespan = lifespan; - computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setEmitDirection(glm::vec3 emitDirection) { _emitDirection = glm::normalize(emitDirection); - computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setDirectionSpread(glm::vec3 directionSpread) { _directionSpread = directionSpread; } -void ParticleEffectEntityItem::setEmitStrength(float emitStrength) { - _emitStrength = emitStrength; - computeAndUpdateDimensions(); -} void ParticleEffectEntityItem::setLocalGravity(float localGravity) { _localGravity = localGravity; - computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { _particleRadius = particleRadius; - computeAndUpdateDimensions(); } -void ParticleEffectEntityItem::computeAndUpdateDimensions() { - const float t = _lifespan * 1.1f; // add 10% extra time, to account for incremental timer accumulation error. - const float MAX_RANDOM_FACTOR = (0.5f * 0.25f); - const float maxOffset = (MAX_RANDOM_FACTOR * _emitStrength) + _particleRadius; - - // bounds for x and z is easy to compute because there is no at^2 term. - float xMax = (_emitDirection.x * _emitStrength + maxOffset) * t; - float xMin = (_emitDirection.x * _emitStrength - maxOffset) * t; - - float zMax = (_emitDirection.z * _emitStrength + maxOffset) * t; - float zMin = (_emitDirection.z * _emitStrength - maxOffset) * t; - - // yEnd is where the particle will end. - float a = _localGravity; - float atSquared = a * t * t; - float v = _emitDirection.y * _emitStrength + maxOffset; - float vt = v * t; - float yEnd = 0.5f * atSquared + vt; - - // yApex is where the particle is at it's apex. - float yApexT = (-v / a); - float yApex = 0.0f; - - // only set apex if it's within the lifespan of the particle. - if (yApexT >= 0.0f && yApexT <= t) { - yApex = -(v * v) / (2.0f * a); - } - - float yMax = std::max(yApex, yEnd); - float yMin = std::min(yApex, yEnd); - - // times 2 because dimensions are diameters not radii. - glm::vec3 dims(2.0f * std::max(fabsf(xMin), fabsf(xMax)), - 2.0f * std::max(fabsf(yMin), fabsf(yMax)), - 2.0f * std::max(fabsf(zMin), fabsf(zMax))); - - EntityItem::setDimensions(dims); -} EntityItemProperties ParticleEffectEntityItem::getProperties() const { EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class @@ -182,7 +131,7 @@ EntityItemProperties ParticleEffectEntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRate, getEmitRate); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitDirection, getEmitDirection); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitStrength, getEmitStrength); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(localGravity, getLocalGravity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius); COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures); @@ -204,7 +153,6 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitDirection, setEmitDirection); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitStrength, setEmitStrength); SET_ENTITY_PROPERTY_FROM_PROPERTIES(localGravity, setLocalGravity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); @@ -260,7 +208,6 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); READ_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); - READ_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, float, setEmitStrength); READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, setLocalGravity); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); @@ -284,7 +231,6 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_LIFESPAN; requestedProperties += PROP_EMIT_RATE; requestedProperties += PROP_EMIT_DIRECTION; - requestedProperties += PROP_EMIT_STRENGTH; requestedProperties += PROP_LOCAL_GRAVITY; requestedProperties += PROP_PARTICLE_RADIUS; requestedProperties += PROP_TEXTURES; @@ -312,7 +258,6 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, getLifespan()); APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, getEmitRate()); APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, getEmitDirection()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, getEmitStrength()); APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, getLocalGravity()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, getParticleRadius()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures()); @@ -544,7 +489,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // set initial conditions _particlePositions[i] = glm::vec3(0.0f, 0.0f, 0.0f); - _particleVelocities[i] = _emitDirection * _emitStrength + randOffset; + _particleVelocities[i] = _emitDirection + randOffset; integrateParticle(i, timeLeftInFrame); extendBounds(_particlePositions[i]); diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 651dc55616..584bc7beff 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -86,8 +86,6 @@ public: void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); } float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } - virtual void setDimensions(const glm::vec3& value) override; - static const quint32 DEFAULT_MAX_PARTICLES; void setMaxParticles(quint32 maxParticles); quint32 getMaxParticles() const { return _maxParticles; } @@ -109,9 +107,6 @@ public: void setDirectionSpread(glm::vec3 directionSpread); const glm::vec3& getDirectionSpread() const { return _directionSpread; } - static const float DEFAULT_EMIT_STRENGTH; - void setEmitStrength(float emitStrength); - float getEmitStrength() const { return _emitStrength; } static const float DEFAULT_LOCAL_GRAVITY; void setLocalGravity(float localGravity); @@ -121,7 +116,6 @@ public: void setParticleRadius(float particleRadius); float getParticleRadius() const { return _particleRadius; } - void computeAndUpdateDimensions(); bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); } float getAnimationFrameIndex() const { return _animationLoop.getFrameIndex(); } @@ -152,7 +146,6 @@ protected: float _emitRate; glm::vec3 _emitDirection; glm::vec3 _directionSpread; - float _emitStrength; float _localGravity; float _particleRadius; quint64 _lastAnimated; From c2915fc0f582020edbe9c9e74f6a480ebc27f0b0 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 11 Aug 2015 15:16:36 -0700 Subject: [PATCH 06/57] changing to velocity spread --- .../entities/src/EntityItemProperties.cpp | 28 ++++++------- libraries/entities/src/EntityItemProperties.h | 6 +-- libraries/entities/src/EntityPropertyFlags.h | 6 +-- .../entities/src/ParticleEffectEntityItem.cpp | 42 +++++++++---------- .../entities/src/ParticleEffectEntityItem.h | 16 +++---- 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index c4364858e8..ddf7257775 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -84,8 +84,8 @@ CONSTRUCT_PROPERTY(shapeType, SHAPE_TYPE_NONE), CONSTRUCT_PROPERTY(maxParticles, ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES), CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), -CONSTRUCT_PROPERTY(emitDirection, ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION), -CONSTRUCT_PROPERTY(directionSpread, ParticleEffectEntityItem::DEFAULT_DIRECTION_SPREAD), +CONSTRUCT_PROPERTY(emitVelocity, ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY), +CONSTRUCT_PROPERTY(velocitySpread, ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD), CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), @@ -349,8 +349,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_MAX_PARTICLES, maxParticles); CHECK_PROPERTY_CHANGE(PROP_LIFESPAN, lifespan); CHECK_PROPERTY_CHANGE(PROP_EMIT_RATE, emitRate); - CHECK_PROPERTY_CHANGE(PROP_EMIT_DIRECTION, emitDirection); - CHECK_PROPERTY_CHANGE(PROP_DIRECTION_SPREAD, directionSpread); + CHECK_PROPERTY_CHANGE(PROP_EMIT_VELOCITY, emitVelocity); + CHECK_PROPERTY_CHANGE(PROP_VELOCITY_SPREAD, velocitySpread); CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID); @@ -451,8 +451,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(maxParticles); COPY_PROPERTY_TO_QSCRIPTVALUE(lifespan); COPY_PROPERTY_TO_QSCRIPTVALUE(emitRate); - COPY_PROPERTY_TO_QSCRIPTVALUE(emitDirection); - COPY_PROPERTY_TO_QSCRIPTVALUE(directionSpread); + COPY_PROPERTY_TO_QSCRIPTVALUE(emitVelocity); + COPY_PROPERTY_TO_QSCRIPTVALUE(velocitySpread); COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity); COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID); @@ -571,8 +571,8 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, float, setMaxParticles); COPY_PROPERTY_FROM_QSCRIPTVALUE(lifespan, float, setLifespan); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate); - COPY_PROPERTY_FROM_QSCRIPTVALUE(emitDirection, glmVec3, setEmitDirection); - COPY_PROPERTY_FROM_QSCRIPTVALUE(directionSpread, glmVec3, setDirectionSpread); + COPY_PROPERTY_FROM_QSCRIPTVALUE(emitVelocity, glmVec3, setEmitVelocity); + COPY_PROPERTY_FROM_QSCRIPTVALUE(velocitySpread, glmVec3, setVelocitySpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(localGravity, float, setLocalGravity); COPY_PROPERTY_FROM_QSCRIPTVALUE(particleRadius, float, setParticleRadius); COPY_PROPERTY_FROM_QSCRIPTVALUE(marketplaceID, QString, setMarketplaceID); @@ -812,8 +812,8 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, properties.getMaxParticles()); APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, properties.getLifespan()); APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, properties.getEmitRate()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, properties.getEmitDirection()); - APPEND_ENTITY_PROPERTY(PROP_DIRECTION_SPREAD, properties.getDirectionSpread()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, properties.getEmitVelocity()); + APPEND_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, properties.getVelocitySpread()); APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, properties.getLocalGravity()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius()); @@ -1081,8 +1081,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DIRECTION_SPREAD, glm::vec3, setDirectionSpread); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); } @@ -1212,8 +1212,8 @@ void EntityItemProperties::markAllChanged() { _maxParticlesChanged = true; _lifespanChanged = true; _emitRateChanged = true; - _emitDirectionChanged = true; - _directionSpreadChanged = true; + _emitVelocityChanged = true; + _velocitySpreadChanged = true; _localGravityChanged = true; _particleRadiusChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 4ebe29eda9..db4ebb9229 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -131,8 +131,8 @@ public: DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32); DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float); DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); - DEFINE_PROPERTY_REF(PROP_EMIT_DIRECTION, EmitDirection, emitDirection, glm::vec3); - DEFINE_PROPERTY_REF(PROP_DIRECTION_SPREAD, DirectionSpread, directionSpread, glm::vec3); + DEFINE_PROPERTY_REF(PROP_EMIT_VELOCITY, EmitVelocity, emitVelocity, glm::vec3); + DEFINE_PROPERTY_REF(PROP_VELOCITY_SPREAD, VelocitySpread, velocitySpread, glm::vec3); DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float); DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); @@ -311,7 +311,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, MaxParticles, maxParticles, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifespan, lifespan, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRate, emitRate, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitDirection, emitDirection, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitVelocity, emitVelocity, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 6c32b39700..66a3fcb2f6 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -96,7 +96,7 @@ enum EntityPropertyList { PROP_MAX_PARTICLES, PROP_LIFESPAN, PROP_EMIT_RATE, - PROP_EMIT_DIRECTION, + PROP_EMIT_VELOCITY, PROP_EMIT_STRENGTH, PROP_LOCAL_GRAVITY, PROP_PARTICLE_RADIUS, @@ -136,7 +136,7 @@ enum EntityPropertyList { PROP_STROKE_WIDTHS, // used by particles - PROP_DIRECTION_SPREAD, + PROP_VELOCITY_SPREAD, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line @@ -170,7 +170,7 @@ enum EntityPropertyList { PROP_ATMOSPHERE_CENTER = PROP_MAX_PARTICLES, PROP_ATMOSPHERE_INNER_RADIUS = PROP_LIFESPAN, PROP_ATMOSPHERE_OUTER_RADIUS = PROP_EMIT_RATE, - PROP_ATMOSPHERE_MIE_SCATTERING = PROP_EMIT_DIRECTION, + PROP_ATMOSPHERE_MIE_SCATTERING = PROP_EMIT_VELOCITY, PROP_ATMOSPHERE_RAYLEIGH_SCATTERING = PROP_EMIT_STRENGTH, PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS = PROP_LOCAL_GRAVITY, PROP_ATMOSPHERE_HAS_STARS = PROP_PARTICLE_RADIUS, diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 403d9e4df5..99a1e7d2ab 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -50,8 +50,8 @@ const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f; const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; -const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION(0.0f, 1.0f, 0.0f); -const glm::vec3 ParticleEffectEntityItem::DEFAULT_DIRECTION_SPREAD(0.0f, 0.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY(0.0f, 0.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(0.0f, 0.0f, 0.0f); const float ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY = -9.8f; const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = ""; @@ -67,7 +67,7 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte _maxParticles(DEFAULT_MAX_PARTICLES), _lifespan(DEFAULT_LIFESPAN), _emitRate(DEFAULT_EMIT_RATE), - _emitDirection(DEFAULT_EMIT_DIRECTION), + _emitVelocity(DEFAULT_EMIT_VELOCITY), _localGravity(DEFAULT_LOCAL_GRAVITY), _particleRadius(DEFAULT_PARTICLE_RADIUS), _lastAnimated(usecTimestampNow()), @@ -98,12 +98,12 @@ void ParticleEffectEntityItem::setLifespan(float lifespan) { _lifespan = lifespan; } -void ParticleEffectEntityItem::setEmitDirection(glm::vec3 emitDirection) { - _emitDirection = glm::normalize(emitDirection); +void ParticleEffectEntityItem::setEmitVelocity(glm::vec3 emitVelocity) { + _emitVelocity = emitVelocity; } -void ParticleEffectEntityItem::setDirectionSpread(glm::vec3 directionSpread) { - _directionSpread = directionSpread; +void ParticleEffectEntityItem::setVelocitySpread(glm::vec3 velocitySpread) { + _velocitySpread = velocitySpread; } @@ -130,7 +130,7 @@ EntityItemProperties ParticleEffectEntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRate, getEmitRate); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitDirection, getEmitDirection); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitVelocity, getEmitVelocity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(localGravity, getLocalGravity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius); @@ -152,11 +152,11 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxParticles, setMaxParticles); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitDirection, setEmitDirection); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitVelocity, setEmitVelocity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(localGravity, setLocalGravity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(directionSpread, setDirectionSpread); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocitySpread, setVelocitySpread); if (somethingChanged) { bool wantDebug = false; @@ -207,11 +207,11 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); - READ_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); + READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, setLocalGravity); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); - READ_ENTITY_PROPERTY(PROP_DIRECTION_SPREAD, glm::vec3, setDirectionSpread); + READ_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); return bytesRead; } @@ -230,11 +230,11 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_MAX_PARTICLES; requestedProperties += PROP_LIFESPAN; requestedProperties += PROP_EMIT_RATE; - requestedProperties += PROP_EMIT_DIRECTION; + requestedProperties += PROP_EMIT_VELOCITY; requestedProperties += PROP_LOCAL_GRAVITY; requestedProperties += PROP_PARTICLE_RADIUS; requestedProperties += PROP_TEXTURES; - requestedProperties += PROP_DIRECTION_SPREAD; + requestedProperties += PROP_VELOCITY_SPREAD; return requestedProperties; } @@ -257,11 +257,11 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, getMaxParticles()); APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, getLifespan()); APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, getEmitRate()); - APPEND_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, getEmitDirection()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, getEmitVelocity()); APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, getLocalGravity()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, getParticleRadius()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures()); - APPEND_ENTITY_PROPERTY(PROP_DIRECTION_SPREAD, getDirectionSpread()); + APPEND_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, getVelocitySpread()); } bool ParticleEffectEntityItem::isAnimatingSomething() const { @@ -480,16 +480,16 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { quint32 i = _particleTailIndex; _particleLifetimes[i] = _lifespan; - // jitter the _emitDirection by a random offset + // jitter the _emitVelocity by a random offset glm::vec3 randOffset; - randOffset.x = -_directionSpread.x + randFloat() * (_directionSpread.x * 2.0f); - randOffset.y = -_directionSpread.y + randFloat() * (_directionSpread.y * 2.0f); - randOffset.z = -_directionSpread.z + randFloat() * (_directionSpread.z * 2.0f); + randOffset.x = -_velocitySpread.x + randFloat() * (_velocitySpread.x * 2.0f); + randOffset.y = -_velocitySpread.y + randFloat() * (_velocitySpread.y * 2.0f); + randOffset.z = -_velocitySpread.z + randFloat() * (_velocitySpread.z * 2.0f); // set initial conditions _particlePositions[i] = glm::vec3(0.0f, 0.0f, 0.0f); - _particleVelocities[i] = _emitDirection + randOffset; + _particleVelocities[i] = _emitVelocity + randOffset; integrateParticle(i, timeLeftInFrame); extendBounds(_particlePositions[i]); diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 584bc7beff..237f008f1f 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -98,14 +98,14 @@ public: void setEmitRate(float emitRate) { _emitRate = emitRate; } float getEmitRate() const { return _emitRate; } - static const glm::vec3 DEFAULT_EMIT_DIRECTION; - void setEmitDirection(glm::vec3 emitDirection); - const glm::vec3& getEmitDirection() const { return _emitDirection; } + static const glm::vec3 DEFAULT_EMIT_VELOCITY; + void setEmitVelocity(glm::vec3 emitVelocity); + const glm::vec3& getEmitVelocity() const { return _emitVelocity; } - static const glm::vec3 DEFAULT_DIRECTION_SPREAD; - void setDirectionSpread(glm::vec3 directionSpread); - const glm::vec3& getDirectionSpread() const { return _directionSpread; } + static const glm::vec3 DEFAULT_VELOCITY_SPREAD; + void setVelocitySpread(glm::vec3 velocitySpread); + const glm::vec3& getVelocitySpread() const { return _velocitySpread; } static const float DEFAULT_LOCAL_GRAVITY; @@ -144,8 +144,8 @@ protected: quint32 _maxParticles; float _lifespan; float _emitRate; - glm::vec3 _emitDirection; - glm::vec3 _directionSpread; + glm::vec3 _emitVelocity; + glm::vec3 _velocitySpread; float _localGravity; float _particleRadius; quint64 _lastAnimated; From 0031c2a39a37e975a9aa091e0488b64375f6e205 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 11 Aug 2015 16:05:18 -0700 Subject: [PATCH 07/57] changed localGravity prop to acceleration, which can be along any arbitrary direction --- .../entities/src/EntityItemProperties.cpp | 14 ++++++------ libraries/entities/src/EntityItemProperties.h | 4 ++-- libraries/entities/src/EntityPropertyFlags.h | 4 ++-- .../entities/src/ParticleEffectEntityItem.cpp | 22 +++++++++---------- .../entities/src/ParticleEffectEntityItem.h | 8 +++---- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ddf7257775..612f6da900 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -86,7 +86,7 @@ CONSTRUCT_PROPERTY(lifespan, ParticleEffectEntityItem::DEFAULT_LIFESPAN), CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), CONSTRUCT_PROPERTY(emitVelocity, ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY), CONSTRUCT_PROPERTY(velocitySpread, ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD), -CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), +CONSTRUCT_PROPERTY(emitAcceleration, ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION), CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), CONSTRUCT_PROPERTY(keyLightColor, ZoneEntityItem::DEFAULT_KEYLIGHT_COLOR), @@ -351,7 +351,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_EMIT_RATE, emitRate); CHECK_PROPERTY_CHANGE(PROP_EMIT_VELOCITY, emitVelocity); CHECK_PROPERTY_CHANGE(PROP_VELOCITY_SPREAD, velocitySpread); - CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); + CHECK_PROPERTY_CHANGE(PROP_EMIT_ACCELERATION, emitAcceleration); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID); CHECK_PROPERTY_CHANGE(PROP_NAME, name); @@ -453,7 +453,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(emitRate); COPY_PROPERTY_TO_QSCRIPTVALUE(emitVelocity); COPY_PROPERTY_TO_QSCRIPTVALUE(velocitySpread); - COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity); + COPY_PROPERTY_TO_QSCRIPTVALUE(emitAcceleration); COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID); COPY_PROPERTY_TO_QSCRIPTVALUE(name); @@ -573,7 +573,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitVelocity, glmVec3, setEmitVelocity); COPY_PROPERTY_FROM_QSCRIPTVALUE(velocitySpread, glmVec3, setVelocitySpread); - COPY_PROPERTY_FROM_QSCRIPTVALUE(localGravity, float, setLocalGravity); + COPY_PROPERTY_FROM_QSCRIPTVALUE(emitAcceleration, glmVec3, setEmitAcceleration); COPY_PROPERTY_FROM_QSCRIPTVALUE(particleRadius, float, setParticleRadius); COPY_PROPERTY_FROM_QSCRIPTVALUE(marketplaceID, QString, setMarketplaceID); COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName); @@ -814,7 +814,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, properties.getEmitRate()); APPEND_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, properties.getEmitVelocity()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, properties.getVelocitySpread()); - APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, properties.getLocalGravity()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, properties.getEmitAcceleration()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius()); } @@ -1083,7 +1083,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); } @@ -1214,7 +1214,7 @@ void EntityItemProperties::markAllChanged() { _emitRateChanged = true; _emitVelocityChanged = true; _velocitySpreadChanged = true; - _localGravityChanged = true; + _emitAccelerationChanged = true; _particleRadiusChanged = true; _marketplaceIDChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index db4ebb9229..9001483358 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -133,7 +133,7 @@ public: DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float); DEFINE_PROPERTY_REF(PROP_EMIT_VELOCITY, EmitVelocity, emitVelocity, glm::vec3); DEFINE_PROPERTY_REF(PROP_VELOCITY_SPREAD, VelocitySpread, velocitySpread, glm::vec3); - DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float); + DEFINE_PROPERTY(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3); DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor); @@ -312,7 +312,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, Lifespan, lifespan, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRate, emitRate, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitVelocity, emitVelocity, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitAcceleration, emitAcceleration, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, BackgroundMode, backgroundMode, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 66a3fcb2f6..42b5a46e0a 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -98,7 +98,7 @@ enum EntityPropertyList { PROP_EMIT_RATE, PROP_EMIT_VELOCITY, PROP_EMIT_STRENGTH, - PROP_LOCAL_GRAVITY, + PROP_EMIT_ACCELERATION, PROP_PARTICLE_RADIUS, PROP_COMPOUND_SHAPE_URL, // used by Model + zones entities @@ -172,7 +172,7 @@ enum EntityPropertyList { PROP_ATMOSPHERE_OUTER_RADIUS = PROP_EMIT_RATE, PROP_ATMOSPHERE_MIE_SCATTERING = PROP_EMIT_VELOCITY, PROP_ATMOSPHERE_RAYLEIGH_SCATTERING = PROP_EMIT_STRENGTH, - PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS = PROP_LOCAL_GRAVITY, + PROP_ATMOSPHERE_SCATTERING_WAVELENGTHS = PROP_EMIT_ACCELERATION, PROP_ATMOSPHERE_HAS_STARS = PROP_PARTICLE_RADIUS, PROP_BACKGROUND_MODE = PROP_MODEL_URL, PROP_SKYBOX_COLOR = PROP_ANIMATION_URL, diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 99a1e7d2ab..8e26bac210 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -52,7 +52,7 @@ const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY(0.0f, 0.0f, 0.0f); const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(0.0f, 0.0f, 0.0f); -const float ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY = -9.8f; +const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, 0.0f, 0.0f); const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = ""; @@ -68,7 +68,7 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte _lifespan(DEFAULT_LIFESPAN), _emitRate(DEFAULT_EMIT_RATE), _emitVelocity(DEFAULT_EMIT_VELOCITY), - _localGravity(DEFAULT_LOCAL_GRAVITY), + _emitAcceleration(DEFAULT_EMIT_ACCELERATION), _particleRadius(DEFAULT_PARTICLE_RADIUS), _lastAnimated(usecTimestampNow()), _animationLoop(), @@ -107,8 +107,8 @@ void ParticleEffectEntityItem::setVelocitySpread(glm::vec3 velocitySpread) { } -void ParticleEffectEntityItem::setLocalGravity(float localGravity) { - _localGravity = localGravity; +void ParticleEffectEntityItem::setEmitAcceleration(glm::vec3 emitAcceleration) { + _emitAcceleration = emitAcceleration; } void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { @@ -132,7 +132,7 @@ EntityItemProperties ParticleEffectEntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitRate, getEmitRate); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitVelocity, getEmitVelocity); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(localGravity, getLocalGravity); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitAcceleration, getEmitAcceleration); COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius); COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures); @@ -153,7 +153,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitVelocity, setEmitVelocity); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(localGravity, setLocalGravity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitAcceleration, setEmitAcceleration); SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocitySpread, setVelocitySpread); @@ -208,7 +208,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); - READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, setLocalGravity); + READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); READ_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); @@ -231,7 +231,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_LIFESPAN; requestedProperties += PROP_EMIT_RATE; requestedProperties += PROP_EMIT_VELOCITY; - requestedProperties += PROP_LOCAL_GRAVITY; + requestedProperties += PROP_EMIT_ACCELERATION; requestedProperties += PROP_PARTICLE_RADIUS; requestedProperties += PROP_TEXTURES; requestedProperties += PROP_VELOCITY_SPREAD; @@ -258,7 +258,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, getLifespan()); APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, getEmitRate()); APPEND_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, getEmitVelocity()); - APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, getLocalGravity()); + APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, getEmitAcceleration()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, getParticleRadius()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, getVelocitySpread()); @@ -441,8 +441,8 @@ void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) { } void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { - glm::vec3 atSquared(0.0f, 0.5f * _localGravity * deltaTime * deltaTime, 0.0f); - glm::vec3 at(0.0f, _localGravity * deltaTime, 0.0f); + glm::vec3 atSquared(0.5f * _emitAcceleration.x * deltaTime * deltaTime, 0.5f * _emitAcceleration.y * deltaTime * deltaTime, 0.5f * _emitAcceleration.z * deltaTime * deltaTime); + glm::vec3 at(0.0f, _emitAcceleration.y * deltaTime, 0.0f); _particlePositions[index] += _particleVelocities[index] * deltaTime + atSquared; _particleVelocities[index] += at; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 237f008f1f..f25da2bbec 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -108,9 +108,9 @@ public: const glm::vec3& getVelocitySpread() const { return _velocitySpread; } - static const float DEFAULT_LOCAL_GRAVITY; - void setLocalGravity(float localGravity); - float getLocalGravity() const { return _localGravity; } + static const glm::vec3 DEFAULT_EMIT_ACCELERATION; + void setEmitAcceleration(glm::vec3 emitAcceleration); + const glm::vec3& getEmitAcceleration() const { return _emitAcceleration; } static const float DEFAULT_PARTICLE_RADIUS; void setParticleRadius(float particleRadius); @@ -146,7 +146,7 @@ protected: float _emitRate; glm::vec3 _emitVelocity; glm::vec3 _velocitySpread; - float _localGravity; + glm::vec3 _emitAcceleration; float _particleRadius; quint64 _lastAnimated; AnimationLoop _animationLoop; From 2db053e56a23f7fce224e3e7951d81cf3cf052f3 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 11 Aug 2015 17:09:48 -0700 Subject: [PATCH 08/57] adding acceleration spread property --- .../entities/src/EntityItemProperties.cpp | 7 +++++ libraries/entities/src/EntityItemProperties.h | 2 ++ libraries/entities/src/EntityPropertyFlags.h | 1 + .../entities/src/ParticleEffectEntityItem.cpp | 27 ++++++++++++++----- .../entities/src/ParticleEffectEntityItem.h | 5 ++++ 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 612f6da900..c6c02f248c 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -87,6 +87,7 @@ CONSTRUCT_PROPERTY(emitRate, ParticleEffectEntityItem::DEFAULT_EMIT_RATE), CONSTRUCT_PROPERTY(emitVelocity, ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY), CONSTRUCT_PROPERTY(velocitySpread, ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD), CONSTRUCT_PROPERTY(emitAcceleration, ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION), +CONSTRUCT_PROPERTY(accelerationSpread, ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD), CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), CONSTRUCT_PROPERTY(keyLightColor, ZoneEntityItem::DEFAULT_KEYLIGHT_COLOR), @@ -352,6 +353,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_EMIT_VELOCITY, emitVelocity); CHECK_PROPERTY_CHANGE(PROP_VELOCITY_SPREAD, velocitySpread); CHECK_PROPERTY_CHANGE(PROP_EMIT_ACCELERATION, emitAcceleration); + CHECK_PROPERTY_CHANGE(PROP_ACCELERATION_SPREAD, accelerationSpread); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID); CHECK_PROPERTY_CHANGE(PROP_NAME, name); @@ -454,6 +456,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(emitVelocity); COPY_PROPERTY_TO_QSCRIPTVALUE(velocitySpread); COPY_PROPERTY_TO_QSCRIPTVALUE(emitAcceleration); + COPY_PROPERTY_TO_QSCRIPTVALUE(accelerationSpread); COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID); COPY_PROPERTY_TO_QSCRIPTVALUE(name); @@ -574,6 +577,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(emitVelocity, glmVec3, setEmitVelocity); COPY_PROPERTY_FROM_QSCRIPTVALUE(velocitySpread, glmVec3, setVelocitySpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitAcceleration, glmVec3, setEmitAcceleration); + COPY_PROPERTY_FROM_QSCRIPTVALUE(accelerationSpread, glmVec3, setAccelerationSpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(particleRadius, float, setParticleRadius); COPY_PROPERTY_FROM_QSCRIPTVALUE(marketplaceID, QString, setMarketplaceID); COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName); @@ -815,6 +819,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent APPEND_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, properties.getEmitVelocity()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, properties.getVelocitySpread()); APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, properties.getEmitAcceleration()); + APPEND_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, properties.getAccelerationSpread()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius()); } @@ -1084,6 +1089,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); } @@ -1215,6 +1221,7 @@ void EntityItemProperties::markAllChanged() { _emitVelocityChanged = true; _velocitySpreadChanged = true; _emitAccelerationChanged = true; + _accelerationSpreadChanged = true; _particleRadiusChanged = true; _marketplaceIDChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 9001483358..a657efe788 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -134,6 +134,7 @@ public: DEFINE_PROPERTY_REF(PROP_EMIT_VELOCITY, EmitVelocity, emitVelocity, glm::vec3); DEFINE_PROPERTY_REF(PROP_VELOCITY_SPREAD, VelocitySpread, velocitySpread, glm::vec3); DEFINE_PROPERTY(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3); + DEFINE_PROPERTY(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3); DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); DEFINE_PROPERTY_REF(PROP_KEYLIGHT_COLOR, KeyLightColor, keyLightColor, xColor); @@ -313,6 +314,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitRate, emitRate, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitVelocity, emitVelocity, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitAcceleration, emitAcceleration, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, AccelerationSpread, accelerationSpread, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, BackgroundMode, backgroundMode, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 42b5a46e0a..abb8241d8f 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -137,6 +137,7 @@ enum EntityPropertyList { // used by particles PROP_VELOCITY_SPREAD, + PROP_ACCELERATION_SPREAD, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 8e26bac210..91314afc96 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -53,6 +53,7 @@ const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY(0.0f, 0.0f, 0.0f); const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(0.0f, 0.0f, 0.0f); const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, 0.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f); const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = ""; @@ -111,6 +112,10 @@ void ParticleEffectEntityItem::setEmitAcceleration(glm::vec3 emitAcceleration) { _emitAcceleration = emitAcceleration; } +void ParticleEffectEntityItem::setAccelerationSpread(glm::vec3 accelerationSpread){ + _accelerationSpread = accelerationSpread; +} + void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { _particleRadius = particleRadius; } @@ -154,6 +159,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitRate, setEmitRate); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitVelocity, setEmitVelocity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitAcceleration, setEmitAcceleration); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(accelerationSpread, setAccelerationSpread); SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocitySpread, setVelocitySpread); @@ -209,6 +215,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration); + READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); READ_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); @@ -232,6 +239,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_EMIT_RATE; requestedProperties += PROP_EMIT_VELOCITY; requestedProperties += PROP_EMIT_ACCELERATION; + requestedProperties += PROP_ACCELERATION_SPREAD; requestedProperties += PROP_PARTICLE_RADIUS; requestedProperties += PROP_TEXTURES; requestedProperties += PROP_VELOCITY_SPREAD; @@ -259,6 +267,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, getEmitRate()); APPEND_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, getEmitVelocity()); APPEND_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, getEmitAcceleration()); + APPEND_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, getAccelerationSpread()); APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, getParticleRadius()); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures()); APPEND_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, getVelocitySpread()); @@ -441,7 +450,11 @@ void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) { } void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { - glm::vec3 atSquared(0.5f * _emitAcceleration.x * deltaTime * deltaTime, 0.5f * _emitAcceleration.y * deltaTime * deltaTime, 0.5f * _emitAcceleration.z * deltaTime * deltaTime); + glm::vec3 spreadOffset; + spreadOffset.x = -_accelerationSpread.x + randFloat() * (_accelerationSpread.x * 2.0f); + spreadOffset.y = -_accelerationSpread.y + randFloat() * (_accelerationSpread.y * 2.0f); + spreadOffset.z = -_accelerationSpread.z + randFloat() * (_accelerationSpread.z * 2.0f); + glm::vec3 atSquared(0.5f * (_emitAcceleration.x + spreadOffset.x) * deltaTime * deltaTime, 0.5f * _emitAcceleration.y * deltaTime * deltaTime, 0.5f * _emitAcceleration.z * deltaTime * deltaTime); glm::vec3 at(0.0f, _emitAcceleration.y * deltaTime, 0.0f); _particlePositions[index] += _particleVelocities[index] * deltaTime + atSquared; _particleVelocities[index] += at; @@ -480,16 +493,16 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { quint32 i = _particleTailIndex; _particleLifetimes[i] = _lifespan; - // jitter the _emitVelocity by a random offset - glm::vec3 randOffset; - randOffset.x = -_velocitySpread.x + randFloat() * (_velocitySpread.x * 2.0f); - randOffset.y = -_velocitySpread.y + randFloat() * (_velocitySpread.y * 2.0f); - randOffset.z = -_velocitySpread.z + randFloat() * (_velocitySpread.z * 2.0f); + + glm::vec3 spreadOffset; + spreadOffset.x = -_velocitySpread.x + randFloat() * (_velocitySpread.x * 2.0f); + spreadOffset.y = -_velocitySpread.y + randFloat() * (_velocitySpread.y * 2.0f); + spreadOffset.z = -_velocitySpread.z + randFloat() * (_velocitySpread.z * 2.0f); // set initial conditions _particlePositions[i] = glm::vec3(0.0f, 0.0f, 0.0f); - _particleVelocities[i] = _emitVelocity + randOffset; + _particleVelocities[i] = _emitVelocity + spreadOffset; integrateParticle(i, timeLeftInFrame); extendBounds(_particlePositions[i]); diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index f25da2bbec..f116b3d3c3 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -111,6 +111,10 @@ public: static const glm::vec3 DEFAULT_EMIT_ACCELERATION; void setEmitAcceleration(glm::vec3 emitAcceleration); const glm::vec3& getEmitAcceleration() const { return _emitAcceleration; } + + static const glm::vec3 DEFAULT_ACCELERATION_SPREAD; + void setAccelerationSpread(glm::vec3 accelerationSpread); + const glm::vec3& getAccelerationSpread() const { return _accelerationSpread; } static const float DEFAULT_PARTICLE_RADIUS; void setParticleRadius(float particleRadius); @@ -147,6 +151,7 @@ protected: glm::vec3 _emitVelocity; glm::vec3 _velocitySpread; glm::vec3 _emitAcceleration; + glm::vec3 _accelerationSpread; float _particleRadius; quint64 _lastAnimated; AnimationLoop _animationLoop; From 528d662c5890775b3863889869a48cf21bf2e592 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 12 Aug 2015 09:50:01 -0700 Subject: [PATCH 09/57] getting acceleration spread hooked up --- libraries/entities/src/ParticleEffectEntityItem.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 91314afc96..c08b3e9015 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -450,11 +450,7 @@ void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) { } void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { - glm::vec3 spreadOffset; - spreadOffset.x = -_accelerationSpread.x + randFloat() * (_accelerationSpread.x * 2.0f); - spreadOffset.y = -_accelerationSpread.y + randFloat() * (_accelerationSpread.y * 2.0f); - spreadOffset.z = -_accelerationSpread.z + randFloat() * (_accelerationSpread.z * 2.0f); - glm::vec3 atSquared(0.5f * (_emitAcceleration.x + spreadOffset.x) * deltaTime * deltaTime, 0.5f * _emitAcceleration.y * deltaTime * deltaTime, 0.5f * _emitAcceleration.z * deltaTime * deltaTime); + glm::vec3 atSquared(0.5f * _emitAcceleration.x * deltaTime * deltaTime, 0.5f * _emitAcceleration.y * deltaTime * deltaTime, 0.5f * _emitAcceleration.z * deltaTime * deltaTime); glm::vec3 at(0.0f, _emitAcceleration.y * deltaTime, 0.0f); _particlePositions[index] += _particleVelocities[index] * deltaTime + atSquared; _particleVelocities[index] += at; From 16279bd41564df61751042ff3ce56ca4bbafa22c Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 12 Aug 2015 14:01:42 -0700 Subject: [PATCH 10/57] emitters trail particles now --- .../src/RenderableParticleEffectEntityItem.cpp | 2 +- libraries/entities/src/ParticleEffectEntityItem.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 2b4626c2c3..a91b17e0ee 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -245,7 +245,7 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { glm::vec3 pos = _transform.getTranslation(); Transform t; t.setRotation(rot); - t.setTranslation(pos); +// t.setTranslation(pos); payload.setModelTransform(t); // transform _particleMinBound and _particleMaxBound corners into world coords diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index c08b3e9015..89db8add5b 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -497,7 +497,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // set initial conditions - _particlePositions[i] = glm::vec3(0.0f, 0.0f, 0.0f); + _particlePositions[i] = getPosition(); _particleVelocities[i] = _emitVelocity + spreadOffset; integrateParticle(i, timeLeftInFrame); From 36ca0c54fcc5e125599ab42f08de0b37a3937307 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 12 Aug 2015 16:13:00 -0700 Subject: [PATCH 11/57] acceleration spread working properly --- .../src/RenderableParticleEffectEntityItem.cpp | 2 +- libraries/entities/src/ParticleEffectEntityItem.cpp | 12 ++++++++++-- libraries/entities/src/ParticleEffectEntityItem.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index a91b17e0ee..4c8f8721c6 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -283,8 +283,8 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { payload.setPipeline(_untexturedPipeline); } }); - _scene->enqueuePendingChanges(pendingChanges); + } void RenderableParticleEffectEntityItem::createPipelines() { diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 89db8add5b..1ac2372e90 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -80,6 +80,7 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte _particleLifetimes(DEFAULT_MAX_PARTICLES, 0.0f), _particlePositions(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)), _particleVelocities(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)), + _particleAccelerations(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)), _timeUntilNextEmit(0.0f), _particleHeadIndex(0), _particleTailIndex(0), @@ -450,8 +451,9 @@ void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) { } void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { - glm::vec3 atSquared(0.5f * _emitAcceleration.x * deltaTime * deltaTime, 0.5f * _emitAcceleration.y * deltaTime * deltaTime, 0.5f * _emitAcceleration.z * deltaTime * deltaTime); - glm::vec3 at(0.0f, _emitAcceleration.y * deltaTime, 0.0f); + glm::vec3 accel = _particleAccelerations[index]; + glm::vec3 atSquared(0.5f * accel.x * deltaTime * deltaTime, 0.5f * accel.y * deltaTime * deltaTime, 0.5f * accel.z * deltaTime * deltaTime); + glm::vec3 at(accel.x * deltaTime, accel.y * deltaTime, accel.z * deltaTime ); _particlePositions[index] += _particleVelocities[index] * deltaTime + atSquared; _particleVelocities[index] += at; } @@ -499,6 +501,12 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // set initial conditions _particlePositions[i] = getPosition(); _particleVelocities[i] = _emitVelocity + spreadOffset; + + spreadOffset.x = -_accelerationSpread.x + randFloat() * (_accelerationSpread.x * 2.0f); + spreadOffset.y = -_accelerationSpread.y + randFloat() * (_accelerationSpread.y * 2.0f); + spreadOffset.z = -_accelerationSpread.z + randFloat() * (_accelerationSpread.z * 2.0f); + + _particleAccelerations[i] = _emitAcceleration + spreadOffset; integrateParticle(i, timeLeftInFrame); extendBounds(_particlePositions[i]); diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index f116b3d3c3..6d60570a06 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -164,6 +164,7 @@ protected: QVector _particleLifetimes; QVector _particlePositions; QVector _particleVelocities; + QVector _particleAccelerations; float _timeUntilNextEmit; // particle arrays are a ring buffer, use these indicies From 81844a82e819753526a98576c940fda5ec6e307d Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 12 Aug 2015 16:25:56 -0700 Subject: [PATCH 12/57] fixed spacing issues and removed dead line --- .../src/RenderableParticleEffectEntityItem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 4c8f8721c6..2bde880ead 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -245,7 +245,6 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { glm::vec3 pos = _transform.getTranslation(); Transform t; t.setRotation(rot); -// t.setTranslation(pos); payload.setModelTransform(t); // transform _particleMinBound and _particleMaxBound corners into world coords @@ -283,8 +282,8 @@ void RenderableParticleEffectEntityItem::updateRenderItem() { payload.setPipeline(_untexturedPipeline); } }); + _scene->enqueuePendingChanges(pendingChanges); - } void RenderableParticleEffectEntityItem::createPipelines() { From f3d6992dd29e3181481ec306a49e847467ca7569 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 12 Aug 2015 17:28:07 -0700 Subject: [PATCH 13/57] remove outdated comment --- libraries/entities/src/ParticleEffectEntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 1ac2372e90..9ac620821b 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -16,7 +16,6 @@ // - Just to get this out the door, I just did forward Euler integration. There are better ways. // - Gravity always points along the Y axis. Support an actual gravity vector. // - Add the ability to add arbitrary forces to the simulation. -// - Add controls for spread (which is currently hard-coded) and varying emission strength (not currently implemented). // - Add drag. // - Add some kind of support for collisions. // - There's no synchronization of the simulation across clients at all. In fact, it's using rand() under the hood, so From d38d29e0f581bd751e1c19aad5129b573fc20cef Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 13 Aug 2015 10:35:32 -0700 Subject: [PATCH 14/57] fixed argument signatues and optimized particle position calculations --- .../entities/src/ParticleEffectEntityItem.cpp | 14 +++++--------- libraries/entities/src/ParticleEffectEntityItem.h | 8 ++++---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 9ac620821b..21f414a97c 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -99,20 +99,20 @@ void ParticleEffectEntityItem::setLifespan(float lifespan) { _lifespan = lifespan; } -void ParticleEffectEntityItem::setEmitVelocity(glm::vec3 emitVelocity) { +void ParticleEffectEntityItem::setEmitVelocity(const glm::vec3& emitVelocity) { _emitVelocity = emitVelocity; } -void ParticleEffectEntityItem::setVelocitySpread(glm::vec3 velocitySpread) { +void ParticleEffectEntityItem::setVelocitySpread(const glm::vec3& velocitySpread) { _velocitySpread = velocitySpread; } -void ParticleEffectEntityItem::setEmitAcceleration(glm::vec3 emitAcceleration) { +void ParticleEffectEntityItem::setEmitAcceleration(const glm::vec3& emitAcceleration) { _emitAcceleration = emitAcceleration; } -void ParticleEffectEntityItem::setAccelerationSpread(glm::vec3 accelerationSpread){ +void ParticleEffectEntityItem::setAccelerationSpread(const glm::vec3& accelerationSpread){ _accelerationSpread = accelerationSpread; } @@ -450,11 +450,7 @@ void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) { } void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { - glm::vec3 accel = _particleAccelerations[index]; - glm::vec3 atSquared(0.5f * accel.x * deltaTime * deltaTime, 0.5f * accel.y * deltaTime * deltaTime, 0.5f * accel.z * deltaTime * deltaTime); - glm::vec3 at(accel.x * deltaTime, accel.y * deltaTime, accel.z * deltaTime ); - _particlePositions[index] += _particleVelocities[index] * deltaTime + atSquared; - _particleVelocities[index] += at; + _particlePositions[index] += deltaTime * (_particleVelocities[index] + (0.5f * deltaTime) * _particleAccelerations[index]); } void ParticleEffectEntityItem::stepSimulation(float deltaTime) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 6d60570a06..bbc14561d4 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -99,21 +99,21 @@ public: float getEmitRate() const { return _emitRate; } static const glm::vec3 DEFAULT_EMIT_VELOCITY; - void setEmitVelocity(glm::vec3 emitVelocity); + void setEmitVelocity(const glm::vec3& emitVelocity); const glm::vec3& getEmitVelocity() const { return _emitVelocity; } static const glm::vec3 DEFAULT_VELOCITY_SPREAD; - void setVelocitySpread(glm::vec3 velocitySpread); + void setVelocitySpread(const glm::vec3& velocitySpread); const glm::vec3& getVelocitySpread() const { return _velocitySpread; } static const glm::vec3 DEFAULT_EMIT_ACCELERATION; - void setEmitAcceleration(glm::vec3 emitAcceleration); + void setEmitAcceleration(const glm::vec3& emitAcceleration); const glm::vec3& getEmitAcceleration() const { return _emitAcceleration; } static const glm::vec3 DEFAULT_ACCELERATION_SPREAD; - void setAccelerationSpread(glm::vec3 accelerationSpread); + void setAccelerationSpread(const glm::vec3& accelerationSpread); const glm::vec3& getAccelerationSpread() const { return _accelerationSpread; } static const float DEFAULT_PARTICLE_RADIUS; From 5b2e966ca571bc0d369c62723581e952209db1be Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 13 Aug 2015 10:55:21 -0700 Subject: [PATCH 15/57] fixing accel issues --- libraries/entities/src/ParticleEffectEntityItem.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 21f414a97c..cc5c698dab 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -450,7 +450,11 @@ void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) { } void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) { - _particlePositions[index] += deltaTime * (_particleVelocities[index] + (0.5f * deltaTime) * _particleAccelerations[index]); + glm::vec3 accel = _particleAccelerations[index]; + glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * accel; + glm::vec3 at = accel * deltaTime; + _particlePositions[index] += _particleVelocities[index] * deltaTime + atSquared; + _particleVelocities[index] += at; } void ParticleEffectEntityItem::stepSimulation(float deltaTime) { From 9322960c63b7361d2b6bb1020fe576d0df5baa3b Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 13 Aug 2015 15:36:13 -0700 Subject: [PATCH 16/57] updated particle example for new properties --- examples/particles.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/particles.js b/examples/particles.js index deb6228fff..fc1a936a72 100644 --- a/examples/particles.js +++ b/examples/particles.js @@ -39,10 +39,11 @@ this.entity = Entities.addEntity({ type: "ParticleEffect", animationSettings: animationSettings, position: spawnPoint, - textures: "http://www.hyperlogic.org/images/particle.png", - emitRate: emitRate, - emitStrength: emitStrength, - emitDirection: emitDirection, + dimensions: {x: 2, y: 2, z: 2}, + emitVelocity: {x: 0, y: 5, z: 0}, + velocitySpread: {x: 2, y: 0, z: 2}, + emitAcceleration: {x: 0, y: -9.8, z: 0}, + textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png", color: color, lifespan: 1.0, visible: true, From 6fe8703492ae9d0663faccf404b05555fd8aa0a4 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 13 Aug 2015 15:50:00 -0700 Subject: [PATCH 17/57] added defaults to particle effect for velocity and acceleration --- libraries/entities/src/ParticleEffectEntityItem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index cc5c698dab..b5fad9a1e6 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -50,8 +50,8 @@ const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY(0.0f, 0.0f, 0.0f); -const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(0.0f, 0.0f, 0.0f); -const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, 0.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(0.0f, 10.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, -9.8f, 0.0f); const glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f); const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = ""; From bb84e0e40380fdc697c972ba69e280314b317582 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 13 Aug 2015 15:57:45 -0700 Subject: [PATCH 18/57] fixed defaults --- libraries/entities/src/ParticleEffectEntityItem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index b5fad9a1e6..d9b97385b6 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -49,8 +49,8 @@ const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f; const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; -const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY(0.0f, 0.0f, 0.0f); -const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(0.0f, 10.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY(0.0f, 10.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(0.0f, 0.0f, 0.0f); const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, -9.8f, 0.0f); const glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f); const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; From e191a301d80fcc7d207e093d143c3c2895626853 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 13 Aug 2015 16:08:38 -0700 Subject: [PATCH 19/57] added a spread to defaults to create a default fountain effect --- libraries/entities/src/ParticleEffectEntityItem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index d9b97385b6..f8420a3323 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -49,8 +49,8 @@ const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f; const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; -const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY(0.0f, 10.0f, 0.0f); -const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(0.0f, 0.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_VELOCITY(0.0f, 5.0f, 0.0f); +const glm::vec3 ParticleEffectEntityItem::DEFAULT_VELOCITY_SPREAD(3.0f, 0.0f, 3.0f); const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, -9.8f, 0.0f); const glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f); const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; From ec25d7994c9dc304b3a6b729cd8297dfdaab6d21 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 14 Aug 2015 21:58:22 -0700 Subject: [PATCH 20/57] bumped protocol number for new particle properties --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 5562490344..7e73b4c660 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -67,7 +67,7 @@ PacketVersion versionForPacketType(PacketType::Value packetType) { case EntityAdd: case EntityEdit: case EntityData: - return VERSION_ENTITIES_POLYLINE; + return VERSION_ENTITIES_PARTICLE_MODIFICATIONS; case AvatarData: return 12; default: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 1aeadb1af9..d60fc105e5 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -142,5 +142,6 @@ const PacketVersion VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE const PacketVersion VERSION_ENTITIES_NEW_PROTOCOL_LAYER = 35; const PacketVersion VERSION_POLYVOX_TEXTURES = 36; const PacketVersion VERSION_ENTITIES_POLYLINE = 37; +const PacketVersion VERSION_ENTITIES_PARTICLE_MODIFICATIONS = 38; #endif // hifi_PacketHeaders_h \ No newline at end of file From 07c9a0e2bb303f1ffafdd9415b0fd36b687de6e3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 24 Aug 2015 10:48:58 -0700 Subject: [PATCH 21/57] Add Developer > Crash Interface menu item --- interface/src/Application.cpp | 6 ++++++ interface/src/Application.h | 2 ++ interface/src/Menu.cpp | 2 ++ interface/src/Menu.h | 1 + 4 files changed, 11 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0f3282582f..6bb12d4d06 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5137,3 +5137,9 @@ void Application::emulateMouse(Hand* hand, float click, float shift, int index) _oldHandLeftClick[index] = false; } } + +void Application::crashApplication() { + QObject* object = nullptr; + bool value = object->isWindowType(); + qCDebug(interfaceapp) << "Intentionally crashed Interface"; +} diff --git a/interface/src/Application.h b/interface/src/Application.h index 6394aa12d0..2297ff157e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -438,6 +438,8 @@ public slots: void reloadResourceCaches(); + void crashApplication(); + private slots: void clearDomainOctreeDetails(); void checkFPS(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f99b3ba579..d08970a693 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -575,6 +575,8 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowOwned); addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls); + addActionToQMenuAndActionHash(developerMenu, MenuOption::CrashInterface, 0, qApp, SLOT(crashApplication())); + MenuWrapper* helpMenu = addMenu("Help"); addActionToQMenuAndActionHash(helpMenu, MenuOption::EditEntitiesHelp, 0, qApp, SLOT(showEditEntitiesHelp())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 278da363d1..e9ce8bcaba 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -164,6 +164,7 @@ namespace MenuOption { const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyPath = "Copy Path to Clipboard"; const QString CoupleEyelids = "Couple Eyelids"; + const QString CrashInterface = "Crash Interface"; const QString DebugAmbientOcclusion = "Debug Ambient Occlusion"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DeleteBookmark = "Delete Bookmark..."; From 5fa27a7cf1b9aba48c61691e5d49d80367f25c4b Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 24 Aug 2015 10:59:38 -0700 Subject: [PATCH 22/57] added back computeAndUpdate mmethod for particles, and now handling parsing old streams --- .../RenderableParticleEffectEntityItem.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 1 + .../entities/src/ParticleEffectEntityItem.cpp | 62 +++++++++++++++---- .../entities/src/ParticleEffectEntityItem.h | 2 + 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 59bad7a130..c053a552bd 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -290,7 +290,7 @@ void RenderableParticleEffectEntityItem::createPipelines() { state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, - gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, + gpu::State::ONE, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(untextured_particle_vert))); auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(untextured_particle_frag))); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 0ffcc00ead..9fa6ccac65 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -610,6 +610,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef auto nodeList = DependencyManager::get(); const QUuid& myNodeID = nodeList->getSessionUUID(); bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID); + if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_SIMULATION_OWNER_AND_ACTIONS_OVER_WIRE) { // pack SimulationOwner and terse update properties near each other diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f8420a3323..3b95f415aa 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -101,25 +101,51 @@ void ParticleEffectEntityItem::setLifespan(float lifespan) { void ParticleEffectEntityItem::setEmitVelocity(const glm::vec3& emitVelocity) { _emitVelocity = emitVelocity; + computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setVelocitySpread(const glm::vec3& velocitySpread) { _velocitySpread = velocitySpread; + computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setEmitAcceleration(const glm::vec3& emitAcceleration) { _emitAcceleration = emitAcceleration; + computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setAccelerationSpread(const glm::vec3& accelerationSpread){ _accelerationSpread = accelerationSpread; + computeAndUpdateDimensions(); } void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { _particleRadius = particleRadius; } +void ParticleEffectEntityItem::computeAndUpdateDimensions() { + const float time = _lifespan * 1.1f; // add 10% extra time to account for incremental timer accumulation error + + float maxVelocityX = fabsf(_velocity.x) + _velocitySpread.x; + float maxAccelerationX = fabsf(_acceleration.x) + _accelerationSpread.x; + float maxXDistance = (maxVelocityX * time) + (0.5 * maxAccelerationX * time * time); + + float maxVelocityY = fabs(_velocity.y) + _velocitySpread.y; + float maxAccelerationY = fabsf(_acceleration.y) + _accelerationSpread.y; + float maxYDistance = (maxVelocityY * time) + (0.5 * maxAccelerationY * time * time); + + float maxVelocityZ = fabsf(_velocity.z) + _velocitySpread.z; + float maxAccelerationZ = fabsf(_acceleration.z) + _accelerationSpread.z; + float maxZDistance = (maxVelocityZ * time) + (0.5 * maxAccelerationZ * time * time); + + float maxDistance = std::max(maxXDistance, std::max(maxYDistance, maxZDistance)); + + //times 2 because dimensions are diameters not radii + glm::vec3 dims(2.0 * maxDistance); + qDebug() << "max Distance: ***** : " << maxDistance; + EntityItem::setDimensions(dims); +} EntityItemProperties ParticleEffectEntityItem::getProperties() const { @@ -207,18 +233,30 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) { setAnimationFrameIndex(animationFrameIndex); } - - READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); - READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); - READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); - READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); - READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); - READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); - READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration); - READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread); - READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); - READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); - READ_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); + if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_MODIFICATIONS) { + READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); + READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); + READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); + READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); + READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); + READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); + READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration); + READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread); + READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); + READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); + READ_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); + } else { + READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); + READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); + READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); + READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); + READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); + READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); + READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); + READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration); + READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); + READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); + } return bytesRead; } diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index bbc14561d4..4ed9216e85 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -119,6 +119,8 @@ public: static const float DEFAULT_PARTICLE_RADIUS; void setParticleRadius(float particleRadius); float getParticleRadius() const { return _particleRadius; } + + void computeAndUpdateDimensions(); bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); } From 63ad972576d4dbf4569cb20d2f6f7d86ad4c2b78 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 24 Aug 2015 11:09:41 -0700 Subject: [PATCH 23/57] Write and delete "application is running" marker file --- interface/src/Application.cpp | 4 ++++ interface/src/CrashHandler.cpp | 42 ++++++++++++++++++++++++++++++++++ interface/src/CrashHandler.h | 27 ++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 interface/src/CrashHandler.cpp create mode 100644 interface/src/CrashHandler.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6bb12d4d06..8b59fd16d4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -104,6 +104,7 @@ #include #include "AudioClient.h" +#include "CrashHandler.h" #include "DiscoverabilityManager.h" #include "GLCanvas.h" #include "LODManager.h" @@ -256,6 +257,9 @@ bool setupEssentials(int& argc, char** argv) { // Set build version QCoreApplication::setApplicationVersion(BUILD_VERSION); + CrashHandler::writeRunningMarkerFiler(); + qAddPostRoutine(CrashHandler::deleteRunningMarkerFile); + DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp new file mode 100644 index 0000000000..c95e513898 --- /dev/null +++ b/interface/src/CrashHandler.cpp @@ -0,0 +1,42 @@ +// +// CrashHandler.cpp +// interface/src +// +// Created by David Rowe on 24 Aug 2015. +// Copyright 2015 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 "CrashHandler.h" + +#include +#include +#include +#include +#include + +static const QString RUNNING_MARKER_FILENAME = "Interface.running"; + +void CrashHandler::writeRunningMarkerFiler() { + QFile runningMarkerFile(runningMarkerFilePath()); + if (!runningMarkerFile.exists()) { + runningMarkerFile.open(QIODevice::WriteOnly); + runningMarkerFile.close(); + } +} +void CrashHandler::deleteRunningMarkerFile() { + QFile runningMarkerFile(runningMarkerFilePath()); + if (runningMarkerFile.exists()) { + runningMarkerFile.remove(); + } +} + +const QString CrashHandler::runningMarkerFilePath() { + QSettings::setDefaultFormat(QSettings::IniFormat); + QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); + applicationInfo.beginGroup("INFO"); + QCoreApplication::setOrganizationName(applicationInfo.value("organizationName").toString()); + return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + RUNNING_MARKER_FILENAME; +} diff --git a/interface/src/CrashHandler.h b/interface/src/CrashHandler.h new file mode 100644 index 0000000000..d354c49d07 --- /dev/null +++ b/interface/src/CrashHandler.h @@ -0,0 +1,27 @@ +// +// CrashHandler.h +// interface/src +// +// Created by David Rowe on 24 Aug 2015. +// Copyright 2015 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_CrashHandler_h +#define hifi_CrashHandler_h + +#include + +class CrashHandler { + +public: + static void writeRunningMarkerFiler(); + static void deleteRunningMarkerFile(); + +private: + static const QString runningMarkerFilePath(); +}; + +#endif // hifi_CrashHandler_h From 484db87abcda00d98c63f5354ee0776f21bb4bc4 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 24 Aug 2015 11:10:29 -0700 Subject: [PATCH 24/57] Set head pitch before making downstream eye corrections. --- interface/src/avatar/SkeletonModel.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index d58cd8d7c4..0439997bc4 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -41,7 +41,7 @@ SkeletonModel::~SkeletonModel() { void SkeletonModel::initJointStates(QVector states) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); - glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; + glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset/* * glm::mat4_cast(getRotation())*/; int rootJointIndex = geometry.rootJointIndex; int leftHandJointIndex = geometry.leftHandJointIndex; @@ -123,20 +123,23 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { params.rightEyeJointIndex = geometry.rightEyeJointIndex; _rig->updateFromHeadParameters(params); - } else { - // This is a little more work than we really want. - // + } else if (true/*_owningAvatar->getHead()->isLookingAtMe()*/) { // Other avatars joint, including their eyes, should already be set just like any other joints // from the wire data. But when looking at me, we want the eyes to use the corrected lookAt. // - // Thus this should really only be ... else if (_owningAvatar->getHead()->isLookingAtMe()) {... - // However, in the !isLookingAtMe case, the eyes aren't rotating the way they should right now. - // (They latch their looking at me position.) We will revisit that as priorities allow. const FBXGeometry& geometry = _geometry->getFBXGeometry(); Head* head = _owningAvatar->getHead(); - _rig->updateEyeJoints(geometry.leftEyeJointIndex, geometry.rightEyeJointIndex, - getTranslation(), getRotation(), - head->getFinalOrientationInWorldFrame(), head->getCorrectedLookAtPosition()); + // If the head is not positioned, updateEyeJoints won't get the math right + glm::quat headOrientation; + _rig->getJointRotation(geometry.headJointIndex, headOrientation); + glm::quat modelOrientation = getRotation(); + glm::quat adjust = modelOrientation; + glm::quat headOrientationInAvatar = adjust * headOrientation; + glm::vec3 eulers = safeEulerAngles(headOrientationInAvatar); + head->setBasePitch(glm::degrees(-eulers.x)); + _rig->updateEyeJoints(geometry.leftEyeJointIndex, geometry.rightEyeJointIndex, + getTranslation(), modelOrientation, + head->getFinalOrientationInWorldFrame(), head->getCorrectedLookAtPosition()); } } From 9c782f6a6d59f6c3ed1f2207daa7283de68cc967 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 24 Aug 2015 12:45:35 -0700 Subject: [PATCH 25/57] Display dialog of crash handling options at startup if Interface crashed Default option and Esc continue without taking any action. --- interface/src/Application.cpp | 1 + interface/src/CrashHandler.cpp | 59 ++++++++++++++++++++++++++++++++++ interface/src/CrashHandler.h | 11 +++++++ 3 files changed, 71 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8b59fd16d4..ca09960abd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -257,6 +257,7 @@ bool setupEssentials(int& argc, char** argv) { // Set build version QCoreApplication::setApplicationVersion(BUILD_VERSION); + CrashHandler::checkForAndHandleCrash(); CrashHandler::writeRunningMarkerFiler(); qAddPostRoutine(CrashHandler::deleteRunningMarkerFile); diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index c95e513898..b58e739176 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -12,13 +12,72 @@ #include "CrashHandler.h" #include +#include +#include #include +#include #include +#include #include #include +#include static const QString RUNNING_MARKER_FILENAME = "Interface.running"; +void CrashHandler::checkForAndHandleCrash() { + QFile runningMarkerFile(runningMarkerFilePath()); + if (runningMarkerFile.exists()) { + Action action = promptUserForAction(); + if (action != DO_NOTHING) { + handleCrash(action); + } + } +} + +CrashHandler::Action CrashHandler::promptUserForAction() { + QDialog crashDialog; + crashDialog.setWindowTitle("Interface Crashed Last Run"); + + QVBoxLayout* layout = new QVBoxLayout; + + QLabel* label = new QLabel("What would you like to do?"); + layout->addWidget(label); + + QRadioButton* option1 = new QRadioButton("Delete Interface.ini"); + QRadioButton* option2 = new QRadioButton("Delete Interface.ini but retain login and avatar info."); + QRadioButton* option3 = new QRadioButton("Continue with my current Interface.ini"); + option3->setChecked(true); + layout->addWidget(option1); + layout->addWidget(option2); + layout->addWidget(option3); + layout->addSpacing(12); + layout->addStretch(); + + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok); + layout->addWidget(buttons); + crashDialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); + + crashDialog.setLayout(layout); + + int result = crashDialog.exec(); + + if (result == QDialog::Accepted) { + if (option1->isChecked()) { + return CrashHandler::DELETE_INTERFACE; + } + if (option2->isChecked()) { + return CrashHandler::RETAIN_LOGIN_AND_AVATAR_INFO; + } + } + + // Dialog cancelled or "do nothing" option chosen + return CrashHandler::DO_NOTHING; +} + +void CrashHandler::handleCrash(CrashHandler::Action action) { + // TODO +} + void CrashHandler::writeRunningMarkerFiler() { QFile runningMarkerFile(runningMarkerFilePath()); if (!runningMarkerFile.exists()) { diff --git a/interface/src/CrashHandler.h b/interface/src/CrashHandler.h index d354c49d07..2b3b78c1f2 100644 --- a/interface/src/CrashHandler.h +++ b/interface/src/CrashHandler.h @@ -17,10 +17,21 @@ class CrashHandler { public: + static void checkForAndHandleCrash(); + static void writeRunningMarkerFiler(); static void deleteRunningMarkerFile(); private: + enum Action { + DELETE_INTERFACE, + RETAIN_LOGIN_AND_AVATAR_INFO, + DO_NOTHING + }; + + static Action promptUserForAction(); + static void handleCrash(Action action); + static const QString runningMarkerFilePath(); }; From f6cf77ae689434964ea7b60a5f04494ccead53a4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 24 Aug 2015 13:24:31 -0700 Subject: [PATCH 26/57] Add Developer > Display Crash Options menu item Is enabled by default. Disabling it stops the display of the crash handling options dialog at start-up. --- interface/src/Application.cpp | 2 ++ interface/src/CrashHandler.cpp | 16 +++++++++------- interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + libraries/shared/src/SettingInterface.cpp | 11 +++++++---- libraries/shared/src/SettingInterface.h | 1 + 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ca09960abd..6e8c1065c9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -257,6 +257,8 @@ bool setupEssentials(int& argc, char** argv) { // Set build version QCoreApplication::setApplicationVersion(BUILD_VERSION); + Setting::preInit(); + CrashHandler::checkForAndHandleCrash(); CrashHandler::writeRunningMarkerFiler(); qAddPostRoutine(CrashHandler::deleteRunningMarkerFile); diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index b58e739176..c64aa3d201 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -22,14 +22,20 @@ #include #include +#include "Menu.h" + static const QString RUNNING_MARKER_FILENAME = "Interface.running"; void CrashHandler::checkForAndHandleCrash() { QFile runningMarkerFile(runningMarkerFilePath()); if (runningMarkerFile.exists()) { - Action action = promptUserForAction(); - if (action != DO_NOTHING) { - handleCrash(action); + QSettings settings; + settings.beginGroup("Developer"); + if (settings.value(MenuOption::DisplayCrashOptions).toBool()) { + Action action = promptUserForAction(); + if (action != DO_NOTHING) { + handleCrash(action); + } } } } @@ -93,9 +99,5 @@ void CrashHandler::deleteRunningMarkerFile() { } const QString CrashHandler::runningMarkerFilePath() { - QSettings::setDefaultFormat(QSettings::IniFormat); - QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); - applicationInfo.beginGroup("INFO"); - QCoreApplication::setOrganizationName(applicationInfo.value("organizationName").toString()); return QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + RUNNING_MARKER_FILENAME; } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d08970a693..8c86d47710 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -575,6 +575,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowOwned); addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls); + addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisplayCrashOptions, 0, true); addActionToQMenuAndActionHash(developerMenu, MenuOption::CrashInterface, 0, qApp, SLOT(crashApplication())); MenuWrapper* helpMenu = addMenu("Help"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index e9ce8bcaba..f81a38872e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -173,6 +173,7 @@ namespace MenuOption { const QString DisableLightEntities = "Disable Light Entities"; const QString DisableNackPackets = "Disable Entity NACK Packets"; const QString DiskCacheEditor = "Disk Cache Editor"; + const QString DisplayCrashOptions = "Display Crash Options"; const QString DisplayHands = "Show Hand Info"; const QString DisplayHandTargets = "Show Hand Targets"; const QString DisplayModelBounds = "Display Model Bounds"; diff --git a/libraries/shared/src/SettingInterface.cpp b/libraries/shared/src/SettingInterface.cpp index b60ffc0891..b3b9ce32f9 100644 --- a/libraries/shared/src/SettingInterface.cpp +++ b/libraries/shared/src/SettingInterface.cpp @@ -35,9 +35,9 @@ namespace Setting { settingsManagerThread->quit(); settingsManagerThread->wait(); } - - // Sets up the settings private instance. Should only be run once at startup - void init() { + + // Set up application settings. Should only be run once at startup. + void preInit() { // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings::setDefaultFormat(QSettings::IniFormat); QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -46,7 +46,10 @@ namespace Setting { QCoreApplication::setApplicationName(applicationInfo.value("name").toString()); QCoreApplication::setOrganizationName(applicationInfo.value("organizationName").toString()); QCoreApplication::setOrganizationDomain(applicationInfo.value("organizationDomain").toString()); - + } + + // Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand, + void init() { // Let's set up the settings Private instance on its own thread QThread* thread = new QThread(); Q_CHECK_PTR(thread); diff --git a/libraries/shared/src/SettingInterface.h b/libraries/shared/src/SettingInterface.h index 5092fd09c8..c8b1595a75 100644 --- a/libraries/shared/src/SettingInterface.h +++ b/libraries/shared/src/SettingInterface.h @@ -16,6 +16,7 @@ #include namespace Setting { + void preInit(); void init(); void cleanupSettings(); From 110e7a773b196ffe2589c2a5d57d485a372cc84e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 24 Aug 2015 13:36:03 -0700 Subject: [PATCH 27/57] Implement crash option that deletes Interface.ini --- interface/src/CrashHandler.cpp | 14 +++++++++++++- interface/src/CrashHandler.h | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index c64aa3d201..6e9897fb82 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -69,7 +69,7 @@ CrashHandler::Action CrashHandler::promptUserForAction() { if (result == QDialog::Accepted) { if (option1->isChecked()) { - return CrashHandler::DELETE_INTERFACE; + return CrashHandler::DELETE_INTERFACE_INI; } if (option2->isChecked()) { return CrashHandler::RETAIN_LOGIN_AND_AVATAR_INFO; @@ -81,7 +81,19 @@ CrashHandler::Action CrashHandler::promptUserForAction() { } void CrashHandler::handleCrash(CrashHandler::Action action) { + if (action == CrashHandler::DELETE_INTERFACE_INI) { + QSettings settings; + QFile settingsFile(settings.fileName()); + if (settingsFile.exists()) { + settingsFile.remove(); + } + return; + } + // TODO + + // CrashHandler::DO_NOTHING or unexpected value + return; } void CrashHandler::writeRunningMarkerFiler() { diff --git a/interface/src/CrashHandler.h b/interface/src/CrashHandler.h index 2b3b78c1f2..fc754cf1ac 100644 --- a/interface/src/CrashHandler.h +++ b/interface/src/CrashHandler.h @@ -24,7 +24,7 @@ public: private: enum Action { - DELETE_INTERFACE, + DELETE_INTERFACE_INI, RETAIN_LOGIN_AND_AVATAR_INFO, DO_NOTHING }; From e8772277de2a54e92fccbe81002b9c67a371283a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Aug 2015 14:19:33 -0700 Subject: [PATCH 28/57] de-bloat the domain-server by adding a DomainGatekeeper --- domain-server/src/DomainGatekeeper.cpp | 589 ++++++++++++++++++ domain-server/src/DomainGatekeeper.h | 93 +++ domain-server/src/DomainServer.cpp | 567 ++--------------- domain-server/src/DomainServer.h | 39 +- domain-server/src/NodeConnectionData.cpp | 37 ++ domain-server/src/NodeConnectionData.h | 32 + domain-server/src/PendingAssignedNodeData.cpp | 6 +- domain-server/src/PendingAssignedNodeData.h | 2 +- libraries/networking/src/LimitedNodeList.h | 2 +- libraries/networking/src/UUIDHasher.h | 12 +- libraries/octree/src/OctreeEditPacketSender.h | 8 - 11 files changed, 816 insertions(+), 571 deletions(-) create mode 100644 domain-server/src/DomainGatekeeper.cpp create mode 100644 domain-server/src/DomainGatekeeper.h create mode 100644 domain-server/src/NodeConnectionData.cpp create mode 100644 domain-server/src/NodeConnectionData.h diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp new file mode 100644 index 0000000000..f712229e2d --- /dev/null +++ b/domain-server/src/DomainGatekeeper.cpp @@ -0,0 +1,589 @@ +// +// DomainGatekeeper.cpp +// domain-server/src +// +// Created by Stephen Birarda on 2015-08-24. +// Copyright 2015 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 "DomainGatekeeper.h" + +#include +#include +#include + +#include +#include +#include + +#include "DomainServer.h" +#include "DomainServerNodeData.h" + +using SharedAssignmentPointer = QSharedPointer; + +DomainGatekeeper::DomainGatekeeper(DomainServer* server) : + _server(server) +{ + +} + +void DomainGatekeeper::addPendingAssignedNode(const QUuid& nodeUUID, const QUuid& assignmentUUID, + const QUuid& walletUUID, const QString& nodeVersion) { + _pendingAssignedNodes.emplace(std::piecewise_construct, + std::forward_as_tuple(nodeUUID), + std::forward_as_tuple(assignmentUUID, walletUUID, nodeVersion)); +} + +QUuid DomainGatekeeper::assignmentUUIDForPendingAssignment(const QUuid& tempUUID) { + auto it = _pendingAssignedNodes.find(tempUUID); + + if (it != _pendingAssignedNodes.end()) { + return it->second.getAssignmentUUID(); + } else { + return QUuid(); + } +} + +const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer +<< NodeType::AvatarMixer << NodeType::EntityServer; + +void DomainGatekeeper::processConnectRequestPacket(QSharedPointer packet) { + if (packet->getPayloadSize() == 0) { + return; + } + + QDataStream packetStream(packet.data()); + + // read a NodePacketHeader from the packet so we can pass around this data while we're inspecting it + NodeConnectionData nodeConnection = NodeConnectionData::fromDataStream(packetStream, packet->getSenderSockAddr()); + + if (nodeConnection.localSockAddr.isNull() || nodeConnection.publicSockAddr.isNull()) { + qDebug() << "Unexpected data received for node local socket or public socket. Will not allow connection."; + return; + } + + // check if this connect request matches an assignment in the queue + auto pendingAssignment = _pendingAssignedNodes.find(nodeConnection.connectUUID); + + SharedNodePointer node; + + if (pendingAssignment != _pendingAssignedNodes.end()) { + node = processAssignmentConnectRequest(nodeConnection, pendingAssignment->second); + } else if (!STATICALLY_ASSIGNED_NODES.contains(nodeConnection.nodeType)) { + QString username; + QByteArray usernameSignature; + + if (packet->bytesLeftToRead() > 0) { + // read username from packet + packetStream >> username; + + if (packet->bytesLeftToRead() > 0) { + // read user signature from packet + packetStream >> usernameSignature; + } + } + + node = processAgentConnectRequest(nodeConnection, username, usernameSignature); + } + + if (node) { + // set the sending sock addr and node interest set on this node + DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + nodeData->setSendingSockAddr(packet->getSenderSockAddr()); + nodeData->setNodeInterestSet(nodeConnection.interestList.toSet()); + + // signal that we just connected a node so the DomainServer can get it a list + // and broadcast its presence right away + emit connectedNode(node); + } +} + +SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeConnectionData& nodeConnection, + const PendingAssignedNodeData& pendingAssignment) { + SharedAssignmentPointer matchingQueuedAssignment = SharedAssignmentPointer(); + auto it = _pendingAssignedNodes.find(nodeConnection.connectUUID); + + if (it != _pendingAssignedNodes.end()) { + matchingQueuedAssignment = _server->dequeueMatchingAssignment(it->second.getAssignmentUUID(), nodeConnection.nodeType); + + if (matchingQueuedAssignment) { + qDebug() << "Assignment deployed with" << uuidStringWithoutCurlyBraces(nodeConnection.connectUUID) + << "matches unfulfilled assignment" + << uuidStringWithoutCurlyBraces(matchingQueuedAssignment->getUUID()); + } else { + // this is a node connecting to fulfill an assignment that doesn't exist + // don't reply back to them so they cycle back and re-request an assignment + qDebug() << "No match for assignment deployed with" << uuidStringWithoutCurlyBraces(nodeConnection.connectUUID); + return SharedNodePointer(); + } + } else { + qDebug() << "No assignment was deployed with UUID" << uuidStringWithoutCurlyBraces(nodeConnection.connectUUID); + return SharedNodePointer(); + } + + SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); + + // when the newNode is created the linked data is also created + // if this was a static assignment set the UUID, set the sendingSockAddr + DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); + + nodeData->setAssignmentUUID(matchingQueuedAssignment->getUUID()); + nodeData->setWalletUUID(it->second.getWalletUUID()); + nodeData->setNodeVersion(it->second.getNodeVersion()); + + // cleanup the PendingAssignedNodeData for this assignment now that it's connecting + _pendingAssignedNodes.erase(it); + + // always allow assignment clients to create and destroy entities + newNode->setCanAdjustLocks(true); + newNode->setCanRez(true); + + return newNode; +} + +const QString MAXIMUM_USER_CAPACITY = "security.maximum_user_capacity"; +const QString ALLOWED_EDITORS_SETTINGS_KEYPATH = "security.allowed_editors"; +const QString EDITORS_ARE_REZZERS_KEYPATH = "security.editors_are_rezzers"; + +SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnectionData& nodeConnection, + const QString& username, + const QByteArray& usernameSignature) { + + auto limitedNodeList = DependencyManager::get(); + + bool isRestrictingAccess = + _server->_settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); + + // check if this user is on our local machine - is this is true they are always allowed to connect + QHostAddress senderHostAddress = nodeConnection.senderSockAddr.getAddress(); + bool isLocalUser = + (senderHostAddress == limitedNodeList->getLocalSockAddr().getAddress() || senderHostAddress == QHostAddress::LocalHost); + + // if we're using restricted access and this user is not local make sure we got a user signature + if (isRestrictingAccess && !isLocalUser) { + if (!username.isEmpty()) { + if (usernameSignature.isEmpty()) { + // if user didn't include usernameSignature in connect request, send a connectionToken packet + sendConnectionTokenPacket(username, nodeConnection.senderSockAddr); + return SharedNodePointer(); + } + } + } + + bool verifiedUsername = false; + + // if we do not have a local user we need to subject them to our verification and capacity checks + if (!isLocalUser) { + + // check if we need to look at the username signature + if (isRestrictingAccess) { + if (isVerifiedAllowedUser(username, usernameSignature, nodeConnection.senderSockAddr)) { + // we verified the user via their username and signature - set the verifiedUsername + // so we don't re-decrypt their sig if we're trying to exempt them from max capacity check (due to + // being in the allowed editors list) + verifiedUsername = true; + } else { + // failed to verify user - return a null shared ptr + return SharedNodePointer(); + } + } + + if (!isWithinMaxCapacity(username, usernameSignature, verifiedUsername, nodeConnection.senderSockAddr)) { + // we can't allow this user to connect because we are at max capacity (and they either aren't an allowed editor + // or couldn't be verified as one) + return SharedNodePointer(); + } + } + + SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); + + // if this user is in the editors list (or if the editors list is empty) set the user's node's canAdjustLocks to true + const QVariant* allowedEditorsVariant = + valueForKeyPath(_server->_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); + QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); + + bool isAllowedEditor = allowedEditors.isEmpty() || allowedEditors.contains(username); + + bool canAdjustLocks = false; + + if (isAllowedEditor) { + if (!verifiedUsername) { + if (!verifyUserSignature(username, usernameSignature, HifiSockAddr())) { + qDebug() << "Could not verify user" << username << "as allowed editor. User will still be allowed to connect" + << "but will not have edit privileges."; + + canAdjustLocks = true; + } else { + canAdjustLocks = true; + } + } else { + canAdjustLocks = true; + } + } + + const QVariant* editorsAreRezzersVariant = + valueForKeyPath(_server->_settingsManager.getSettingsMap(), EDITORS_ARE_REZZERS_KEYPATH); + + bool onlyEditorsAreRezzers = false; + if (editorsAreRezzersVariant) { + onlyEditorsAreRezzers = editorsAreRezzersVariant->toBool(); + } + + bool canRez = true; + if (onlyEditorsAreRezzers) { + canRez = canAdjustLocks; + } + + DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); + + // if we have a username from the connect request, set it on the DomainServerNodeData + nodeData->setUsername(username); + + // also add an interpolation to JSONBreakableMarshal so that servers can get username in stats + JSONBreakableMarshal::addInterpolationForKey(USERNAME_UUID_REPLACEMENT_STATS_KEY, + uuidStringWithoutCurlyBraces(newNode->getUUID()), username); + + return newNode; +} + +SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection) { + HifiSockAddr discoveredSocket = nodeConnection.senderSockAddr; + SharedNetworkPeer connectedPeer = _icePeers.value(nodeConnection.connectUUID); + + QUuid nodeUUID; + + if (connectedPeer) { + // this user negotiated a connection with us via ICE, so re-use their ICE client ID + nodeUUID = nodeConnection.connectUUID; + + if (connectedPeer->getActiveSocket()) { + // set their discovered socket to whatever the activated socket on the network peer object was + discoveredSocket = *connectedPeer->getActiveSocket(); + } + } else { + // we got a connectUUID we didn't recognize, just add the node with a new UUID + nodeUUID = QUuid::createUuid(); + } + + auto limitedNodeList = DependencyManager::get(); + + SharedNodePointer newNode = limitedNodeList->addOrUpdateNode(nodeUUID, nodeConnection.nodeType, + nodeConnection.publicSockAddr, nodeConnection.localSockAddr); + + // So that we can send messages to this node at will - we need to activate the correct socket on this node now + newNode->activateMatchingOrNewSymmetricSocket(discoveredSocket); + + return newNode; +} + +bool DomainGatekeeper::verifyUserSignature(const QString& username, + const QByteArray& usernameSignature, + const HifiSockAddr& senderSockAddr) { + + // it's possible this user can be allowed to connect, but we need to check their username signature + QByteArray publicKeyArray = _userPublicKeys.value(username); + + const QUuid& connectionToken = _connectionTokenHash.value(username.toLower()); + + if (!publicKeyArray.isEmpty() && !connectionToken.isNull()) { + // if we do have a public key for the user, check for a signature match + + const unsigned char* publicKeyData = reinterpret_cast(publicKeyArray.constData()); + + // first load up the public key into an RSA struct + RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); + + QByteArray lowercaseUsername = username.toLower().toUtf8(); + QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), + QCryptographicHash::Sha256); + + if (rsaPublicKey) { + QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); + int decryptResult = RSA_verify(NID_sha256, + reinterpret_cast(usernameWithToken.constData()), + usernameWithToken.size(), + reinterpret_cast(usernameSignature.constData()), + usernameSignature.size(), + rsaPublicKey); + + if (decryptResult == 1) { + qDebug() << "Username signature matches for" << username << "- allowing connection."; + + // free up the public key and remove connection token before we return + RSA_free(rsaPublicKey); + _connectionTokenHash.remove(username); + + return true; + + } else { + if (!senderSockAddr.isNull()) { + qDebug() << "Error decrypting username signature for " << username << "- denying connection."; + sendConnectionDeniedPacket("Error decrypting username signature.", senderSockAddr); + } + + // free up the public key, we don't need it anymore + RSA_free(rsaPublicKey); + } + + } else { + + // we can't let this user in since we couldn't convert their public key to an RSA key we could use + if (!senderSockAddr.isNull()) { + qDebug() << "Couldn't convert data to RSA key for" << username << "- denying connection."; + sendConnectionDeniedPacket("Couldn't convert data to RSA key.", senderSockAddr); + } + } + } else { + if (!senderSockAddr.isNull()) { + qDebug() << "Insufficient data to decrypt username signature - denying connection."; + sendConnectionDeniedPacket("Insufficient data", senderSockAddr); + } + } + + requestUserPublicKey(username); // no joy. maybe next time? + return false; +} + +bool DomainGatekeeper::isVerifiedAllowedUser(const QString& username, const QByteArray& usernameSignature, + const HifiSockAddr& senderSockAddr) { + + QStringList allowedUsers = + _server->_settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); + + if (allowedUsers.contains(username, Qt::CaseInsensitive)) { + if (username.isEmpty()) { + qDebug() << "Connect request denied - no username provided."; + + sendConnectionDeniedPacket("No username provided", senderSockAddr); + + return false; + } + if (!verifyUserSignature(username, usernameSignature, senderSockAddr)) { + return false; + } + } else { + qDebug() << "Connect request denied for user" << username << "- not in allowed users list."; + sendConnectionDeniedPacket("User not on whitelist.", senderSockAddr); + + return false; + } + + return true; +} + +bool DomainGatekeeper::isWithinMaxCapacity(const QString& username, const QByteArray& usernameSignature, + bool& verifiedUsername, + const HifiSockAddr& senderSockAddr) { + // find out what our maximum capacity is + const QVariant* maximumUserCapacityVariant = valueForKeyPath(_server->_settingsManager.getSettingsMap(), MAXIMUM_USER_CAPACITY); + unsigned int maximumUserCapacity = maximumUserCapacityVariant ? maximumUserCapacityVariant->toUInt() : 0; + + if (maximumUserCapacity > 0) { + unsigned int connectedUsers = _server->countConnectedUsers(); + + if (connectedUsers >= maximumUserCapacity) { + // too many users, deny the new connection unless this user is an allowed editor + + const QVariant* allowedEditorsVariant = + valueForKeyPath(_server->_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); + + QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); + if (allowedEditors.contains(username)) { + if (verifiedUsername || verifyUserSignature(username, usernameSignature, senderSockAddr)) { + verifiedUsername = true; + return true; + } + } + + // deny connection from this user + qDebug() << connectedUsers << "/" << maximumUserCapacity << "users connected, denying new connection."; + sendConnectionDeniedPacket("Too many connected users.", senderSockAddr); + + return false; + } + + qDebug() << connectedUsers << "/" << maximumUserCapacity << "users connected, allowing new connection."; + } + + return true; +} + + +void DomainGatekeeper::preloadAllowedUserPublicKeys() { + const QVariant* allowedUsersVariant = valueForKeyPath(_server->_settingsManager.getSettingsMap(), ALLOWED_USERS_SETTINGS_KEYPATH); + QStringList allowedUsers = allowedUsersVariant ? allowedUsersVariant->toStringList() : QStringList(); + + if (allowedUsers.size() > 0) { + // in the future we may need to limit how many requests here - for now assume that lists of allowed users are not + // going to create > 100 requests + foreach(const QString& username, allowedUsers) { + requestUserPublicKey(username); + } + } +} + +void DomainGatekeeper::requestUserPublicKey(const QString& username) { + // even if we have a public key for them right now, request a new one in case it has just changed + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "publicKeyJSONCallback"; + + const QString USER_PUBLIC_KEY_PATH = "api/v1/users/%1/public_key"; + + qDebug() << "Requesting public key for user" << username; + + AccountManager::getInstance().sendRequest(USER_PUBLIC_KEY_PATH.arg(username), + AccountManagerAuth::None, + QNetworkAccessManager::GetOperation, callbackParams); +} + +void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply& requestReply) { + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + + if (jsonObject["status"].toString() == "success") { + // figure out which user this is for + + const QString PUBLIC_KEY_URL_REGEX_STRING = "api\\/v1\\/users\\/([A-Za-z0-9_\\.]+)\\/public_key"; + QRegExp usernameRegex(PUBLIC_KEY_URL_REGEX_STRING); + + if (usernameRegex.indexIn(requestReply.url().toString()) != -1) { + QString username = usernameRegex.cap(1); + + qDebug() << "Storing a public key for user" << username; + + // pull the public key as a QByteArray from this response + const QString JSON_DATA_KEY = "data"; + const QString JSON_PUBLIC_KEY_KEY = "public_key"; + + _userPublicKeys[username] = + QByteArray::fromBase64(jsonObject[JSON_DATA_KEY].toObject()[JSON_PUBLIC_KEY_KEY].toString().toUtf8()); + } + } +} + +void DomainGatekeeper::sendConnectionDeniedPacket(const QString& reason, const HifiSockAddr& senderSockAddr) { + // this is an agent and we've decided we won't let them connect - send them a packet to deny connection + QByteArray utfString = reason.toUtf8(); + quint16 payloadSize = utfString.size(); + + // setup the DomainConnectionDenied packet + auto connectionDeniedPacket = NLPacket::create(PacketType::DomainConnectionDenied, payloadSize + sizeof(payloadSize)); + + // packet in the reason the connection was denied (the client displays this) + if (payloadSize > 0) { + connectionDeniedPacket->writePrimitive(payloadSize); + connectionDeniedPacket->write(utfString); + } + + // send the packet off + DependencyManager::get()->sendPacket(std::move(connectionDeniedPacket), senderSockAddr); +} + +void DomainGatekeeper::sendConnectionTokenPacket(const QString& username, const HifiSockAddr& senderSockAddr) { + // get the existing connection token or create a new one + QUuid& connectionToken = _connectionTokenHash[username.toLower()]; + + if (connectionToken.isNull()) { + connectionToken = QUuid::createUuid(); + } + + // setup a static connection token packet + static auto connectionTokenPacket = NLPacket::create(PacketType::DomainServerConnectionToken, NUM_BYTES_RFC4122_UUID); + + // reset the packet before each time we send + connectionTokenPacket->reset(); + + // write the connection token + connectionTokenPacket->write(connectionToken.toRfc4122()); + + // send off the packet unreliably + DependencyManager::get()->sendUnreliablePacket(*connectionTokenPacket, senderSockAddr); +} + +const int NUM_PEER_PINGS_BEFORE_DELETE = 2000 / UDP_PUNCH_PING_INTERVAL_MS; + +void DomainGatekeeper::pingPunchForConnectingPeer(const SharedNetworkPeer& peer) { + + if (peer->getConnectionAttempts() > 0 && peer->getConnectionAttempts() % NUM_PEER_PINGS_BEFORE_DELETE == 0) { + // we've reached the maximum number of ping attempts + qDebug() << "Maximum number of ping attempts reached for peer with ID" << peer->getUUID(); + qDebug() << "Removing from list of connecting peers."; + + _icePeers.remove(peer->getUUID()); + } else { + auto limitedNodeList = DependencyManager::get(); + + // send the ping packet to the local and public sockets for this node + auto localPingPacket = limitedNodeList->constructICEPingPacket(PingType::Local, limitedNodeList->getSessionUUID()); + limitedNodeList->sendPacket(std::move(localPingPacket), peer->getLocalSocket()); + + auto publicPingPacket = limitedNodeList->constructICEPingPacket(PingType::Public, limitedNodeList->getSessionUUID()); + limitedNodeList->sendPacket(std::move(publicPingPacket), peer->getPublicSocket()); + + peer->incrementConnectionAttempts(); + } +} + +void DomainGatekeeper::handlePeerPingTimeout() { + NetworkPeer* senderPeer = qobject_cast(sender()); + + if (senderPeer) { + SharedNetworkPeer sharedPeer = _icePeers.value(senderPeer->getUUID()); + + if (sharedPeer && !sharedPeer->getActiveSocket()) { + pingPunchForConnectingPeer(sharedPeer); + } + } +} + +void DomainGatekeeper::processICEPeerInformationPacket(QSharedPointer packet) { + // loop through the packet and pull out network peers + // any peer we don't have we add to the hash, otherwise we update + QDataStream iceResponseStream(packet.data()); + + NetworkPeer* receivedPeer = new NetworkPeer; + iceResponseStream >> *receivedPeer; + + if (!_icePeers.contains(receivedPeer->getUUID())) { + qDebug() << "New peer requesting ICE connection being added to hash -" << *receivedPeer; + SharedNetworkPeer newPeer = SharedNetworkPeer(receivedPeer); + _icePeers[receivedPeer->getUUID()] = newPeer; + + // make sure we know when we should ping this peer + connect(newPeer.data(), &NetworkPeer::pingTimerTimeout, this, &DomainGatekeeper::handlePeerPingTimeout); + + // immediately ping the new peer, and start a timer to continue pinging it until we connect to it + newPeer->startPingTimer(); + + qDebug() << "Sending ping packets to establish connectivity with ICE peer with ID" + << newPeer->getUUID(); + + pingPunchForConnectingPeer(newPeer); + } else { + delete receivedPeer; + } +} + +void DomainGatekeeper::processICEPingPacket(QSharedPointer packet) { + auto limitedNodeList = DependencyManager::get(); + auto pingReplyPacket = limitedNodeList->constructICEPingReplyPacket(*packet, limitedNodeList->getSessionUUID()); + + limitedNodeList->sendPacket(std::move(pingReplyPacket), packet->getSenderSockAddr()); +} + +void DomainGatekeeper::processICEPingReplyPacket(QSharedPointer packet) { + QDataStream packetStream(packet.data()); + + QUuid nodeUUID; + packetStream >> nodeUUID; + + SharedNetworkPeer sendingPeer = _icePeers.value(nodeUUID); + + if (sendingPeer) { + // we had this NetworkPeer in our connecting list - add the right sock addr to our connected list + sendingPeer->activateMatchingOrNewSymmetricSocket(packet->getSenderSockAddr()); + } +} diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h new file mode 100644 index 0000000000..857b4419da --- /dev/null +++ b/domain-server/src/DomainGatekeeper.h @@ -0,0 +1,93 @@ +// +// DomainGatekeeper.h +// domain-server/src +// +// Created by Stephen Birarda on 2015-08-24. +// Copyright 2015 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_DomainGatekeeper_h +#define hifi_DomainGatekeeper_h + +#include + +#include +#include + +#include +#include +#include + +#include "NodeConnectionData.h" +#include "PendingAssignedNodeData.h" + +class DomainServer; + +class DomainGatekeeper : public QObject { + Q_OBJECT +public: + DomainGatekeeper(DomainServer* server); + + void addPendingAssignedNode(const QUuid& nodeUUID, const QUuid& assignmentUUID, + const QUuid& walletUUID, const QString& nodeVersion); + QUuid assignmentUUIDForPendingAssignment(const QUuid& tempUUID); + + void preloadAllowedUserPublicKeys(); + + void removeICEPeer(const QUuid& peerUUID) { _icePeers.remove(peerUUID); } +public slots: + void processConnectRequestPacket(QSharedPointer packet); + void processICEPingPacket(QSharedPointer packet); + void processICEPingReplyPacket(QSharedPointer packet); + void processICEPeerInformationPacket(QSharedPointer packet); + + void publicKeyJSONCallback(QNetworkReply& requestReply); + +signals: + void connectedNode(SharedNodePointer node); + +private slots: + void handlePeerPingTimeout(); +private: + SharedNodePointer processAssignmentConnectRequest(const NodeConnectionData& nodeConnection, + const PendingAssignedNodeData& pendingAssignment); + SharedNodePointer processAgentConnectRequest(const NodeConnectionData& nodeConnection, + const QString& username, + const QByteArray& usernameSignature); + SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection); + + bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature, + const HifiSockAddr& senderSockAddr); + bool isVerifiedAllowedUser(const QString& username, const QByteArray& usernameSignature, + const HifiSockAddr& senderSockAddr); + bool isWithinMaxCapacity(const QString& username, const QByteArray& usernameSignature, + bool& verifiedUsername, + const HifiSockAddr& senderSockAddr); + + bool shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature, + const HifiSockAddr& senderSockAddr); + + void sendConnectionTokenPacket(const QString& username, const HifiSockAddr& senderSockAddr); + void sendConnectionDeniedPacket(const QString& reason, const HifiSockAddr& senderSockAddr); + + void pingPunchForConnectingPeer(const SharedNetworkPeer& peer); + + void requestUserPublicKey(const QString& username); + + DomainServer* _server; + + std::unordered_map _pendingAssignedNodes; + + QHash _icePeers; + + QHash _connectionTokenHash; + QHash _userPublicKeys; +}; + + +#endif // hifi_DomainGatekeeper_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 23957380e6..12a9e094aa 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -9,9 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include +#include "DomainServer.h" #include #include @@ -38,24 +36,19 @@ #include #include "DomainServerNodeData.h" - -#include "DomainServer.h" +#include "NodeConnectionData.h" int const DomainServer::EXIT_CODE_REBOOT = 234923; const QString ICE_SERVER_DEFAULT_HOSTNAME = "ice.highfidelity.io"; -const QString MAXIMUM_USER_CAPACITY = "security.maximum_user_capacity"; -const QString ALLOWED_EDITORS_SETTINGS_KEYPATH = "security.allowed_editors"; -const QString EDITORS_ARE_REZZERS_KEYPATH = "security.editors_are_rezzers"; - DomainServer::DomainServer(int argc, char* argv[]) : QCoreApplication(argc, argv), + _gatekeeper(this), _httpManager(DOMAIN_SERVER_HTTP_PORT, QString("%1/resources/web/").arg(QCoreApplication::applicationDirPath()), this), _httpsManager(NULL), _allAssignments(), _unfulfilledAssignments(), - _pendingAssignedNodes(), _isUsingDTLS(false), _oauthProviderURL(), _oauthClientID(), @@ -94,6 +87,9 @@ DomainServer::DomainServer(int argc, char* argv[]) : qRegisterMetaType("DomainServerWebSessionData"); qRegisterMetaTypeStreamOperators("DomainServerWebSessionData"); + + // make sure we hear about newly connected nodes from our gatekeeper + connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode); if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth() && optionallySetupAssignmentPayment()) { // we either read a certificate and private key or were not passed one @@ -108,7 +104,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : setupAutomaticNetworking(); // preload some user public keys so they can connect on first request - preloadAllowedUserPublicKeys(); + _gatekeeper.preloadAllowedUserPublicKeys(); } } @@ -284,13 +280,13 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { // register as the packet receiver for the types we want PacketReceiver& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::RequestAssignment, this, "processRequestAssignmentPacket"); - packetReceiver.registerListener(PacketType::DomainConnectRequest, this, "processConnectRequestPacket"); + packetReceiver.registerListener(PacketType::DomainConnectRequest, &_gatekeeper, "processConnectRequestPacket"); packetReceiver.registerListener(PacketType::DomainListRequest, this, "processListRequestPacket"); packetReceiver.registerListener(PacketType::DomainServerPathQuery, this, "processPathQueryPacket"); packetReceiver.registerListener(PacketType::NodeJsonStats, this, "processNodeJSONStatsPacket"); - packetReceiver.registerListener(PacketType::ICEPing, this, "processICEPingPacket"); - packetReceiver.registerListener(PacketType::ICEPingReply, this, "processICEPingReplyPacket"); - packetReceiver.registerListener(PacketType::ICEServerPeerInformation, this, "processICEPeerInformationPacket"); + packetReceiver.registerListener(PacketType::ICEPing, &_gatekeeper, "processICEPingPacket"); + packetReceiver.registerListener(PacketType::ICEPingReply, &_gatekeeper, "processICEPingReplyPacket"); + packetReceiver.registerListener(PacketType::ICEServerPeerInformation, &_gatekeeper, "processICEPeerInformationPacket"); // add whatever static assignments that have been parsed to the queue addStaticAssignmentsToQueue(); @@ -575,217 +571,20 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet packet) { - NodeType_t nodeType; - HifiSockAddr publicSockAddr, localSockAddr; - - if (packet->getPayloadSize() == 0) { - return; - } - - QDataStream packetStream(packet.data()); - - QUuid connectUUID; - packetStream >> connectUUID; - - const HifiSockAddr& senderSockAddr = packet->getSenderSockAddr(); - - parseNodeData(packetStream, nodeType, publicSockAddr, localSockAddr, senderSockAddr); - - if (localSockAddr.isNull() || senderSockAddr.isNull()) { - qDebug() << "Unexpected data received for node local socket or public socket. Will not allow connection."; - return; - } - - // check if this connect request matches an assignment in the queue - bool isAssignment = _pendingAssignedNodes.contains(connectUUID); - SharedAssignmentPointer matchingQueuedAssignment = SharedAssignmentPointer(); - PendingAssignedNodeData* pendingAssigneeData = NULL; - - if (isAssignment) { - pendingAssigneeData = _pendingAssignedNodes.value(connectUUID); - - if (pendingAssigneeData) { - matchingQueuedAssignment = matchingQueuedAssignmentForCheckIn(pendingAssigneeData->getAssignmentUUID(), nodeType); - - if (matchingQueuedAssignment) { - qDebug() << "Assignment deployed with" << uuidStringWithoutCurlyBraces(connectUUID) - << "matches unfulfilled assignment" - << uuidStringWithoutCurlyBraces(matchingQueuedAssignment->getUUID()); - - // remove this unique assignment deployment from the hash of pending assigned nodes - // cleanup of the PendingAssignedNodeData happens below after the node has been added to the LimitedNodeList - _pendingAssignedNodes.remove(connectUUID); - } else { - // this is a node connecting to fulfill an assignment that doesn't exist - // don't reply back to them so they cycle back and re-request an assignment - qDebug() << "No match for assignment deployed with" << uuidStringWithoutCurlyBraces(connectUUID); - return; - } - } - } - - QList nodeInterestList; - QString username; - QByteArray usernameSignature; - - auto limitedNodeList = DependencyManager::get(); - - packetStream >> nodeInterestList; - - if (packet->bytesLeftToRead() > 0) { - // try to verify username - packetStream >> username; - } - - bool isRestrictingAccess = - _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); - - // we always let in a user who is sending a packet from our local socket or from the localhost address - bool isLocalUser = (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost); - - if (isRestrictingAccess && !isLocalUser) { - if (!username.isEmpty()) { - // if there's a username, try to unpack username signature - packetStream >> usernameSignature; - - if (usernameSignature.isEmpty()) { - // if user didn't include usernameSignature in connect request, send a connectionToken packet - QUuid& connectionToken = _connectionTokenHash[username.toLower()]; - - if (connectionToken.isNull()) { - connectionToken = QUuid::createUuid(); - } - - static auto connectionTokenPacket = NLPacket::create(PacketType::DomainServerConnectionToken, NUM_BYTES_RFC4122_UUID); - connectionTokenPacket->reset(); - connectionTokenPacket->write(connectionToken.toRfc4122()); - limitedNodeList->sendUnreliablePacket(*connectionTokenPacket, packet->getSenderSockAddr()); - return; - } - } - } - - QString reason; - if (!isAssignment && !shouldAllowConnectionFromNode(username, usernameSignature, senderSockAddr, reason)) { - // this is an agent and we've decided we won't let them connect - send them a packet to deny connection - QByteArray utfString = reason.toUtf8(); - quint16 payloadSize = utfString.size(); - - auto connectionDeniedPacket = NLPacket::create(PacketType::DomainConnectionDenied, payloadSize + sizeof(payloadSize)); - if (payloadSize > 0) { - connectionDeniedPacket->writePrimitive(payloadSize); - connectionDeniedPacket->write(utfString); - } - // tell client it has been refused. - limitedNodeList->sendPacket(std::move(connectionDeniedPacket), senderSockAddr); - return; - } - - if ((!isAssignment && !STATICALLY_ASSIGNED_NODES.contains(nodeType)) - || (isAssignment && matchingQueuedAssignment)) { - // this was either not a static assignment or it was and we had a matching one in the queue - - QUuid nodeUUID; - - HifiSockAddr discoveredSocket = senderSockAddr; - SharedNetworkPeer connectedPeer = _icePeers.value(connectUUID); - - if (connectedPeer) { - // this user negotiated a connection with us via ICE, so re-use their ICE client ID - nodeUUID = connectUUID; - - if (connectedPeer->getActiveSocket()) { - // set their discovered socket to whatever the activated socket on the network peer object was - discoveredSocket = *connectedPeer->getActiveSocket(); - } - } else { - // we got a connectUUID we didn't recognize, just add the node with a new UUID - nodeUUID = QUuid::createUuid(); - } - - // if this user is in the editors list (or if the editors list is empty) set the user's node's canAdjustLocks to true - const QVariant* allowedEditorsVariant = - valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); - QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); - bool canAdjustLocks = allowedEditors.isEmpty() || allowedEditors.contains(username); - - const QVariant* editorsAreRezzersVariant = - valueForKeyPath(_settingsManager.getSettingsMap(), EDITORS_ARE_REZZERS_KEYPATH); - - bool onlyEditorsAreRezzers = false; - if (editorsAreRezzersVariant) { - onlyEditorsAreRezzers = editorsAreRezzersVariant->toBool(); - } - - bool canRez = true; - if (onlyEditorsAreRezzers) { - canRez = canAdjustLocks; - } - - SharedNodePointer newNode = limitedNodeList->addOrUpdateNode(nodeUUID, nodeType, - publicSockAddr, localSockAddr, - canAdjustLocks, canRez); - - // So that we can send messages to this node at will - we need to activate the correct socket on this node now - newNode->activateMatchingOrNewSymmetricSocket(discoveredSocket); - - // when the newNode is created the linked data is also created - // if this was a static assignment set the UUID, set the sendingSockAddr - DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); - - if (isAssignment) { - nodeData->setAssignmentUUID(matchingQueuedAssignment->getUUID()); - nodeData->setWalletUUID(pendingAssigneeData->getWalletUUID()); - nodeData->setNodeVersion(pendingAssigneeData->getNodeVersion()); - - // always allow assignment clients to create and destroy entities - newNode->setCanAdjustLocks(true); - newNode->setCanRez(true); - - // now that we've pulled the wallet UUID and added the node to our list, delete the pending assignee data - delete pendingAssigneeData; - } - - if (!username.isEmpty()) { - // if we have a username from the connect request, set it on the DomainServerNodeData - nodeData->setUsername(username); - - // also add an interpolation to JSONBreakableMarshal so that servers can get username in stats - JSONBreakableMarshal::addInterpolationForKey(USERNAME_UUID_REPLACEMENT_STATS_KEY, - uuidStringWithoutCurlyBraces(nodeUUID), username); - } - - nodeData->setSendingSockAddr(senderSockAddr); - - // reply back to the user with a PacketType::DomainList - sendDomainListToNode(newNode, senderSockAddr, nodeInterestList.toSet()); - - // send out this node to our other connected nodes - broadcastNewNode(newNode); - } -} - - void DomainServer::processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { - NodeType_t throwawayNodeType; - HifiSockAddr nodePublicAddress, nodeLocalAddress; - QDataStream packetStream(packet.data()); + NodeConnectionData nodeRequestData = NodeConnectionData::fromDataStream(packetStream, packet->getSenderSockAddr()); - parseNodeData(packetStream, throwawayNodeType, nodePublicAddress, nodeLocalAddress, packet->getSenderSockAddr()); + // update this node's sockets in case they have changed + sendingNode->setPublicSocket(nodeRequestData.publicSockAddr); + sendingNode->setLocalSocket(nodeRequestData.localSockAddr); + + // update the NodeInterestSet in case there have been any changes + DomainServerNodeData* nodeData = reinterpret_cast(sendingNode->getLinkedData()); + nodeData->setNodeInterestSet(nodeRequestData.interestList.toSet()); - sendingNode->setPublicSocket(nodePublicAddress); - sendingNode->setLocalSocket(nodeLocalAddress); - - QList nodeInterestList; - packetStream >> nodeInterestList; - - sendDomainListToNode(sendingNode, packet->getSenderSockAddr(), nodeInterestList.toSet()); + sendDomainListToNode(sendingNode, packet->getSenderSockAddr()); } unsigned int DomainServer::countConnectedUsers() { @@ -799,156 +598,6 @@ unsigned int DomainServer::countConnectedUsers() { return result; } - -bool DomainServer::verifyUserSignature(const QString& username, - const QByteArray& usernameSignature, - QString& reasonReturn) { - - // it's possible this user can be allowed to connect, but we need to check their username signature - QByteArray publicKeyArray = _userPublicKeys.value(username); - - const QUuid& connectionToken = _connectionTokenHash.value(username.toLower()); - - if (!publicKeyArray.isEmpty() && !connectionToken.isNull()) { - // if we do have a public key for the user, check for a signature match - - const unsigned char* publicKeyData = reinterpret_cast(publicKeyArray.constData()); - - // first load up the public key into an RSA struct - RSA* rsaPublicKey = d2i_RSA_PUBKEY(NULL, &publicKeyData, publicKeyArray.size()); - - QByteArray lowercaseUsername = username.toLower().toUtf8(); - QByteArray usernameWithToken = QCryptographicHash::hash(lowercaseUsername.append(connectionToken.toRfc4122()), - QCryptographicHash::Sha256); - - if (rsaPublicKey) { - QByteArray decryptedArray(RSA_size(rsaPublicKey), 0); - int decryptResult = RSA_verify(NID_sha256, - reinterpret_cast(usernameWithToken.constData()), - usernameWithToken.size(), - reinterpret_cast(usernameSignature.constData()), - usernameSignature.size(), - rsaPublicKey); - - if (decryptResult == 1) { - qDebug() << "Username signature matches for" << username << "- allowing connection."; - - // free up the public key and remove connection token before we return - RSA_free(rsaPublicKey); - _connectionTokenHash.remove(username); - - return true; - - } else { - qDebug() << "Error decrypting username signature for " << username << "- denying connection."; - reasonReturn = "Error decrypting username signature."; - // free up the public key, we don't need it anymore - RSA_free(rsaPublicKey); - } - - } else { - - // we can't let this user in since we couldn't convert their public key to an RSA key we could use - qDebug() << "Couldn't convert data to RSA key for" << username << "- denying connection."; - reasonReturn = "Couldn't convert data to RSA key."; - } - } else { - qDebug() << "Insufficient data to decrypt username signature - denying connection."; - reasonReturn = "Insufficient data"; - } - - requestUserPublicKey(username); // no joy. maybe next time? - return false; -} - - -bool DomainServer::shouldAllowConnectionFromNode(const QString& username, - const QByteArray& usernameSignature, - const HifiSockAddr& senderSockAddr, - QString& reasonReturn) { - - //TODO: improve flow so these bools aren't declared twice - bool isRestrictingAccess = - _settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); - bool isLocalUser = (senderSockAddr.getAddress() == DependencyManager::get()->getLocalSockAddr().getAddress() || senderSockAddr.getAddress() == QHostAddress::LocalHost); - - if (isRestrictingAccess && !isLocalUser) { - QStringList allowedUsers = - _settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); - - if (allowedUsers.contains(username, Qt::CaseInsensitive)) { - if (username.isEmpty()) { - qDebug() << "Connect request denied - no username provided."; - reasonReturn = "No username provided"; - return false; - } - if (!verifyUserSignature(username, usernameSignature, reasonReturn)) { - return false; - } - } else { - qDebug() << "Connect request denied for user" << username << "not in allowed users list."; - reasonReturn = "User not on whitelist."; - - return false; - } - } - - // either we aren't restricting users, or this user is in the allowed list - // if this user is in the editors list, exempt them from the max-capacity check - const QVariant* allowedEditorsVariant = - valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); - QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); - if (allowedEditors.contains(username)) { - if (verifyUserSignature(username, usernameSignature, reasonReturn)) { - return true; - } - } - - // if we haven't reached max-capacity, let them in. - const QVariant* maximumUserCapacityVariant = valueForKeyPath(_settingsManager.getSettingsMap(), MAXIMUM_USER_CAPACITY); - unsigned int maximumUserCapacity = maximumUserCapacityVariant ? maximumUserCapacityVariant->toUInt() : 0; - if (maximumUserCapacity > 0) { - unsigned int connectedUsers = countConnectedUsers(); - if (connectedUsers >= maximumUserCapacity) { - // too many users, deny the new connection. - qDebug() << connectedUsers << "/" << maximumUserCapacity << "users connected, denying new connection."; - reasonReturn = "Too many connected users."; - return false; - } - qDebug() << connectedUsers << "/" << maximumUserCapacity << "users connected, perhaps allowing new connection."; - } - - return true; -} - -void DomainServer::preloadAllowedUserPublicKeys() { - const QVariant* allowedUsersVariant = valueForKeyPath(_settingsManager.getSettingsMap(), ALLOWED_USERS_SETTINGS_KEYPATH); - QStringList allowedUsers = allowedUsersVariant ? allowedUsersVariant->toStringList() : QStringList(); - - if (allowedUsers.size() > 0) { - // in the future we may need to limit how many requests here - for now assume that lists of allowed users are not - // going to create > 100 requests - foreach(const QString& username, allowedUsers) { - requestUserPublicKey(username); - } - } -} - -void DomainServer::requestUserPublicKey(const QString& username) { - // even if we have a public key for them right now, request a new one in case it has just changed - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = this; - callbackParams.jsonCallbackMethod = "publicKeyJSONCallback"; - - const QString USER_PUBLIC_KEY_PATH = "api/v1/users/%1/public_key"; - - qDebug() << "Requesting public key for user" << username; - - AccountManager::getInstance().sendRequest(USER_PUBLIC_KEY_PATH.arg(username), - AccountManagerAuth::None, - QNetworkAccessManager::GetOperation, callbackParams); -} - QUrl DomainServer::oauthRedirectURL() { return QString("https://%1:%2/oauth").arg(_hostname).arg(_httpsManager->serverPort()); } @@ -983,30 +632,18 @@ QUrl DomainServer::oauthAuthorizationURL(const QUuid& stateUUID) { return authorizationURL; } -int DomainServer::parseNodeData(QDataStream& packetStream, NodeType_t& nodeType, - HifiSockAddr& publicSockAddr, HifiSockAddr& localSockAddr, - const HifiSockAddr& senderSockAddr) { - packetStream >> nodeType; - packetStream >> publicSockAddr >> localSockAddr; +void DomainServer::handleConnectedNode(SharedNodePointer newNode) { - if (publicSockAddr.getAddress().isNull()) { - // this node wants to use us its STUN server - // so set the node public address to whatever we perceive the public address to be - - // if the sender is on our box then leave its public address to 0 so that - // other users attempt to reach it on the same address they have for the domain-server - if (senderSockAddr.getAddress().isLoopback()) { - publicSockAddr.setAddress(QHostAddress()); - } else { - publicSockAddr.setAddress(senderSockAddr.getAddress()); - } - } - - return packetStream.device()->pos(); + DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); + + // reply back to the user with a PacketType::DomainList + sendDomainListToNode(newNode, nodeData->getSendingSockAddr()); + + // send out this node to our other connected nodes + broadcastNewNode(newNode); } -void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr &senderSockAddr, - const NodeSet& nodeInterestSet) { +void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr &senderSockAddr) { const int NUM_DOMAIN_LIST_EXTENDED_HEADER_BYTES = NUM_BYTES_RFC4122_UUID + NUM_BYTES_RFC4122_UUID + 2; // setup the extended header for the domain list packets @@ -1029,7 +666,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); // store the nodeInterestSet on this DomainServerNodeData, in case it has changed - nodeData->setNodeInterestSet(nodeInterestSet); + auto& nodeInterestSet = nodeData->getNodeInterestSet(); if (nodeInterestSet.size() > 0) { @@ -1169,11 +806,10 @@ void DomainServer::processRequestAssignmentPacket(QSharedPointer packe auto limitedNodeList = DependencyManager::get(); limitedNodeList->sendUnreliablePacket(*assignmentPacket, packet->getSenderSockAddr()); - // add the information for that deployed assignment to the hash of pending assigned nodes - PendingAssignedNodeData* pendingNodeData = new PendingAssignedNodeData(assignmentToDeploy->getUUID(), - requestAssignment.getWalletUUID(), - requestAssignment.getNodeVersion()); - _pendingAssignedNodes.insert(uniqueAssignment.getUUID(), pendingNodeData); + // give the information for that deployed assignment to the gatekeeper so it knows to that that node + // in when it comes back around + _gatekeeper.addPendingAssignedNode(uniqueAssignment.getUUID(), assignmentToDeploy->getUUID(), + requestAssignment.getWalletUUID(), requestAssignment.getNodeVersion()); } else { if (requestAssignment.getType() != Assignment::AgentType || noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) { @@ -1253,30 +889,6 @@ void DomainServer::sendPendingTransactionsToServer() { } } -void DomainServer::publicKeyJSONCallback(QNetworkReply& requestReply) { - QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); - - if (jsonObject["status"].toString() == "success") { - // figure out which user this is for - - const QString PUBLIC_KEY_URL_REGEX_STRING = "api\\/v1\\/users\\/([A-Za-z0-9_\\.]+)\\/public_key"; - QRegExp usernameRegex(PUBLIC_KEY_URL_REGEX_STRING); - - if (usernameRegex.indexIn(requestReply.url().toString()) != -1) { - QString username = usernameRegex.cap(1); - - qDebug() << "Storing a public key for user" << username; - - // pull the public key as a QByteArray from this response - const QString JSON_DATA_KEY = "data"; - const QString JSON_PUBLIC_KEY_KEY = "public_key"; - - _userPublicKeys[username] = - QByteArray::fromBase64(jsonObject[JSON_DATA_KEY].toObject()[JSON_PUBLIC_KEY_KEY].toString().toUtf8()); - } - } -} - void DomainServer::transactionJSONCallback(const QJsonObject& data) { // check if this was successful - if so we can remove it from our list of pending if (data.value("status").toString() == "success") { @@ -1373,91 +985,6 @@ void DomainServer::sendHeartbeatToIceServer() { DependencyManager::get()->sendHeartbeatToIceServer(_iceServerSocket); } -const int NUM_PEER_PINGS_BEFORE_DELETE = 2000 / UDP_PUNCH_PING_INTERVAL_MS; - -void DomainServer::pingPunchForConnectingPeer(const SharedNetworkPeer& peer) { - - if (peer->getConnectionAttempts() > 0 && peer->getConnectionAttempts() % NUM_PEER_PINGS_BEFORE_DELETE == 0) { - // we've reached the maximum number of ping attempts - qDebug() << "Maximum number of ping attempts reached for peer with ID" << peer->getUUID(); - qDebug() << "Removing from list of connecting peers."; - - _icePeers.remove(peer->getUUID()); - } else { - auto limitedNodeList = DependencyManager::get(); - - // send the ping packet to the local and public sockets for this node - auto localPingPacket = limitedNodeList->constructICEPingPacket(PingType::Local, limitedNodeList->getSessionUUID()); - limitedNodeList->sendPacket(std::move(localPingPacket), peer->getLocalSocket()); - - auto publicPingPacket = limitedNodeList->constructICEPingPacket(PingType::Public, limitedNodeList->getSessionUUID()); - limitedNodeList->sendPacket(std::move(publicPingPacket), peer->getPublicSocket()); - - peer->incrementConnectionAttempts(); - } -} - -void DomainServer::handlePeerPingTimeout() { - NetworkPeer* senderPeer = qobject_cast(sender()); - - if (senderPeer) { - SharedNetworkPeer sharedPeer = _icePeers.value(senderPeer->getUUID()); - - if (sharedPeer && !sharedPeer->getActiveSocket()) { - pingPunchForConnectingPeer(sharedPeer); - } - } -} - -void DomainServer::processICEPeerInformationPacket(QSharedPointer packet) { - // loop through the packet and pull out network peers - // any peer we don't have we add to the hash, otherwise we update - QDataStream iceResponseStream(packet.data()); - - NetworkPeer* receivedPeer = new NetworkPeer; - iceResponseStream >> *receivedPeer; - - if (!_icePeers.contains(receivedPeer->getUUID())) { - qDebug() << "New peer requesting ICE connection being added to hash -" << *receivedPeer; - SharedNetworkPeer newPeer = SharedNetworkPeer(receivedPeer); - _icePeers[receivedPeer->getUUID()] = newPeer; - - // make sure we know when we should ping this peer - connect(newPeer.data(), &NetworkPeer::pingTimerTimeout, this, &DomainServer::handlePeerPingTimeout); - - // immediately ping the new peer, and start a timer to continue pinging it until we connect to it - newPeer->startPingTimer(); - - qDebug() << "Sending ping packets to establish connectivity with ICE peer with ID" - << newPeer->getUUID(); - - pingPunchForConnectingPeer(newPeer); - } else { - delete receivedPeer; - } -} - -void DomainServer::processICEPingPacket(QSharedPointer packet) { - auto limitedNodeList = DependencyManager::get(); - auto pingReplyPacket = limitedNodeList->constructICEPingReplyPacket(*packet, limitedNodeList->getSessionUUID()); - - limitedNodeList->sendPacket(std::move(pingReplyPacket), packet->getSenderSockAddr()); -} - -void DomainServer::processICEPingReplyPacket(QSharedPointer packet) { - QDataStream packetStream(packet.data()); - - QUuid nodeUUID; - packetStream >> nodeUUID; - - SharedNetworkPeer sendingPeer = _icePeers.value(nodeUUID); - - if (sendingPeer) { - // we had this NetworkPeer in our connecting list - add the right sock addr to our connected list - sendingPeer->activateMatchingOrNewSymmetricSocket(packet->getSenderSockAddr()); - } -} - void DomainServer::processNodeJSONStatsPacket(QSharedPointer packet, SharedNodePointer sendingNode) { auto nodeData = dynamic_cast(sendingNode->getLinkedData()); if (nodeData) { @@ -1569,9 +1096,9 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url SharedAssignmentPointer matchingAssignment = _allAssignments.value(matchingUUID); if (!matchingAssignment) { // check if we have a pending assignment that matches this temp UUID, and it is a scripted assignment - PendingAssignedNodeData* pendingData = _pendingAssignedNodes.value(matchingUUID); - if (pendingData) { - matchingAssignment = _allAssignments.value(pendingData->getAssignmentUUID()); + QUuid assignmentUUID = _gatekeeper.assignmentUUIDForPendingAssignment(matchingUUID); + if (!assignmentUUID.isNull()) { + matchingAssignment = _allAssignments.value(assignmentUUID); if (matchingAssignment && matchingAssignment->getType() == Assignment::AgentType) { // we have a matching assignment and it is for the right type, have the HTTP manager handle it @@ -1579,7 +1106,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QUrl scriptURL = url; scriptURL.setPath(URI_ASSIGNMENT + "/scripts/" - + uuidStringWithoutCurlyBraces(pendingData->getAssignmentUUID())); + + uuidStringWithoutCurlyBraces(assignmentUUID)); // have the HTTPManager serve the appropriate script file return _httpManager.handleHTTPRequest(connection, scriptURL, true); @@ -2113,7 +1640,7 @@ void DomainServer::nodeAdded(SharedNodePointer node) { void DomainServer::nodeKilled(SharedNodePointer node) { // if this peer connected via ICE then remove them from our ICE peers hash - _icePeers.remove(node->getUUID()); + _gatekeeper.removeICEPeer(node->getUUID()); DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); @@ -2141,7 +1668,7 @@ void DomainServer::nodeKilled(SharedNodePointer node) { } } -SharedAssignmentPointer DomainServer::matchingQueuedAssignmentForCheckIn(const QUuid& assignmentUUID, NodeType_t nodeType) { +SharedAssignmentPointer DomainServer::dequeueMatchingAssignment(const QUuid& assignmentUUID, NodeType_t nodeType) { QQueue::iterator i = _unfulfilledAssignments.begin(); while (i != _unfulfilledAssignments.end()) { @@ -2192,20 +1719,6 @@ SharedAssignmentPointer DomainServer::deployableAssignmentForRequest(const Assig return SharedAssignmentPointer(); } -void DomainServer::removeMatchingAssignmentFromQueue(const SharedAssignmentPointer& removableAssignment) { - QQueue::iterator potentialMatchingAssignment = _unfulfilledAssignments.begin(); - while (potentialMatchingAssignment != _unfulfilledAssignments.end()) { - if (potentialMatchingAssignment->data()->getUUID() == removableAssignment->getUUID()) { - _unfulfilledAssignments.erase(potentialMatchingAssignment); - - // we matched and removed an assignment, bail out - break; - } else { - ++potentialMatchingAssignment; - } - } -} - void DomainServer::addStaticAssignmentsToQueue() { // if the domain-server has just restarted, diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 7495e080de..a7e1a37c10 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -25,6 +25,7 @@ #include #include +#include "DomainGatekeeper.h" #include "DomainServerSettingsManager.h" #include "DomainServerWebSessionData.h" #include "WalletTransaction.h" @@ -50,19 +51,14 @@ public slots: /// Called by NodeList to inform us a node has been killed void nodeKilled(SharedNodePointer node); - void publicKeyJSONCallback(QNetworkReply& requestReply); void transactionJSONCallback(const QJsonObject& data); void restart(); void processRequestAssignmentPacket(QSharedPointer packet); - void processConnectRequestPacket(QSharedPointer packet); void processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processNodeJSONStatsPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processPathQueryPacket(QSharedPointer packet); - void processICEPingPacket(QSharedPointer packet); - void processICEPingReplyPacket(QSharedPointer packet); - void processICEPeerInformationPacket(QSharedPointer packet); private slots: void aboutToQuit(); @@ -74,7 +70,9 @@ private slots: void performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr); void sendHeartbeatToDataServer() { sendHeartbeatToDataServer(QString()); } void sendHeartbeatToIceServer(); - void handlePeerPingTimeout(); + + void handleConnectedNode(SharedNodePointer newNode); + private: void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid()); bool optionallySetupOAuth(); @@ -87,20 +85,9 @@ private: void setupAutomaticNetworking(); void sendHeartbeatToDataServer(const QString& networkAddress); - void pingPunchForConnectingPeer(const SharedNetworkPeer& peer); - unsigned int countConnectedUsers(); - bool verifyUserSignature (const QString& username, const QByteArray& usernameSignature, QString& reasonReturn); - bool shouldAllowConnectionFromNode(const QString& username, const QByteArray& usernameSignature, - const HifiSockAddr& senderSockAddr, QString& reasonReturn); - void preloadAllowedUserPublicKeys(); - void requestUserPublicKey(const QString& username); - - int parseNodeData(QDataStream& packetStream, NodeType_t& nodeType, - HifiSockAddr& publicSockAddr, HifiSockAddr& localSockAddr, const HifiSockAddr& senderSockAddr); - void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr, - const NodeSet& nodeInterestSet); + void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr); QUuid connectionSecretForNodes(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB); void broadcastNewNode(const SharedNodePointer& node); @@ -111,12 +98,11 @@ private: void populateDefaultStaticAssignmentsExcludingTypes(const QSet& excludedTypes); void populateStaticScriptedAssignmentsFromSettings(); - SharedAssignmentPointer matchingQueuedAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType); + SharedAssignmentPointer dequeueMatchingAssignment(const QUuid& checkInUUID, NodeType_t nodeType); SharedAssignmentPointer deployableAssignmentForRequest(const Assignment& requestAssignment); - void removeMatchingAssignmentFromQueue(const SharedAssignmentPointer& removableAssignment); void refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& assignment); void addStaticAssignmentsToQueue(); - + QUrl oauthRedirectURL(); QUrl oauthAuthorizationURL(const QUuid& stateUUID = QUuid::createUuid()); @@ -131,13 +117,14 @@ private: QJsonObject jsonForSocket(const HifiSockAddr& socket); QJsonObject jsonObjectForNode(const SharedNodePointer& node); + + DomainGatekeeper _gatekeeper; HTTPManager _httpManager; HTTPSManager* _httpsManager; QHash _allAssignments; QQueue _unfulfilledAssignments; - QHash _pendingAssignedNodes; TransactionHash _pendingAssignmentCredits; bool _isUsingDTLS; @@ -149,18 +136,14 @@ private: QSet _webAuthenticationStateSet; QHash _cookieSessionHash; - - QHash _connectionTokenHash; - - QHash _userPublicKeys; - - QHash _icePeers; QString _automaticNetworkingSetting; DomainServerSettingsManager _settingsManager; HifiSockAddr _iceServerSocket; + + friend class DomainGatekeeper; }; diff --git a/domain-server/src/NodeConnectionData.cpp b/domain-server/src/NodeConnectionData.cpp new file mode 100644 index 0000000000..6e6e35f205 --- /dev/null +++ b/domain-server/src/NodeConnectionData.cpp @@ -0,0 +1,37 @@ +// +// NodeConnectionData.cpp +// domain-server/src +// +// Created by Stephen Birarda on 2015-08-24. +// Copyright 2015 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 "NodeConnectionData.h" + +NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, const HifiSockAddr& senderSockAddr) { + NodeConnectionData newHeader; + + dataStream >> newHeader.connectUUID >> newHeader.nodeType + >> newHeader.publicSockAddr >> newHeader.localSockAddr + >> newHeader.interestList; + + newHeader.senderSockAddr = senderSockAddr; + + if (newHeader.publicSockAddr.getAddress().isNull()) { + // this node wants to use us its STUN server + // so set the node public address to whatever we perceive the public address to be + + // if the sender is on our box then leave its public address to 0 so that + // other users attempt to reach it on the same address they have for the domain-server + if (senderSockAddr.getAddress().isLoopback()) { + newHeader.publicSockAddr.setAddress(QHostAddress()); + } else { + newHeader.publicSockAddr.setAddress(senderSockAddr.getAddress()); + } + } + + return newHeader; +} diff --git a/domain-server/src/NodeConnectionData.h b/domain-server/src/NodeConnectionData.h new file mode 100644 index 0000000000..60b0e9edfa --- /dev/null +++ b/domain-server/src/NodeConnectionData.h @@ -0,0 +1,32 @@ +// +// NodeConnectionData.h +// domain-server/src +// +// Created by Stephen Birarda on 2015-08-24. +// Copyright 2015 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_NodeConnectionData_h +#define hifi_NodeConnectionData_h + +#include + +class NodeConnectionData { +public: + static NodeConnectionData fromDataStream(QDataStream& dataStream, const HifiSockAddr& senderSockAddr); + + QUuid connectUUID; + NodeType_t nodeType; + HifiSockAddr publicSockAddr; + HifiSockAddr localSockAddr; + HifiSockAddr senderSockAddr; + QList interestList; +}; + + +#endif // hifi_NodeConnectionData_h diff --git a/domain-server/src/PendingAssignedNodeData.cpp b/domain-server/src/PendingAssignedNodeData.cpp index 30310ac01f..e0b6b68eb5 100644 --- a/domain-server/src/PendingAssignedNodeData.cpp +++ b/domain-server/src/PendingAssignedNodeData.cpp @@ -11,10 +11,12 @@ #include "PendingAssignedNodeData.h" +#include + PendingAssignedNodeData::PendingAssignedNodeData(const QUuid& assignmentUUID, const QUuid& walletUUID, const QString& nodeVersion) : _assignmentUUID(assignmentUUID), _walletUUID(walletUUID), _nodeVersion(nodeVersion) { - -} \ No newline at end of file + +} diff --git a/domain-server/src/PendingAssignedNodeData.h b/domain-server/src/PendingAssignedNodeData.h index 2d546f573f..eb384a7a93 100644 --- a/domain-server/src/PendingAssignedNodeData.h +++ b/domain-server/src/PendingAssignedNodeData.h @@ -34,4 +34,4 @@ private: QString _nodeVersion; }; -#endif // hifi_PendingAssignedNodeData_h \ No newline at end of file +#endif // hifi_PendingAssignedNodeData_h diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 33d490c960..88a3ccf8ff 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -138,7 +138,7 @@ public: SharedNodePointer addOrUpdateNode(const QUuid& uuid, NodeType_t nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket, - bool canAdjustLocks, bool canRez, + bool canAdjustLocks = false, bool canRez = false, const QUuid& connectionSecret = QUuid()); bool hasCompletedInitialSTUN() const { return _hasCompletedInitialSTUN; } diff --git a/libraries/networking/src/UUIDHasher.h b/libraries/networking/src/UUIDHasher.h index 5429e151c7..b05e517841 100644 --- a/libraries/networking/src/UUIDHasher.h +++ b/libraries/networking/src/UUIDHasher.h @@ -20,10 +20,14 @@ class UUIDHasher { public: size_t operator()(const QUuid& uuid) const { - return uuid.data1 ^ uuid.data2 ^ (uuid.data3 << 16) - ^ ((uuid.data4[0] << 24) | (uuid.data4[1] << 16) | (uuid.data4[2] << 8) | uuid.data4[3]) - ^ ((uuid.data4[4] << 24) | (uuid.data4[5] << 16) | (uuid.data4[6] << 8) | uuid.data4[7]); + return qHash(uuid); } }; -#endif // hifi_UUIDHasher_h \ No newline at end of file +template <> struct std::hash { + size_t operator()(const QUuid& uuid) const { + return qHash(uuid); + } +}; + +#endif // hifi_UUIDHasher_h diff --git a/libraries/octree/src/OctreeEditPacketSender.h b/libraries/octree/src/OctreeEditPacketSender.h index 8c77a1e388..65d5315206 100644 --- a/libraries/octree/src/OctreeEditPacketSender.h +++ b/libraries/octree/src/OctreeEditPacketSender.h @@ -18,14 +18,6 @@ #include "JurisdictionMap.h" #include "SentPacketHistory.h" -namespace std { - template <> struct hash { - size_t operator()(const QUuid& uuid) const { - return qHash(uuid); - } - }; -} - /// Utility for processing, packing, queueing and sending of outbound edit messages. class OctreeEditPacketSender : public PacketSender { Q_OBJECT From d2acf327dd585092895a8ad26c6cda052c2852bc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Aug 2015 14:43:49 -0700 Subject: [PATCH 29/57] fix NodeConnectionData discrepancy on request --- domain-server/src/DomainGatekeeper.cpp | 12 ++++++++---- domain-server/src/DomainServer.cpp | 3 ++- domain-server/src/NodeConnectionData.cpp | 9 +++++++-- domain-server/src/NodeConnectionData.h | 3 ++- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index f712229e2d..9578e0565f 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -168,6 +168,10 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect if (usernameSignature.isEmpty()) { // if user didn't include usernameSignature in connect request, send a connectionToken packet sendConnectionTokenPacket(username, nodeConnection.senderSockAddr); + + // ask for their public key right now to make sure we have it + requestUserPublicKey(username); + return SharedNodePointer(); } } @@ -205,11 +209,9 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect valueForKeyPath(_server->_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); - bool isAllowedEditor = allowedEditors.isEmpty() || allowedEditors.contains(username); + bool canAdjustLocks = allowedEditors.empty(); - bool canAdjustLocks = false; - - if (isAllowedEditor) { + if (allowedEditors.contains(username)) { if (!verifiedUsername) { if (!verifyUserSignature(username, usernameSignature, HifiSockAddr())) { qDebug() << "Could not verify user" << username << "as allowed editor. User will still be allowed to connect" @@ -394,6 +396,8 @@ bool DomainGatekeeper::isWithinMaxCapacity(const QString& username, const QByteA if (allowedEditors.contains(username)) { if (verifiedUsername || verifyUserSignature(username, usernameSignature, senderSockAddr)) { verifiedUsername = true; + qDebug() << "Above maximum capacity -" << connectedUsers << "/" << maximumUserCapacity << + "but user" << username << "is in allowed editors list so will be allowed to connect."; return true; } } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 12a9e094aa..392c09bd8a 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -574,7 +574,7 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet packet, SharedNodePointer sendingNode) { QDataStream packetStream(packet.data()); - NodeConnectionData nodeRequestData = NodeConnectionData::fromDataStream(packetStream, packet->getSenderSockAddr()); + NodeConnectionData nodeRequestData = NodeConnectionData::fromDataStream(packetStream, packet->getSenderSockAddr(), false); // update this node's sockets in case they have changed sendingNode->setPublicSocket(nodeRequestData.publicSockAddr); @@ -675,6 +675,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif // if this authenticated node has any interest types, send back those nodes as well limitedNodeList->eachNode([&](const SharedNodePointer& otherNode){ if (otherNode->getUUID() != node->getUUID() && nodeInterestSet.contains(otherNode->getType())) { + // since we're about to add a node to the packet we start a segment domainListPackets.startSegment(); diff --git a/domain-server/src/NodeConnectionData.cpp b/domain-server/src/NodeConnectionData.cpp index 6e6e35f205..3c75e8faad 100644 --- a/domain-server/src/NodeConnectionData.cpp +++ b/domain-server/src/NodeConnectionData.cpp @@ -11,10 +11,15 @@ #include "NodeConnectionData.h" -NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, const HifiSockAddr& senderSockAddr) { +NodeConnectionData NodeConnectionData::fromDataStream(QDataStream& dataStream, const HifiSockAddr& senderSockAddr, + bool isConnectRequest) { NodeConnectionData newHeader; - dataStream >> newHeader.connectUUID >> newHeader.nodeType + if (isConnectRequest) { + dataStream >> newHeader.connectUUID; + } + + dataStream >> newHeader.nodeType >> newHeader.publicSockAddr >> newHeader.localSockAddr >> newHeader.interestList; diff --git a/domain-server/src/NodeConnectionData.h b/domain-server/src/NodeConnectionData.h index 60b0e9edfa..6b3b8eb7c1 100644 --- a/domain-server/src/NodeConnectionData.h +++ b/domain-server/src/NodeConnectionData.h @@ -18,7 +18,8 @@ class NodeConnectionData { public: - static NodeConnectionData fromDataStream(QDataStream& dataStream, const HifiSockAddr& senderSockAddr); + static NodeConnectionData fromDataStream(QDataStream& dataStream, const HifiSockAddr& senderSockAddr, + bool isConnectRequest = true); QUuid connectUUID; NodeType_t nodeType; From 7591a29c48fff7c71cef166dd9ab72dc8f26d2ec Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Aug 2015 14:44:24 -0700 Subject: [PATCH 30/57] add back indentation to STATICALLY_ASSIGNED_NODES --- domain-server/src/DomainGatekeeper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 9578e0565f..08f60e6d37 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -48,7 +48,7 @@ QUuid DomainGatekeeper::assignmentUUIDForPendingAssignment(const QUuid& tempUUID } const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer -<< NodeType::AvatarMixer << NodeType::EntityServer; + << NodeType::AvatarMixer << NodeType::EntityServer; void DomainGatekeeper::processConnectRequestPacket(QSharedPointer packet) { if (packet->getPayloadSize() == 0) { From d57c1fc2d52740d768f7286edb9711dc0e27e590 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Aug 2015 14:50:18 -0700 Subject: [PATCH 31/57] fix a typo in DomainGatekeeper comment --- domain-server/src/DomainGatekeeper.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 08f60e6d37..7746f658cf 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -103,10 +103,14 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer pack SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeConnectionData& nodeConnection, const PendingAssignedNodeData& pendingAssignment) { - SharedAssignmentPointer matchingQueuedAssignment = SharedAssignmentPointer(); + + // make sure this matches an assignment the DS told us we sent out auto it = _pendingAssignedNodes.find(nodeConnection.connectUUID); + SharedAssignmentPointer matchingQueuedAssignment = SharedAssignmentPointer(); + if (it != _pendingAssignedNodes.end()) { + // find the matching queued static assignment in DS queue matchingQueuedAssignment = _server->dequeueMatchingAssignment(it->second.getAssignmentUUID(), nodeConnection.nodeType); if (matchingQueuedAssignment) { @@ -124,12 +128,12 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo return SharedNodePointer(); } + // add the new node SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); - // when the newNode is created the linked data is also created - // if this was a static assignment set the UUID, set the sendingSockAddr DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); + // set assignment related data on the linked data for this node nodeData->setAssignmentUUID(matchingQueuedAssignment->getUUID()); nodeData->setWalletUUID(it->second.getWalletUUID()); nodeData->setNodeVersion(it->second.getNodeVersion()); @@ -157,7 +161,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect bool isRestrictingAccess = _server->_settingsManager.valueOrDefaultValueForKeyPath(RESTRICTED_ACCESS_SETTINGS_KEYPATH).toBool(); - // check if this user is on our local machine - is this is true they are always allowed to connect + // check if this user is on our local machine - if this is true they are always allowed to connect QHostAddress senderHostAddress = nodeConnection.senderSockAddr.getAddress(); bool isLocalUser = (senderHostAddress == limitedNodeList->getLocalSockAddr().getAddress() || senderHostAddress == QHostAddress::LocalHost); @@ -202,6 +206,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect } } + // add the new node SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); // if this user is in the editors list (or if the editors list is empty) set the user's node's canAdjustLocks to true @@ -209,23 +214,30 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect valueForKeyPath(_server->_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); QStringList allowedEditors = allowedEditorsVariant ? allowedEditorsVariant->toStringList() : QStringList(); + // if the allowed editors list is empty then everyone can adjust locks bool canAdjustLocks = allowedEditors.empty(); if (allowedEditors.contains(username)) { + // we have a non-empty allowed editors list - check if this user is verified to be in it if (!verifiedUsername) { if (!verifyUserSignature(username, usernameSignature, HifiSockAddr())) { + // failed to verify a user that is in the allowed editors list + qDebug() << "Could not verify user" << username << "as allowed editor. User will still be allowed to connect" << "but will not have edit privileges."; - canAdjustLocks = true; + canAdjustLocks = false; } else { + // just verified this user and they are in the allowed editors list canAdjustLocks = true; } } else { + // already verified this user and they are in the allowed editors list canAdjustLocks = true; } } + // check if only editors should be able to rez entities const QVariant* editorsAreRezzersVariant = valueForKeyPath(_server->_settingsManager.getSettingsMap(), EDITORS_ARE_REZZERS_KEYPATH); @@ -239,6 +251,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect canRez = canAdjustLocks; } + // grab the linked data for our new node so we can set the username DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); // if we have a username from the connect request, set it on the DomainServerNodeData From fe591f61ccd52c3818f6b8cad809a62020af34d2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Aug 2015 14:54:48 -0700 Subject: [PATCH 32/57] fix class rename in processConnectRequestPacket --- domain-server/src/DomainGatekeeper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 7746f658cf..d272ab3a84 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -57,7 +57,7 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer pack QDataStream packetStream(packet.data()); - // read a NodePacketHeader from the packet so we can pass around this data while we're inspecting it + // read a NodeConnectionData object from the packet so we can pass around this data while we're inspecting it NodeConnectionData nodeConnection = NodeConnectionData::fromDataStream(packetStream, packet->getSenderSockAddr()); if (nodeConnection.localSockAddr.isNull() || nodeConnection.publicSockAddr.isNull()) { From c6f1567361dadd561a7cad4ab84f6a12940a1f25 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Aug 2015 14:58:25 -0700 Subject: [PATCH 33/57] add a debug for refused connection in DomainGatekeeper --- domain-server/src/DomainGatekeeper.cpp | 2 ++ domain-server/src/PendingAssignedNodeData.cpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index d272ab3a84..1e040f62ed 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -98,6 +98,8 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer pack // signal that we just connected a node so the DomainServer can get it a list // and broadcast its presence right away emit connectedNode(node); + } else { + qDebug() << "Refusing connection from node at" << packet->getSenderSockAddr(); } } diff --git a/domain-server/src/PendingAssignedNodeData.cpp b/domain-server/src/PendingAssignedNodeData.cpp index e0b6b68eb5..1376e6aa0e 100644 --- a/domain-server/src/PendingAssignedNodeData.cpp +++ b/domain-server/src/PendingAssignedNodeData.cpp @@ -11,8 +11,6 @@ #include "PendingAssignedNodeData.h" -#include - PendingAssignedNodeData::PendingAssignedNodeData(const QUuid& assignmentUUID, const QUuid& walletUUID, const QString& nodeVersion) : _assignmentUUID(assignmentUUID), _walletUUID(walletUUID), From 476ca364607b877b02a5a241db63cac45aa50be7 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 24 Aug 2015 15:01:01 -0700 Subject: [PATCH 34/57] final --- interface/src/avatar/SkeletonModel.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 0439997bc4..c80992feec 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -41,7 +41,7 @@ SkeletonModel::~SkeletonModel() { void SkeletonModel::initJointStates(QVector states) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); - glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset/* * glm::mat4_cast(getRotation())*/; + glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; int rootJointIndex = geometry.rootJointIndex; int leftHandJointIndex = geometry.leftHandJointIndex; @@ -123,10 +123,15 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { params.rightEyeJointIndex = geometry.rightEyeJointIndex; _rig->updateFromHeadParameters(params); - } else if (true/*_owningAvatar->getHead()->isLookingAtMe()*/) { + } else { + // This is a little more work than we really want. + // // Other avatars joint, including their eyes, should already be set just like any other joints // from the wire data. But when looking at me, we want the eyes to use the corrected lookAt. // + // Thus this should really only be ... else if (_owningAvatar->getHead()->isLookingAtMe()) {... + // However, in the !isLookingAtMe case, the eyes aren't rotating the way they should right now. + // We will revisit that as priorities allow, and particularly after the new rig/animation/joints. const FBXGeometry& geometry = _geometry->getFBXGeometry(); Head* head = _owningAvatar->getHead(); // If the head is not positioned, updateEyeJoints won't get the math right From a9c04e5116a7f8b58ceea2789b6041db314c7128 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Aug 2015 15:01:39 -0700 Subject: [PATCH 35/57] don't allow verified connection without username --- domain-server/src/DomainGatekeeper.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 1e040f62ed..a86ce068c3 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -367,17 +367,18 @@ bool DomainGatekeeper::verifyUserSignature(const QString& username, bool DomainGatekeeper::isVerifiedAllowedUser(const QString& username, const QByteArray& usernameSignature, const HifiSockAddr& senderSockAddr) { + if (username.isEmpty()) { + qDebug() << "Connect request denied - no username provided."; + + sendConnectionDeniedPacket("No username provided", senderSockAddr); + + return false; + } + QStringList allowedUsers = _server->_settingsManager.valueOrDefaultValueForKeyPath(ALLOWED_USERS_SETTINGS_KEYPATH).toStringList(); if (allowedUsers.contains(username, Qt::CaseInsensitive)) { - if (username.isEmpty()) { - qDebug() << "Connect request denied - no username provided."; - - sendConnectionDeniedPacket("No username provided", senderSockAddr); - - return false; - } if (!verifyUserSignature(username, usernameSignature, senderSockAddr)) { return false; } From d02e5b2450c6ea7d880dccdd4b3195569f2f6cf1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Aug 2015 15:10:27 -0700 Subject: [PATCH 36/57] fix a typo in comment in DomainGatekeeper --- domain-server/src/DomainGatekeeper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index a86ce068c3..01e98868ec 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -492,7 +492,7 @@ void DomainGatekeeper::sendConnectionDeniedPacket(const QString& reason, const H // setup the DomainConnectionDenied packet auto connectionDeniedPacket = NLPacket::create(PacketType::DomainConnectionDenied, payloadSize + sizeof(payloadSize)); - // packet in the reason the connection was denied (the client displays this) + // pack in the reason the connection was denied (the client displays this) if (payloadSize > 0) { connectionDeniedPacket->writePrimitive(payloadSize); connectionDeniedPacket->write(utfString); From 110ba131a614729d2d9ec6bfb73496fb58140512 Mon Sep 17 00:00:00 2001 From: Lars Christensen Date: Tue, 25 Aug 2015 01:36:19 +0200 Subject: [PATCH 37/57] moved translation efforts into subdir --- interface/{ => i18n}/interface_da.ts | 0 interface/{ => i18n}/interface_en.ts | 0 interface/src/main.cpp | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename interface/{ => i18n}/interface_da.ts (100%) rename interface/{ => i18n}/interface_en.ts (100%) diff --git a/interface/interface_da.ts b/interface/i18n/interface_da.ts similarity index 100% rename from interface/interface_da.ts rename to interface/i18n/interface_da.ts diff --git a/interface/interface_en.ts b/interface/i18n/interface_en.ts similarity index 100% rename from interface/interface_en.ts rename to interface/i18n/interface_en.ts diff --git a/interface/src/main.cpp b/interface/src/main.cpp index e591034fb5..1de8f9224c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -103,7 +103,7 @@ int main(int argc, const char* argv[]) { Application app(argc, const_cast(argv), startupTime); QTranslator translator; - translator.load("interface_en"); + translator.load("i18n/interface_en"); app.installTranslator(&translator); qCDebug(interfaceapp, "Created QT Application."); From b27d25b46edc0f0dd1b047f1d7eda8f5604718c8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 24 Aug 2015 16:41:25 -0700 Subject: [PATCH 38/57] Implement crash option that retains only login and avatar information --- interface/src/CrashHandler.cpp | 87 ++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index 6e9897fb82..b6d28ef161 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -22,16 +22,22 @@ #include #include +#include "DataServerAccountInfo.h" #include "Menu.h" +Q_DECLARE_METATYPE(DataServerAccountInfo) + static const QString RUNNING_MARKER_FILENAME = "Interface.running"; void CrashHandler::checkForAndHandleCrash() { QFile runningMarkerFile(runningMarkerFilePath()); if (runningMarkerFile.exists()) { + QSettings::setDefaultFormat(QSettings::IniFormat); QSettings settings; settings.beginGroup("Developer"); - if (settings.value(MenuOption::DisplayCrashOptions).toBool()) { + bool displayCrashOptions = settings.value(MenuOption::DisplayCrashOptions).toBool(); + settings.endGroup(); + if (displayCrashOptions) { Action action = promptUserForAction(); if (action != DO_NOTHING) { handleCrash(action); @@ -81,19 +87,80 @@ CrashHandler::Action CrashHandler::promptUserForAction() { } void CrashHandler::handleCrash(CrashHandler::Action action) { - if (action == CrashHandler::DELETE_INTERFACE_INI) { - QSettings settings; - QFile settingsFile(settings.fileName()); - if (settingsFile.exists()) { - settingsFile.remove(); - } + if (action != CrashHandler::DELETE_INTERFACE_INI && action != CrashHandler::RETAIN_LOGIN_AND_AVATAR_INFO) { + // CrashHandler::DO_NOTHING or unexpected value return; } - // TODO + QSettings::setDefaultFormat(QSettings::IniFormat); + QSettings settings; + const QString ADDRESS_MANAGER_GROUP = "AddressManager"; + const QString ADDRESS_KEY = "address"; + const QString AVATAR_GROUP = "Avatar"; + const QString DISPLAY_NAME_KEY = "displayName"; + const QString FULL_AVATAR_URL_KEY = "fullAvatarURL"; + const QString FULL_AVATAR_MODEL_NAME_KEY = "fullAvatarModelName"; + const QString ACCOUNTS_GROUP = "accounts"; + QString displayName; + QUrl fullAvatarURL; + QString fullAvatarModelName; + QUrl address; + QMap accounts; - // CrashHandler::DO_NOTHING or unexpected value - return; + if (action == CrashHandler::RETAIN_LOGIN_AND_AVATAR_INFO) { + // Read login and avatar info + + qRegisterMetaType("DataServerAccountInfo"); + qRegisterMetaTypeStreamOperators("DataServerAccountInfo"); + + // Location and orientation + settings.beginGroup(ADDRESS_MANAGER_GROUP); + address = settings.value(ADDRESS_KEY).toUrl(); + settings.endGroup(); + + // Display name and avatar + settings.beginGroup(AVATAR_GROUP); + displayName = settings.value(DISPLAY_NAME_KEY).toString(); + fullAvatarURL = settings.value(FULL_AVATAR_URL_KEY).toUrl(); + fullAvatarModelName = settings.value(FULL_AVATAR_MODEL_NAME_KEY).toString(); + settings.endGroup(); + + // Accounts + settings.beginGroup(ACCOUNTS_GROUP); + foreach(const QString& key, settings.allKeys()) { + accounts.insert(key, settings.value(key).value()); + } + settings.endGroup(); + } + + // Delete Interface.ini + QFile settingsFile(settings.fileName()); + if (settingsFile.exists()) { + settingsFile.remove(); + } + + if (action == CrashHandler::RETAIN_LOGIN_AND_AVATAR_INFO) { + // Write login and avatar info + + // Location and orientation + settings.beginGroup(ADDRESS_MANAGER_GROUP); + settings.setValue(ADDRESS_KEY, address); + settings.endGroup(); + + // Display name and avatar + settings.beginGroup(AVATAR_GROUP); + settings.setValue(DISPLAY_NAME_KEY, displayName); + settings.setValue(FULL_AVATAR_URL_KEY, fullAvatarURL); + settings.setValue(FULL_AVATAR_MODEL_NAME_KEY, fullAvatarModelName); + settings.endGroup(); + + // Accounts + settings.beginGroup(ACCOUNTS_GROUP); + foreach(const QString& key, accounts.keys()) { + settings.setValue(key, QVariant::fromValue(accounts.value(key))); + } + settings.endGroup(); + } } void CrashHandler::writeRunningMarkerFiler() { From 324f592719a8a33e6d6bfb918e73faacfdb202bf Mon Sep 17 00:00:00 2001 From: Lars Christensen Date: Tue, 25 Aug 2015 01:55:52 +0200 Subject: [PATCH 39/57] updated FontAwesome to v4.4 --- .../resources/fonts/fontawesome-webfont.ttf | Bin 122092 -> 138204 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/interface/resources/fonts/fontawesome-webfont.ttf b/interface/resources/fonts/fontawesome-webfont.ttf index ed9372f8ea0fbaa04f42630a48887e4b38945345..d7994e13086b1ac1a216bd754c93e1bccd65f237 100644 GIT binary patch delta 19019 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 JJK@Cu{|~g|*opuE From c8ba24817f37459f1c7c7934184d5d95db11daa2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 24 Aug 2015 17:09:52 -0700 Subject: [PATCH 40/57] fix for hash specialization for QUuid --- libraries/networking/src/UUIDHasher.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libraries/networking/src/UUIDHasher.h b/libraries/networking/src/UUIDHasher.h index b05e517841..0bdfe9792a 100644 --- a/libraries/networking/src/UUIDHasher.h +++ b/libraries/networking/src/UUIDHasher.h @@ -24,10 +24,13 @@ public: } }; -template <> struct std::hash { - size_t operator()(const QUuid& uuid) const { - return qHash(uuid); - } -}; +namespace std { + template <> struct hash { + size_t operator()(const QUuid& uuid) const { + return qHash(uuid); + } + }; +} + #endif // hifi_UUIDHasher_h From 2ed6900c7e2f717da5728fb9f6edd1a07bbb7dc4 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 25 Aug 2015 09:55:04 -0700 Subject: [PATCH 41/57] Clear the brush, clear the cobwebs, and set the other orientations now that we're clear on what coordinate system we're in. --- interface/src/avatar/SkeletonModel.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index c80992feec..93da3c673e 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -137,15 +137,14 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { // If the head is not positioned, updateEyeJoints won't get the math right glm::quat headOrientation; _rig->getJointRotation(geometry.headJointIndex, headOrientation); - glm::quat modelOrientation = getRotation(); - glm::quat adjust = modelOrientation; - glm::quat headOrientationInAvatar = adjust * headOrientation; - glm::vec3 eulers = safeEulerAngles(headOrientationInAvatar); + glm::vec3 eulers = safeEulerAngles(headOrientation); head->setBasePitch(glm::degrees(-eulers.x)); + head->setBaseYaw(glm::degrees(eulers.y)); + head->setBaseRoll(glm::degrees(-eulers.z)); _rig->updateEyeJoints(geometry.leftEyeJointIndex, geometry.rightEyeJointIndex, - getTranslation(), modelOrientation, + getTranslation(), getRotation(), head->getFinalOrientationInWorldFrame(), head->getCorrectedLookAtPosition()); - } + } } // Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed), From 9940f375ea3e368dae626d2d5dad3b1b002113b0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Aug 2015 10:02:43 -0700 Subject: [PATCH 42/57] repairs for CR comments --- domain-server/src/DomainGatekeeper.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 01e98868ec..efd156e1a9 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -253,6 +253,10 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect canRez = canAdjustLocks; } + // set the edit rights for this user + newNode->setCanAdjustLocks(canAdjustLocks); + newNode->setCanRez(canRez); + // grab the linked data for our new node so we can set the username DomainServerNodeData* nodeData = reinterpret_cast(newNode->getLinkedData()); @@ -527,7 +531,7 @@ const int NUM_PEER_PINGS_BEFORE_DELETE = 2000 / UDP_PUNCH_PING_INTERVAL_MS; void DomainGatekeeper::pingPunchForConnectingPeer(const SharedNetworkPeer& peer) { - if (peer->getConnectionAttempts() > 0 && peer->getConnectionAttempts() % NUM_PEER_PINGS_BEFORE_DELETE == 0) { + if (peer->getConnectionAttempts() >= NUM_PEER_PINGS_BEFORE_DELETE) { // we've reached the maximum number of ping attempts qDebug() << "Maximum number of ping attempts reached for peer with ID" << peer->getUUID(); qDebug() << "Removing from list of connecting peers."; From a98a867b06bb10b097bf057ff784b0aa8288358c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 25 Aug 2015 11:07:20 -0700 Subject: [PATCH 43/57] Delete Interface.ini.lock before accessing to check crash option --- libraries/shared/src/SettingInterface.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libraries/shared/src/SettingInterface.cpp b/libraries/shared/src/SettingInterface.cpp index b3b9ce32f9..11ed64cac4 100644 --- a/libraries/shared/src/SettingInterface.cpp +++ b/libraries/shared/src/SettingInterface.cpp @@ -46,6 +46,15 @@ namespace Setting { QCoreApplication::setApplicationName(applicationInfo.value("name").toString()); QCoreApplication::setOrganizationName(applicationInfo.value("organizationName").toString()); QCoreApplication::setOrganizationDomain(applicationInfo.value("organizationDomain").toString()); + + // Delete Interface.ini.lock file if it exists, otherwise Interface freezes. + QSettings settings; + QString settingsLockFilename = settings.fileName() + ".lock"; + QFile settingsLockFile(settingsLockFilename); + if (settingsLockFile.exists()) { + bool deleted = settingsLockFile.remove(); + qCDebug(shared) << (deleted ? "Deleted" : "Failed to delete") << "settings lock file" << settingsLockFilename; + } } // Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand, @@ -58,14 +67,6 @@ namespace Setting { privateInstance = new Manager(); Q_CHECK_PTR(privateInstance); - // Delete Interface.ini.lock file if it exists, otherwise Interface freezes. - QString settingsLockFilename = privateInstance->fileName() + ".lock"; - QFile settingsLockFile(settingsLockFilename); - if (settingsLockFile.exists()) { - bool deleted = settingsLockFile.remove(); - qCDebug(shared) << (deleted ? "Deleted" : "Failed to delete") << "settings lock file" << settingsLockFilename; - } - QObject::connect(privateInstance, SIGNAL(destroyed()), thread, SLOT(quit())); QObject::connect(thread, SIGNAL(started()), privateInstance, SLOT(startTimer())); QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); From 7c8ff4dcbdce6cb676f2ed341f32d2b64b63533c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 25 Aug 2015 11:07:55 -0700 Subject: [PATCH 44/57] If Interface.ini doesn't contain crash option value assume default --- interface/src/CrashHandler.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index b6d28ef161..349b48da37 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -35,9 +35,10 @@ void CrashHandler::checkForAndHandleCrash() { QSettings::setDefaultFormat(QSettings::IniFormat); QSettings settings; settings.beginGroup("Developer"); - bool displayCrashOptions = settings.value(MenuOption::DisplayCrashOptions).toBool(); + QVariant displayCrashOptions = settings.value(MenuOption::DisplayCrashOptions); settings.endGroup(); - if (displayCrashOptions) { + if (!displayCrashOptions.isValid() // Option does not exist in Interface.ini so assume default behavior. + || displayCrashOptions.toBool()) { Action action = promptUserForAction(); if (action != DO_NOTHING) { handleCrash(action); From 1f541832b69f26bdd223e2fe19b098a52e0d5d2a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 25 Aug 2015 14:24:15 -0700 Subject: [PATCH 45/57] Reword dialog --- interface/src/CrashHandler.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/CrashHandler.cpp b/interface/src/CrashHandler.cpp index 349b48da37..ce5facb580 100644 --- a/interface/src/CrashHandler.cpp +++ b/interface/src/CrashHandler.cpp @@ -53,12 +53,12 @@ CrashHandler::Action CrashHandler::promptUserForAction() { QVBoxLayout* layout = new QVBoxLayout; - QLabel* label = new QLabel("What would you like to do?"); + QLabel* label = new QLabel("If you are having trouble starting would you like to reset your settings?"); layout->addWidget(label); - QRadioButton* option1 = new QRadioButton("Delete Interface.ini"); - QRadioButton* option2 = new QRadioButton("Delete Interface.ini but retain login and avatar info."); - QRadioButton* option3 = new QRadioButton("Continue with my current Interface.ini"); + QRadioButton* option1 = new QRadioButton("Reset all my settings"); + QRadioButton* option2 = new QRadioButton("Reset my settings but retain login and avatar info."); + QRadioButton* option3 = new QRadioButton("Continue with my current settings"); option3->setChecked(true); layout->addWidget(option1); layout->addWidget(option2); From c776f04ab2ce4eabcf74d459a8270cd4985bd398 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Aug 2015 14:36:22 -0700 Subject: [PATCH 46/57] don't allow in a user who should have edit but not verified --- domain-server/src/DomainGatekeeper.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index efd156e1a9..72b353f8a0 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -208,9 +208,6 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect } } - // add the new node - SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); - // if this user is in the editors list (or if the editors list is empty) set the user's node's canAdjustLocks to true const QVariant* allowedEditorsVariant = valueForKeyPath(_server->_settingsManager.getSettingsMap(), ALLOWED_EDITORS_SETTINGS_KEYPATH); @@ -222,13 +219,13 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect if (allowedEditors.contains(username)) { // we have a non-empty allowed editors list - check if this user is verified to be in it if (!verifiedUsername) { - if (!verifyUserSignature(username, usernameSignature, HifiSockAddr())) { + if (!verifyUserSignature(username, usernameSignature, nodeConnection.senderSockAddr)) { // failed to verify a user that is in the allowed editors list + sendConnectionTokenPacket(username, nodeConnection.senderSockAddr); - qDebug() << "Could not verify user" << username << "as allowed editor. User will still be allowed to connect" - << "but will not have edit privileges."; + qDebug() << "Could not verify user" << username << "as allowed editor. Forcing user to attempt reconnect."; - canAdjustLocks = false; + return SharedNodePointer(); } else { // just verified this user and they are in the allowed editors list canAdjustLocks = true; @@ -253,6 +250,9 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect canRez = canAdjustLocks; } + // add the new node + SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection); + // set the edit rights for this user newNode->setCanAdjustLocks(canAdjustLocks); newNode->setCanRez(canRez); From 0aaa07a2ded462426c26175db133072f03c87916 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 24 Aug 2015 22:55:40 -0700 Subject: [PATCH 47/57] Remove items from the QML version of the menu when they are removed from the main menu --- interface/resources/qml/VrMenu.qml | 22 ++++++ interface/src/Menu.cpp | 3 + libraries/ui/src/VrMenu.cpp | 115 +++++++++++------------------ libraries/ui/src/VrMenu.h | 2 - 4 files changed, 68 insertions(+), 74 deletions(-) diff --git a/interface/resources/qml/VrMenu.qml b/interface/resources/qml/VrMenu.qml index f0b7bf9fd3..ef7ae852d4 100644 --- a/interface/resources/qml/VrMenu.qml +++ b/interface/resources/qml/VrMenu.qml @@ -185,4 +185,26 @@ Hifi.VrMenu { } } } + + function addMenu(menu, newMenu) { + return menu.addMenu(newMenu); + } + + function addItem(menu, newMenuItem) { + return menu.addItem(newMenuItem); + } + + function insertItem(menu, beforeItem, newMenuItem) { + for (var i = 0; i < menu.items.length; ++i) { + console.log(menu.items[i]); + if (menu.items[i] === beforeItem) { + return menu.insertItem(i, newMenuItem); + } + } + return addItem(menu, newMenuItem); + } + + function removeItem(menu, menuItem) { + menu.removeItem(menuItem); + } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1c2cdbaa26..9d47df1c73 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1046,6 +1046,9 @@ QAction* MenuWrapper::addAction(const QString& menuName, const QObject* receiver void MenuWrapper::removeAction(QAction* action) { _realMenu->removeAction(action); + VrMenu::executeOrQueue([=](VrMenu* vrMenu) { + vrMenu->removeAction(action); + }); } void MenuWrapper::insertAction(QAction* before, QAction* action) { diff --git a/libraries/ui/src/VrMenu.cpp b/libraries/ui/src/VrMenu.cpp index ce4aba83d3..1ede74fc86 100644 --- a/libraries/ui/src/VrMenu.cpp +++ b/libraries/ui/src/VrMenu.cpp @@ -83,46 +83,6 @@ VrMenu::VrMenu(QQuickItem* parent) : QQuickItem(parent) { this->setEnabled(false); } - -// QML helper functions -QObject* addMenu(QObject* parent, const QString& text) { - // FIXME add more checking here to ensure no name conflicts - QVariant returnedValue; - QMetaObject::invokeMethod(parent, "addMenu", Qt::DirectConnection, - Q_RETURN_ARG(QVariant, returnedValue), - Q_ARG(QVariant, text)); - QObject* result = returnedValue.value(); - if (result) { - result->setObjectName(text); - } - return result; -} - -class QQuickMenuItem; -QObject* addItem(QObject* parent, const QString& text) { - // FIXME add more checking here to ensure no name conflicts - QQuickMenuItem* returnedValue{ nullptr }; - bool invokeResult = - QMetaObject::invokeMethod(parent, "addItem", Qt::DirectConnection, Q_RETURN_ARG(QQuickMenuItem*, returnedValue), - Q_ARG(QString, text)); - -#ifndef QT_NO_DEBUG - Q_ASSERT(invokeResult); -#else - Q_UNUSED(invokeResult); -#endif - QObject* result = reinterpret_cast(returnedValue); - return result; -} - -const QObject* VrMenu::findMenuObject(const QString& menuOption) const { - if (menuOption.isEmpty()) { - return _rootMenu; - } - const QObject* result = _rootMenu->findChild(menuOption); - return result; -} - QObject* VrMenu::findMenuObject(const QString& menuOption) { if (menuOption.isEmpty()) { return _rootMenu; @@ -147,7 +107,16 @@ void VrMenu::addMenu(QMenu* menu) { } else { Q_ASSERT(false); } - QObject* result = ::addMenu(qmlParent, menu->title()); + QVariant returnedValue; + bool invokeResult = QMetaObject::invokeMethod(this, "addMenu", Qt::DirectConnection, + Q_RETURN_ARG(QVariant, returnedValue), + Q_ARG(QVariant, QVariant::fromValue(qmlParent)), + Q_ARG(QVariant, QVariant::fromValue(menu->title()))); + Q_ASSERT(invokeResult); + QObject* result = returnedValue.value(); + Q_ASSERT(result); + + // Bind the QML and Widget together new MenuUserData(menu, result); } @@ -175,9 +144,15 @@ void VrMenu::addAction(QMenu* menu, QAction* action) { Q_ASSERT(!MenuUserData::forObject(action)); Q_ASSERT(MenuUserData::forObject(menu)); MenuUserData* userData = MenuUserData::forObject(menu); - QObject* parent = findMenuObject(userData->uuid.toString()); - Q_ASSERT(parent); - QObject* result = ::addItem(parent, action->text()); + QObject* menuQml = findMenuObject(userData->uuid.toString()); + Q_ASSERT(menuQml); + QVariant returnedValue; + bool invokeResult = QMetaObject::invokeMethod(this, "addItem", Qt::DirectConnection, + Q_RETURN_ARG(QVariant, returnedValue), + Q_ARG(QVariant, QVariant::fromValue(menuQml)), + Q_ARG(QVariant, QVariant::fromValue(action->text()))); + Q_ASSERT(invokeResult); + QObject* result = returnedValue.value(); Q_ASSERT(result); // Bind the QML and Widget together bindActionToQmlAction(result, action); @@ -190,38 +165,34 @@ void VrMenu::insertAction(QAction* before, QAction* action) { Q_ASSERT(beforeUserData); beforeQml = findMenuObject(beforeUserData->uuid.toString()); } - QObject* menu = beforeQml->parent(); - int index{ -1 }; - QVariant itemsVar = menu->property("items"); - QList items = itemsVar.toList(); - // FIXME add more checking here to ensure no name conflicts - for (index = 0; index < items.length(); ++index) { - QObject* currentQmlItem = items.at(index).value(); - if (currentQmlItem == beforeQml) { - break; - } - } - - QObject* result{ nullptr }; - if (index < 0 || index >= items.length()) { - result = ::addItem(menu, action->text()); - } else { - QQuickMenuItem* returnedValue{ nullptr }; - bool invokeResult = - QMetaObject::invokeMethod(menu, "insertItem", Qt::DirectConnection, Q_RETURN_ARG(QQuickMenuItem*, returnedValue), - Q_ARG(int, index), Q_ARG(QString, action->text())); -#ifndef QT_NO_DEBUG - Q_ASSERT(invokeResult); -#else - Q_UNUSED(invokeResult); -#endif - result = reinterpret_cast(returnedValue); - } + QVariant returnedValue; + bool invokeResult = QMetaObject::invokeMethod(this, "insertItem", Qt::DirectConnection, + Q_RETURN_ARG(QVariant, returnedValue), + Q_ARG(QVariant, QVariant::fromValue(menu)), + Q_ARG(QVariant, QVariant::fromValue(beforeQml)), + Q_ARG(QVariant, QVariant::fromValue(action->text()))); + Q_ASSERT(invokeResult); + QObject* result = returnedValue.value(); Q_ASSERT(result); bindActionToQmlAction(result, action); } void VrMenu::removeAction(QAction* action) { - // FIXME implement + MenuUserData* userData = MenuUserData::forObject(action); + if (!userData) { + qWarning("Attempted to remove menu action with no found QML object"); + return; + } + QObject* item = findMenuObject(userData->uuid.toString()); + QObject* menu = item->parent(); + // Proxy QuickItem requests through the QML layer + bool invokeResult = QMetaObject::invokeMethod(this, "removeItem", Qt::DirectConnection, + Q_ARG(QVariant, QVariant::fromValue(menu)), + Q_ARG(QVariant, QVariant::fromValue(item))); +#ifndef QT_NO_DEBUG + Q_ASSERT(invokeResult); +#else + Q_UNUSED(invokeResult); +#endif } diff --git a/libraries/ui/src/VrMenu.h b/libraries/ui/src/VrMenu.h index 06a16588af..38e3b54739 100644 --- a/libraries/ui/src/VrMenu.h +++ b/libraries/ui/src/VrMenu.h @@ -38,9 +38,7 @@ public: protected: QObject* _rootMenu{ nullptr }; - QObject* findMenuObject(const QString& name); - const QObject* findMenuObject(const QString& name) const; static VrMenu* _instance; friend class MenuUserData; From d311e4f2ea3a2f08cf9c05d60314125a9298ccd9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 24 Aug 2015 12:37:52 -0700 Subject: [PATCH 48/57] Fixing problems reported by static analysis tool --- .../src/AssignmentActionFactory.cpp | 3 +-- .../octree/OctreeInboundPacketProcessor.cpp | 3 --- assignment-client/src/octree/OctreeServer.cpp | 8 +++---- interface/src/Application.cpp | 1 - interface/src/GLCanvas.cpp | 2 +- interface/src/ModelSelector.cpp | 5 ++--- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/ui/OctreeStatsDialog.cpp | 1 - libraries/animation/src/JointState.h | 3 ++- libraries/audio/src/AudioBuffer.h | 6 ++--- libraries/audio/src/AudioFilterBank.h | 4 ++-- libraries/audio/src/AudioRingBuffer.h | 2 +- libraries/fbx/src/FBXReader.cpp | 1 + libraries/gpu/src/gpu/Framebuffer.h | 2 +- .../input-plugins/ViveControllerManager.cpp | 6 ++--- libraries/octree/src/CoverageMap.cpp | 2 +- libraries/octree/src/Octree.cpp | 3 ++- libraries/render-utils/src/TextureCache.cpp | 1 + libraries/script-engine/src/WebSocketClass.h | 4 +++- libraries/shared/src/Extents.cpp | 4 ++-- libraries/shared/src/Extents.h | 11 +++++----- libraries/shared/src/GLMHelpers.cpp | 18 +++++++++++++++ libraries/shared/src/GLMHelpers.h | 22 +++++++++++++++++++ libraries/shared/src/LogHandler.cpp | 12 +++++----- libraries/shared/src/LogHandler.h | 8 +++---- libraries/shared/src/RingBufferHistory.h | 2 +- libraries/shared/src/Transform.cpp | 2 +- tools/scribe/src/TextTemplate.cpp | 4 ++-- 28 files changed, 89 insertions(+), 53 deletions(-) diff --git a/assignment-client/src/AssignmentActionFactory.cpp b/assignment-client/src/AssignmentActionFactory.cpp index 7c404cbd97..f99e712b72 100644 --- a/assignment-client/src/AssignmentActionFactory.cpp +++ b/assignment-client/src/AssignmentActionFactory.cpp @@ -13,10 +13,9 @@ EntityActionPointer assignmentActionFactory(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) { - return (EntityActionPointer) new AssignmentAction(type, id, ownerEntity); + return EntityActionPointer(new AssignmentAction(type, id, ownerEntity)); } - EntityActionPointer AssignmentActionFactory::factory(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity, diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp index fe61a3945c..06dcee0a41 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.cpp @@ -131,9 +131,6 @@ void OctreeInboundPacketProcessor::processPacket(QSharedPointer packet qDebug() << " numBytesPacketHeader=" << packet->totalHeadersSize(); qDebug() << " sizeof(sequence)=" << sizeof(sequence); qDebug() << " sizeof(sentAt)=" << sizeof(sentAt); - } - - if (debugProcessPacket) { qDebug() << " atByte (in payload)=" << packet->pos(); qDebug() << " payload size=" << packet->getPayloadSize(); diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 062fe39dbd..a0350622db 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -643,7 +643,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url quint64 averageLoggingTime = _tree->getAverageLoggingTime(); - float averageElementsPerPacket = totalPacketsProcessed == 0 ? 0 : totalElementsProcessed / totalPacketsProcessed; + float averageElementsPerPacket = totalPacketsProcessed == 0 ? 0 : (float)totalElementsProcessed / totalPacketsProcessed; statsString += QString(" Current Inbound Packets Queue: %1 packets\r\n") .arg(locale.toString((uint)currentPacketsInQueue).rightJustified(COLUMN_WIDTH, ' ')); @@ -695,7 +695,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url totalElementsProcessed = senderStats.getTotalElementsProcessed(); totalPacketsProcessed = senderStats.getTotalPacketsProcessed(); - averageElementsPerPacket = totalPacketsProcessed == 0 ? 0 : totalElementsProcessed / totalPacketsProcessed; + averageElementsPerPacket = totalPacketsProcessed == 0 ? 0 : (float)totalElementsProcessed / totalPacketsProcessed; statsString += QString(" Total Inbound Packets: %1 packets\r\n") .arg(locale.toString((uint)totalPacketsProcessed).rightJustified(COLUMN_WIDTH, ' ')); @@ -1075,9 +1075,7 @@ void OctreeServer::run() { // now set up PersistThread _persistThread = new OctreePersistThread(_tree, _persistFilename, _persistInterval, _wantBackup, _settings, _debugTimestampNow, _persistAsFileType); - if (_persistThread) { - _persistThread->initialize(true); - } + _persistThread->initialize(true); } HifiSockAddr senderSockAddr; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c59c24de71..47ec83d268 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1425,7 +1425,6 @@ void Application::keyPressEvent(QKeyEvent* event) { bool isMeta = event->modifiers().testFlag(Qt::ControlModifier); bool isOption = event->modifiers().testFlag(Qt::AltModifier); switch (event->key()) { - break; case Qt::Key_Enter: case Qt::Key_Return: if (isOption) { diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index bfa2dacf3a..66aae5343b 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -62,7 +62,7 @@ void GLCanvas::paintGL() { // FIXME - I'm not sure why this still remains, it appears as if this GLCanvas gets a single paintGL call near // the beginning of the application starting up. I'm not sure if we really need to call Application::paintGL() // in this case, since the display plugins eventually handle all the painting - if ((!Application::getInstance()->getWindow()->isMinimized() || !Application::getInstance()->isThrottleFPSEnabled())) { + if (!Application::getInstance()->getWindow()->isMinimized() || !Application::getInstance()->isThrottleFPSEnabled()) { Application::getInstance()->paintGL(); } } diff --git a/interface/src/ModelSelector.cpp b/interface/src/ModelSelector.cpp index 8e130cec1a..c4922bdd70 100644 --- a/interface/src/ModelSelector.cpp +++ b/interface/src/ModelSelector.cpp @@ -65,9 +65,8 @@ FSTReader::ModelType ModelSelector::getModelType() const { return FSTReader::ATTACHMENT_MODEL; } else if (text == ENTITY_MODEL_STRING) { return FSTReader::ENTITY_MODEL; - } else { - Q_UNREACHABLE(); - } + } + Q_UNREACHABLE(); } void ModelSelector::accept() { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1fec536082..eb72ddd2fd 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1307,7 +1307,7 @@ glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVe bool isThrust = (glm::length2(_thrust) > EPSILON); if (_isPushing || isThrust || (_scriptedMotorTimescale < MAX_KEYBOARD_MOTOR_TIMESCALE && - _motionBehaviors | AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED)) { + (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED))) { // we don't want to brake if something is pushing the avatar around timescale = _keyboardMotorTimescale; _isBraking = false; diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 89e5899acd..7e6111bd83 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -437,7 +437,6 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser case MOST: { extraDetails << "
" ; - const unsigned long USECS_PER_MSEC = 1000; float lastFullEncode = stats.getLastFullTotalEncodeTime() / USECS_PER_MSEC; float lastFullSend = stats.getLastFullElapsedTime() / USECS_PER_MSEC; float lastFullSendInSeconds = stats.getLastFullElapsedTime() / USECS_PER_SECOND; diff --git a/libraries/animation/src/JointState.h b/libraries/animation/src/JointState.h index 694700338d..8d2c1a7cd0 100644 --- a/libraries/animation/src/JointState.h +++ b/libraries/animation/src/JointState.h @@ -27,9 +27,10 @@ class AngularConstraint; class JointState { public: JointState() {} - JointState(const JointState& other) : _constraint(NULL) { copyState(other); } + JointState(const JointState& other) { copyState(other); } JointState(const FBXJoint& joint); ~JointState(); + JointState& operator=(const JointState& other) { copyState(other); return *this; } void copyState(const JointState& state); void buildConstraint(); diff --git a/libraries/audio/src/AudioBuffer.h b/libraries/audio/src/AudioBuffer.h index d2f7c50c91..558d686861 100644 --- a/libraries/audio/src/AudioBuffer.h +++ b/libraries/audio/src/AudioBuffer.h @@ -77,10 +77,8 @@ AudioFrameBuffer< T >::~AudioFrameBuffer() { template< typename T > void AudioFrameBuffer< T >::allocateFrames() { _frameBuffer = new T*[_channelCountMax]; - if (_frameBuffer) { - for (uint32_t i = 0; i < _channelCountMax; ++i) { - _frameBuffer[i] = new T[_frameCountMax]; - } + for (uint32_t i = 0; i < _channelCountMax; ++i) { + _frameBuffer[i] = new T[_frameCountMax]; } } diff --git a/libraries/audio/src/AudioFilterBank.h b/libraries/audio/src/AudioFilterBank.h index a581b79b98..4ea5a3568a 100644 --- a/libraries/audio/src/AudioFilterBank.h +++ b/libraries/audio/src/AudioFilterBank.h @@ -108,14 +108,14 @@ public: void setParameters(uint32_t filterStage, uint32_t filterChannel, const float32_t sampleRate, const float32_t frequency, const float32_t gain, const float32_t slope) { - if (filterStage >= 0 && filterStage < _filterCount && filterChannel >= 0 && filterChannel < _channelCount) { + if (filterStage < _filterCount && filterChannel >= 0 && filterChannel < _channelCount) { _filters[filterStage][filterChannel].setParameters(sampleRate,frequency,gain,slope); } } void getParameters(uint32_t filterStage, uint32_t filterChannel, float32_t& sampleRate, float32_t& frequency, float32_t& gain, float32_t& slope) { - if (filterStage >= 0 && filterStage < _filterCount && filterChannel >= 0 && filterChannel < _channelCount) { + if (filterStage < _filterCount && filterChannel >= 0 && filterChannel < _channelCount) { _filters[filterStage][filterChannel].getParameters(sampleRate,frequency,gain,slope); } } diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index cc8743de16..e4391d6029 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -85,12 +85,12 @@ public: _bufferFirst(NULL), _bufferLast(NULL), _at(NULL) {} - ConstIterator(int16_t* bufferFirst, int capacity, int16_t* at) : _bufferLength(capacity), _bufferFirst(bufferFirst), _bufferLast(bufferFirst + capacity - 1), _at(at) {} + ConstIterator(const ConstIterator& rhs) = default; bool isNull() const { return _at == NULL; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index f0d13f8792..8bbe8dafd8 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -2003,6 +2003,7 @@ FBXGeometry* extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping material._material = make_shared(); material._material->setEmissive(material.emissive); + // FIXME both cases are identical if (glm::all(glm::equal(material.diffuse, glm::vec3(0.0f)))) { material._material->setDiffuse(material.diffuse); } else { diff --git a/libraries/gpu/src/gpu/Framebuffer.h b/libraries/gpu/src/gpu/Framebuffer.h index 6f2b762bb0..310255af9f 100755 --- a/libraries/gpu/src/gpu/Framebuffer.h +++ b/libraries/gpu/src/gpu/Framebuffer.h @@ -149,7 +149,7 @@ protected: void updateSize(const TexturePointer& texture); // Non exposed - Framebuffer(const Framebuffer& framebuffer) {} + Framebuffer(const Framebuffer& framebuffer) = delete; Framebuffer() {} // This shouldn't be used by anything else than the Backend class with the proper casting. diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp index e76983cce9..3aef37e502 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp @@ -95,7 +95,7 @@ void ViveControllerManager::activate() { vr::RenderModel_t model; if (!_hmd->LoadRenderModel(CONTROLLER_MODEL_STRING.toStdString().c_str(), &model)) { - qDebug("Unable to load render model %s\n", CONTROLLER_MODEL_STRING); + qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING); } else { model::Mesh* mesh = new model::Mesh(); model::MeshPointer meshPtr(mesh); @@ -198,7 +198,7 @@ void ViveControllerManager::renderHand(UserInputMapper::PoseValue pose, gpu::Bat Transform transform(userInputMapper->getSensorToWorldMat()); transform.postTranslate(pose.getTranslation() + pose.getRotation() * glm::vec3(0, 0, CONTROLLER_LENGTH_OFFSET)); - int sign = index == LEFT_HAND ? 1.0f : -1.0f; + int sign = index == LEFT_HAND ? 1 : -1; glm::quat rotation = pose.getRotation() * glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::angleAxis(sign * PI_OVER_TWO, glm::vec3(0.0f, 0.0f, 1.0f)); transform.postRotate(rotation); @@ -325,7 +325,7 @@ void ViveControllerManager::handlePoseEvent(const mat4& mat, int index) { glm::quat rotation = glm::quat_cast(mat); // Flip the rotation appropriately for each hand - int sign = index == LEFT_HAND ? 1.0f : -1.0f; + int sign = index == LEFT_HAND ? 1 : -1; rotation = rotation * glm::angleAxis(PI, glm::vec3(1.0f, 0.0f, 0.0f)) * glm::angleAxis(sign * PI_OVER_TWO, glm::vec3(0.0f, 0.0f, 1.0f)); position += rotation * glm::vec3(0, 0, -CONTROLLER_LENGTH_OFFSET); diff --git a/libraries/octree/src/CoverageMap.cpp b/libraries/octree/src/CoverageMap.cpp index b1feaff6c0..626d4bcf1a 100644 --- a/libraries/octree/src/CoverageMap.cpp +++ b/libraries/octree/src/CoverageMap.cpp @@ -338,7 +338,7 @@ void CoverageRegion::erase() { } **/ // If we're in charge of managing the polygons, then clean them up first - if (_managePolygons) { + if (_polygons && _managePolygons) { for (int i = 0; i < _polygonCount; i++) { delete _polygons[i]; _polygons[i] = NULL; // do we need to do this? diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 267769ad49..93933c5301 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1318,7 +1318,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, // If the user also asked for occlusion culling, check if this element is occluded if (params.wantOcclusionCulling && childElement->isLeaf()) { // Don't check occlusion here, just add them to our distance ordered array... - + + // FIXME params.ViewFrustum is used here, but later it is checked against nullptr. OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon( params.viewFrustum->getProjectedPolygon(childElement->getAACube())); diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index deeec58f49..c4fb4c9989 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -621,6 +621,7 @@ QSharedPointer DilatableNetworkTexture::getDilatedTexture(float dilatio gpu::Element formatMip = gpu::Element(gpu::VEC3, gpu::UINT8, (isLinearRGB ? gpu::RGB : gpu::SRGB)); if (dilatedImage.hasAlphaChannel()) { formatGPU = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::RGBA : gpu::SRGBA)); + // FIXME either remove the ?: operator or provide different arguments depending on linear formatMip = gpu::Element(gpu::VEC4, gpu::UINT8, (isLinearRGB ? gpu::BGRA : gpu::BGRA)); } texture->_gpuTexture = gpu::TexturePointer(gpu::Texture::create2D(formatGPU, dilatedImage.width(), dilatedImage.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); diff --git a/libraries/script-engine/src/WebSocketClass.h b/libraries/script-engine/src/WebSocketClass.h index 8ba8ecf362..dbc9729c61 100644 --- a/libraries/script-engine/src/WebSocketClass.h +++ b/libraries/script-engine/src/WebSocketClass.h @@ -81,8 +81,10 @@ public: return OPEN; case QAbstractSocket::SocketState::ClosingState: return CLOSING; + case QAbstractSocket::SocketState::UnconnectedState: + default: + return CLOSED; } - return CLOSED; } void setOnClose(QScriptValue eventFunction) { _onCloseEvent = eventFunction; } diff --git a/libraries/shared/src/Extents.cpp b/libraries/shared/src/Extents.cpp index ad00683cf2..10f97cc337 100644 --- a/libraries/shared/src/Extents.cpp +++ b/libraries/shared/src/Extents.cpp @@ -20,8 +20,8 @@ #include "Transform.h" void Extents::reset() { - minimum = glm::vec3(FLT_MAX); - maximum = glm::vec3(-FLT_MAX); + minimum = Vectors::MAX; + maximum = Vectors::MIN; } bool Extents::containsPoint(const glm::vec3& point) const { diff --git a/libraries/shared/src/Extents.h b/libraries/shared/src/Extents.h index 3d5a2dbcec..07fad60a04 100644 --- a/libraries/shared/src/Extents.h +++ b/libraries/shared/src/Extents.h @@ -18,14 +18,15 @@ #include #include "StreamUtils.h" +#include "GLMHelpers.h" class AABox; class Transform; class Extents { public: - Extents(const glm::vec3& minimum, const glm::vec3& maximum) : minimum(minimum), maximum(maximum) { } - Extents() { reset(); } + Extents() { } + Extents(const glm::vec3& minimum, const glm::vec3& maximum) : minimum(minimum), maximum(maximum) {} Extents(const AABox& box) { reset(); add(box); } /// set minimum and maximum to FLT_MAX and -FLT_MAX respectively @@ -49,7 +50,7 @@ public: /// \return whether or not the extents are empty bool isEmpty() const { return minimum == maximum; } - bool isValid() const { return !((minimum == glm::vec3(FLT_MAX)) && (maximum == glm::vec3(-FLT_MAX))); } + bool isValid() const { return !((minimum == Vectors::MAX) && (maximum == Vectors::MIN)); } /// \param vec3 for delta amount to shift the extents by /// \return true if point is within current limits @@ -75,8 +76,8 @@ public: return temp; } - glm::vec3 minimum; - glm::vec3 maximum; + glm::vec3 minimum{ Vectors::MAX }; + glm::vec3 maximum{ Vectors::MIN }; }; inline QDebug operator<<(QDebug debug, const Extents& extents) { diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 138d3f2c20..8c58928de5 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -13,6 +13,24 @@ #include "NumericalConstants.h" +const vec3 Vectors::UNIT_X{ 1.0f, 0.0f, 0.0f }; +const vec3 Vectors::UNIT_Y{ 0.0f, 1.0f, 0.0f }; +const vec3 Vectors::UNIT_Z{ 0.0f, 0.0f, 1.0f }; +const vec3 Vectors::UNIT_NEG_X{ -1.0f, 0.0f, 0.0f }; +const vec3 Vectors::UNIT_NEG_Y{ 0.0f, -1.0f, 0.0f }; +const vec3 Vectors::UNIT_NEG_Z{ 0.0f, 0.0f, -1.0f }; +const vec3 Vectors::UNIT_XY{ glm::normalize(UNIT_X + UNIT_Y) }; +const vec3 Vectors::UNIT_XZ{ glm::normalize(UNIT_X + UNIT_Z) }; +const vec3 Vectors::UNIT_YZ{ glm::normalize(UNIT_Y + UNIT_Z) }; +const vec3 Vectors::UNIT_XYZ{ glm::normalize(UNIT_X + UNIT_Y + UNIT_Z) }; +const vec3 Vectors::MAX{ FLT_MAX }; +const vec3 Vectors::MIN{ FLT_MIN }; +const vec3 Vectors::ZERO{ 0.0f }; +const vec3 Vectors::ONE{ 1.0f }; +const vec3& Vectors::RIGHT = Vectors::UNIT_X; +const vec3& Vectors::UP = Vectors::UNIT_Y; +const vec3& Vectors::FRONT = Vectors::UNIT_NEG_Z; + // Safe version of glm::mix; based on the code in Nick Bobick's article, // http://www.gamasutra.com/features/19980703/quaternions_01.htm (via Clyde, // https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java) diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index 79addbc5f1..4b03ed2525 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -53,6 +53,28 @@ const glm::vec3 IDENTITY_FRONT = glm::vec3( 0.0f, 0.0f,-1.0f); glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float alpha); +class Vectors { +public: + static const vec3 UNIT_X; + static const vec3 UNIT_Y; + static const vec3 UNIT_Z; + static const vec3 UNIT_NEG_X; + static const vec3 UNIT_NEG_Y; + static const vec3 UNIT_NEG_Z; + static const vec3 UNIT_XY; + static const vec3 UNIT_XZ; + static const vec3 UNIT_YZ; + static const vec3 UNIT_ZX; + static const vec3 UNIT_XYZ; + static const vec3 MAX; + static const vec3 MIN; + static const vec3 ZERO; + static const vec3 ONE; + static const vec3& RIGHT; + static const vec3& UP; + static const vec3& FRONT; +}; + // These pack/unpack functions are designed to start specific known types in as efficient a manner // as possible. Taking advantage of the known characteristics of the semantic types. diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index 60cddb5cfe..d1f23531cb 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -38,14 +38,14 @@ LogHandler::LogHandler() : const char* stringForLogType(LogMsgType msgType) { switch (msgType) { - case QtDebugMsg: + case LogDebug: return "DEBUG"; - case QtCriticalMsg: - return "CRITICAL"; - case QtFatalMsg: - return "FATAL"; - case QtWarningMsg: + case LogWarning: return "WARNING"; + case LogCritical: + return "CRITICAL"; + case LogFatal: + return "FATAL"; case LogSuppressed: return "SUPPRESS"; default: diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index 914cad212d..6af721f96c 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -22,10 +22,10 @@ const int VERBOSE_LOG_INTERVAL_SECONDS = 5; enum LogMsgType { - LogDebug, - LogWarning, - LogCritical, - LogFatal, + LogDebug = QtDebugMsg, + LogWarning = QtWarningMsg, + LogCritical = QtCriticalMsg, + LogFatal = QtFatalMsg, LogSuppressed }; diff --git a/libraries/shared/src/RingBufferHistory.h b/libraries/shared/src/RingBufferHistory.h index c0bd1e2a6e..c5222b9c39 100644 --- a/libraries/shared/src/RingBufferHistory.h +++ b/libraries/shared/src/RingBufferHistory.h @@ -174,7 +174,7 @@ public: } bool operator<=(const Iterator& rhs) { - return age() < rhs.age(); + return age() <= rhs.age(); } bool operator>=(const Iterator& rhs) { diff --git a/libraries/shared/src/Transform.cpp b/libraries/shared/src/Transform.cpp index a00761fd50..4b2a481f41 100644 --- a/libraries/shared/src/Transform.cpp +++ b/libraries/shared/src/Transform.cpp @@ -37,7 +37,7 @@ void Transform::evalRotationScale(Quat& rotation, Vec3& scale, const Mat3& rotat norm = (norm > n ? norm : n); } rotationMat = nextRotation; - } while (count < 100 && norm > ACCURACY_THREASHOLD); + } while (count++ < 100 && norm > ACCURACY_THREASHOLD); // extract scale of the matrix as the length of each axis diff --git a/tools/scribe/src/TextTemplate.cpp b/tools/scribe/src/TextTemplate.cpp index c468df278b..e7537508bc 100755 --- a/tools/scribe/src/TextTemplate.cpp +++ b/tools/scribe/src/TextTemplate.cpp @@ -196,7 +196,7 @@ bool TextTemplate::grabUntilEndTag(std::istream* str, std::string& grabbed, Tag: preEnd = Tag::REM; } - while (!str->eof()) { + while (!str->eof() && !str->fail()) { // looking for the end of the tag means find the next preEnd std::string dataToken; getline((*str), dataToken, preEnd); @@ -233,7 +233,7 @@ bool TextTemplate::stepForward(std::istream* str, std::string& grabbed, std::str if (grabUntilEndTag(str, tag, tagType)) { // skip trailing space and new lines only after Command or Remark tag block if ((tagType == Tag::COMMAND) || (tagType == Tag::REMARK)) { - while (!str->eof()) { + while (!str->eof() && !str->fail()) { char c = str->peek(); if ((c == ' ') || (c == '\t') || (c == '\n')) { str->get(); From f25b75093c8230dd446f6d37b27fd997a76bc37a Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 26 Aug 2015 09:44:29 -0700 Subject: [PATCH 49/57] cleaned up conditional bitstream parsing --- .../entities/src/ParticleEffectEntityItem.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index f2b3953b70..bb91e44aa6 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -234,25 +234,20 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) { setAnimationFrameIndex(animationFrameIndex); } + READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); + READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); + READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); + READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); + READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); + READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); + if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLE_MODIFICATIONS) { - READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); - READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); - READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); - READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); - READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); - READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); READ_ENTITY_PROPERTY(PROP_EMIT_ACCELERATION, glm::vec3, setEmitAcceleration); READ_ENTITY_PROPERTY(PROP_ACCELERATION_SPREAD, glm::vec3, setAccelerationSpread); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); READ_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); } else { - READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); - READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); - READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); - READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); - READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); - READ_ENTITY_PROPERTY(PROP_EMIT_VELOCITY, glm::vec3, setEmitVelocity); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); From 695ffa29c7196463e119e40d8a0ddf515d8f0e0d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 26 Aug 2015 11:09:59 -0700 Subject: [PATCH 50/57] call setup_memory_debugger from common macros rather than from every CMakeLists.txt file --- assignment-client/CMakeLists.txt | 2 -- cmake/macros/LinkHifiLibraries.cmake | 3 +++ cmake/macros/SetupHifiLibrary.cmake | 2 ++ domain-server/CMakeLists.txt | 2 -- gvr-interface/CMakeLists.txt | 2 -- ice-server/CMakeLists.txt | 2 -- interface/CMakeLists.txt | 2 -- libraries/animation/CMakeLists.txt | 2 -- libraries/audio-client/CMakeLists.txt | 2 -- libraries/audio/CMakeLists.txt | 2 -- libraries/auto-updater/CMakeLists.txt | 2 -- libraries/avatars/CMakeLists.txt | 2 -- libraries/display-plugins/CMakeLists.txt | 2 -- libraries/embedded-webserver/CMakeLists.txt | 2 -- libraries/entities-renderer/CMakeLists.txt | 2 -- libraries/entities/CMakeLists.txt | 2 -- libraries/environment/CMakeLists.txt | 2 -- libraries/fbx/CMakeLists.txt | 2 -- libraries/gpu/CMakeLists.txt | 2 -- libraries/input-plugins/CMakeLists.txt | 2 -- libraries/model/CMakeLists.txt | 2 -- libraries/networking/CMakeLists.txt | 2 -- libraries/octree/CMakeLists.txt | 2 -- libraries/physics/CMakeLists.txt | 2 -- libraries/plugins/CMakeLists.txt | 2 -- libraries/render-utils/CMakeLists.txt | 2 -- libraries/render/CMakeLists.txt | 2 -- libraries/script-engine/CMakeLists.txt | 2 -- libraries/shared/CMakeLists.txt | 2 -- libraries/ui/CMakeLists.txt | 2 -- tests/CMakeLists.txt | 2 -- tests/animation/CMakeLists.txt | 2 -- tests/audio/CMakeLists.txt | 2 -- tests/entities/CMakeLists.txt | 2 -- tests/jitter/CMakeLists.txt | 2 -- tests/networking/CMakeLists.txt | 2 -- tests/octree/CMakeLists.txt | 2 -- tests/physics/CMakeLists.txt | 2 -- tests/render-utils/CMakeLists.txt | 2 -- tests/shaders/CMakeLists.txt | 2 -- tests/shared/CMakeLists.txt | 2 -- tests/ui/CMakeLists.txt | 2 -- tools/CMakeLists.txt | 2 -- tools/mtc/CMakeLists.txt | 2 -- tools/scribe/CMakeLists.txt | 2 -- tools/vhacd-util/CMakeLists.txt | 2 -- 46 files changed, 5 insertions(+), 88 deletions(-) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index dc20763953..c9fd769822 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -19,6 +19,4 @@ endif (UNIX) include_application_version() -setup_memory_debugger() - copy_dlls_beside_windows_executable() diff --git a/cmake/macros/LinkHifiLibraries.cmake b/cmake/macros/LinkHifiLibraries.cmake index ef7467e170..d0a12f3bea 100644 --- a/cmake/macros/LinkHifiLibraries.cmake +++ b/cmake/macros/LinkHifiLibraries.cmake @@ -33,4 +33,7 @@ macro(LINK_HIFI_LIBRARIES) list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES ${LINKED_TARGET_DEPENDENCY_INCLUDES}) endif() endforeach() + + setup_memory_debugger() + endmacro(LINK_HIFI_LIBRARIES) \ No newline at end of file diff --git a/cmake/macros/SetupHifiLibrary.cmake b/cmake/macros/SetupHifiLibrary.cmake index e38e224084..aba8d500a5 100644 --- a/cmake/macros/SetupHifiLibrary.cmake +++ b/cmake/macros/SetupHifiLibrary.cmake @@ -15,6 +15,8 @@ macro(SETUP_HIFI_LIBRARY) file(GLOB_RECURSE LIB_SRCS "src/*.h" "src/*.cpp" "src/*.c") list(APPEND ${TARGET_NAME}_SRCS ${LIB_SRCS}) + setup_memory_debugger() + # create a library and set the property so it can be referenced later if (${${TARGET_NAME}_SHARED}) add_library(${TARGET_NAME} SHARED ${LIB_SRCS} ${AUTOMTC_SRC} ${AUTOSCRIBE_SHADER_LIB_SRC} ${QT_RESOURCES_FILE}) diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index d2f30b6c25..e4fa1d874d 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME domain-server) -setup_memory_debugger() - if (UPPER_CMAKE_BUILD_TYPE MATCHES DEBUG AND NOT WIN32) set(_SHOULD_SYMLINK_RESOURCES TRUE) else () diff --git a/gvr-interface/CMakeLists.txt b/gvr-interface/CMakeLists.txt index c4880a80b6..2c1e87c8b4 100644 --- a/gvr-interface/CMakeLists.txt +++ b/gvr-interface/CMakeLists.txt @@ -88,6 +88,4 @@ if (ANDROID) endif (ANDROID) -setup_memory_debugger() - copy_dlls_beside_windows_executable() diff --git a/ice-server/CMakeLists.txt b/ice-server/CMakeLists.txt index d62192bcec..b056d79efd 100644 --- a/ice-server/CMakeLists.txt +++ b/ice-server/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME ice-server) -setup_memory_debugger() - # setup the project and link required Qt modules setup_hifi_project(Network) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0c531dfacb..d7ee9228f4 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -205,6 +205,4 @@ else (APPLE) endif() endif (APPLE) -setup_memory_debugger() - copy_dlls_beside_windows_executable() diff --git a/libraries/animation/CMakeLists.txt b/libraries/animation/CMakeLists.txt index fc7fa23dcc..115a2e360c 100644 --- a/libraries/animation/CMakeLists.txt +++ b/libraries/animation/CMakeLists.txt @@ -3,6 +3,4 @@ set(TARGET_NAME animation) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network Script) -setup_memory_debugger() - link_hifi_libraries(shared gpu model fbx) diff --git a/libraries/audio-client/CMakeLists.txt b/libraries/audio-client/CMakeLists.txt index c313aecbc0..76f4cb4a0f 100644 --- a/libraries/audio-client/CMakeLists.txt +++ b/libraries/audio-client/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME audio-client) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network Multimedia) diff --git a/libraries/audio/CMakeLists.txt b/libraries/audio/CMakeLists.txt index a0d40b1a10..c03f588d94 100644 --- a/libraries/audio/CMakeLists.txt +++ b/libraries/audio/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME audio) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network) diff --git a/libraries/auto-updater/CMakeLists.txt b/libraries/auto-updater/CMakeLists.txt index 6960d8368d..c3d6e74a6f 100644 --- a/libraries/auto-updater/CMakeLists.txt +++ b/libraries/auto-updater/CMakeLists.txt @@ -1,6 +1,4 @@ set(TARGET_NAME auto-updater) -setup_memory_debugger() - setup_hifi_library(Network) link_hifi_libraries(shared networking) diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index b05c667c71..acc939b25c 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME avatars) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network Script) diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt index 79b41fa957..384fa57b62 100644 --- a/libraries/display-plugins/CMakeLists.txt +++ b/libraries/display-plugins/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME display-plugins) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(OpenGL) diff --git a/libraries/embedded-webserver/CMakeLists.txt b/libraries/embedded-webserver/CMakeLists.txt index 2d8915998b..45d9827d42 100644 --- a/libraries/embedded-webserver/CMakeLists.txt +++ b/libraries/embedded-webserver/CMakeLists.txt @@ -1,6 +1,4 @@ set(TARGET_NAME embedded-webserver) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network) diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 3387715348..c4dddb8971 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -26,6 +26,4 @@ find_package(PolyVox REQUIRED) target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${POLYVOX_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${POLYVOX_LIBRARIES}) -setup_memory_debugger() - link_hifi_libraries(shared gpu script-engine render render-utils) diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index 368257661e..f7936ff125 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME entities) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network Script) diff --git a/libraries/environment/CMakeLists.txt b/libraries/environment/CMakeLists.txt index fbdc614d26..e3fc143c14 100644 --- a/libraries/environment/CMakeLists.txt +++ b/libraries/environment/CMakeLists.txt @@ -7,6 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -setup_memory_debugger() - link_hifi_libraries(shared networking) diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index c06bb0efc1..9d9f57ad20 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -7,6 +7,4 @@ add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) -setup_memory_debugger() - link_hifi_libraries(shared gpu model networking octree) diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 84320297eb..7a88580f7f 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME gpu) -setup_memory_debugger() - AUTOSCRIBE_SHADER_LIB(gpu) # use setup_hifi_library macro to setup our project and link appropriate Qt modules diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 5d6dae7ad1..1ac8047edc 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -33,8 +33,6 @@ endif() #target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS}) #target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) -setup_memory_debugger() - # perform standard include and linking for found externals foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) diff --git a/libraries/model/CMakeLists.txt b/libraries/model/CMakeLists.txt index 2099f83fec..701c132e61 100755 --- a/libraries/model/CMakeLists.txt +++ b/libraries/model/CMakeLists.txt @@ -2,8 +2,6 @@ set(TARGET_NAME model) AUTOSCRIBE_SHADER_LIB(gpu model) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index d0e0b850c7..400fc5446a 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME networking) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network) diff --git a/libraries/octree/CMakeLists.txt b/libraries/octree/CMakeLists.txt index 8b9ff6bda2..cc36aead15 100644 --- a/libraries/octree/CMakeLists.txt +++ b/libraries/octree/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME octree) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index 802665b948..b1f9fbb79c 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME physics) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library() diff --git a/libraries/plugins/CMakeLists.txt b/libraries/plugins/CMakeLists.txt index 98fd5fdc93..42b8cb1625 100644 --- a/libraries/plugins/CMakeLists.txt +++ b/libraries/plugins/CMakeLists.txt @@ -8,6 +8,4 @@ link_hifi_libraries(shared) add_dependency_external_projects(glm) find_package(GLM REQUIRED) -setup_memory_debugger() - target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index ceb1a192ab..0ea71e54e3 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -40,6 +40,4 @@ add_dependency_external_projects(oglplus) find_package(OGLPLUS REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS}) -setup_memory_debugger() - link_hifi_libraries(animation fbx shared gpu model render environment) diff --git a/libraries/render/CMakeLists.txt b/libraries/render/CMakeLists.txt index 1f73d93519..f2bcb7c47c 100644 --- a/libraries/render/CMakeLists.txt +++ b/libraries/render/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME render) -setup_memory_debugger() - AUTOSCRIBE_SHADER_LIB(gpu model) # use setup_hifi_library macro to setup our project and link appropriate Qt modules diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 670a13f081..139b99e426 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME script-engine) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Gui Network Script WebSockets Widgets) diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index a80f4194ef..00a80619bc 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -1,7 +1,5 @@ set(TARGET_NAME shared) -setup_memory_debugger() - # use setup_hifi_library macro to setup our project and link appropriate Qt modules # TODO: there isn't really a good reason to have Script linked here - let's get what is requiring it out (RegisteredMetaTypes.cpp) setup_hifi_library(Gui Network Script Widgets) diff --git a/libraries/ui/CMakeLists.txt b/libraries/ui/CMakeLists.txt index 68caa940c1..b07651f7d4 100644 --- a/libraries/ui/CMakeLists.txt +++ b/libraries/ui/CMakeLists.txt @@ -8,6 +8,4 @@ link_hifi_libraries(render-utils shared) add_dependency_external_projects(glm) find_package(GLM REQUIRED) -setup_memory_debugger() - target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c2dc30c4bb..1593b649a0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,5 +35,3 @@ set_target_properties("all-tests" PROPERTIES FOLDER "hidden/test-targets") set_target_properties("all-tests" PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE EXCLUDE_FROM_ALL TRUE) - -setup_memory_debugger() diff --git a/tests/animation/CMakeLists.txt b/tests/animation/CMakeLists.txt index bc1e93a94f..2e9dbc9424 100644 --- a/tests/animation/CMakeLists.txt +++ b/tests/animation/CMakeLists.txt @@ -6,6 +6,4 @@ macro (setup_testcase_dependencies) copy_dlls_beside_windows_executable() endmacro () -setup_memory_debugger() - setup_hifi_testcase() diff --git a/tests/audio/CMakeLists.txt b/tests/audio/CMakeLists.txt index c56ef049bd..f7dd1d23b9 100644 --- a/tests/audio/CMakeLists.txt +++ b/tests/audio/CMakeLists.txt @@ -6,6 +6,4 @@ macro (SETUP_TESTCASE_DEPENDENCIES) copy_dlls_beside_windows_executable() endmacro () -setup_memory_debugger() - setup_hifi_testcase() diff --git a/tests/entities/CMakeLists.txt b/tests/entities/CMakeLists.txt index f83efe7f64..b2c7969386 100644 --- a/tests/entities/CMakeLists.txt +++ b/tests/entities/CMakeLists.txt @@ -9,6 +9,4 @@ set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries link_hifi_libraries(entities avatars shared octree gpu model fbx networking animation environment) -setup_memory_debugger() - copy_dlls_beside_windows_executable() diff --git a/tests/jitter/CMakeLists.txt b/tests/jitter/CMakeLists.txt index ba46582b02..98be42530c 100644 --- a/tests/jitter/CMakeLists.txt +++ b/tests/jitter/CMakeLists.txt @@ -7,6 +7,4 @@ macro (setup_testcase_dependencies) copy_dlls_beside_windows_executable() endmacro() -setup_memory_debugger() - setup_hifi_testcase() diff --git a/tests/networking/CMakeLists.txt b/tests/networking/CMakeLists.txt index fcf32d89c8..efa744e4c9 100644 --- a/tests/networking/CMakeLists.txt +++ b/tests/networking/CMakeLists.txt @@ -7,6 +7,4 @@ macro (setup_testcase_dependencies) copy_dlls_beside_windows_executable() endmacro () -setup_memory_debugger() - setup_hifi_testcase() diff --git a/tests/octree/CMakeLists.txt b/tests/octree/CMakeLists.txt index 77511c682a..e2a756105a 100644 --- a/tests/octree/CMakeLists.txt +++ b/tests/octree/CMakeLists.txt @@ -7,6 +7,4 @@ macro (setup_testcase_dependencies) copy_dlls_beside_windows_executable() endmacro () -setup_memory_debugger() - setup_hifi_testcase(Script Network) diff --git a/tests/physics/CMakeLists.txt b/tests/physics/CMakeLists.txt index 1a6f49430b..36cf21c681 100644 --- a/tests/physics/CMakeLists.txt +++ b/tests/physics/CMakeLists.txt @@ -21,6 +21,4 @@ macro (SETUP_TESTCASE_DEPENDENCIES) copy_dlls_beside_windows_executable() endmacro () -setup_memory_debugger() - setup_hifi_testcase(Script) diff --git a/tests/render-utils/CMakeLists.txt b/tests/render-utils/CMakeLists.txt index 1b47f85099..62ed401d2e 100644 --- a/tests/render-utils/CMakeLists.txt +++ b/tests/render-utils/CMakeLists.txt @@ -10,6 +10,4 @@ link_hifi_libraries(render-utils gpu shared) message(${PROJECT_BINARY_DIR}) -setup_memory_debugger() - copy_dlls_beside_windows_executable() diff --git a/tests/shaders/CMakeLists.txt b/tests/shaders/CMakeLists.txt index 3ee9f4ae9f..9b2a079e88 100644 --- a/tests/shaders/CMakeLists.txt +++ b/tests/shaders/CMakeLists.txt @@ -19,6 +19,4 @@ include_directories("${PROJECT_BINARY_DIR}/../../libraries/model/") message(${PROJECT_BINARY_DIR}) -setup_memory_debugger() - copy_dlls_beside_windows_executable() diff --git a/tests/shared/CMakeLists.txt b/tests/shared/CMakeLists.txt index c3d6cfd810..7bddb4b2ed 100644 --- a/tests/shared/CMakeLists.txt +++ b/tests/shared/CMakeLists.txt @@ -8,6 +8,4 @@ macro (setup_testcase_dependencies) copy_dlls_beside_windows_executable() endmacro () -setup_memory_debugger() - setup_hifi_testcase() diff --git a/tests/ui/CMakeLists.txt b/tests/ui/CMakeLists.txt index c0f20a280f..6a2d8c394a 100644 --- a/tests/ui/CMakeLists.txt +++ b/tests/ui/CMakeLists.txt @@ -13,6 +13,4 @@ endif() # link in the shared libraries link_hifi_libraries(ui render-utils gpu shared) -setup_memory_debugger() - copy_dlls_beside_windows_executable() diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 4d8618b37c..a8564d7f1c 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,5 +1,3 @@ -setup_memory_debugger() - # add the tool directories add_subdirectory(mtc) set_target_properties(mtc PROPERTIES FOLDER "Tools") diff --git a/tools/mtc/CMakeLists.txt b/tools/mtc/CMakeLists.txt index fe5f1920bc..16c812673d 100644 --- a/tools/mtc/CMakeLists.txt +++ b/tools/mtc/CMakeLists.txt @@ -1,6 +1,4 @@ set(TARGET_NAME mtc) setup_hifi_project() -setup_memory_debugger() - copy_dlls_beside_windows_executable() diff --git a/tools/scribe/CMakeLists.txt b/tools/scribe/CMakeLists.txt index 0abf70f727..e62a3467e0 100755 --- a/tools/scribe/CMakeLists.txt +++ b/tools/scribe/CMakeLists.txt @@ -1,5 +1,3 @@ set(TARGET_NAME scribe) -setup_memory_debugger() - setup_hifi_project() diff --git a/tools/vhacd-util/CMakeLists.txt b/tools/vhacd-util/CMakeLists.txt index b79a6a1893..c94b2ad083 100644 --- a/tools/vhacd-util/CMakeLists.txt +++ b/tools/vhacd-util/CMakeLists.txt @@ -8,8 +8,6 @@ find_package(VHACD REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${VHACD_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${VHACD_LIBRARIES}) -setup_memory_debugger() - if (UNIX AND NOT APPLE) include(FindOpenMP) if(OPENMP_FOUND) From 5586c2ff17ecc6df952d606bf8357e15c340ded7 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 26 Aug 2015 11:45:19 -0700 Subject: [PATCH 51/57] fixed ordering of bitsream reading for old svo files with particle entities --- libraries/entities/src/ParticleEffectEntityItem.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index bb91e44aa6..9e45efe88d 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -248,8 +248,11 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); READ_ENTITY_PROPERTY(PROP_VELOCITY_SPREAD, glm::vec3, setVelocitySpread); } else { + // EMIT_STRENGTH FAKEOUT READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); - READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration); + // LOCAL_GRAVITY FAKEOUT + READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); + // ACTUALLY PARTICLE RADIUS READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); } From f857ccfe167a1b26ddcdc8d6d4b44aa0bc1f8408 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Aug 2015 11:46:50 -0700 Subject: [PATCH 52/57] fix Vectors::MIN --- libraries/shared/src/GLMHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 8c58928de5..c1d168557d 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -24,7 +24,7 @@ const vec3 Vectors::UNIT_XZ{ glm::normalize(UNIT_X + UNIT_Z) }; const vec3 Vectors::UNIT_YZ{ glm::normalize(UNIT_Y + UNIT_Z) }; const vec3 Vectors::UNIT_XYZ{ glm::normalize(UNIT_X + UNIT_Y + UNIT_Z) }; const vec3 Vectors::MAX{ FLT_MAX }; -const vec3 Vectors::MIN{ FLT_MIN }; +const vec3 Vectors::MIN{ -FLT_MAX }; const vec3 Vectors::ZERO{ 0.0f }; const vec3 Vectors::ONE{ 1.0f }; const vec3& Vectors::RIGHT = Vectors::UNIT_X; From 0fc2713be1578aa8cc3b11f96f03b46abf6c24c8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 26 Aug 2015 12:40:09 -0700 Subject: [PATCH 53/57] don't request a cert from peer in HTTPSManager --- libraries/embedded-webserver/src/HTTPSManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/embedded-webserver/src/HTTPSManager.cpp b/libraries/embedded-webserver/src/HTTPSManager.cpp index 94e1a35e20..a745d7605e 100644 --- a/libraries/embedded-webserver/src/HTTPSManager.cpp +++ b/libraries/embedded-webserver/src/HTTPSManager.cpp @@ -30,6 +30,7 @@ void HTTPSManager::incomingConnection(qintptr socketDescriptor) { sslSocket->setLocalCertificate(_certificate); sslSocket->setPrivateKey(_privateKey); + sslSocket->setPeerVerifyMode(QSslSocket::VerifyNone); if (sslSocket->setSocketDescriptor(socketDescriptor)) { new HTTPSConnection(sslSocket, this); @@ -48,4 +49,4 @@ bool HTTPSManager::handleHTTPSRequest(HTTPSConnection* connection, const QUrl& u bool HTTPSManager::requestHandledByRequestHandler(HTTPConnection* connection, const QUrl& url) { return _sslRequestHandler && _sslRequestHandler->handleHTTPSRequest(reinterpret_cast(connection), url); -} \ No newline at end of file +} From cd7d0f383b05c5af811ae2d257d12dcef2d0e71a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 26 Aug 2015 15:07:29 -0700 Subject: [PATCH 54/57] allow editors who can't be verified in the short term --- domain-server/src/DomainGatekeeper.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 72b353f8a0..0b0e0fedd3 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -219,17 +219,15 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect if (allowedEditors.contains(username)) { // we have a non-empty allowed editors list - check if this user is verified to be in it if (!verifiedUsername) { - if (!verifyUserSignature(username, usernameSignature, nodeConnection.senderSockAddr)) { + if (!verifyUserSignature(username, usernameSignature, HifiSockAddr())) { // failed to verify a user that is in the allowed editors list - sendConnectionTokenPacket(username, nodeConnection.senderSockAddr); - qDebug() << "Could not verify user" << username << "as allowed editor. Forcing user to attempt reconnect."; - - return SharedNodePointer(); - } else { - // just verified this user and they are in the allowed editors list - canAdjustLocks = true; + // TODO: fix public key refresh in interface/metaverse and force this check + qDebug() << "Could not verify user" << username << "as allowed editor. In the interim this user" + << "will be given edit rights to avoid a thrasing of public key requests and connect requests."; } + + canAdjustLocks = true; } else { // already verified this user and they are in the allowed editors list canAdjustLocks = true; From f53704051ffadfeb964d55a1a1a1d6021dd4108d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 26 Aug 2015 15:09:58 -0700 Subject: [PATCH 55/57] ifdef out debug prints in OBJ reader --- libraries/fbx/src/OBJReader.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 841fdcfad9..3eff3bdec5 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -211,13 +211,17 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { while (true) { switch (tokenizer.nextToken()) { case OBJTokenizer::COMMENT_TOKEN: + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader MTLLIB comment:" << tokenizer.getComment(); + #endif break; case OBJTokenizer::DATUM_TOKEN: break; default: materials[matName] = currentMaterial; + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader Last material shininess:" << currentMaterial.shininess << " opacity:" << currentMaterial.opacity << " diffuse color:" << currentMaterial.diffuseColor << " specular color:" << currentMaterial.specularColor << " diffuse texture:" << currentMaterial.diffuseTextureFilename << " specular texture:" << currentMaterial.specularTextureFilename; + #endif return; } QByteArray token = tokenizer.getDatum(); @@ -229,14 +233,18 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { matName = tokenizer.getDatum(); currentMaterial = materials[matName]; currentMaterial.diffuseTextureFilename = "test"; + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader Starting new material definition " << matName; + #endif currentMaterial.diffuseTextureFilename = ""; } else if (token == "Ns") { currentMaterial.shininess = tokenizer.getFloat(); } else if ((token == "d") || (token == "Tr")) { currentMaterial.opacity = tokenizer.getFloat(); } else if (token == "Ka") { + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader Ignoring material Ka " << tokenizer.getVec3(); + #endif } else if (token == "Kd") { currentMaterial.diffuseColor = tokenizer.getVec3(); } else if (token == "Ks") { @@ -244,7 +252,9 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { } else if ((token == "map_Kd") || (token == "map_Ks")) { QByteArray filename = QUrl(tokenizer.getLineAsDatum()).fileName().toUtf8(); if (filename.endsWith(".tga")) { + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader WARNING: currently ignoring tga texture " << filename << " in " << _url; + #endif break; } if (isValidTexture(filename)) { @@ -254,7 +264,9 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { currentMaterial.specularTextureFilename = filename; } } else { + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader WARNING: " << _url << " ignoring missing texture " << filename; + #endif } } } @@ -318,7 +330,6 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi } QByteArray groupName = tokenizer.getDatum(); currentGroup = groupName; - //qCDebug(modelformat) << "new group:" << groupName; } else if (token == "mtllib" && _url) { if (tokenizer.nextToken() != OBJTokenizer::DATUM_TOKEN) { break; @@ -330,13 +341,17 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi librariesSeen[libraryName] = true; // Throw away any path part of libraryName, and merge against original url. QUrl libraryUrl = _url->resolved(QUrl(libraryName).fileName()); + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader new library:" << libraryName << " at:" << libraryUrl; + #endif QNetworkReply* netReply = request(libraryUrl, false); if (netReply->isFinished() && (netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200)) { parseMaterialLibrary(netReply); } else { + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader " << libraryName << " did not answer. Got " << netReply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); + #endif } netReply->deleteLater(); } else if (token == "usemtl") { @@ -344,7 +359,9 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi break; } currentMaterialName = tokenizer.getDatum(); + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader new current material:" << currentMaterialName; + #endif } else if (token == "v") { vertices.append(tokenizer.getVec3()); } else if (token == "vn") { @@ -394,7 +411,6 @@ done: } else { faceGroups.append(faces); // We're done with this group. Add the faces. } - //qCDebug(modelformat) << "end group:" << meshPart.materialID << " original faces:" << originalFaceCountForDebugging << " triangles:" << faces.count() << " keep going:" << result; return result; } @@ -475,13 +491,17 @@ FBXGeometry* OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, OBJFace leadFace = faceGroup[0]; // All the faces in the same group will have the same name and material. QString groupMaterialName = leadFace.materialName; if (groupMaterialName.isEmpty() && (leadFace.textureUVIndices.count() > 0)) { + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " needs a texture that isn't specified. Using default mechanism."; + #endif groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; } else if (!groupMaterialName.isEmpty() && !materials.contains(groupMaterialName)) { + #ifdef WANT_DEBUG qCDebug(modelformat) << "OBJ Reader WARNING: " << url << " specifies a material " << groupMaterialName << " that is not defined. Using default mechanism."; + #endif groupMaterialName = SMART_DEFAULT_MATERIAL_NAME; } if (!groupMaterialName.isEmpty()) { @@ -496,7 +516,6 @@ FBXGeometry* OBJReader::readOBJ(QIODevice* device, const QVariantHash& mapping, meshPart._material->setGloss(material->shininess); meshPart._material->setOpacity(material->opacity); } - // qCDebug(modelformat) << "OBJ Reader part:" << meshPartCount << "name:" << leadFace.groupName << "material:" << groupMaterialName << "diffuse:" << meshPart._material->getDiffuse() << "faces:" << faceGroup.count() << "triangle indices will start with:" << mesh.vertices.count(); foreach(OBJFace face, faceGroup) { glm::vec3 v0 = vertices[face.vertexIndices[0]]; glm::vec3 v1 = vertices[face.vertexIndices[1]]; From 270f2f7a3b3e391056a5cc049a2acc2dd82f9205 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 25 Aug 2015 00:55:00 -0700 Subject: [PATCH 56/57] Fixing framerate limit, moving vsync to 2d plugin --- interface/src/Application.cpp | 227 +++++------------- interface/src/Application.h | 6 - interface/src/Menu.cpp | 21 +- interface/src/Menu.h | 7 - .../Basic2DWindowOpenGLDisplayPlugin.cpp | 109 ++++++++- .../Basic2DWindowOpenGLDisplayPlugin.h | 8 +- .../src/display-plugins/DisplayPlugin.cpp | 5 +- .../src/display-plugins/DisplayPlugin.h | 2 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 27 +++ .../src/display-plugins/OpenGLDisplayPlugin.h | 4 + .../stereo/StereoDisplayPlugin.cpp | 2 +- libraries/shared/src/NumericalConstants.h | 1 + 12 files changed, 206 insertions(+), 213 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fbe47eb83f..2ed91037be 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -189,6 +189,11 @@ static QTimer* billboardPacketTimer = NULL; static QTimer* checkFPStimer = NULL; static QTimer* idleTimer = NULL; +static const unsigned int TARGET_SIM_FRAMERATE = 60; +static const unsigned int THROTTLED_SIM_FRAMERATE = 15; +static const int TARGET_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / TARGET_SIM_FRAMERATE; +static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE; + const QString CHECK_VERSION_URL = "https://highfidelity.com/latestVersion.xml"; const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; @@ -347,7 +352,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _trayIcon(new QSystemTrayIcon(_window)), _lastNackTime(usecTimestampNow()), _lastSendDownstreamAudioStats(usecTimestampNow()), - _isVSyncOn(true), _isThrottleFPSEnabled(true), _aboutToQuit(false), _notifiedPacketVersionMismatchThisDomain(false), @@ -745,8 +749,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : }); connect(this, &Application::applicationStateChanged, this, &Application::activeChanged); - - setVSyncEnabled(); // make sure VSync is set properly at startup } void Application::aboutToQuit() { @@ -920,7 +922,7 @@ void Application::initializeGL() { // call our idle function whenever we can idleTimer = new QTimer(this); connect(idleTimer, SIGNAL(timeout()), SLOT(idle())); - idleTimer->start(0); + idleTimer->start(TARGET_SIM_FRAME_PERIOD_MS); _idleLoopStdev.reset(); if (_justStarted) { @@ -2033,38 +2035,38 @@ void Application::checkFPS() { } void Application::idle() { - PROFILE_RANGE(__FUNCTION__); - static SimpleAverage interIdleDurations; - - static uint64_t lastIdleStart{ 0 }; - static uint64_t lastIdleEnd{ 0 }; - uint64_t now = usecTimestampNow(); - uint64_t idleStartToStartDuration = now - lastIdleStart; - - if (lastIdleStart > 0 && idleStartToStartDuration > 0) { - _simsPerSecond.updateAverage((float)USECS_PER_SECOND / (float)idleStartToStartDuration); - } - - lastIdleStart = now; - - if (lastIdleEnd != 0) { - interIdleDurations.update(now - lastIdleEnd); - static uint64_t lastReportTime = now; - if ((now - lastReportTime) >= (USECS_PER_SECOND)) { - static QString LOGLINE("Average inter-idle time: %1 us for %2 samples"); - if (Menu::getInstance()->isOptionChecked(MenuOption::LogExtraTimings)) { - qCDebug(interfaceapp_timing) << LOGLINE.arg((int)interIdleDurations.getAverage()).arg(interIdleDurations.getCount()); - } - interIdleDurations.reset(); - lastReportTime = now; - } - } - - PerformanceTimer perfTimer("idle"); if (_aboutToQuit) { return; // bail early, nothing to do here. } + // depending on whether we're throttling or not. + // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in + // perpetuity and not expect events to get backed up. + bool isThrottled = getActiveDisplayPlugin()->isThrottled(); + // Only run simulation code if more than the targetFramePeriod have passed since last time we ran + // This attempts to lock the simulation at 60 updates per second, regardless of framerate + float timeSinceLastUpdateUs = (float)_lastTimeUpdated.nsecsElapsed() / NSECS_PER_USEC; + float secondsSinceLastUpdate = timeSinceLastUpdateUs / USECS_PER_SECOND; + + if (isThrottled && (timeSinceLastUpdateUs / USECS_PER_MSEC) < THROTTLED_SIM_FRAME_PERIOD_MS) { + return; // bail early, we're throttled and not enough time has elapsed + } + + _lastTimeUpdated.start(); + + + { + PROFILE_RANGE(__FUNCTION__); + uint64_t now = usecTimestampNow(); + static uint64_t lastIdleStart{ now }; + uint64_t idleStartToStartDuration = now - lastIdleStart; + if (idleStartToStartDuration != 0) { + _simsPerSecond.updateAverage((float)USECS_PER_SECOND / (float)idleStartToStartDuration); + } + lastIdleStart = now; + } + + PerformanceTimer perfTimer("idle"); // Drop focus from _keyboardFocusedItem if no keyboard messages for 30 seconds if (!_keyboardFocusedItem.isInvalidID()) { const quint64 LOSE_FOCUS_AFTER_ELAPSED_TIME = 30 * USECS_PER_SECOND; // if idle for 30 seconds, drop focus @@ -2080,69 +2082,42 @@ void Application::idle() { bool showWarnings = getLogger()->extraDebugging(); PerformanceWarning warn(showWarnings, "idle()"); - // Only run simulation code if more than the targetFramePeriod have passed since last time we ran - double targetFramePeriod = 0.0; - unsigned int targetFramerate = getRenderTargetFramerate(); - if (targetFramerate > 0) { - targetFramePeriod = 1000.0 / targetFramerate; + { + PerformanceTimer perfTimer("update"); + PerformanceWarning warn(showWarnings, "Application::idle()... update()"); + static const float BIGGEST_DELTA_TIME_SECS = 0.25f; + update(glm::clamp(secondsSinceLastUpdate, 0.0f, BIGGEST_DELTA_TIME_SECS)); } - double timeSinceLastUpdate = (double)_lastTimeUpdated.nsecsElapsed() / 1000000.0; - if (timeSinceLastUpdate > targetFramePeriod) { - _lastTimeUpdated.start(); - { - PerformanceTimer perfTimer("update"); - PerformanceWarning warn(showWarnings, "Application::idle()... update()"); - const float BIGGEST_DELTA_TIME_SECS = 0.25f; - PROFILE_RANGE(__FUNCTION__ "/idleUpdate"); - update(glm::clamp((float)timeSinceLastUpdate / 1000.0f, 0.0f, BIGGEST_DELTA_TIME_SECS)); - } - { - PerformanceTimer perfTimer("updateGL"); - PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); - getActiveDisplayPlugin()->idle(); - auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); - foreach(auto inputPlugin, inputPlugins) { - QString name = inputPlugin->getName(); - QAction* action = Menu::getInstance()->getActionForOption(name); - if (action && action->isChecked()) { - inputPlugin->idle(); - } + { + PerformanceTimer perfTimer("pluginIdle"); + PerformanceWarning warn(showWarnings, "Application::idle()... pluginIdle()"); + getActiveDisplayPlugin()->idle(); + auto inputPlugins = PluginManager::getInstance()->getInputPlugins(); + foreach(auto inputPlugin, inputPlugins) { + QString name = inputPlugin->getName(); + QAction* action = Menu::getInstance()->getActionForOption(name); + if (action && action->isChecked()) { + inputPlugin->idle(); } } - { - PerformanceTimer perfTimer("rest"); - PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); - _idleLoopStdev.addValue(timeSinceLastUpdate); + } + { + PerformanceTimer perfTimer("rest"); + PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); + _idleLoopStdev.addValue(secondsSinceLastUpdate); - // Record standard deviation and reset counter if needed - const int STDEV_SAMPLES = 500; - if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) { - _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); - _idleLoopStdev.reset(); - } - } - - float secondsSinceLastUpdate = (float)timeSinceLastUpdate / 1000.0f; - _overlayConductor.update(secondsSinceLastUpdate); - - // depending on whether we're throttling or not. - // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in - // perpetuity and not expect events to get backed up. - - bool isThrottled = getActiveDisplayPlugin()->isThrottled(); - static const int THROTTLED_IDLE_TIMER_DELAY = MSECS_PER_SECOND / 15; - static const int IDLE_TIMER_DELAY_MS = 2; - int desiredInterval = isThrottled ? THROTTLED_IDLE_TIMER_DELAY : IDLE_TIMER_DELAY_MS; - //qDebug() << "isThrottled:" << isThrottled << "desiredInterval:" << desiredInterval; - - if (idleTimer->interval() != desiredInterval) { - idleTimer->start(desiredInterval); + // Record standard deviation and reset counter if needed + const int STDEV_SAMPLES = 500; + if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) { + _idleLoopMeasuredJitter = _idleLoopStdev.getStDev(); + _idleLoopStdev.reset(); } } + + _overlayConductor.update(secondsSinceLastUpdate); // check for any requested background downloads. emit checkBackgroundDownloads(); - lastIdleEnd = usecTimestampNow(); } float Application::getAverageSimsPerSecond() { @@ -4476,90 +4451,10 @@ void Application::takeSnapshot() { } -void Application::setVSyncEnabled() { - _glWidget->makeCurrent(); -#if defined(Q_OS_WIN) - bool vsyncOn = Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerateVSyncOn); - if (wglewGetExtension("WGL_EXT_swap_control")) { - wglSwapIntervalEXT(vsyncOn); - int swapInterval = wglGetSwapIntervalEXT(); - qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); - } else { - qCDebug(interfaceapp, "V-Sync is FORCED ON on this system\n"); - } -#elif defined(Q_OS_LINUX) - // TODO: write the poper code for linux - /* - if (glQueryExtension.... ("GLX_EXT_swap_control")) { - glxSwapIntervalEXT(vsyncOn); - int swapInterval = xglGetSwapIntervalEXT(); - _isVSyncOn = swapInterval; - qCDebug(interfaceapp, "V-Sync is %s\n", (swapInterval > 0 ? "ON" : "OFF")); - } else { - qCDebug(interfaceapp, "V-Sync is FORCED ON on this system\n"); - } - */ -#else - qCDebug(interfaceapp, "V-Sync is FORCED ON on this system\n"); -#endif - _offscreenContext->makeCurrent(); -} - void Application::setThrottleFPSEnabled() { _isThrottleFPSEnabled = Menu::getInstance()->isOptionChecked(MenuOption::ThrottleFPSIfNotFocus); } -bool Application::isVSyncOn() const { -#if defined(Q_OS_WIN) - if (wglewGetExtension("WGL_EXT_swap_control")) { - int swapInterval = wglGetSwapIntervalEXT(); - return (swapInterval > 0); - } -#elif defined(Q_OS_LINUX) - // TODO: write the poper code for linux - /* - if (glQueryExtension.... ("GLX_EXT_swap_control")) { - int swapInterval = xglGetSwapIntervalEXT(); - return (swapInterval > 0); - } else { - return true; - } - */ -#endif - return true; -} - -bool Application::isVSyncEditable() const { -#if defined(Q_OS_WIN) - if (wglewGetExtension("WGL_EXT_swap_control")) { - return true; - } -#elif defined(Q_OS_LINUX) - // TODO: write the poper code for linux - /* - if (glQueryExtension.... ("GLX_EXT_swap_control")) { - return true; - } - */ -#endif - return false; -} - -unsigned int Application::getRenderTargetFramerate() const { - if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerateUnlimited)) { - return 0; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate60)) { - return 60; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate50)) { - return 50; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate40)) { - return 40; - } else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerate30)) { - return 30; - } - return 0; -} - float Application::getRenderResolutionScale() const { if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionOne)) { return 1.0f; diff --git a/interface/src/Application.h b/interface/src/Application.h index 6394aa12d0..7e4e340eee 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -300,9 +300,6 @@ public: float getRenderResolutionScale() const; int getRenderAmbientLight() const; - unsigned int getRenderTargetFramerate() const; - bool isVSyncOn() const; - bool isVSyncEditable() const; bool isAboutToQuit() const { return _aboutToQuit; } // the isHMDmode is true whenever we use the interface from an HMD and not a standard flat display @@ -411,8 +408,6 @@ public slots: void domainSettingsReceived(const QJsonObject& domainSettingsObject); - void setVSyncEnabled(); - void setThrottleFPSEnabled(); bool isThrottleFPSEnabled() { return _isThrottleFPSEnabled; } @@ -626,7 +621,6 @@ private: quint64 _lastNackTime; quint64 _lastSendDownstreamAudioStats; - bool _isVSyncOn; bool _isThrottleFPSEnabled; bool _aboutToQuit; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9d47df1c73..b756236fe0 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -222,7 +222,7 @@ Menu::Menu() { addActionToQMenuAndActionHash(toolsMenu, MenuOption::PackageModel, 0, qApp, SLOT(packageModel())); - MenuWrapper* displayMenu = addMenu(DisplayPlugin::MENU_PATH); + MenuWrapper* displayMenu = addMenu(DisplayPlugin::MENU_PATH()); { MenuWrapper* displayModeMenu = addMenu(MenuOption::OutputMenu); QActionGroup* displayModeGroup = new QActionGroup(displayModeMenu); @@ -333,25 +333,8 @@ Menu::Menu() { ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight8, 0, false)); ambientLightGroup->addAction(addCheckableActionToQMenuAndActionHash(ambientLightMenu, MenuOption::RenderAmbientLight9, 0, false)); - { - MenuWrapper* framerateMenu = renderOptionsMenu->addMenu(MenuOption::RenderTargetFramerate); - QActionGroup* framerateGroup = new QActionGroup(framerateMenu); - framerateGroup->setExclusive(true); - framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerateUnlimited, 0, true)); - framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate60, 0, false)); - framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate50, 0, false)); - framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate40, 0, false)); - framerateGroup->addAction(addCheckableActionToQMenuAndActionHash(framerateMenu, MenuOption::RenderTargetFramerate30, 0, false)); - -#if defined(Q_OS_MAC) -#else - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::RenderTargetFramerateVSyncOn, 0, true, - qApp, SLOT(setVSyncEnabled())); -#endif - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true, + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true, qApp, SLOT(setThrottleFPSEnabled())); - } - MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution); QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 4bd1e7f664..98b3fe9892 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -238,13 +238,6 @@ namespace MenuOption { const QString RenderLookAtTargets = "Show Look-at Targets"; const QString RenderLookAtVectors = "Show Look-at Vectors"; const QString RenderSkeletonCollisionShapes = "Show Skeleton Collision Shapes"; - const QString RenderTargetFramerate = "Framerate"; - const QString RenderTargetFramerateUnlimited = "Unlimited"; - const QString RenderTargetFramerate60 = "60"; - const QString RenderTargetFramerate50 = "50"; - const QString RenderTargetFramerate40 = "40"; - const QString RenderTargetFramerate30 = "30"; - const QString RenderTargetFramerateVSyncOn = "V-Sync On"; const QString RenderResolution = "Scale Resolution"; const QString RenderResolutionOne = "1"; const QString RenderResolutionTwoThird = "2/3"; diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index da8deefa74..914d30d58a 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -7,21 +7,35 @@ // #include "Basic2DWindowOpenGLDisplayPlugin.h" +#include + +#include +#include +#include + #include -#include -#include const QString Basic2DWindowOpenGLDisplayPlugin::NAME("2D Display"); static const QString FULLSCREEN = "Fullscreen"; +static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate"; +static const QString FRAMERATE_UNLIMITED = "Unlimited"; +static const QString FRAMERATE_60 = "60"; +static const QString FRAMERATE_50 = "50"; +static const QString FRAMERATE_40 = "40"; +static const QString FRAMERATE_30 = "30"; +static const QString VSYNC_ON = "V-Sync On"; const QString& Basic2DWindowOpenGLDisplayPlugin::getName() const { return NAME; } +std::vector _framerateActions; +QAction* _vsyncAction{ nullptr }; + void Basic2DWindowOpenGLDisplayPlugin::activate() { - CONTAINER->addMenu(MENU_PATH); - CONTAINER->addMenuItem(MENU_PATH, FULLSCREEN, + _framerateActions.clear(); + CONTAINER->addMenuItem(MENU_PATH(), FULLSCREEN, [this](bool clicked) { if (clicked) { CONTAINER->setFullscreen(getFullscreenTarget()); @@ -29,18 +43,65 @@ void Basic2DWindowOpenGLDisplayPlugin::activate() { CONTAINER->unsetFullscreen(); } }, true, false); + CONTAINER->addMenu(FRAMERATE); + _framerateActions.push_back( + CONTAINER->addMenuItem(FRAMERATE, FRAMERATE_UNLIMITED, + [this](bool) { updateFramerate(); }, true, true, FRAMERATE)); + _framerateActions.push_back( + CONTAINER->addMenuItem(FRAMERATE, FRAMERATE_60, + [this](bool) { updateFramerate(); }, true, false, FRAMERATE)); + _framerateActions.push_back( + CONTAINER->addMenuItem(FRAMERATE, FRAMERATE_50, + [this](bool) { updateFramerate(); }, true, false, FRAMERATE)); + _framerateActions.push_back( + CONTAINER->addMenuItem(FRAMERATE, FRAMERATE_40, + [this](bool) { updateFramerate(); }, true, false, FRAMERATE)); + _framerateActions.push_back( + CONTAINER->addMenuItem(FRAMERATE, FRAMERATE_30, + [this](bool) { updateFramerate(); }, true, false, FRAMERATE)); + WindowOpenGLDisplayPlugin::activate(); + + // Vsync detection happens in the parent class activate, so we need to check after that + if (_vsyncSupported) { + _vsyncAction = CONTAINER->addMenuItem(MENU_PATH(), VSYNC_ON, [this](bool) {}, true, true); + } else { + _vsyncAction = nullptr; + } + + updateFramerate(); } void Basic2DWindowOpenGLDisplayPlugin::deactivate() { WindowOpenGLDisplayPlugin::deactivate(); } -int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval(bool isThrottled) const { - static const int THROTTLED_PAINT_TIMER_DELAY = MSECS_PER_SECOND / 15; - static const int PAINT_TIMER_DELAY_MS = 1; +void Basic2DWindowOpenGLDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize) { + if (_vsyncAction) { + bool wantVsync = _vsyncAction->isChecked(); + bool vsyncEnabed = isVsyncEnabled(); + if (vsyncEnabed ^ wantVsync) { + enableVsync(wantVsync); + } + } - return isThrottled ? THROTTLED_PAINT_TIMER_DELAY : PAINT_TIMER_DELAY_MS; + WindowOpenGLDisplayPlugin::display(sceneTexture, sceneSize); +} + + +int Basic2DWindowOpenGLDisplayPlugin::getDesiredInterval() const { + static const int THROTTLED_PAINT_TIMER_DELAY_MS = MSECS_PER_SECOND / 15; + static const int ULIMIITED_PAINT_TIMER_DELAY_MS = 1; + int result = ULIMIITED_PAINT_TIMER_DELAY_MS; + if (_isThrottled) { + result = THROTTLED_PAINT_TIMER_DELAY_MS; + } + if (0 != _framerateTarget) { + result = MSECS_PER_SECOND / _framerateTarget; + } + + qDebug() << "New interval " << result; + return result; } bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { @@ -49,14 +110,42 @@ bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { bool shouldThrottle = (!CONTAINER->isForeground() && CONTAINER->isOptionChecked(ThrottleFPSIfNotFocus)); if (_isThrottled != shouldThrottle) { - int desiredInterval = getDesiredInterval(shouldThrottle); - _timer.start(desiredInterval); _isThrottled = shouldThrottle; + _timer.start(getDesiredInterval()); } return shouldThrottle; } + +void Basic2DWindowOpenGLDisplayPlugin::updateFramerate() { + QAction* checkedFramerate{ nullptr }; + foreach(auto action, _framerateActions) { + if (action->isChecked()) { + checkedFramerate = action; + break; + } + } + + _framerateTarget = 0; + if (checkedFramerate) { + QString actionText = checkedFramerate->text(); + if (FRAMERATE_60 == actionText) { + _framerateTarget = 60; + } else if (FRAMERATE_50 == actionText) { + _framerateTarget = 50; + } else if (FRAMERATE_40 == actionText) { + _framerateTarget = 40; + } else if (FRAMERATE_30 == actionText) { + _framerateTarget = 30; + } + } + + int newInterval = getDesiredInterval(); + qDebug() << newInterval; + _timer.start(getDesiredInterval()); +} + // FIXME target the screen the window is currently on QScreen* Basic2DWindowOpenGLDisplayPlugin::getFullscreenTarget() { return qApp->primaryScreen(); diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 64edfe3600..f4655ab79f 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -14,19 +14,23 @@ class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { Q_OBJECT public: + virtual const QString & getName() const override; + virtual void activate() override; virtual void deactivate() override; - virtual const QString & getName() const override; + virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override; virtual bool isThrottled() const override; protected: - int getDesiredInterval(bool isThrottled) const; + int getDesiredInterval() const; mutable bool _isThrottled = false; private: + void updateFramerate(); static const QString NAME; QScreen* getFullscreenTarget(); + uint32_t _framerateTarget{ 0 }; int _fullscreenTarget{ -1 }; }; diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp index 5840b3cbba..598e78e500 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp @@ -18,7 +18,10 @@ #include "oculus/OculusDisplayPlugin.h" #include "oculus/OculusLegacyDisplayPlugin.h" -const QString DisplayPlugin::MENU_PATH{ "Display" }; +const QString& DisplayPlugin::MENU_PATH() { + static const QString value = "Display"; + return value; +} // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class DisplayPluginList getDisplayPlugins() { diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h index 0696cc6229..a9220d68f6 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h @@ -120,7 +120,7 @@ public: virtual void resetSensors() {} virtual float devicePixelRatio() { return 1.0; } - static const QString MENU_PATH; + static const QString& MENU_PATH(); signals: void recommendedFramebufferSizeChanged(const QSize & size); void requestRender(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 0409899739..eb38e1bf4f 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -38,6 +38,11 @@ void OpenGLDisplayPlugin::finishFrame() { void OpenGLDisplayPlugin::customizeContext() { using namespace oglplus; + // TODO: write the poper code for linux +#if defined(Q_OS_WIN) + _vsyncSupported = wglewGetExtension("WGL_EXT_swap_control"); +#endif + Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha); Context::Disable(Capability::Blend); Context::Disable(Capability::DepthTest); @@ -46,6 +51,8 @@ void OpenGLDisplayPlugin::customizeContext() { _program = loadDefaultShader(); _plane = loadPlane(_program); + + enableVsync(); } void OpenGLDisplayPlugin::activate() { @@ -114,4 +121,24 @@ void OpenGLDisplayPlugin::display( void OpenGLDisplayPlugin::drawUnitQuad() { _program->Bind(); _plane->Draw(); +} + +void OpenGLDisplayPlugin::enableVsync(bool enable) { + if (!_vsyncSupported) { + return; + } +#ifdef Q_OS_WIN + wglSwapIntervalEXT(enable ? 1 : 0); +#endif +} + +bool OpenGLDisplayPlugin::isVsyncEnabled() { + if (!_vsyncSupported) { + return true; + } +#ifdef Q_OS_WIN + return wglGetSwapIntervalEXT() != 0; +#else + return true; +#endif } \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 3152500232..0dc94b72f5 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -38,9 +38,13 @@ protected: virtual void doneCurrent() = 0; virtual void swapBuffers() = 0; + virtual bool isVsyncEnabled(); + virtual void enableVsync(bool enable = true); + mutable QTimer _timer; ProgramPtr _program; ShapeWrapperPtr _plane; + bool _vsyncSupported{ false }; }; diff --git a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp index df691f06f3..017977bf69 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp @@ -69,7 +69,7 @@ void StereoDisplayPlugin::activate() { if (screen == qApp->primaryScreen()) { checked = true; } - auto action = CONTAINER->addMenuItem(MENU_PATH, name, + auto action = CONTAINER->addMenuItem(MENU_PATH(), name, [this](bool clicked) { updateScreen(); }, true, checked, "Screens"); _screenActions[i] = action; } diff --git a/libraries/shared/src/NumericalConstants.h b/libraries/shared/src/NumericalConstants.h index b632147641..9a946e35f7 100644 --- a/libraries/shared/src/NumericalConstants.h +++ b/libraries/shared/src/NumericalConstants.h @@ -31,6 +31,7 @@ const float METERS_PER_DECIMETER = 0.1f; const float METERS_PER_CENTIMETER = 0.01f; const float METERS_PER_MILLIMETER = 0.001f; const float MILLIMETERS_PER_METER = 1000.0f; +const quint64 NSECS_PER_USEC = 1000; const quint64 USECS_PER_MSEC = 1000; const quint64 MSECS_PER_SECOND = 1000; const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND; From 96c74ebbd5f697bdfcc29470ac9db79b3d3ac31b Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 27 Aug 2015 12:25:40 -0700 Subject: [PATCH 57/57] Enable Rig Animations is now a developer menu item (rather than requiring javascript to set). Also turning it off resets you to bind pose and deliberately throws away old animations. Default animations are the new ones for our standard T-pose. (Had been for the double-A pose fightbot.) Rig state machine now does "backup", and doesn't apply strafe while turning. --- interface/src/Menu.cpp | 2 ++ interface/src/Menu.h | 1 + interface/src/avatar/MyAvatar.cpp | 7 ++++--- interface/src/avatar/MyAvatar.h | 2 +- libraries/animation/src/Rig.cpp | 26 ++++++++++++-------------- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 17e64b5765..1d90e2c771 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -431,6 +431,8 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowWhosLookingAtMe, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::FixGaze, 0, false); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableRigAnimations, 0, false, + avatar, SLOT(setEnableRigAnimations(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Connexion, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 9bcfd1f7aa..94e49abcc7 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -188,6 +188,7 @@ namespace MenuOption { const QString EditEntitiesHelp = "Edit Entities Help..."; const QString Enable3DTVMode = "Enable 3DTV Mode"; const QString EnableCharacterController = "Enable avatar collisions"; + const QString EnableRigAnimations = "Enable Rig Animations"; const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation"; const QString ExpandMyAvatarTiming = "Expand /myAvatar"; const QString ExpandOtherAvatarTiming = "Expand /otherAvatar"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index eb72ddd2fd..bf42cfa7e1 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -705,9 +705,10 @@ float loadSetting(QSettings& settings, const char* name, float defaultValue) { } void MyAvatar::setEnableRigAnimations(bool isEnabled) { - Settings settings; - settings.setValue("enableRig", isEnabled); _rig->setEnableRig(isEnabled); + if (!isEnabled) { + _rig->deleteAnimations(); + } } void MyAvatar::loadData() { @@ -769,7 +770,7 @@ void MyAvatar::loadData() { setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString()); settings.endGroup(); - _rig->setEnableRig(settings.value("enableRig").toBool()); + _rig->setEnableRig(Menu::getInstance()->isOptionChecked(MenuOption::EnableRigAnimations)); } void MyAvatar::saveAttachmentData(const AttachmentData& attachment) const { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 8ff9211101..9e7ab11aa6 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -87,7 +87,6 @@ public: Q_INVOKABLE AnimationDetails getAnimationDetailsByRole(const QString& role); Q_INVOKABLE AnimationDetails getAnimationDetails(const QString& url); void clearJointAnimationPriorities(); - Q_INVOKABLE void setEnableRigAnimations(bool isEnabled); // get/set avatar data void saveData(); @@ -190,6 +189,7 @@ public slots: void loadLastRecording(); virtual void rebuildSkeletonBody(); + void setEnableRigAnimations(bool isEnabled); signals: void transformChanged(); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 2212e06e31..3e466b94d6 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -100,24 +100,21 @@ AnimationHandlePointer Rig::addAnimationByRole(const QString& role, const QStrin AnimationHandlePointer handle = createAnimationHandle(); QString standard = ""; if (url.isEmpty()) { // Default animations for fight club - const QString& base = "https://hifi-public.s3.amazonaws.com/ozan/"; + const QString& base = "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/"; if (role == "walk") { - standard = base + "support/FightClubBotTest1/Animations/standard_walk.fbx"; - lastFrame = 60; + standard = base + "walk_fwd.fbx"; + } else if (role == "backup") { + standard = base + "walk_bwd.fbx"; } else if (role == "leftTurn") { - standard = base + "support/FightClubBotTest1/Animations/left_turn_noHipRotation.fbx"; - lastFrame = 29; + standard = base + "turn_left.fbx"; } else if (role == "rightTurn") { - standard = base + "support/FightClubBotTest1/Animations/right_turn_noHipRotation.fbx"; - lastFrame = 31; + standard = base + "turn_right.fbx"; } else if (role == "leftStrafe") { - standard = base + "animations/fightclub_bot_anims/side_step_left_inPlace.fbx"; - lastFrame = 31; + standard = base + "strafe_left.fbx"; } else if (role == "rightStrafe") { - standard = base + "animations/fightclub_bot_anims/side_step_right_inPlace.fbx"; - lastFrame = 31; + standard = base + "strafe_right.fbx"; } else if (role == "idle") { - standard = base + "support/FightClubBotTest1/Animations/standard_idle.fbx"; + standard = base + "idle.fbx"; fps = 25.0f; } if (!standard.isEmpty()) { @@ -438,11 +435,12 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos } } }; - updateRole("walk", std::abs(forwardSpeed) > 0.01f); + updateRole("walk", forwardSpeed > 0.01f); + updateRole("backup", forwardSpeed < -0.01f); bool isTurning = std::abs(rightTurningSpeed) > 0.5f; updateRole("rightTurn", isTurning && (rightTurningSpeed > 0)); updateRole("leftTurn", isTurning && (rightTurningSpeed < 0)); - bool isStrafing = std::abs(rightLateralSpeed) > 0.01f; + bool isStrafing = !isTurning && (std::abs(rightLateralSpeed) > 0.01f); updateRole("rightStrafe", isStrafing && (rightLateralSpeed > 0.0f)); updateRole("leftStrafe", isStrafing && (rightLateralSpeed < 0.0f)); updateRole("idle", !isMoving); // Must be last, as it makes isMoving bogus.