From 4624649b1b66dc1c3f6df7eb88de4b0acb895736 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 7 Oct 2015 08:57:55 -0700 Subject: [PATCH 01/34] Sanitize particle properties, fix crashes --- examples/example/entities/particlesTest.js | 2 +- .../entities/src/EntityItemProperties.cpp | 4 +- .../entities/src/EntityItemPropertiesMacros.h | 4 + .../entities/src/ParticleEffectEntityItem.cpp | 248 +++++++++++++++--- .../entities/src/ParticleEffectEntityItem.h | 58 ++-- 5 files changed, 261 insertions(+), 55 deletions(-) diff --git a/examples/example/entities/particlesTest.js b/examples/example/entities/particlesTest.js index bfa4a47ffb..5f2cbc0849 100644 --- a/examples/example/entities/particlesTest.js +++ b/examples/example/entities/particlesTest.js @@ -28,7 +28,7 @@ FAST_EMIT_SPEED = 1.0, GRAVITY_EMIT_ACCELERATON = { x: 0.0, y: -0.3, z: 0.0 }, ZERO_EMIT_ACCELERATON = { x: 0.0, y: 0.0, z: 0.0 }, - PI = 3.141593, + PI = 3.141592, DEG_TO_RAD = PI / 180.0, NUM_PARTICLE_EXAMPLES = 18; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 61e369cf96..3326cde9aa 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -694,7 +694,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(textColor, xColor, setTextColor); COPY_PROPERTY_FROM_QSCRIPTVALUE(backgroundColor, xColor, setBackgroundColor); COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType); - COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, float, setMaxParticles); + COPY_PROPERTY_FROM_QSCRIPTVALUE(maxParticles, quint32, setMaxParticles); COPY_PROPERTY_FROM_QSCRIPTVALUE(lifespan, float, setLifespan); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitRate, float, setEmitRate); COPY_PROPERTY_FROM_QSCRIPTVALUE(emitSpeed, float, setEmitSpeed); @@ -1401,7 +1401,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, quint32, 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_SPEED, float, setEmitSpeed); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 731e49b388..659b3bd14c 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -160,6 +160,10 @@ typedef QVector qVectorVec3; typedef QVector qVectorFloat; inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); } inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); } +inline quint32 quint32_convertFromScriptValue(const QScriptValue& v, bool& isValid) { + // Use QString::toUInt() so that isValid is set to false if the number is outside the quint32 range. + return v.toString().toUInt(&isValid); +} inline uint16_t uint16_t_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); } inline int int_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toInt(&isValid); } inline bool bool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toBool(); } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 40d3853c39..869c39db97 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -1,4 +1,3 @@ - // // ParticleEffectEntityItem.cpp // libraries/entities/src @@ -31,8 +30,6 @@ #include #include -#include - #include #include #include @@ -46,30 +43,56 @@ const glm::vec3 X_AXIS = glm::vec3(1.0f, 0.0f, 0.0f); const glm::vec3 Z_AXIS = glm::vec3(0.0f, 0.0f, 1.0f); +const float SCRIPT_MAXIMUM_PI = 3.1416f; // Round up so that reasonable property values work + const xColor ParticleEffectEntityItem::DEFAULT_COLOR = { 255, 255, 255 }; const xColor ParticleEffectEntityItem::DEFAULT_COLOR_SPREAD = { 0, 0, 0 }; const float ParticleEffectEntityItem::DEFAULT_ALPHA = 1.0f; const float ParticleEffectEntityItem::DEFAULT_ALPHA_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_ALPHA_START = DEFAULT_ALPHA; const float ParticleEffectEntityItem::DEFAULT_ALPHA_FINISH = DEFAULT_ALPHA; +const float ParticleEffectEntityItem::MINIMUM_ALPHA = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_ALPHA = 1.0f; const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f; const bool ParticleEffectEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false; const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f; const quint32 ParticleEffectEntityItem::DEFAULT_MAX_PARTICLES = 1000; +const quint32 ParticleEffectEntityItem::MINIMUM_MAX_PARTICLES = 1; +const quint32 ParticleEffectEntityItem::MAXIMUM_MAX_PARTICLES = 10000; const float ParticleEffectEntityItem::DEFAULT_LIFESPAN = 3.0f; +const float ParticleEffectEntityItem::MINIMUM_LIFESPAN = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_LIFESPAN = 86400.0f; // 1 day const float ParticleEffectEntityItem::DEFAULT_EMIT_RATE = 15.0f; +const float ParticleEffectEntityItem::MINIMUM_EMIT_RATE = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_EMIT_RATE = 1000.0f; const float ParticleEffectEntityItem::DEFAULT_EMIT_SPEED = 5.0f; +const float ParticleEffectEntityItem::MINIMUM_EMIT_SPEED = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_EMIT_SPEED = 1000.0f; // Approx mach 3 const float ParticleEffectEntityItem::DEFAULT_SPEED_SPREAD = 1.0f; const glm::quat ParticleEffectEntityItem::DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, X_AXIS); // Vertical const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIMENSIONS = glm::vec3(0.0f, 0.0f, 0.0f); // Emit from point +const float ParticleEffectEntityItem::MINIMUM_EMIT_DIMENSION = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_EMIT_DIMENSION = (float)TREE_SCALE; const float ParticleEffectEntityItem::DEFAULT_EMIT_RADIUS_START = 1.0f; // Emit from surface (when emitDimensions > 0) +const float ParticleEffectEntityItem::MINIMUM_EMIT_RADIUS_START = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_EMIT_RADIUS_START = 1.0f; +const float ParticleEffectEntityItem::MINIMUM_POLAR = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_POLAR = SCRIPT_MAXIMUM_PI; const float ParticleEffectEntityItem::DEFAULT_POLAR_START = 0.0f; // Emit along z-axis const float ParticleEffectEntityItem::DEFAULT_POLAR_FINISH = 0.0f; // "" +const float ParticleEffectEntityItem::MINIMUM_AZIMUTH = -SCRIPT_MAXIMUM_PI; +const float ParticleEffectEntityItem::MAXIMUM_AZIMUTH = SCRIPT_MAXIMUM_PI; const float ParticleEffectEntityItem::DEFAULT_AZIMUTH_START = -PI; // Emit full circumference (when polarFinish > 0) const float ParticleEffectEntityItem::DEFAULT_AZIMUTH_FINISH = PI; // "" const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_ACCELERATION(0.0f, -9.8f, 0.0f); +const float ParticleEffectEntityItem::MINIMUM_EMIT_ACCELERATION = -100.0f; // ~ 10g +const float ParticleEffectEntityItem::MAXIMUM_EMIT_ACCELERATION = 100.0f; const glm::vec3 ParticleEffectEntityItem::DEFAULT_ACCELERATION_SPREAD(0.0f, 0.0f, 0.0f); +const float ParticleEffectEntityItem::MINIMUM_ACCELERATION_SPREAD = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_ACCELERATION_SPREAD = 100.0f; const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f; +const float ParticleEffectEntityItem::MINIMUM_PARTICLE_RADIUS = 0.0f; +const float ParticleEffectEntityItem::MAXIMUM_PARTICLE_RADIUS = (float)TREE_SCALE; const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f; const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS; const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS; @@ -114,37 +137,177 @@ ParticleEffectEntityItem::~ParticleEffectEntityItem() { } +void ParticleEffectEntityItem::setAlpha(float alpha) { + if (MINIMUM_ALPHA <= alpha && alpha <= MAXIMUM_ALPHA) { + _alpha = alpha; + } +} + +void ParticleEffectEntityItem::setAlphaStart(float alphaStart) { + if (MINIMUM_ALPHA <= alphaStart && alphaStart <= MAXIMUM_ALPHA) { + _alphaStart = alphaStart; + _isAlphaStartInitialized = true; + } +} + +void ParticleEffectEntityItem::setAlphaFinish(float alphaFinish) { + if (MINIMUM_ALPHA <= alphaFinish && alphaFinish <= MAXIMUM_ALPHA) { + _alphaFinish = alphaFinish; + _isAlphaFinishInitialized = true; + } +} + +void ParticleEffectEntityItem::setAlphaSpread(float alphaSpread) { + if (MINIMUM_ALPHA <= alphaSpread && alphaSpread <= MAXIMUM_ALPHA) { + _alphaSpread = alphaSpread; + } +} + +void ParticleEffectEntityItem::setLifespan(float lifespan) { + if (MINIMUM_LIFESPAN <= lifespan && lifespan <= MAXIMUM_LIFESPAN) { + _lifespan = lifespan; + } +} + +void ParticleEffectEntityItem::setEmitRate(float emitRate) { + if (MINIMUM_EMIT_RATE <= emitRate && emitRate <= MAXIMUM_EMIT_RATE) { + _emitRate = emitRate; + } +} + void ParticleEffectEntityItem::setEmitSpeed(float emitSpeed) { - _emitSpeed = emitSpeed; - computeAndUpdateDimensions(); + if (MINIMUM_EMIT_SPEED <= emitSpeed && emitSpeed <= MAXIMUM_EMIT_SPEED) { + _emitSpeed = emitSpeed; + computeAndUpdateDimensions(); + } } void ParticleEffectEntityItem::setSpeedSpread(float speedSpread) { - _speedSpread = speedSpread; - computeAndUpdateDimensions(); + if (MINIMUM_EMIT_SPEED <= speedSpread && speedSpread <= MAXIMUM_EMIT_SPEED) { + _speedSpread = speedSpread; + computeAndUpdateDimensions(); + } } void ParticleEffectEntityItem::setEmitOrientation(const glm::quat& emitOrientation) { - _emitOrientation = emitOrientation; + _emitOrientation = glm::normalize(emitOrientation); computeAndUpdateDimensions(); } - void ParticleEffectEntityItem::setEmitDimensions(const glm::vec3& emitDimensions) { - _emitDimensions = emitDimensions; - computeAndUpdateDimensions(); + bool updated = false; + if (MINIMUM_EMIT_DIMENSION <= emitDimensions.x && emitDimensions.x <= MAXIMUM_EMIT_DIMENSION) { + _emitDimensions.x = emitDimensions.x; + updated = true; + } + if (MINIMUM_EMIT_DIMENSION <= emitDimensions.y && emitDimensions.y <= MAXIMUM_EMIT_DIMENSION) { + _emitDimensions.y = emitDimensions.y; + updated = true; + } + if (MINIMUM_EMIT_DIMENSION <= emitDimensions.z && emitDimensions.z <= MAXIMUM_EMIT_DIMENSION) { + _emitDimensions.z = emitDimensions.z; + updated = true; + } + if (updated) { + computeAndUpdateDimensions(); + } +} + +void ParticleEffectEntityItem::setEmitRadiusStart(float emitRadiusStart) { + if (MINIMUM_EMIT_RADIUS_START <= emitRadiusStart && emitRadiusStart <= MAXIMUM_EMIT_RADIUS_START) { + _emitRadiusStart = emitRadiusStart; + } +} + +void ParticleEffectEntityItem::setPolarStart(float polarStart) { + if (MINIMUM_POLAR <= polarStart && polarStart <= MAXIMUM_POLAR) { + _polarStart = polarStart; + } +} + +void ParticleEffectEntityItem::setPolarFinish(float polarFinish) { + if (MINIMUM_POLAR <= polarFinish && polarFinish <= MAXIMUM_POLAR) { + _polarFinish = polarFinish; + } +} + +void ParticleEffectEntityItem::setAzimuthStart(float azimuthStart) { + if (MINIMUM_AZIMUTH <= azimuthStart && azimuthStart <= MAXIMUM_AZIMUTH) { + _azimuthStart = azimuthStart; + } +} + +void ParticleEffectEntityItem::setAzimuthFinish(float azimuthFinish) { + if (MINIMUM_AZIMUTH <= azimuthFinish && azimuthFinish <= MAXIMUM_AZIMUTH) { + _azimuthFinish = azimuthFinish; + } } void ParticleEffectEntityItem::setEmitAcceleration(const glm::vec3& emitAcceleration) { - _emitAcceleration = emitAcceleration; - computeAndUpdateDimensions(); + bool updated = false; + if (MINIMUM_EMIT_ACCELERATION <= emitAcceleration.x && emitAcceleration.x <= MAXIMUM_EMIT_ACCELERATION) { + _emitAcceleration.x = emitAcceleration.x; + updated = true; + } + if (MINIMUM_EMIT_ACCELERATION <= emitAcceleration.y && emitAcceleration.y <= MAXIMUM_EMIT_ACCELERATION) { + _emitAcceleration.y = emitAcceleration.y; + updated = true; + } + if (MINIMUM_EMIT_ACCELERATION <= emitAcceleration.z && emitAcceleration.z <= MAXIMUM_EMIT_ACCELERATION) { + _emitAcceleration.z = emitAcceleration.z; + updated = true; + } + if (updated) { + computeAndUpdateDimensions(); + } } void ParticleEffectEntityItem::setAccelerationSpread(const glm::vec3& accelerationSpread){ - _accelerationSpread = accelerationSpread; - computeAndUpdateDimensions(); + bool updated = false; + if (MINIMUM_ACCELERATION_SPREAD <= accelerationSpread.x && accelerationSpread.x <= MAXIMUM_ACCELERATION_SPREAD) { + _accelerationSpread.x = accelerationSpread.x; + updated = true; + } + if (MINIMUM_ACCELERATION_SPREAD <= accelerationSpread.y && accelerationSpread.y <= MAXIMUM_ACCELERATION_SPREAD) { + _accelerationSpread.y = accelerationSpread.y; + updated = true; + } + if (MINIMUM_ACCELERATION_SPREAD <= accelerationSpread.z && accelerationSpread.z <= MAXIMUM_ACCELERATION_SPREAD) { + _accelerationSpread.z = accelerationSpread.z; + updated = true; + } + if (updated) { + computeAndUpdateDimensions(); + } } +void ParticleEffectEntityItem::setParticleRadius(float particleRadius) { + if (MINIMUM_PARTICLE_RADIUS <= particleRadius && particleRadius <= MAXIMUM_PARTICLE_RADIUS) { + _particleRadius = particleRadius; + } +} + +void ParticleEffectEntityItem::setRadiusStart(float radiusStart) { + if (MINIMUM_PARTICLE_RADIUS <= radiusStart && radiusStart <= MAXIMUM_PARTICLE_RADIUS) { + _radiusStart = radiusStart; + _isRadiusStartInitialized = true; + } +} + +void ParticleEffectEntityItem::setRadiusFinish(float radiusFinish) { + if (MINIMUM_PARTICLE_RADIUS <= radiusFinish && radiusFinish <= MAXIMUM_PARTICLE_RADIUS) { + _radiusFinish = radiusFinish; + _isRadiusFinishInitialized = true; + } +} + +void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) { + if (MINIMUM_PARTICLE_RADIUS <= radiusSpread && radiusSpread <= MAXIMUM_PARTICLE_RADIUS) { + _radiusSpread = radiusSpread; + } +} + + void ParticleEffectEntityItem::computeAndUpdateDimensions() { const float time = _lifespan * 1.1f; // add 10% extra time to account for incremental timer accumulation error @@ -639,12 +802,12 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _particleLifetimes[i] -= deltaTime; // if particle has died. - if (_particleLifetimes[i] <= 0.0f) { + if (_particleLifetimes[i] <= 0.0f || _lifespan == 0.0f) { // move head forward _particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles; } else { - float age = (1.0f - _particleLifetimes[i] / _lifespan); // 0.0 .. 1.0 + float age = 1.0f - _particleLifetimes[i] / _lifespan; // 0.0 .. 1.0 updateRadius(i, age); updateColor(i, age); updateAlpha(i, age); @@ -654,7 +817,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } // emit new particles, but only if animation is playing - if (getAnimationIsPlaying()) { + if (getAnimationIsPlaying() && _emitRate > 0.0f && _lifespan > 0.0f && _polarStart <= _polarFinish) { float timeLeftInFrame = deltaTime; while (_timeUntilNextEmit < timeLeftInFrame) { @@ -672,10 +835,18 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _radiusMiddles[i] =_particleRadius; _radiusFinishes[i] = getRadiusFinish(); } else { - float spreadMultiplier = 1.0f + (2.0f * randFloat() - 1.0f) * _radiusSpread / _particleRadius; - _radiusStarts[i] = spreadMultiplier * getRadiusStart(); - _radiusMiddles[i] = spreadMultiplier * _particleRadius; - _radiusFinishes[i] = spreadMultiplier * getRadiusFinish(); + float spreadMultiplier; + if (_particleRadius > 0.0f) { + spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _radiusSpread / _particleRadius; + } else { + spreadMultiplier = 1.0f; + } + _radiusStarts[i] = + glm::clamp(spreadMultiplier * getRadiusStart(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + _radiusMiddles[i] = + glm::clamp(spreadMultiplier * _particleRadius, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); + _radiusFinishes[i] = + glm::clamp(spreadMultiplier * getRadiusFinish(), MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS); } updateRadius(i, 0.0f); @@ -684,8 +855,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { // Emit along z-axis from position _particlePositions[i] = getPosition(); _particleVelocities[i] = - (_emitSpeed + (2.0f * randFloat() - 1.0f) * _speedSpread) * (_emitOrientation * Z_AXIS); - _particleAccelerations[i] = _emitAcceleration + (2.0f * randFloat() - 1.0f) * _accelerationSpread; + (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * Z_AXIS); + _particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } else { // Emit around point or from ellipsoid @@ -701,15 +872,14 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { if (_azimuthFinish >= _azimuthStart) { azimuth = _azimuthStart + (_azimuthFinish - _azimuthStart) * randFloat(); } else { - azimuth = _azimuthStart + (2.0f * PI + _azimuthFinish - _azimuthStart) * randFloat(); + azimuth = _azimuthStart + (TWO_PI + _azimuthFinish - _azimuthStart) * randFloat(); } - + glm::vec3 emitDirection; if (_emitDimensions == glm::vec3()) { // Point - emitDirection = glm::angleAxis(PI_OVER_TWO - elevation, X_AXIS) * Z_AXIS; - emitDirection = glm::angleAxis(azimuth, Z_AXIS) * emitDirection; + emitDirection = glm::quat(glm::vec3(PI_OVER_TWO - elevation, 0.0f, azimuth)) * Z_AXIS; _particlePositions[i] = getPosition(); } else { @@ -717,7 +887,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { float radiusScale = 1.0f; if (_emitRadiusStart < 1.0f) { float emitRadiusStart = glm::max(_emitRadiusStart, EPSILON); // Avoid math complications at center - float randRadius = emitRadiusStart + (1.0f - emitRadiusStart) * randFloat(); + float randRadius = + emitRadiusStart + randFloatInRange(0.0f, MAXIMUM_EMIT_RADIUS_START - emitRadiusStart); radiusScale = 1.0f - std::pow(1.0f - randRadius, 3.0f); } @@ -736,8 +907,8 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } _particleVelocities[i] = - (_emitSpeed + (2.0f * randFloat() - 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); - _particleAccelerations[i] = _emitAcceleration + (2.0f * randFloat() - 1.0f) * _accelerationSpread; + (_emitSpeed + randFloatInRange(-1.0f, 1.0f) * _speedSpread) * (_emitOrientation * emitDirection); + _particleAccelerations[i] = _emitAcceleration + randFloatInRange(-1.0f, 1.0f) * _accelerationSpread; } integrateParticle(i, timeLeftInFrame); extendBounds(_particlePositions[i]); @@ -752,10 +923,13 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { xColor middleColor = getXColor(); xColor finishColor = getColorFinish(); - float spread = 2.0f * randFloat() - 1.0f; - float spreadMultiplierRed = 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red; - float spreadMultiplierGreen = 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green; - float spreadMultiplierBlue = 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue; + float spread = randFloatInRange(-1.0f, 1.0f); + float spreadMultiplierRed = + middleColor.red > 0 ? 1.0f + spread * (float)_colorSpread.red / (float)middleColor.red : 1.0f; + float spreadMultiplierGreen = + middleColor.green > 0 ? 1.0f + spread * (float)_colorSpread.green / (float)middleColor.green : 1.0f; + float spreadMultiplierBlue = + middleColor.blue > 0 ? 1.0f + spread * (float)_colorSpread.blue / (float)middleColor.blue : 1.0f; _colorStarts[i].red = (int)glm::clamp(spreadMultiplierRed * (float)startColor.red, 0.0f, 255.0f); _colorStarts[i].green = (int)glm::clamp(spreadMultiplierGreen * (float)startColor.green, 0.0f, 255.0f); @@ -777,7 +951,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { _alphaMiddles[i] = _alpha; _alphaFinishes[i] = getAlphaFinish(); } else { - float spreadMultiplier = 1.0f + (2.0f * randFloat() - 1) * _alphaSpread / _alpha; + float spreadMultiplier = 1.0f + randFloatInRange(-1.0f, 1.0f) * _alphaSpread / _alpha; _alphaStarts[i] = spreadMultiplier * getAlphaStart(); _alphaMiddles[i] = spreadMultiplier * _alpha; _alphaFinishes[i] = spreadMultiplier * getAlphaFinish(); @@ -799,7 +973,7 @@ void ParticleEffectEntityItem::stepSimulation(float deltaTime) { } void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) { - if (_maxParticles != maxParticles) { + if (_maxParticles != maxParticles && MINIMUM_MAX_PARTICLES <= maxParticles && maxParticles <= MAXIMUM_MAX_PARTICLES) { _maxParticles = maxParticles; // TODO: try to do something smart here and preserve the state of existing particles. diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 6d5b8761b0..d4a9da40c6 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -12,6 +12,7 @@ #define hifi_ParticleEffectEntityItem_h #include + #include "EntityItem.h" class ParticleEffectEntityItem : public EntityItem { @@ -68,22 +69,25 @@ public: void setColorSpread(const xColor& colorSpread) { _colorSpread = colorSpread; } xColor getColorSpread() const { return _colorSpread; } + static const float MAXIMUM_ALPHA; + static const float MINIMUM_ALPHA; + static const float DEFAULT_ALPHA; - void setAlpha(float alpha) { _alpha = alpha; } + void setAlpha(float alpha); float getAlpha() const { return _alpha; } static const float DEFAULT_ALPHA_START; bool _isAlphaStartInitialized = false; - void setAlphaStart(float alphaStart) { _alphaStart = alphaStart; _isAlphaStartInitialized = true; } + void setAlphaStart(float alphaStart); float getAlphaStart() const { return _isAlphaStartInitialized ? _alphaStart : _alpha; } static const float DEFAULT_ALPHA_FINISH; bool _isAlphaFinishInitialized = false; - void setAlphaFinish(float alphaFinish) { _alphaFinish = alphaFinish; _isAlphaFinishInitialized = true; } + void setAlphaFinish(float alphaFinish); float getAlphaFinish() const { return _isAlphaFinishInitialized ? _alphaFinish : _alpha; } static const float DEFAULT_ALPHA_SPREAD; - void setAlphaSpread(float alphaSpread) { _alphaSpread = alphaSpread; } + void setAlphaSpread(float alphaSpread); float getAlphaSpread() const { return _alphaSpread; } void updateShapeType(ShapeType type); @@ -117,18 +121,26 @@ public: float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } static const quint32 DEFAULT_MAX_PARTICLES; + static const quint32 MINIMUM_MAX_PARTICLES; + static const quint32 MAXIMUM_MAX_PARTICLES; void setMaxParticles(quint32 maxParticles); quint32 getMaxParticles() const { return _maxParticles; } static const float DEFAULT_LIFESPAN; - void setLifespan(float lifespan) { _lifespan = lifespan; } + static const float MINIMUM_LIFESPAN; + static const float MAXIMUM_LIFESPAN; + void setLifespan(float lifespan); float getLifespan() const { return _lifespan; } static const float DEFAULT_EMIT_RATE; - void setEmitRate(float emitRate) { _emitRate = emitRate; } + static const float MINIMUM_EMIT_RATE; + static const float MAXIMUM_EMIT_RATE; + void setEmitRate(float emitRate); float getEmitRate() const { return _emitRate; } static const float DEFAULT_EMIT_SPEED; + static const float MINIMUM_EMIT_SPEED; + static const float MAXIMUM_EMIT_SPEED; void setEmitSpeed(float emitSpeed); float getEmitSpeed() const { return _emitSpeed; } @@ -141,53 +153,69 @@ public: const glm::quat& getEmitOrientation() const { return _emitOrientation; } static const glm::vec3 DEFAULT_EMIT_DIMENSIONS; + static const float MINIMUM_EMIT_DIMENSION; + static const float MAXIMUM_EMIT_DIMENSION; void setEmitDimensions(const glm::vec3& emitDimensions); const glm::vec3& getEmitDimensions() const { return _emitDimensions; } static const float DEFAULT_EMIT_RADIUS_START; - void setEmitRadiusStart(float emitRadiusStart) { _emitRadiusStart = emitRadiusStart; } + static const float MINIMUM_EMIT_RADIUS_START; + static const float MAXIMUM_EMIT_RADIUS_START; + void setEmitRadiusStart(float emitRadiusStart); float getEmitRadiusStart() const { return _emitRadiusStart; } + static const float MINIMUM_POLAR; + static const float MAXIMUM_POLAR; + static const float DEFAULT_POLAR_START; - void setPolarStart(float polarStart) { _polarStart = polarStart; } + void setPolarStart(float polarStart); float getPolarStart() const { return _polarStart; } static const float DEFAULT_POLAR_FINISH; - void setPolarFinish(float polarFinish) { _polarFinish = polarFinish; } + void setPolarFinish(float polarFinish); float getPolarFinish() const { return _polarFinish; } + static const float MINIMUM_AZIMUTH; + static const float MAXIMUM_AZIMUTH; + static const float DEFAULT_AZIMUTH_START; - void setAzimuthStart(float azimuthStart) { _azimuthStart = azimuthStart; } + void setAzimuthStart(float azimuthStart); float getAzimuthStart() const { return _azimuthStart; } static const float DEFAULT_AZIMUTH_FINISH; - void setAzimuthFinish(float azimuthFinish) { _azimuthFinish = azimuthFinish; } + void setAzimuthFinish(float azimuthFinish); float getAzimuthFinish() const { return _azimuthFinish; } static const glm::vec3 DEFAULT_EMIT_ACCELERATION; + static const float MINIMUM_EMIT_ACCELERATION; + static const float MAXIMUM_EMIT_ACCELERATION; void setEmitAcceleration(const glm::vec3& emitAcceleration); const glm::vec3& getEmitAcceleration() const { return _emitAcceleration; } static const glm::vec3 DEFAULT_ACCELERATION_SPREAD; + static const float MINIMUM_ACCELERATION_SPREAD; + static const float MAXIMUM_ACCELERATION_SPREAD; void setAccelerationSpread(const glm::vec3& accelerationSpread); const glm::vec3& getAccelerationSpread() const { return _accelerationSpread; } static const float DEFAULT_PARTICLE_RADIUS; - void setParticleRadius(float particleRadius) { _particleRadius = particleRadius; } + static const float MINIMUM_PARTICLE_RADIUS; + static const float MAXIMUM_PARTICLE_RADIUS; + void setParticleRadius(float particleRadius); float getParticleRadius() const { return _particleRadius; } static const float DEFAULT_RADIUS_START; bool _isRadiusStartInitialized = false; - void setRadiusStart(float radiusStart) { _radiusStart = radiusStart; _isRadiusStartInitialized = true; } + void setRadiusStart(float radiusStart); float getRadiusStart() const { return _isRadiusStartInitialized ? _radiusStart : _particleRadius; } static const float DEFAULT_RADIUS_FINISH; bool _isRadiusFinishInitialized = false; - void setRadiusFinish(float radiusFinish) { _radiusFinish = radiusFinish; _isRadiusFinishInitialized = true; } + void setRadiusFinish(float radiusFinish); float getRadiusFinish() const { return _isRadiusFinishInitialized ? _radiusFinish : _particleRadius; } static const float DEFAULT_RADIUS_SPREAD; - void setRadiusSpread(float radiusSpread) { _radiusSpread = radiusSpread; } + void setRadiusSpread(float radiusSpread); float getRadiusSpread() const { return _radiusSpread; } void computeAndUpdateDimensions(); From 6c2a94fddb1be1cde5885c3c0c8dcfa1b540ab85 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 5 Oct 2015 23:23:53 -0700 Subject: [PATCH 02/34] remove unused method declarations --- libraries/animation/src/Rig.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index ef802e925d..6d9f7b4688 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -132,7 +132,6 @@ public: bool getJointStateTranslation(int index, glm::vec3& translation) const; void applyJointRotationDelta(int jointIndex, const glm::quat& delta, float priority); JointState getJointState(int jointIndex) const; // XXX - bool getVisibleJointState(int index, glm::quat& rotation) const; void clearJointState(int index); void clearJointStates(); void clearJointAnimationPriority(int index); @@ -154,9 +153,6 @@ public: bool getJointRotation(int jointIndex, glm::quat& rotation) const; bool getJointTranslation(int jointIndex, glm::vec3& translation) const; bool getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const; - bool getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position, - glm::vec3 translation, glm::quat rotation) const; - bool getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& result, glm::quat rotation) const; glm::mat4 getJointTransform(int jointIndex) const; glm::mat4 getJointVisibleTransform(int jointIndex) const; void setJointVisibleTransform(int jointIndex, glm::mat4 newTransform); @@ -179,7 +175,6 @@ public: float priority, float mix = 1.0f); bool getJointRotationInConstrainedFrame(int jointIndex, glm::quat& rotOut) const; glm::quat getJointDefaultRotationInParentFrame(int jointIndex); - void updateVisibleJointStates(); void clearJointStatePriorities(); virtual void updateJointState(int index, glm::mat4 rootTransform) = 0; From 76264ae704ab962fbc40875370e83fc252ce02a9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 5 Oct 2015 23:24:27 -0700 Subject: [PATCH 03/34] fix formatting --- libraries/physics/src/DynamicCharacterController.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/physics/src/DynamicCharacterController.cpp b/libraries/physics/src/DynamicCharacterController.cpp index 163cba6aae..604326168c 100644 --- a/libraries/physics/src/DynamicCharacterController.cpp +++ b/libraries/physics/src/DynamicCharacterController.cpp @@ -35,9 +35,8 @@ public: if (rayResult.m_collisionObject == _me) { return 1.0f; } - return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace - ); -} + return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace); + } protected: btRigidBody* _me; }; From 0680be0422d1d30548448ecb9407a9167967513b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 5 Oct 2015 23:25:05 -0700 Subject: [PATCH 04/34] save sixense settings and some UI cleanup --- interface/src/Application.cpp | 1 + interface/src/ui/PreferencesDialog.cpp | 5 -- interface/ui/preferencesDialog.ui | 34 -------- .../src/input-plugins/InputPlugin.cpp | 6 ++ .../src/input-plugins/SixenseManager.cpp | 47 ++++++++--- .../src/input-plugins/SixenseManager.h | 19 ++--- libraries/plugins/src/plugins/Plugin.cpp | 2 + libraries/plugins/src/plugins/Plugin.h | 12 +++ .../plugins/src/plugins/PluginManager.cpp | 6 ++ libraries/plugins/src/plugins/PluginManager.h | 1 + libraries/shared/src/SettingHandle.cpp | 83 +++++++++++++++++++ libraries/shared/src/SettingHandle.h | 15 +++- 12 files changed, 168 insertions(+), 63 deletions(-) create mode 100644 libraries/shared/src/SettingHandle.cpp diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 70cc189ad6..5f61c6d978 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2351,6 +2351,7 @@ void Application::saveSettings() { Menu::getInstance()->saveSettings(); getMyAvatar()->saveData(); + PluginManager::getInstance()->saveSettings(); } bool Application::importEntities(const QString& urlOrFilename) { diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index f90bac234d..4ba248c76c 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -200,9 +200,6 @@ void PreferencesDialog::loadPreferences() { ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed()); - SixenseManager& sixense = SixenseManager::getInstance(); - ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons()); - // LOD items auto lodManager = DependencyManager::get(); ui.desktopMinimumFPSSpin->setValue(lodManager->getDesktopLODDecreaseFPS()); @@ -276,9 +273,7 @@ void PreferencesDialog::savePreferences() { qApp->getApplicationCompositor().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value()); - SixenseManager& sixense = SixenseManager::getInstance(); InputDevice::setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value()); - sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked()); auto audio = DependencyManager::get(); MixedProcessedAudioStream& stream = audio->getReceivedAudioStream(); diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index 53b71fb507..a1137a2bf2 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -2768,40 +2768,6 @@ - - - - 7 - - - 7 - - - - - - 0 - 40 - - - - - Arial - - - - Invert Mouse Buttons - - - - 0 - 0 - - - - - - diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index ea1639ec66..227bd12e1b 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -37,3 +37,9 @@ InputPluginList getInputPlugins() { } return result; } + +void saveInputPluginSettings(const InputPluginList& plugins) { + foreach (auto inputPlugin, plugins) { + inputPlugin->saveSettings(); + } +} diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index e900e8779e..bc64ec4ccc 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "NumericalConstants.h" @@ -38,7 +39,7 @@ const unsigned int RIGHT_MASK = 1U << 1; #ifdef HAVE_SIXENSE const int CALIBRATION_STATE_IDLE = 0; -const int CALIBRATION_STATE_X = 1; +const int CALIBRATION_STATE_IN_PROGRESS = 1; const int CALIBRATION_STATE_COMPLETE = 2; const glm::vec3 DEFAULT_AVATAR_POSITION(-0.25f, -0.35f, -0.3f); // in hydra frame @@ -56,25 +57,23 @@ typedef int (*SixenseTakeIntAndSixenseControllerData)(int, sixenseControllerData #endif const QString SixenseManager::NAME = "Sixense"; +const QString SixenseManager::HYDRA_ID_STRING = "Razer Hydra"; const QString MENU_PARENT = "Avatar"; const QString MENU_NAME = "Sixense"; const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME; const QString TOGGLE_SMOOTH = "Smooth Sixense Movement"; +const float DEFAULT_REACH_LENGTH = 1.5f; -SixenseManager& SixenseManager::getInstance() { - static SixenseManager sharedInstance; - return sharedInstance; -} SixenseManager::SixenseManager() : InputDevice("Hydra"), #ifdef __APPLE__ _sixenseLibrary(NULL), #endif + _reachLength(DEFAULT_REACH_LENGTH), _hydrasConnected(false) { - } bool SixenseManager::isSupported() const { @@ -92,7 +91,7 @@ void SixenseManager::activate() { CONTAINER->addMenu(MENU_PATH); CONTAINER->addMenuItem(MENU_PATH, TOGGLE_SMOOTH, - [this] (bool clicked) { this->setFilter(clicked); }, + [this] (bool clicked) { this->setSixenseFilter(clicked); }, true, true); #ifdef __APPLE__ @@ -120,6 +119,7 @@ void SixenseManager::activate() { SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit"); #endif + loadSettings(); sixenseInit(); #endif } @@ -144,7 +144,7 @@ void SixenseManager::deactivate() { #endif } -void SixenseManager::setFilter(bool filter) { +void SixenseManager::setSixenseFilter(bool filter) { #ifdef HAVE_SIXENSE #ifdef __APPLE__ SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled"); @@ -282,6 +282,7 @@ void SixenseManager::updateCalibration(void* controllersX) { glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft); glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y)); xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis)); + _reachLength = glm::dot(xAxis, _reachRight - _reachLeft); _avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis))); const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f; _avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR; @@ -317,7 +318,7 @@ void SixenseManager::updateCalibration(void* controllersX) { _lastDistance = reach; _lockExpiry = usecTimestampNow() + LOCK_DURATION; // move to next state - _calibrationState = CALIBRATION_STATE_X; + _calibrationState = CALIBRATION_STATE_IN_PROGRESS; } return; } @@ -327,7 +328,7 @@ void SixenseManager::updateCalibration(void* controllersX) { _averageLeft = 0.9f * _averageLeft + 0.1f * positionLeft; _averageRight = 0.9f * _averageRight + 0.1f * positionRight; - if (_calibrationState == CALIBRATION_STATE_X) { + if (_calibrationState == CALIBRATION_STATE_IN_PROGRESS) { // compute new sliding average float distance = glm::distance(_averageLeft, _averageRight); if (fabsf(distance - _lastDistance) > MAXIMUM_NOISE_LEVEL) { @@ -340,7 +341,6 @@ void SixenseManager::updateCalibration(void* controllersX) { // lock has expired so clamp the data and move on _lockExpiry = now + LOCK_DURATION; _lastDistance = 0.0f; - _reachUp = 0.5f * (_reachLeft + _reachRight); _calibrationState = CALIBRATION_STATE_COMPLETE; qCDebug(inputplugins, "success: sixense calibration: left"); } @@ -543,6 +543,31 @@ void SixenseManager::assignDefaultInputMapping(UserInputMapper& mapper) { } +// virtual +void SixenseManager::saveSettings() const { + Settings settings; + QString idString = getID(); + settings.beginGroup(idString); + { + settings.setVec3Value(QString("avatarPosition"), _avatarPosition); + settings.setQuatValue(QString("avatarRotation"), _avatarRotation); + settings.setValue(QString("reachLength"), QVariant(_reachLength)); + } + settings.endGroup(); +} + +void SixenseManager::loadSettings() { + Settings settings; + QString idString = getID(); + settings.beginGroup(idString); + { + settings.getVec3ValueIfValid(QString("avatarPosition"), _avatarPosition); + settings.getQuatValueIfValid(QString("avatarRotation"), _avatarRotation); + settings.getFloatValueIfValid(QString("reachLength"), _reachLength); + } + settings.endGroup(); +} + UserInputMapper::Input SixenseManager::makeInput(unsigned int button, int index) { return UserInputMapper::Input(_deviceID, button | (index == 0 ? LEFT_MASK : RIGHT_MASK), UserInputMapper::ChannelType::BUTTON); } diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 5e3815cd20..9fa7f84a86 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -58,12 +58,11 @@ public: SixenseManager(); - static SixenseManager& getInstance(); - // Plugin functions virtual bool isSupported() const override; virtual bool isJointController() const override { return true; } const QString& getName() const override { return NAME; } + const QString& getID() const override { return HYDRA_ID_STRING; } virtual void activate() override; virtual void deactivate() override; @@ -77,15 +76,15 @@ public: virtual void update(float deltaTime, bool jointsCaptured) override; virtual void focusOutEvent() override; - bool getInvertButtons() const { return _invertButtons; } - void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; } - UserInputMapper::Input makeInput(unsigned int button, int index); UserInputMapper::Input makeInput(JoystickAxisChannel axis, int index); UserInputMapper::Input makeInput(JointChannel joint); + virtual void saveSettings() const override; + virtual void loadSettings() override; + public slots: - void setFilter(bool filter); + void setSixenseFilter(bool filter); private: void handleButtonEvent(unsigned int buttons, int index); @@ -99,7 +98,7 @@ private: // these are calibration results glm::vec3 _avatarPosition; // in hydra-frame glm::quat _avatarRotation; // in hydra-frame - float _armLength; + float _reachLength; // these are measured values used to compute the calibration results quint64 _lockExpiry; @@ -107,9 +106,8 @@ private: glm::vec3 _averageRight; glm::vec3 _reachLeft; glm::vec3 _reachRight; - glm::vec3 _reachUp; - glm::vec3 _reachForward; float _lastDistance; + bool _useSixenseFilter = true; #ifdef __APPLE__ QLibrary* _sixenseLibrary; @@ -117,9 +115,8 @@ private: bool _hydrasConnected; - bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS; - static const QString NAME; + static const QString HYDRA_ID_STRING; }; #endif // hifi_SixenseManager_h diff --git a/libraries/plugins/src/plugins/Plugin.cpp b/libraries/plugins/src/plugins/Plugin.cpp index ffcc682ebd..2c0b9fa5cf 100644 --- a/libraries/plugins/src/plugins/Plugin.cpp +++ b/libraries/plugins/src/plugins/Plugin.cpp @@ -9,6 +9,8 @@ PluginContainer* Plugin::CONTAINER{ nullptr }; +QString Plugin::UNKNOWN_PLUGIN_ID("unknown"); + void Plugin::setContainer(PluginContainer* container) { CONTAINER = container; } diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h index eac355b47d..68e012b8e1 100644 --- a/libraries/plugins/src/plugins/Plugin.h +++ b/libraries/plugins/src/plugins/Plugin.h @@ -7,6 +7,8 @@ // #pragma once +#include + #include #include @@ -14,7 +16,12 @@ class Plugin : public QObject { public: + /// \return human-readable name virtual const QString& getName() const = 0; + + /// \return string ID (not necessarily human-readable) + virtual const QString& getID() const { assert(false); return UNKNOWN_PLUGIN_ID; } + virtual bool isSupported() const; static void setContainer(PluginContainer* container); @@ -37,6 +44,11 @@ public: */ virtual void idle(); + virtual void saveSettings() const {} + virtual void loadSettings() {} + protected: static PluginContainer* CONTAINER; + static QString UNKNOWN_PLUGIN_ID; + }; diff --git a/libraries/plugins/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp index 3a71700c9e..2deb41fb13 100644 --- a/libraries/plugins/src/plugins/PluginManager.cpp +++ b/libraries/plugins/src/plugins/PluginManager.cpp @@ -8,6 +8,8 @@ #include "PluginManager.h" #include +#include "Forward.h" + PluginManager* PluginManager::getInstance() { static PluginManager _manager; return &_manager; @@ -16,6 +18,7 @@ PluginManager* PluginManager::getInstance() { // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class extern DisplayPluginList getDisplayPlugins(); extern InputPluginList getInputPlugins(); +extern void saveInputPluginSettings(const InputPluginList& plugins); const DisplayPluginList& PluginManager::getDisplayPlugins() { static DisplayPluginList displayPlugins; @@ -35,3 +38,6 @@ const InputPluginList& PluginManager::getInputPlugins() { return inputPlugins; } +void PluginManager::saveSettings() { + saveInputPluginSettings(getInputPlugins()); +} diff --git a/libraries/plugins/src/plugins/PluginManager.h b/libraries/plugins/src/plugins/PluginManager.h index b7ec453814..09dcc9d107 100644 --- a/libraries/plugins/src/plugins/PluginManager.h +++ b/libraries/plugins/src/plugins/PluginManager.h @@ -15,4 +15,5 @@ public: const DisplayPluginList& getDisplayPlugins(); const InputPluginList& getInputPlugins(); + void saveSettings(); }; diff --git a/libraries/shared/src/SettingHandle.cpp b/libraries/shared/src/SettingHandle.cpp new file mode 100644 index 0000000000..19239b3cf7 --- /dev/null +++ b/libraries/shared/src/SettingHandle.cpp @@ -0,0 +1,83 @@ +// +// SettingHandle.h +// +// +// Created by AndrewMeadows 2015.10.05 +// 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 "SettingHandle.h" + +#include + + +void Settings::getFloatValueIfValid(const QString& name, float& f) { + const QVariant badDefaultValue = NAN; + bool ok = true; + float tempFloat = value(name, badDefaultValue).toFloat(&ok); + if (ok && !isnan(tempFloat)) { + f = tempFloat; + } +} + +void Settings::getBoolValue(const QString& name, bool& b) { + const QVariant defaultValue = false; + b = value(name, defaultValue).toBool(); +} + + +void Settings::setVec3Value(const QString& name, const glm::vec3& v) { + beginGroup(name); + { + setValue(QString("x"), v.x); + setValue(QString("y"), v.y); + setValue(QString("z"), v.z); + } + endGroup(); +} + +void Settings::getVec3ValueIfValid(const QString& name, glm::vec3& v) { + beginGroup(name); + { + bool ok = true; + const QVariant badDefaultValue = NAN; + float x = value(QString("x"), badDefaultValue).toFloat(&ok); + float y = value(QString("y"), badDefaultValue).toFloat(&ok); + float z = value(QString("z"), badDefaultValue).toFloat(&ok); + if (ok && (!isnan(x) && !isnan(y) && !isnan(z))) { + v = glm::vec3(x, y, z); + } + } + endGroup(); +} + +void Settings::setQuatValue(const QString& name, const glm::quat& q) { + beginGroup(name); + { + setValue(QString("x"), q.x); + setValue(QString("y"), q.y); + setValue(QString("z"), q.z); + setValue(QString("w"), q.w); + } + endGroup(); +} + +void Settings::getQuatValueIfValid(const QString& name, glm::quat& q) { + beginGroup(name); + { + bool ok = true; + const QVariant badDefaultValue = NAN; + float x = value(QString("x"), badDefaultValue).toFloat(&ok); + float y = value(QString("y"), badDefaultValue).toFloat(&ok); + float z = value(QString("z"), badDefaultValue).toFloat(&ok); + float w = value(QString("w"), badDefaultValue).toFloat(&ok); + if (ok && (!isnan(x) && !isnan(y) && !isnan(z) && !isnan(w))) { + q = glm::quat(w, x, y, z); + } + } + endGroup(); +} + diff --git a/libraries/shared/src/SettingHandle.h b/libraries/shared/src/SettingHandle.h index 761e41d321..b86422bcfb 100644 --- a/libraries/shared/src/SettingHandle.h +++ b/libraries/shared/src/SettingHandle.h @@ -18,11 +18,22 @@ #include #include +#include +#include + #include "SettingInterface.h" // TODO: remove class Settings : public QSettings { - +public: + void getFloatValueIfValid(const QString& name, float& f); + void getBoolValue(const QString& name, bool& b); + + void setVec3Value(const QString& name, const glm::vec3& v); + void getVec3ValueIfValid(const QString& name, glm::vec3& v); + + void setQuatValue(const QString& name, const glm::quat& q); + void getQuatValueIfValid(const QString& name, glm::quat& q); }; namespace Setting { @@ -65,4 +76,4 @@ namespace Setting { } } -#endif // hifi_SettingHandle_h \ No newline at end of file +#endif // hifi_SettingHandle_h From 464ef2293da0694216ce622b17b3c8cb354bd97d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 7 Oct 2015 10:52:47 -0700 Subject: [PATCH 05/34] more descriptive variable names --- libraries/shared/src/SettingHandle.cpp | 34 +++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/libraries/shared/src/SettingHandle.cpp b/libraries/shared/src/SettingHandle.cpp index 19239b3cf7..4a2c0cf04b 100644 --- a/libraries/shared/src/SettingHandle.cpp +++ b/libraries/shared/src/SettingHandle.cpp @@ -14,32 +14,32 @@ #include -void Settings::getFloatValueIfValid(const QString& name, float& f) { +void Settings::getFloatValueIfValid(const QString& name, float& floatValue) { const QVariant badDefaultValue = NAN; bool ok = true; float tempFloat = value(name, badDefaultValue).toFloat(&ok); if (ok && !isnan(tempFloat)) { - f = tempFloat; + floatValue = tempFloat; } } -void Settings::getBoolValue(const QString& name, bool& b) { +void Settings::getBoolValue(const QString& name, bool& boolValue) { const QVariant defaultValue = false; - b = value(name, defaultValue).toBool(); + boolValue = value(name, defaultValue).toBool(); } -void Settings::setVec3Value(const QString& name, const glm::vec3& v) { +void Settings::setVec3Value(const QString& name, const glm::vec3& vecValue) { beginGroup(name); { - setValue(QString("x"), v.x); - setValue(QString("y"), v.y); - setValue(QString("z"), v.z); + setValue(QString("x"), vecValue.x); + setValue(QString("y"), vecValue.y); + setValue(QString("z"), vecValue.z); } endGroup(); } -void Settings::getVec3ValueIfValid(const QString& name, glm::vec3& v) { +void Settings::getVec3ValueIfValid(const QString& name, glm::vec3& vecValue) { beginGroup(name); { bool ok = true; @@ -48,24 +48,24 @@ void Settings::getVec3ValueIfValid(const QString& name, glm::vec3& v) { float y = value(QString("y"), badDefaultValue).toFloat(&ok); float z = value(QString("z"), badDefaultValue).toFloat(&ok); if (ok && (!isnan(x) && !isnan(y) && !isnan(z))) { - v = glm::vec3(x, y, z); + vecValue = glm::vec3(x, y, z); } } endGroup(); } -void Settings::setQuatValue(const QString& name, const glm::quat& q) { +void Settings::setQuatValue(const QString& name, const glm::quat& quatValue) { beginGroup(name); { - setValue(QString("x"), q.x); - setValue(QString("y"), q.y); - setValue(QString("z"), q.z); - setValue(QString("w"), q.w); + setValue(QString("x"), quatValue.x); + setValue(QString("y"), quatValue.y); + setValue(QString("z"), quatValue.z); + setValue(QString("w"), quatValue.w); } endGroup(); } -void Settings::getQuatValueIfValid(const QString& name, glm::quat& q) { +void Settings::getQuatValueIfValid(const QString& name, glm::quat& quatValue) { beginGroup(name); { bool ok = true; @@ -75,7 +75,7 @@ void Settings::getQuatValueIfValid(const QString& name, glm::quat& q) { float z = value(QString("z"), badDefaultValue).toFloat(&ok); float w = value(QString("w"), badDefaultValue).toFloat(&ok); if (ok && (!isnan(x) && !isnan(y) && !isnan(z) && !isnan(w))) { - q = glm::quat(w, x, y, z); + quatValue = glm::quat(w, x, y, z); } } endGroup(); From bfd014203e796d807c32b1b1403d739456dd6b1c Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 7 Oct 2015 14:48:42 -0700 Subject: [PATCH 06/34] fix a bunch of warnings --- interface/src/Application.cpp | 18 ------------------ interface/src/Application.h | 1 - .../entities/src/AnimationPropertyGroup.cpp | 2 ++ .../entities/src/AtmospherePropertyGroup.cpp | 2 ++ libraries/entities/src/SkyboxPropertyGroup.cpp | 2 ++ libraries/entities/src/StagePropertyGroup.cpp | 2 ++ libraries/networking/src/udt/PacketQueue.cpp | 2 +- 7 files changed, 9 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 70cc189ad6..e64d4a9bd5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4750,24 +4750,6 @@ mat4 Application::getEyeProjection(int eye) const { return _viewFrustum.getProjection(); } -mat4 Application::getEyePose(int eye) const { - if (isHMDMode()) { - auto hmdInterface = DependencyManager::get(); - float IPDScale = hmdInterface->getIPDScale(); - auto displayPlugin = getActiveDisplayPlugin(); - mat4 headPose = displayPlugin->getHeadPose(); - mat4 eyeToHead = displayPlugin->getEyeToHeadTransform((Eye)eye); - { - vec3 eyeOffset = glm::vec3(eyeToHead[3]); - // Apply IPD scaling - mat4 eyeOffsetTransform = glm::translate(mat4(), eyeOffset * -1.0f * IPDScale); - eyeToHead[3] = vec4(eyeOffset, 1.0); - } - return eyeToHead * headPose; - } - return mat4(); -} - mat4 Application::getEyeOffset(int eye) const { // FIXME invert? return getActiveDisplayPlugin()->getEyeToHeadTransform((Eye)eye); diff --git a/interface/src/Application.h b/interface/src/Application.h index ec5133b131..0b75a94232 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -198,7 +198,6 @@ public: // TODO: carry that information on the Camera as a setting bool isHMDMode() const; glm::mat4 getHMDSensorPose() const; - glm::mat4 getEyePose(int eye) const; glm::mat4 getEyeOffset(int eye) const; glm::mat4 getEyeProjection(int eye) const; diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index 3c22707869..48cedfbf5d 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -249,6 +249,8 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF processedBytes += bytesRead; + Q_UNUSED(somethingChanged); + return true; } diff --git a/libraries/entities/src/AtmospherePropertyGroup.cpp b/libraries/entities/src/AtmospherePropertyGroup.cpp index e24dc5791b..0f0e68ce72 100644 --- a/libraries/entities/src/AtmospherePropertyGroup.cpp +++ b/libraries/entities/src/AtmospherePropertyGroup.cpp @@ -108,6 +108,8 @@ bool AtmospherePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& property processedBytes += bytesRead; + Q_UNUSED(somethingChanged); + return true; } diff --git a/libraries/entities/src/SkyboxPropertyGroup.cpp b/libraries/entities/src/SkyboxPropertyGroup.cpp index d3ed82274a..b79b535d8e 100644 --- a/libraries/entities/src/SkyboxPropertyGroup.cpp +++ b/libraries/entities/src/SkyboxPropertyGroup.cpp @@ -66,6 +66,8 @@ bool SkyboxPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlag processedBytes += bytesRead; + Q_UNUSED(somethingChanged); + return true; } diff --git a/libraries/entities/src/StagePropertyGroup.cpp b/libraries/entities/src/StagePropertyGroup.cpp index bab68c7a4b..7110f0481d 100644 --- a/libraries/entities/src/StagePropertyGroup.cpp +++ b/libraries/entities/src/StagePropertyGroup.cpp @@ -121,6 +121,8 @@ bool StagePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags processedBytes += bytesRead; + Q_UNUSED(somethingChanged); + return true; } diff --git a/libraries/networking/src/udt/PacketQueue.cpp b/libraries/networking/src/udt/PacketQueue.cpp index 1c104e1427..bc3a1796e2 100644 --- a/libraries/networking/src/udt/PacketQueue.cpp +++ b/libraries/networking/src/udt/PacketQueue.cpp @@ -55,7 +55,7 @@ PacketQueue::PacketPointer PacketQueue::takePacket() { } unsigned int PacketQueue::nextIndex() { - _currentIndex = (++_currentIndex) % _channels.size(); + _currentIndex = (_currentIndex + 1) % _channels.size(); return _currentIndex; } From 946d289a992f042c05ed5c32695cb6d45015df72 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 5 Oct 2015 13:05:43 -0700 Subject: [PATCH 07/34] Display name have a arc size instead of pixel size --- interface/src/avatar/Avatar.cpp | 159 +++++++++++--------------------- interface/src/avatar/Avatar.h | 4 +- 2 files changed, 58 insertions(+), 105 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ddee5dfc1f..538d9fb4eb 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -549,7 +549,12 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { auto cameraMode = qApp->getCamera()->getMode(); if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) { - renderDisplayName(batch, *renderArgs->_viewFrustum, renderArgs->_viewport); + auto& frustum = *renderArgs->_viewFrustum; + auto textPosition = getDisplayNamePosition(); + + if (frustum.pointInFrustum(textPosition)) { + renderDisplayName(batch, frustum, textPosition); + } } endRender(); } @@ -716,85 +721,29 @@ glm::vec3 Avatar::getDisplayNamePosition() const { return namePosition; } -Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize, const glm::ivec4& viewport) const { - Transform result; - // We assume textPosition is whithin the frustum - glm::vec3 textPosition = getDisplayNamePosition(); - - // Compute viewProjection matrix - glm::mat4 projMat, viewMat; - Transform view; - frustum.evalProjectionMatrix(projMat); - frustum.evalViewTransform(view); - glm::mat4 viewProj = projMat * view.getInverseMatrix(viewMat); - - // Used to determine correct scale - glm::vec3 testPoint0 = textPosition; - glm::vec3 testPoint1 = testPoint0 + glm::normalize(frustum.getUp()); - // testPoints projections - glm::vec4 p0 = viewProj * glm::vec4(testPoint0, 1.0); - glm::vec4 p1 = viewProj * glm::vec4(testPoint1, 1.0); - - float windowSizeY = viewport.w; - - const float DESIRED_HIGHT_ON_SCREEN = 20; // In pixels (this is double on retinas) - - // Projected point are between -1.0f and 1.0f, hence 0.5f * windowSizeY - float pixelHeight = 0.5f * windowSizeY * glm::abs((p1.y / p1.w) - (p0.y / p0.w)); // - // Handles pixel density (especially for macs retina displays) - float devicePixelRatio = (float)qApp->getDevicePixelRatio() * qApp->getRenderResolutionScale(); // pixels / unit - - // Compute correct scale to apply - float scale = DESIRED_HIGHT_ON_SCREEN / (fontSize * pixelHeight) * devicePixelRatio; -#ifdef DEBUG - // TODO: Temporary logging to track cause of invalid scale value; remove once cause has been fixed. - // Problem is probably due to an invalid getDisplayNamePosition(). See extra logging above. - if (scale == 0.0f || glm::isnan(scale) || glm::isinf(scale)) { - if (scale == 0.0f) { - qDebug() << "ASSERT because scale == 0.0f"; - } - if (glm::isnan(scale)) { - qDebug() << "ASSERT because isnan(scale)"; - } - if (glm::isinf(scale)) { - qDebug() << "ASSERT because isinf(scale)"; - } - qDebug() << "textPosition =" << textPosition; - qDebug() << "projMat =" << projMat; - qDebug() << "viewMat =" << viewMat; - qDebug() << "viewProj =" << viewProj; - qDebug() << "windowSizeY =" << windowSizeY; - qDebug() << "p1 =" << p1; - qDebug() << "p0 =" << p0; - qDebug() << "qApp->getDevicePixelRatio() =" << qApp->getDevicePixelRatio(); - qDebug() << "fontSize =" << fontSize; - qDebug() << "pixelHeight =" << pixelHeight; - qDebug() << "devicePixelRatio =" << devicePixelRatio; - } -#endif - - // Compute pixel alignment offset - float clipToPix = 0.5f * windowSizeY / p1.w; // Got from clip to pixel coordinates - glm::vec4 screenPos = clipToPix * p1; // in pixels coords - glm::vec4 screenOffset = (glm::round(screenPos) - screenPos) / clipToPix; // in clip coords - glm::vec3 worldOffset = glm::vec3(screenOffset.x, screenOffset.y, 0.0f) / (float)pixelHeight; +Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const { + Q_ASSERT_X(frustum.pointInFrustum(textPosition), "Avatar::calculateDisplayNameTransform", + "Text not in viewfrustum."); + glm::vec3 dPosition = frustum.getPosition() - textPosition; // Compute orientation - glm::vec3 dPosition = frustum.getPosition() - getPosition(); - // If x and z are 0, atan(x, z) is undefined, so default to 0 degrees - float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z); + // If x and z are 0, atan(x, z) adais undefined, so default to 0 degrees + const float yawRotation = (dPosition.x == 0.0f && dPosition.z == 0.0f) ? 0.0f : glm::atan(dPosition.x, dPosition.z); glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); - // Set transform (The order IS important) + // Compute correct scale to apply + static const float DESIRED_HIGHT_RAD = glm::radians(2.0f); + float scale = glm::length(dPosition) * glm::tan(DESIRED_HIGHT_RAD); + + // Set transform + Transform result; result.setTranslation(textPosition); result.setRotation(orientation); // Always face the screen - result.postTranslate(worldOffset); // Pixel alignment result.setScale(scale); return result; - } -void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::ivec4& viewport) const { +void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::vec3& textPosition) const { bool shouldShowReceiveStats = DependencyManager::get()->shouldShowReceiveStats() && !isMyAvatar(); // If we have nothing to draw, or it's totally transparent, or it's too close or behind the camera, return @@ -818,39 +767,43 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co } // Compute display name extent/position offset - glm::vec2 extent = renderer->computeExtent(renderedDisplayName); - QRect nameDynamicRect = QRect(0, 0, (int)extent.x, (int)extent.y); - const int text_x = -nameDynamicRect.width() / 2; - const int text_y = -nameDynamicRect.height() / 2; - - // Compute background position/size - static const float SLIGHTLY_IN_FRONT = 0.1f; - const int border = 0.1f * nameDynamicRect.height(); - const int left = text_x - border; - const int bottom = text_y - border; - const int width = nameDynamicRect.width() + 2.0f * border; - const int height = nameDynamicRect.height() + 2.0f * border; - const int bevelDistance = 0.1f * height; - - // Display name and background colors - glm::vec4 textColor(0.93f, 0.93f, 0.93f, _displayNameAlpha); - glm::vec4 backgroundColor(0.2f, 0.2f, 0.2f, - (_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA); - - // Compute display name transform - auto textTransform = calculateDisplayNameTransform(frustum, renderer->getFontSize(), viewport); - batch.setModelTransform(textTransform); - - DependencyManager::get()->bindSimpleProgram(batch, false, true, true, true); - DependencyManager::get()->renderBevelCornersRect(batch, left, bottom, width, height, - bevelDistance, backgroundColor); - // Render actual name - QByteArray nameUTF8 = renderedDisplayName.toLocal8Bit(); - - // Render text slightly in front to avoid z-fighting - textTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_IN_FRONT * renderer->getFontSize())); - batch.setModelTransform(textTransform); - renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor); + const glm::vec2 extent = renderer->computeExtent(renderedDisplayName); + if (!glm::any(glm::isCompNull(extent, EPSILON))) { + const QRect nameDynamicRect = QRect(0, 0, (int)extent.x, (int)extent.y); + const int text_x = -nameDynamicRect.width() / 2; + const int text_y = -nameDynamicRect.height() / 2; + + // Compute background position/size + static const float SLIGHTLY_IN_FRONT = 0.1f; + const int border = 0.1f * nameDynamicRect.height(); + const int left = text_x - border; + const int bottom = text_y - border; + const int width = nameDynamicRect.width() + 2.0f * border; + const int height = nameDynamicRect.height() + 2.0f * border; + const int bevelDistance = 0.1f * height; + + // Display name and background colors + glm::vec4 textColor(0.93f, 0.93f, 0.93f, _displayNameAlpha); + glm::vec4 backgroundColor(0.2f, 0.2f, 0.2f, + (_displayNameAlpha / DISPLAYNAME_ALPHA) * DISPLAYNAME_BACKGROUND_ALPHA); + + // Compute display name transform + auto textTransform = calculateDisplayNameTransform(frustum, textPosition); + // Test on extent above insures abs(height) > 0.0f + textTransform.postScale(1.0f / height); + batch.setModelTransform(textTransform); + + DependencyManager::get()->bindSimpleProgram(batch, false, true, true, true); + DependencyManager::get()->renderBevelCornersRect(batch, left, bottom, width, height, + bevelDistance, backgroundColor); + // Render actual name + QByteArray nameUTF8 = renderedDisplayName.toLocal8Bit(); + + // Render text slightly in front to avoid z-fighting + textTransform.postTranslate(glm::vec3(0.0f, 0.0f, SLIGHTLY_IN_FRONT * renderer->getFontSize())); + batch.setModelTransform(textTransform); + renderer->draw(batch, text_x, -text_y, nameUTF8.data(), textColor); + } } void Avatar::setSkeletonOffset(const glm::vec3& offset) { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 1800f4fdd1..534aefd3cb 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -217,8 +217,8 @@ protected: float getPelvisFloatingHeight() const; glm::vec3 getDisplayNamePosition() const; - Transform calculateDisplayNameTransform(const ViewFrustum& frustum, float fontSize, const glm::ivec4& viewport) const; - void renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::ivec4& viewport) const; + Transform calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const; + void renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, const glm::vec3& textPosition) const; virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f); virtual bool shouldRenderHead(const RenderArgs* renderArgs) const; virtual void fixupModelsInScene(); From 91b46203f3b039c9d8f59d0ecfb42303e9f66581 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 5 Oct 2015 13:56:58 -0700 Subject: [PATCH 08/34] Don't take keyhole into account --- interface/src/avatar/Avatar.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 538d9fb4eb..5b13d6991f 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -552,7 +552,13 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { auto& frustum = *renderArgs->_viewFrustum; auto textPosition = getDisplayNamePosition(); - if (frustum.pointInFrustum(textPosition)) { + // In the view frustum + auto keyhole = frustum.getKeyholeRadius(); + frustum.setKeyholeRadius(-1.0f); + auto inFrustum = frustum.pointInFrustum(textPosition) == ViewFrustum::INSIDE; + frustum.setKeyholeRadius(keyhole); + + if (inFrustum) { renderDisplayName(batch, frustum, textPosition); } } @@ -722,8 +728,8 @@ glm::vec3 Avatar::getDisplayNamePosition() const { } Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const { - Q_ASSERT_X(frustum.pointInFrustum(textPosition), "Avatar::calculateDisplayNameTransform", - "Text not in viewfrustum."); + Q_ASSERT_X(frustum.pointInFrustum(textPosition) == ViewFrustum::INSIDE, + "Avatar::calculateDisplayNameTransform", "Text not in viewfrustum."); glm::vec3 dPosition = frustum.getPosition() - textPosition; // Compute orientation From 79b280f73337389c5321aeaaf68917a90f4c6289 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 5 Oct 2015 14:27:04 -0700 Subject: [PATCH 09/34] Update getDisplayNamePosition debug --- interface/src/avatar/Avatar.cpp | 55 +++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 5b13d6991f..4ee9a1bbb8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -696,34 +696,51 @@ void Avatar::renderBillboard(RenderArgs* renderArgs) { } float Avatar::getBillboardSize() const { - return _scale * BILLBOARD_DISTANCE * tanf(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f)); + return _scale * BILLBOARD_DISTANCE * glm::tan(glm::radians(BILLBOARD_FIELD_OF_VIEW / 2.0f)); } +#ifdef DEBUG +void debugValue(const QString& str, const glm::vec3& value) { + if (glm::any(glm::isnan(value)) || glm::any(glm::isinf(value))) { + qCWarning(interfaceapp) << "debugValue() " << str << value; + } +}; +void debugValue(const QString& str, const float& value) { + if (glm::isnan(value) || glm::isinf(value)) { + qCWarning(interfaceapp) << "debugValue() " << str << value; + } +}; +#define DEBUG_VALUE(str, value) debugValue(str, value) +#else +#define DEBUG_VALUE(str, value) +#endif + glm::vec3 Avatar::getDisplayNamePosition() const { glm::vec3 namePosition(0.0f); + glm::vec3 bodyUpDirection = getBodyUpDirection(); + DEBUG_VALUE("bodyUpDirection =", bodyUpDirection); + if (getSkeletonModel().getNeckPosition(namePosition)) { - namePosition += getBodyUpDirection() * getHeadHeight() * 1.1f; + float headHeight = getHeadHeight(); + DEBUG_VALUE("namePosition =", namePosition); + DEBUG_VALUE("headHeight =", headHeight); + + namePosition += bodyUpDirection * headHeight * 1.1f; } else { const float HEAD_PROPORTION = 0.75f; - namePosition = _position + getBodyUpDirection() * (getBillboardSize() * HEAD_PROPORTION); + float billboardSize = getBillboardSize(); + + DEBUG_VALUE("_position =", _position); + DEBUG_VALUE("billboardSize =", billboardSize); + namePosition = _position + bodyUpDirection * (billboardSize * HEAD_PROPORTION); } -#ifdef DEBUG - // TODO: Temporary logging to track cause of invalid scale value; remove once cause has been fixed. - // See other TODO below. - if (glm::isnan(namePosition.x) || glm::isnan(namePosition.y) || glm::isnan(namePosition.z) - || glm::isinf(namePosition.x) || glm::isinf(namePosition.y) || glm::isinf(namePosition.z)) { - qDebug() << "namePosition =" << namePosition; - glm::vec3 tempPosition(0.0f); - if (getSkeletonModel().getNeckPosition(tempPosition)) { - qDebug() << "getBodyUpDirection() =" << getBodyUpDirection(); - qDebug() << "getHeadHeight() =" << getHeadHeight(); - } else { - qDebug() << "_position =" << _position; - qDebug() << "getBodyUpDirection() =" << getBodyUpDirection(); - qDebug() << "getBillboardSize() =" << getBillboardSize(); - } + + if (glm::any(glm::isnan(namePosition)) || glm::any(glm::isinf(namePosition))) { + qCWarning(interfaceapp) << "Invalid display name position" << namePosition + << ", setting is to (0.0f, 0.5f, 0.0f)"; + namePosition = glm::vec3(0.0f, 0.5f, 0.0f); } -#endif + return namePosition; } From fd6f0213ef1a6801b6727c6318adbd2544251c02 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 6 Oct 2015 17:23:54 -0700 Subject: [PATCH 10/34] CR --- interface/src/avatar/Avatar.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 4ee9a1bbb8..ad714fefc8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -725,7 +725,8 @@ glm::vec3 Avatar::getDisplayNamePosition() const { DEBUG_VALUE("namePosition =", namePosition); DEBUG_VALUE("headHeight =", headHeight); - namePosition += bodyUpDirection * headHeight * 1.1f; + static const float SLIGHTLY_ABOVE = 1.1f; + namePosition += bodyUpDirection * headHeight * SLIGHTLY_ABOVE; } else { const float HEAD_PROPORTION = 0.75f; float billboardSize = getBillboardSize(); @@ -747,16 +748,16 @@ glm::vec3 Avatar::getDisplayNamePosition() const { Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const { Q_ASSERT_X(frustum.pointInFrustum(textPosition) == ViewFrustum::INSIDE, "Avatar::calculateDisplayNameTransform", "Text not in viewfrustum."); - glm::vec3 dPosition = frustum.getPosition() - textPosition; + glm::vec3 toFrustum = frustum.getPosition() - textPosition; // Compute orientation // If x and z are 0, atan(x, z) adais undefined, so default to 0 degrees - const float yawRotation = (dPosition.x == 0.0f && dPosition.z == 0.0f) ? 0.0f : glm::atan(dPosition.x, dPosition.z); + const float yawRotation = (toFrustum.x == 0.0f && toFrustum.z == 0.0f) ? 0.0f : glm::atan(toFrustum.x, toFrustum.z); glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); // Compute correct scale to apply - static const float DESIRED_HIGHT_RAD = glm::radians(2.0f); - float scale = glm::length(dPosition) * glm::tan(DESIRED_HIGHT_RAD); + static const float DESIRED_HEIGHT_RAD = glm::radians(2.0f); + float scale = glm::length(toFrustum) * glm::tan(DESIRED_HEIGHT_RAD); // Set transform Transform result; @@ -770,7 +771,7 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co bool shouldShowReceiveStats = DependencyManager::get()->shouldShowReceiveStats() && !isMyAvatar(); // If we have nothing to draw, or it's totally transparent, or it's too close or behind the camera, return - const float CLIP_DISTANCE = 0.2f; + static const float CLIP_DISTANCE = 0.2f; if ((_displayName.isEmpty() && !shouldShowReceiveStats) || _displayNameAlpha == 0.0f || (glm::dot(frustum.getDirection(), getDisplayNamePosition() - frustum.getPosition()) <= CLIP_DISTANCE)) { return; @@ -798,12 +799,14 @@ void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& frustum, co // Compute background position/size static const float SLIGHTLY_IN_FRONT = 0.1f; - const int border = 0.1f * nameDynamicRect.height(); + static const float BORDER_RELATIVE_SIZE = 0.1f; + static const float BEVEL_FACTOR = 0.1f; + const int border = BORDER_RELATIVE_SIZE * nameDynamicRect.height(); const int left = text_x - border; const int bottom = text_y - border; const int width = nameDynamicRect.width() + 2.0f * border; const int height = nameDynamicRect.height() + 2.0f * border; - const int bevelDistance = 0.1f * height; + const int bevelDistance = BEVEL_FACTOR * height; // Display name and background colors glm::vec4 textColor(0.93f, 0.93f, 0.93f, _displayNameAlpha); From 14a18606709edd4e74116fbc68deab74f7236ca4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 6 Oct 2015 18:08:30 -0700 Subject: [PATCH 11/34] Do not change keyhole radius --- interface/src/avatar/Avatar.cpp | 10 ++-------- libraries/octree/src/ViewFrustum.cpp | 13 +++++++------ libraries/octree/src/ViewFrustum.h | 2 +- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ad714fefc8..ac55f6de83 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -552,13 +552,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { auto& frustum = *renderArgs->_viewFrustum; auto textPosition = getDisplayNamePosition(); - // In the view frustum - auto keyhole = frustum.getKeyholeRadius(); - frustum.setKeyholeRadius(-1.0f); - auto inFrustum = frustum.pointInFrustum(textPosition) == ViewFrustum::INSIDE; - frustum.setKeyholeRadius(keyhole); - - if (inFrustum) { + if (frustum.pointInFrustum(textPosition, true) == ViewFrustum::INSIDE) { renderDisplayName(batch, frustum, textPosition); } } @@ -746,7 +740,7 @@ glm::vec3 Avatar::getDisplayNamePosition() const { } Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const { - Q_ASSERT_X(frustum.pointInFrustum(textPosition) == ViewFrustum::INSIDE, + Q_ASSERT_X(frustum.pointInFrustum(textPosition, true) == ViewFrustum::INSIDE, "Avatar::calculateDisplayNameTransform", "Text not in viewfrustum."); glm::vec3 toFrustum = frustum.getPosition() - textPosition; diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 820ab32b67..fd175a8e5b 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -241,20 +241,21 @@ ViewFrustum::location ViewFrustum::boxInKeyhole(const AABox& box) const { return result; } -ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const { +ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point, bool ignoreKeyhole) const { ViewFrustum::location regularResult = INSIDE; ViewFrustum::location keyholeResult = OUTSIDE; // If we have a keyholeRadius, check that first, since it's cheaper - if (_keyholeRadius >= 0.0f) { + if (!ignoreKeyhole && _keyholeRadius >= 0.0f) { keyholeResult = pointInKeyhole(point); - } - if (keyholeResult == INSIDE) { - return keyholeResult; + + if (keyholeResult == INSIDE) { + return keyholeResult; + } } // If we're not known to be INSIDE the keyhole, then check the regular frustum - for(int i=0; i < 6; i++) { + for(int i = 0; i < 6; ++i) { float distance = _planes[i].distance(point); if (distance < 0) { return keyholeResult; // escape early will be the value from checking the keyhole diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index fe40cfd53c..596d042506 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -79,7 +79,7 @@ public: typedef enum {OUTSIDE, INTERSECT, INSIDE} location; - ViewFrustum::location pointInFrustum(const glm::vec3& point) const; + ViewFrustum::location pointInFrustum(const glm::vec3& point, bool ignoreKeyhole = false) const; ViewFrustum::location sphereInFrustum(const glm::vec3& center, float radius) const; ViewFrustum::location cubeInFrustum(const AACube& cube) const; ViewFrustum::location boxInFrustum(const AABox& box) const; From efeeaa7ea7a2dc147d0cba11d92cafc733e2d972 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 7 Oct 2015 15:14:06 -0700 Subject: [PATCH 12/34] Make display names 25% smaller --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ac55f6de83..0511e5d871 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -750,7 +750,7 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, cons glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f)); // Compute correct scale to apply - static const float DESIRED_HEIGHT_RAD = glm::radians(2.0f); + static const float DESIRED_HEIGHT_RAD = glm::radians(1.5f); float scale = glm::length(toFrustum) * glm::tan(DESIRED_HEIGHT_RAD); // Set transform From 3465e3cc133e2799c5f40dbfe32a03951d1c4b29 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 15:21:24 -0700 Subject: [PATCH 13/34] Adding hidden reset switch to room which, when grabbed or clicked on, will reset room --- unpublishedScripts/hiddenEntityReset.js | 50 + unpublishedScripts/immediateClientReset.js | 8 + unpublishedScripts/masterReset.js | 2143 ++++++++++---------- 3 files changed, 1155 insertions(+), 1046 deletions(-) create mode 100644 unpublishedScripts/hiddenEntityReset.js create mode 100644 unpublishedScripts/immediateClientReset.js diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js new file mode 100644 index 0000000000..0770f561cf --- /dev/null +++ b/unpublishedScripts/hiddenEntityReset.js @@ -0,0 +1,50 @@ +// +// ResetSwitch.js +// +// Created by Eric Levin on 10/2/15. +// 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 +// + + +(function () { + + var _this; + + var masterResetScript = Script.resolvePath("masterReset.js"); + Script.include(masterResetScript); + + ResetSwitch = function () { + _this = this; + }; + + ResetSwitch.prototype = { + + clickReleaseOnEntity: function (entityId, mouseEvent) { + if (!mouseEvent.isLeftButton) { + return; + } + this.triggerReset(); + + }, + + startNearGrabNonColliding: function () { + this.triggerReset(); + }, + + triggerReset: function () { + MasterReset(); + }, + + preload: function (entityID) { + this.entityID = entityID; + } + + }; + + // entity scripts always need to return a newly constructed object of our type + return new ResetSwitch(); +}) \ No newline at end of file diff --git a/unpublishedScripts/immediateClientReset.js b/unpublishedScripts/immediateClientReset.js new file mode 100644 index 0000000000..3748f06bf5 --- /dev/null +++ b/unpublishedScripts/immediateClientReset.js @@ -0,0 +1,8 @@ +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ + +/*global MasterReset */ + +var masterResetScript = Script.resolvePath("masterReset.js"); +Script.include(masterResetScript); + +MasterReset(); \ No newline at end of file diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 4815439091..477bd76985 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -9,1111 +9,1162 @@ /*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ //per script + /*global deleteAllToys, createAllToys, createGates, createPingPongBallGun, createFire, createPottedPlant, createCombinedArmChair, createBasketballHoop, createBasketBall, createSprayCan, createDoll, createWand, createDice, createCat, deleteAllToys, createFlashlight, createBlocks, createMagballs, createLights */ var utilitiesScript = Script.resolvePath("../examples/libraries/utils.js"); Script.include(utilitiesScript); -var resetKey = "resetMe"; -var GRABBABLE_DATA_KEY = "grabbableKey"; +var hiddenEntityScriptURL = Script.resolvePath("hiddenEntityReset.js"); +var sprayPaintScriptURL = Script.resolvePath("../examples/toys/sprayPaintCan.js"); +var catScriptURL = Script.resolvePath("../examples/toys/cat.js"); +var flashlightScriptURL = Script.resolvePath('../examples/toys/flashlight/flashlight.js'); +var pingPongScriptURL = Script.resolvePath('../examples/toys/ping_pong_gun/pingPongGun.js'); +var wandScriptURL = Script.resolvePath("../examples/toys/bubblewand/wand.js"); +var dollScriptURL = Script.resolvePath("../examples/toys/doll/doll.js"); +var lightsScriptURL = Script.resolvePath("../examples/toys/lightSwitch.js"); -var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -var shouldDeleteOnEndScript = false; +MasterReset = function () { -//Before creating anything, first search a radius and delete all the things that should be deleted -deleteAllToys(); -createAllToys(); + var resetKey = "resetMe"; + var GRABBABLE_DATA_KEY = "grabbableKey"; -function createAllToys() { - createBlocks({ - x: 548.3, - y: 495.55, - z: 504.4 - }); + var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; - createSprayCan({ - x: 549.7, - y: 495.6, - z: 503.91 - }); + var shouldDeleteOnEndScript = false; - createBasketBall({ - x: 547.73, - y: 495.5, - z: 505.47 - }); + //Before creating anything, first search a radius and delete all the things that should be deleted + deleteAllToys(); + createAllToys(); - createDoll({ - x: 546.67, - y: 495.41, - z: 505.09 - }); + function createAllToys() { + createBlocks({ + x: 548.3, + y: 495.55, + z: 504.4 + }); - createWand({ - x: 546.71, - y: 495.55, - z: 506.15 - }); + createBasketBall({ + x: 547.73, + y: 495.5, + z: 505.47 + }); - createDice(); + createDoll({ + x: 546.67, + y: 495.41, + z: 505.09 + }); - createFlashlight({ - x: 545.72, - y: 495.41, - z: 505.78 - }); + createWand({ + x: 546.71, + y: 495.55, + z: 506.15 + }); - createCat({ - x: 551.09, - y: 494.98, - z: 503.49 - }); + createDice(); + createFlashlight({ + x: 545.72, + y: 495.41, + z: 505.78 + }); - createCombinedArmChair({ - x: 549.29, - y: 494.9, - z: 508.22 - }); - createPottedPlant({ - x: 554.26, - y: 495.2, - z: 504.53 - }); - createPingPongBallGun(); + createCombinedArmChair({ + x: 549.29, + y: 494.9, + z: 508.22 + }); - createBasketballHoop(); + createPottedPlant({ + x: 554.26, + y: 495.2, + z: 504.53 + }); - createBasketballRack(); + createPingPongBallGun(); - createGates(); + createBasketballHoop(); + createBasketballRack(); - createFire(); - // Handles toggling of all sconce lights - createLights(); + createGates(); -} + createFire(); + // Handles toggling of all sconce lights + createLights(); -function deleteAllToys() { - var entities = Entities.findEntities(MyAvatar.position, 100); - entities.forEach(function(entity) { - //params: customKey, id, defaultValue - var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe; - if (shouldReset === true) { - Entities.deleteEntity(entity); - } - }); -} -function createLights() { - var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx"; + createCat({ + x: 551.09, + y: 494.98, + z: 503.49 + }); - var scriptURL = Script.resolvePath("../examples/toys/lightSwitch.js"); - var rotation = { - w: 0.63280689716339111, - x: 0.63280689716339111, - y: -0.31551080942153931, - z: 0.31548023223876953 - }; - var axis = { - x: 0, - y: 1, - z: 0 - }; - var dQ = Quat.angleAxis(180, axis); - rotation = Quat.multiply(rotation, dQ); + createSprayCan({ + x: 549.7, + y: 495.6, + z: 503.91 + }); + createHiddenMasterSwitch(); - var lightSwitchHall = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "Light Switch Hall", - script: scriptURL, - position: { - x: 543.27764892578125, - y: 495.67999267578125, - z: 511.00564575195312 - }, - rotation: rotation, - dimensions: { - x: 0.10546875, - y: 0.032372996211051941, - z: 0.16242524981498718 - } - }); - setEntityCustomData(resetKey, lightSwitchHall, { - resetMe: true, - on: true, - type: "Hall Light" - }); - - var sconceLight1 = Entities.addEntity({ - type: "Light", - position: { - x: 543.75, - y: 496.24, - z: 511.13 - }, - name: "Sconce 1 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - setEntityCustomData(resetKey, sconceLight1, { - resetMe: true, - type: "Hall Light", - }); - - var sconceLight2 = Entities.addEntity({ - type: "Light", - position: { - x: 540.1, - y: 496.24, - z: 505.57 - }, - name: "Sconce 2 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - setEntityCustomData(resetKey, sconceLight2, { - resetMe: true, - type: "Hall Light", - }); - - - rotation = { - w: 0.20082402229309082, - x: 0.20082402229309082, - y: -0.67800414562225342, - z: 0.67797362804412842 - }; - axis = { - x: 0, - y: 1, - z: 0 - }; - dQ = Quat.angleAxis(180, axis); - rotation = Quat.multiply(rotation, dQ); - - var lightSwitchGarage = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "Light Switch Garage", - script: scriptURL, - position: { - x: 545.62, - y: 495.68, - z: 500.21 - }, - rotation: rotation, - dimensions: { - x: 0.10546875, - y: 0.032372996211051941, - z: 0.16242524981498718 - } - }); - - setEntityCustomData(resetKey, lightSwitchGarage, { - resetMe: true, - on: true, - type: "Garage Light" - }); - - - var sconceLight3 = Entities.addEntity({ - type: "Light", - position: { - x: 545.49468994140625, - y: 496.24026489257812, - z: 500.63516235351562 - }, - - name: "Sconce 3 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - - - setEntityCustomData(resetKey, sconceLight3, { - resetMe: true, - type: "Garage Light", - }); - - var sconceLight4 = Entities.addEntity({ - type: "Light", - position: { - x: 550.90399169921875, - y: 496.24026489257812, - z: 507.90237426757812 - }, - name: "Sconce 4 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - setEntityCustomData(resetKey, sconceLight4, { - resetMe: true, - type: "Garage Light", - }); - - var sconceLight5 = Entities.addEntity({ - type: "Light", - position: { - x: 548.407958984375, - y: 496.24026489257812, - z: 509.5504150390625 - }, - name: "Sconce 5 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - setEntityCustomData(resetKey, sconceLight5, { - resetMe: true, - type: "Garage Light", - }); - -} - - -function createFire() { - - - var myOrientation = Quat.fromPitchYawRollDegrees(-90, 0, 0.0); - - var fire = Entities.addEntity({ - type: "ParticleEffect", - name: "fire", - isEmitting: true, - textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - position: { - x: 551.45, - y: 494.82, - z: 502.05 - }, - emitRate: 100, - colorStart: { - red: 70, - green: 70, - blue: 137 - }, - color: { - red: 200, - green: 99, - blue: 42 - }, - colorFinish: { - red: 255, - green: 99, - blue: 32 - }, - radiusSpread: 0.01, - radiusStart: 0.02, - radiusEnd: 0.001, - particleRadius: 0.05, - radiusFinish: 0.0, - emitOrientation: myOrientation, - emitSpeed: 0.3, - speedSpread: 0.1, - alphaStart: 0.05, - alpha: 0.1, - alphaFinish: 0.05, - emitDimensions: { - x: 1, - y: 1, - z: 0.1 - }, - polarFinish: 0.1, - emitAcceleration: { - x: 0.0, - y: 0.0, - z: 0.0 - }, - accelerationSpread: { - x: 0.1, - y: 0.01, - z: 0.1 - }, - lifespan: 1 - }); - - - setEntityCustomData(resetKey, fire, { - resetMe: true - }); -} - - -function createCat(position) { - var scriptURL = Script.resolvePath("../examples/toys/cat.js"); - var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx"; - var animationSettings = { - url: "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx", - running: true, - }; - var cat = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "cat", - script: scriptURL, - animation: animationSettings, - position: position, - rotation: { - w: 0.35020983219146729, - x: -4.57763671875e-05, - y: 0.93664455413818359, - z: -1.52587890625e-05 - }, - dimensions: { - x: 0.15723302960395813, - y: 0.50762706995010376, - z: 0.90716040134429932 - }, - }); - - setEntityCustomData(resetKey, cat, { - resetMe: true - }); -} - -function createFlashlight(position) { - var scriptURL = Script.resolvePath('../examples/toys/flashlight/flashlight.js'); - var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx"; - - var flashlight = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "flashlight", - script: scriptURL, - position: position, - dimensions: { - x: 0.08, - y: 0.30, - z: 0.08 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -3.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - shapeType: 'box', - }); - - setEntityCustomData(resetKey, flashlight, { - resetMe: true - }); - -} - -function createDice() { - var diceProps = { - type: "Model", - modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx", - collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", - name: "dice", - position: { - x: 541, - y: 494.96, - z: 509.1 - }, - dimensions: { - x: 0.09, - y: 0.09, - z: 0.09 - }, - gravity: { - x: 0, - y: -3.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - shapeType: "box", - collisionsWillMove: true - }; - var dice1 = Entities.addEntity(diceProps); - - diceProps.position = { - x: 541.05, - y: 494.96, - z: 509.0 - }; - - var dice2 = Entities.addEntity(diceProps); - - setEntityCustomData(resetKey, dice1, { - resetMe: true - }); - - setEntityCustomData(resetKey, dice2, { - resetMe: true - }); -} - - -function createGates() { - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; - - var rotation1 = Quat.fromPitchYawRollDegrees(0, 36, 0); - - var gate1 = Entities.addEntity({ - name: 'Back Door Gate', - type: 'Model', - shapeType: 'box', - modelURL: MODEL_URL, - position: { - x: 546.52, - y: 494.76, - z: 498.87 - }, - dimensions: { - x: 1.42, - y: 1.13, - z: 0.25 - }, - rotation: rotation1, - collisionsWillMove: true, - gravity: { - x: 0, - y: -50, - z: 0 - }, - linearDamping: 1, - angularDamping: 10, - mass: 10, - - }); - - setEntityCustomData(resetKey, gate1, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, gate1, { - grabbable: false - }); - - var rotation2 = Quat.fromPitchYawRollDegrees(0, -16, 0); - var gate2 = Entities.addEntity({ - name: 'Front Door Fence', - type: 'Model', - modelURL: MODEL_URL, - shapeType: 'box', - position: { - x: 531.15, - y: 495.11, - z: 520.20 - }, - dimensions: { - x: 1.42, - y: 1.13, - z: 0.2 - }, - rotation: rotation2, - collisionsWillMove: true, - gravity: { - x: 0, - y: -100, - z: 0 - }, - linearDamping: 1, - angularDamping: 10, - mass: 10, - }); - - setEntityCustomData(resetKey, gate2, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, gate2, { - grabbable: false - }); -} - -function createPingPongBallGun() { - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'; - var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; - var scriptURL = Script.resolvePath('../examples/toys/ping_pong_gun/pingPongGun.js'); - - var position = { - x: 548.6, - y: 495.4, - z: 503.39 - }; - - var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); - - var pingPongGun = Entities.addEntity({ - type: "Model", - modelURL: MODEL_URL, - shapeType: 'box', - script: scriptURL, - position: position, - rotation: rotation, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - dimensions: { - x: 0.08, - y: 0.21, - z: 0.47 - }, - collisionsWillMove: true, - }); - - setEntityCustomData(resetKey, pingPongGun, { - resetMe: true - }); -} - -function createBasketballHoop() { - var position = { - x: 539.23, - y: 496.13, - z: 475.89 - }; - var rotation = Quat.fromPitchYawRollDegrees(0, 58.49, 0); - - var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; - var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; - - var hoop = Entities.addEntity({ - type: "Model", - modelURL: hoopURL, - position: position, - rotation: rotation, - shapeType: 'compound', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - dimensions: { - x: 1.89, - y: 3.99, - z: 3.79 - }, - compoundShapeURL: hoopCollisionHullURL - }); - - setEntityCustomData(resetKey, hoop, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, hoop, { - grabbable: false - }); -} - -function createBasketballRack() { - var NUMBER_OF_BALLS = 4; - var DIAMETER = 0.30; - var RESET_DISTANCE = 1; - var MINIMUM_MOVE_LENGTH = 0.05; - var basketballURL = HIFI_PUBLIC_BUCKET + "models/content/basketball2.fbx"; - var basketballCollisionSoundURL = HIFI_PUBLIC_BUCKET + "sounds/basketball/basketball.wav"; - var rackURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/basketball_rack.fbx"; - var rackCollisionHullURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/rack_collision_hull.obj"; - - var rackRotation = Quat.fromPitchYawRollDegrees(0, -90, 0); - - var rackStartPosition = { - x: 542.86, - y: 494.84, - z: 475.06 - }; - var rack = Entities.addEntity({ - name: 'Basketball Rack', - type: "Model", - modelURL: rackURL, - position: rackStartPosition, - rotation: rackRotation, - shapeType: 'compound', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - linearDamping: 1, - dimensions: { - x: 0.4, - y: 1.37, - z: 1.73 - }, - collisionsWillMove: true, - ignoreForCollisions: false, - compoundShapeURL: rackCollisionHullURL - }); - - setEntityCustomData(resetKey, rack, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, rack, { - grabbable: false - }); - - var collidingBalls = []; - var originalBallPositions = []; - - function createCollidingBalls() { - var position = rackStartPosition; - - var i; - for (i = 0; i < NUMBER_OF_BALLS; i++) { - var ballPosition = { - x: position.x, - y: position.y + DIAMETER * 2, - z: position.z + (DIAMETER) - (DIAMETER * i) - }; - - var collidingBall = Entities.addEntity({ - type: "Model", - name: 'Colliding Basketball', - shapeType: 'Sphere', - position: { - x: position.x + (DIAMETER * 2) - (DIAMETER * i), - y: position.y + DIAMETER * 2, - z: position.z - }, - dimensions: { - x: DIAMETER, - y: DIAMETER, - z: DIAMETER - }, - restitution: 1.0, - linearDamping: 0.00001, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - collisionsWillMove: true, - ignoreForCollisions: false, - modelURL: basketballURL, - }); - - collidingBalls.push(collidingBall); - originalBallPositions.push(position); - } } - function testBallDistanceFromStart() { - var resetCount = 0; + function deleteAllToys() { + var entities = Entities.findEntities(MyAvatar.position, 100); - collidingBalls.forEach(function(ball, index) { - var currentPosition = Entities.getEntityProperties(ball, "position").position; - var originalPosition = originalBallPositions[index]; - var distance = Vec3.subtract(originalPosition, currentPosition); - var length = Vec3.length(distance); - - if (length > RESET_DISTANCE) { - Script.setTimeout(function() { - var newPosition = Entities.getEntityProperties(ball, "position").position; - var moving = Vec3.length(Vec3.subtract(currentPosition, newPosition)); - if (moving < MINIMUM_MOVE_LENGTH) { - resetCount++; - if (resetCount === NUMBER_OF_BALLS) { - deleteCollidingBalls(); - createCollidingBalls(); - } - } - }, 200); + entities.forEach(function (entity) { + //params: customKey, id, defaultValue + var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe; + if (shouldReset === true) { + Entities.deleteEntity(entity); } }); } - function deleteEntity(entityID) { - if (entityID === rack) { - deleteCollidingBalls(); - Script.clearInterval(distanceCheckInterval); - Entities.deletingEntity.disconnect(deleteEntity); - } + + + function createHiddenMasterSwitch() { + + + var masterSwitch = Entities.addEntity({ + type: "Box", + name: "Master Switch", + script: hiddenEntityScriptURL, + dimensions: { + x: 0.2, + y: 0.2, + z: 0.2 + }, + color: { + red: 42, + green: 36, + blue: 30 + }, + position: { + x: 554, + y: 495.5, + z: 503.2 + } + }); + + setEntityCustomData(resetKey, masterSwitch, { + resetMe: true + }); } - function deleteCollidingBalls() { - while (collidingBalls.length > 0) { - Entities.deleteEntity(collidingBalls.pop()); - } + function createFire() { + + + var myOrientation = Quat.fromPitchYawRollDegrees(-90, 0, 0.0); + + var animationSettings = JSON.stringify({ + fps: 30, + running: true, + loop: true, + firstFrame: 1, + lastFrame: 10000 + }); + + + var fire = Entities.addEntity({ + type: "ParticleEffect", + name: "fire", + animationSettings: animationSettings, + textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + position: { + x: 551.45, + y: 494.82, + z: 502.05 + }, + emitRate: 100, + colorStart: { + red: 70, + green: 70, + blue: 137 + }, + color: { + red: 200, + green: 99, + blue: 42 + }, + colorFinish: { + red: 255, + green: 99, + blue: 32 + }, + radiusSpread: 0.01, + radiusStart: 0.02, + radiusEnd: 0.001, + particleRadius: 0.05, + radiusFinish: 0.0, + emitOrientation: myOrientation, + emitSpeed: 0.3, + speedSpread: 0.1, + alphaStart: 0.05, + alpha: 0.1, + alphaFinish: 0.05, + emitDimensions: { + x: 1, + y: 1, + z: 0.1 + }, + polarFinish: 0.1, + emitAcceleration: { + x: 0.0, + y: 0.0, + z: 0.0 + }, + accelerationSpread: { + x: 0.1, + y: 0.01, + z: 0.1 + }, + lifespan: 1 + }); + + + setEntityCustomData(resetKey, fire, { + resetMe: true + }); } - createCollidingBalls(); - Entities.deletingEntity.connect(deleteEntity); + function createBasketballRack() { + var NUMBER_OF_BALLS = 4; + var DIAMETER = 0.30; + var RESET_DISTANCE = 1; + var MINIMUM_MOVE_LENGTH = 0.05; + var basketballURL = HIFI_PUBLIC_BUCKET + "models/content/basketball2.fbx"; + var basketballCollisionSoundURL = HIFI_PUBLIC_BUCKET + "sounds/basketball/basketball.wav"; + var rackURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/basketball_rack.fbx"; + var rackCollisionHullURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/rack_collision_hull.obj"; - var distanceCheckInterval = Script.setInterval(testBallDistanceFromStart, 1000); + var rackRotation = Quat.fromPitchYawRollDegrees(0, -90, 0); -} + var rackStartPosition = { + x: 542.86, + y: 494.84, + z: 475.06 + }; + var rack = Entities.addEntity({ + name: 'Basketball Rack', + type: "Model", + modelURL: rackURL, + position: rackStartPosition, + rotation: rackRotation, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + linearDamping: 1, + dimensions: { + x: 0.4, + y: 1.37, + z: 1.73 + }, + collisionsWillMove: true, + ignoreForCollisions: false, + compoundShapeURL: rackCollisionHullURL + }); + setEntityCustomData(resetKey, rack, { + resetMe: true + }); + setEntityCustomData(GRABBABLE_DATA_KEY, rack, { + grabbable: false + }); -function createWand(position) { - var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; - var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/actual_no_top_collision_hull.obj'; - var scriptURL = Script.resolvePath("../examples/toys/bubblewand/wand.js"); + var collidingBalls = []; + var originalBallPositions = []; - var entity = Entities.addEntity({ - name: 'Bubble Wand', - type: "Model", - modelURL: WAND_MODEL, - position: position, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - dimensions: { - x: 0.05, - y: 0.25, - z: 0.05 - }, - //must be enabled to be grabbable in the physics engine - shapeType: 'compound', - collisionsWillMove: true, - compoundShapeURL: WAND_COLLISION_SHAPE, - //Look into why bubble wand is going through table when gravity is enabled - // gravity: {x: 0, y: -3.5, z: 0}, - // velocity: {x: 0, y: -0.01, z:0}, - script: scriptURL - }); + function createCollidingBalls() { + var position = rackStartPosition; - setEntityCustomData(resetKey, entity, { - resetMe: true - }); -} + var i; + for (i = 0; i < NUMBER_OF_BALLS; i++) { + var ballPosition = { + x: position.x, + y: position.y + DIAMETER * 2, + z: position.z + (DIAMETER) - (DIAMETER * i) + }; -function createBasketBall(position) { + var collidingBall = Entities.addEntity({ + type: "Model", + name: 'Colliding Basketball', + shapeType: 'Sphere', + position: { + x: position.x + (DIAMETER * 2) - (DIAMETER * i), + y: position.y + DIAMETER * 2, + z: position.z + }, + dimensions: { + x: DIAMETER, + y: DIAMETER, + z: DIAMETER + }, + restitution: 1.0, + linearDamping: 0.00001, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + collisionsWillMove: true, + ignoreForCollisions: false, + modelURL: basketballURL, + }); - var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - position: position, - collisionsWillMove: true, - shapeType: "sphere", - name: "basketball", - dimensions: { - x: 0.25, - y: 0.26, - z: 0.25 - }, - gravity: { - x: 0, - y: -7, - z: 0 - }, - restitution: 10, - linearDamping: 0.0, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/basketball/basketball.wav" - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); -} - -function createDoll(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"; - var scriptURL = Script.resolvePath("../examples/toys/doll/doll.js"); - - var naturalDimensions = { - x: 1.63, - y: 1.67, - z: 0.26 - }; - var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15); - var entity = Entities.addEntity({ - type: "Model", - name: "doll", - modelURL: modelURL, - script: scriptURL, - position: position, - shapeType: 'box', - dimensions: desiredDimensions, - gravity: { - x: 0, - y: -5, - z: 0 - }, - velocity: { - x: 0, - y: -0.1, - z: 0 - }, - collisionsWillMove: true - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); -} - -function createSprayCan(position) { - var scriptURL = Script.resolvePath("../examples/toys/sprayPaintCan.js"); - var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - name: "spraycan", - modelURL: modelURL, - position: position, - dimensions: { - x: 0.07, - y: 0.17, - z: 0.07 - }, - collisionsWillMove: true, - shapeType: 'box', - script: scriptURL, - gravity: { - x: 0, - y: -0.5, - z: 0 - }, - velocity: { - x: 0, - y: -1, - z: 0 + collidingBalls.push(collidingBall); + originalBallPositions.push(position); + } } - }); - setEntityCustomData(resetKey, entity, { - resetMe: true - }); + function testBallDistanceFromStart() { + var resetCount = 0; -} + collidingBalls.forEach(function (ball, index) { + var currentPosition = Entities.getEntityProperties(ball, "position").position; + var originalPosition = originalBallPositions[index]; + var distance = Vec3.subtract(originalPosition, currentPosition); + var length = Vec3.length(distance); -function createPottedPlant(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/potted_plant/potted_plant.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - name: "Potted Plant", - modelURL: modelURL, - position: position, - dimensions: { - x: 1.10, - y: 2.18, - z: 1.07 - }, - collisionsWillMove: true, - shapeType: 'box', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - velocity: { - x: 0, - y: 0, - z: 0 - }, - linearDamping: 0.4 - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); - - - setEntityCustomData(GRABBABLE_DATA_KEY, entity, { - grabbable: false - }); -} - - -function createCombinedArmChair(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/combined_chair.fbx"; - var RED_ARM_CHAIR_COLLISION_HULL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/red_arm_chair_collision_hull.obj"; - - var rotation = Quat.fromPitchYawRollDegrees(0, -143, 0); - - var entity = Entities.addEntity({ - type: "Model", - name: "Red Arm Chair", - modelURL: modelURL, - shapeType: 'compound', - compoundShapeURL: RED_ARM_CHAIR_COLLISION_HULL, - position: position, - rotation: rotation, - dimensions: { - x: 1.26, - y: 1.56, - z: 1.35 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -0.8, - z: 0 - }, - velocity: { - x: 0, - y: 0, - z: 0 - }, - linearDamping: 0.2 - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, entity, { - grabbable: false - }); -} - -function createBlocks(position) { - var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/"; - var collisionSoundURL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/ToyWoodBlock.L.wav"; - var NUM_BLOCKS_PER_COLOR = 4; - var i, j; - - var blockTypes = [{ - url: "planky_blue.fbx", - dimensions: { - x: 0.05, - y: 0.05, - z: 0.25 - } - }, { - url: "planky_green.fbx", - dimensions: { - x: 0.1, - y: 0.1, - z: 0.25 - } - }, { - url: "planky_natural.fbx", - dimensions: { - x: 0.05, - y: 0.05, - z: 0.05 - } - }, { - url: "planky_yellow.fbx", - dimensions: { - x: 0.03, - y: 0.05, - z: 0.25 - } - }, { - url: "planky_red.fbx", - dimensions: { - x: 0.1, - y: 0.05, - z: 0.25 - } - }, ]; - - var modelURL, entity; - for (i = 0; i < blockTypes.length; i++) { - for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) { - modelURL = baseURL + blockTypes[i].url; - entity = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - position: Vec3.sum(position, { - x: j / 10, - y: i / 10, - z: 0 - }), - shapeType: 'box', - name: "block", - dimensions: blockTypes[i].dimensions, - collisionsWillMove: true, - collisionSoundURL: collisionSoundURL, - gravity: { - x: 0, - y: -2.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 + if (length > RESET_DISTANCE) { + Script.setTimeout(function () { + var newPosition = Entities.getEntityProperties(ball, "position").position; + var moving = Vec3.length(Vec3.subtract(currentPosition, newPosition)); + if (moving < MINIMUM_MOVE_LENGTH) { + resetCount++; + if (resetCount === NUMBER_OF_BALLS) { + deleteCollidingBalls(); + createCollidingBalls(); + } + } + }, 200); } }); + } - //customKey, id, data - setEntityCustomData(resetKey, entity, { - resetMe: true - }); + function deleteEntity(entityID) { + if (entityID === rack) { + deleteCollidingBalls(); + Script.clearInterval(distanceCheckInterval); + Entities.deletingEntity.disconnect(deleteEntity); + } + } + + function deleteCollidingBalls() { + while (collidingBalls.length > 0) { + Entities.deleteEntity(collidingBalls.pop()); + } + } + + createCollidingBalls(); + Entities.deletingEntity.connect(deleteEntity); + + var distanceCheckInterval = Script.setInterval(testBallDistanceFromStart, 1000); + } + + function createCat(position) { + + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx"; + var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx"; + var animationSettings = JSON.stringify({ + running: true, + }); + var cat = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "cat", + script: catScriptURL, + animationURL: animationURL, + animationSettings: animationSettings, + position: position, + rotation: { + w: 0.35020983219146729, + x: -4.57763671875e-05, + y: 0.93664455413818359, + z: -1.52587890625e-05 + }, + dimensions: { + x: 0.15723302960395813, + y: 0.50762706995010376, + z: 0.90716040134429932 + }, + }); + + setEntityCustomData(resetKey, cat, { + resetMe: true + }); + } + + function createFlashlight(position) { + var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx"; + + var flashlight = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "flashlight", + script: flashlightScriptURL, + position: position, + dimensions: { + x: 0.08, + y: 0.30, + z: 0.08 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -3.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + shapeType: 'box', + }); + + setEntityCustomData(resetKey, flashlight, { + resetMe: true + }); + + } + + function createLights() { + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx"; + + + var rotation = { + w: 0.63280689716339111, + x: 0.63280689716339111, + y: -0.31551080942153931, + z: 0.31548023223876953 + }; + var axis = { + x: 0, + y: 1, + z: 0 + }; + var dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); + + var lightSwitchHall = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Hall", + script: lightsScriptURL, + position: { + x: 543.27764892578125, + y: 495.67999267578125, + z: 511.00564575195312 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + } + }); + setEntityCustomData(resetKey, lightSwitchHall, { + resetMe: true, + on: true, + type: "Hall Light" + }); + + var sconceLight1 = Entities.addEntity({ + type: "Light", + position: { + x: 543.75, + y: 496.24, + z: 511.13 + }, + name: "Sconce 1 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight1, { + resetMe: true, + type: "Hall Light", + }); + + var sconceLight2 = Entities.addEntity({ + type: "Light", + position: { + x: 540.1, + y: 496.24, + z: 505.57 + }, + name: "Sconce 2 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight2, { + resetMe: true, + type: "Hall Light", + }); + + + rotation = { + w: 0.20082402229309082, + x: 0.20082402229309082, + y: -0.67800414562225342, + z: 0.67797362804412842 + }; + axis = { + x: 0, + y: 1, + z: 0 + }; + dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); + + var lightSwitchGarage = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Garage", + script: lightsScriptURL, + position: { + x: 545.62, + y: 495.68, + z: 500.21 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + } + }); + + setEntityCustomData(resetKey, lightSwitchGarage, { + resetMe: true, + on: true, + type: "Garage Light" + }); + + + var sconceLight3 = Entities.addEntity({ + type: "Light", + position: { + x: 545.49468994140625, + y: 496.24026489257812, + z: 500.63516235351562 + }, + + name: "Sconce 3 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + + + setEntityCustomData(resetKey, sconceLight3, { + resetMe: true, + type: "Garage Light", + }); + + var sconceLight4 = Entities.addEntity({ + type: "Light", + position: { + x: 550.90399169921875, + y: 496.24026489257812, + z: 507.90237426757812 + }, + name: "Sconce 4 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight4, { + resetMe: true, + type: "Garage Light", + }); + + var sconceLight5 = Entities.addEntity({ + type: "Light", + position: { + x: 548.407958984375, + y: 496.24026489257812, + z: 509.5504150390625 + }, + name: "Sconce 5 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight5, { + resetMe: true, + type: "Garage Light", + }); + + } + + + + function createDice() { + var diceProps = { + type: "Model", + modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx", + collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", + name: "dice", + position: { + x: 541, + y: 494.96, + z: 509.1 + }, + dimensions: { + x: 0.09, + y: 0.09, + z: 0.09 + }, + gravity: { + x: 0, + y: -3.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + shapeType: "box", + collisionsWillMove: true + }; + var dice1 = Entities.addEntity(diceProps); + + diceProps.position = { + x: 541.05, + y: 494.96, + z: 509.0 + }; + + var dice2 = Entities.addEntity(diceProps); + + setEntityCustomData(resetKey, dice1, { + resetMe: true + }); + + setEntityCustomData(resetKey, dice2, { + resetMe: true + }); + } + + + function createGates() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; + + var rotation1 = Quat.fromPitchYawRollDegrees(0, 36, 0); + + var gate1 = Entities.addEntity({ + name: 'Back Door Gate', + type: 'Model', + shapeType: 'box', + modelURL: MODEL_URL, + position: { + x: 546.52, + y: 494.76, + z: 498.87 + }, + dimensions: { + x: 1.42, + y: 1.13, + z: 0.25 + }, + rotation: rotation1, + collisionsWillMove: true, + gravity: { + x: 0, + y: -50, + z: 0 + }, + linearDamping: 1, + angularDamping: 10, + mass: 10, + + }); + + setEntityCustomData(resetKey, gate1, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, gate1, { + grabbable: false + }); + + var rotation2 = Quat.fromPitchYawRollDegrees(0, -16, 0); + var gate2 = Entities.addEntity({ + name: 'Front Door Fence', + type: 'Model', + modelURL: MODEL_URL, + shapeType: 'box', + position: { + x: 531.15, + y: 495.11, + z: 520.20 + }, + dimensions: { + x: 1.42, + y: 1.13, + z: 0.2 + }, + rotation: rotation2, + collisionsWillMove: true, + gravity: { + x: 0, + y: -100, + z: 0 + }, + linearDamping: 1, + angularDamping: 10, + mass: 10, + }); + + setEntityCustomData(resetKey, gate2, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, gate2, { + grabbable: false + }); + } + + function createPingPongBallGun() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'; + var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; + + var position = { + x: 548.6, + y: 495.4, + z: 503.39 + }; + + var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); + + var pingPongGun = Entities.addEntity({ + type: "Model", + modelURL: MODEL_URL, + shapeType: 'box', + script: pingPongScriptURL, + position: position, + rotation: rotation, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 0.08, + y: 0.21, + z: 0.47 + }, + collisionsWillMove: true, + }); + + setEntityCustomData(resetKey, pingPongGun, { + resetMe: true + }); + } + + function createBasketballHoop() { + var position = { + x: 539.23, + y: 496.13, + z: 475.89 + }; + var rotation = Quat.fromPitchYawRollDegrees(0, 58.49, 0); + + var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; + var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; + + var hoop = Entities.addEntity({ + type: "Model", + modelURL: hoopURL, + position: position, + rotation: rotation, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 1.89, + y: 3.99, + z: 3.79 + }, + compoundShapeURL: hoopCollisionHullURL + }); + + setEntityCustomData(resetKey, hoop, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, hoop, { + grabbable: false + }); + } + + function createWand(position) { + var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; + var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/actual_no_top_collision_hull.obj'; + + var entity = Entities.addEntity({ + name: 'Bubble Wand', + type: "Model", + modelURL: WAND_MODEL, + position: position, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 0.05, + y: 0.25, + z: 0.05 + }, + //must be enabled to be grabbable in the physics engine + shapeType: 'compound', + collisionsWillMove: true, + compoundShapeURL: WAND_COLLISION_SHAPE, + //Look into why bubble wand is going through table when gravity is enabled + // gravity: {x: 0, y: -3.5, z: 0}, + // velocity: {x: 0, y: -0.01, z:0}, + script: wandScriptURL + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + + function createBasketBall(position) { + + var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: position, + collisionsWillMove: true, + shapeType: "sphere", + name: "basketball", + dimensions: { + x: 0.25, + y: 0.26, + z: 0.25 + }, + gravity: { + x: 0, + y: -7, + z: 0 + }, + restitution: 10, + linearDamping: 0.0, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/basketball/basketball.wav" + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + + function createDoll(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"; + + var naturalDimensions = { + x: 1.63, + y: 1.67, + z: 0.26 + }; + var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15); + var entity = Entities.addEntity({ + type: "Model", + name: "doll", + modelURL: modelURL, + script: dollScriptURL, + position: position, + shapeType: 'box', + dimensions: desiredDimensions, + gravity: { + x: 0, + y: -5, + z: 0 + }, + velocity: { + x: 0, + y: -0.1, + z: 0 + }, + collisionsWillMove: true + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + + function createSprayCan(position) { + + var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + name: "spraycan", + script: sprayPaintScriptURL, + modelURL: modelURL, + position: position, + dimensions: { + x: 0.07, + y: 0.17, + z: 0.07 + }, + collisionsWillMove: true, + shapeType: 'box', + gravity: { + x: 0, + y: -0.5, + z: 0 + }, + velocity: { + x: 0, + y: -1, + z: 0 + } + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + + } + + function createPottedPlant(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/potted_plant/potted_plant.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + name: "Potted Plant", + modelURL: modelURL, + position: position, + dimensions: { + x: 1.10, + y: 2.18, + z: 1.07 + }, + collisionsWillMove: true, + shapeType: 'box', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.4 + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + + + setEntityCustomData(GRABBABLE_DATA_KEY, entity, { + grabbable: false + }); + } + + + function createCombinedArmChair(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/combined_chair.fbx"; + var RED_ARM_CHAIR_COLLISION_HULL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/red_arm_chair_collision_hull.obj"; + + var rotation = Quat.fromPitchYawRollDegrees(0, -143, 0); + + var entity = Entities.addEntity({ + type: "Model", + name: "Red Arm Chair", + modelURL: modelURL, + shapeType: 'compound', + compoundShapeURL: RED_ARM_CHAIR_COLLISION_HULL, + position: position, + rotation: rotation, + dimensions: { + x: 1.26, + y: 1.56, + z: 1.35 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -0.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.2 + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, entity, { + grabbable: false + }); + } + + function createBlocks(position) { + var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/"; + var collisionSoundURL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/ToyWoodBlock.L.wav"; + var NUM_BLOCKS_PER_COLOR = 4; + var i, j; + + var blockTypes = [{ + url: "planky_blue.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_green.fbx", + dimensions: { + x: 0.1, + y: 0.1, + z: 0.25 + } + }, { + url: "planky_natural.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.05 + } + }, { + url: "planky_yellow.fbx", + dimensions: { + x: 0.03, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_red.fbx", + dimensions: { + x: 0.1, + y: 0.05, + z: 0.25 + } + }, ]; + + var modelURL, entity; + for (i = 0; i < blockTypes.length; i++) { + for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) { + modelURL = baseURL + blockTypes[i].url; + entity = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: Vec3.sum(position, { + x: j / 10, + y: i / 10, + z: 0 + }), + shapeType: 'box', + name: "block", + dimensions: blockTypes[i].dimensions, + collisionsWillMove: true, + collisionSoundURL: collisionSoundURL, + gravity: { + x: 0, + y: -2.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + } + }); + + //customKey, id, data + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } } } -} -function cleanup() { - deleteAllToys(); -} + function cleanup() { + deleteAllToys(); + } -if (shouldDeleteOnEndScript) { + if (shouldDeleteOnEndScript) { - Script.scriptEnding.connect(cleanup); -} + Script.scriptEnding.connect(cleanup); + } +}; \ No newline at end of file From fb284448b5f07edc05e03cb2ecda7c2820f4b2d1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 7 Oct 2015 15:21:35 -0700 Subject: [PATCH 14/34] Raise display name not to collide with heads --- interface/src/avatar/Avatar.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 0511e5d871..c0636314b5 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -758,6 +758,9 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, cons result.setTranslation(textPosition); result.setRotation(orientation); // Always face the screen result.setScale(scale); + // raise by half the scale up so that textPosition be the bottom + result.postTranslate(Vectors::UP / 2.0f); + return result; } From 7a918eb2883c8ee3b96c28d7dbab99d8f1b2cf4b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 7 Oct 2015 15:25:07 -0700 Subject: [PATCH 15/34] fix variable names in header --- libraries/shared/src/SettingHandle.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/shared/src/SettingHandle.h b/libraries/shared/src/SettingHandle.h index b86422bcfb..c0b6de7bd4 100644 --- a/libraries/shared/src/SettingHandle.h +++ b/libraries/shared/src/SettingHandle.h @@ -26,14 +26,14 @@ // TODO: remove class Settings : public QSettings { public: - void getFloatValueIfValid(const QString& name, float& f); - void getBoolValue(const QString& name, bool& b); + void getFloatValueIfValid(const QString& name, float& floatValue); + void getBoolValue(const QString& name, bool& boolValue); - void setVec3Value(const QString& name, const glm::vec3& v); - void getVec3ValueIfValid(const QString& name, glm::vec3& v); + void setVec3Value(const QString& name, const glm::vec3& vecValue); + void getVec3ValueIfValid(const QString& name, glm::vec3& vecValue); - void setQuatValue(const QString& name, const glm::quat& q); - void getQuatValueIfValid(const QString& name, glm::quat& q); + void setQuatValue(const QString& name, const glm::quat& quatValue); + void getQuatValueIfValid(const QString& name, glm::quat& quatValue); }; namespace Setting { From 0cebeb7fe9a6d3d917cdd3d491124f9937033cbd Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 7 Oct 2015 15:32:10 -0700 Subject: [PATCH 16/34] Separated AvatarMixer inbound and outbound bandwidth on stats overlay Also, small bug fix to BandwidthRecorder. It would incorrectly calculate outbound pps if the input pps was 0. --- interface/resources/qml/Stats.qml | 11 +++++++++-- interface/src/ui/Stats.cpp | 16 ++++++++-------- interface/src/ui/Stats.h | 12 ++++++++---- libraries/networking/src/BandwidthRecorder.cpp | 4 ++-- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index eb39fbc70f..780f9cb89f 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -142,8 +142,15 @@ Item { color: root.fontColor; font.pixelSize: root.fontSize visible: root.expanded; - text: "Avatar Mixer: " + root.avatarMixerKbps + " kbps, " + - root.avatarMixerPps + "pps"; + text: "Avatar Mixer In: " + root.avatarMixerInKbps + " kbps, " + + root.avatarMixerInPps + "pps"; + } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded; + text: "Avatar Mixer Out: " + root.avatarMixerOutKbps + " kbps, " + + root.avatarMixerOutPps + "pps"; } Text { color: root.fontColor; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 5e73e62832..7e2143c454 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -167,15 +167,15 @@ void Stats::updateStats(bool force) { if (_expanded || force) { SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer); if (avatarMixer) { - STAT_UPDATE(avatarMixerKbps, roundf( - bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer) + - bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer))); - STAT_UPDATE(avatarMixerPps, roundf( - bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer) + - bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer))); + STAT_UPDATE(avatarMixerInKbps, roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer))); + STAT_UPDATE(avatarMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer))); + STAT_UPDATE(avatarMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer))); + STAT_UPDATE(avatarMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer))); } else { - STAT_UPDATE(avatarMixerKbps, -1); - STAT_UPDATE(avatarMixerPps, -1); + STAT_UPDATE(avatarMixerInKbps, -1); + STAT_UPDATE(avatarMixerInPps, -1); + STAT_UPDATE(avatarMixerOutKbps, -1); + STAT_UPDATE(avatarMixerOutPps, -1); } SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); if (audioMixerNode || force) { diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index d6aa255dc6..f1426a9e37 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -47,8 +47,10 @@ class Stats : public QQuickItem { STATS_PROPERTY(QVector3D, position, QVector3D(0, 0, 0) ) STATS_PROPERTY(float, velocity, 0) STATS_PROPERTY(float, yaw, 0) - STATS_PROPERTY(int, avatarMixerKbps, 0) - STATS_PROPERTY(int, avatarMixerPps, 0) + STATS_PROPERTY(int, avatarMixerInKbps, 0) + STATS_PROPERTY(int, avatarMixerInPps, 0) + STATS_PROPERTY(int, avatarMixerOutKbps, 0) + STATS_PROPERTY(int, avatarMixerOutPps, 0) STATS_PROPERTY(int, audioMixerKbps, 0) STATS_PROPERTY(int, audioMixerPps, 0) STATS_PROPERTY(int, downloads, 0) @@ -122,8 +124,10 @@ signals: void positionChanged(); void velocityChanged(); void yawChanged(); - void avatarMixerKbpsChanged(); - void avatarMixerPpsChanged(); + void avatarMixerInKbpsChanged(); + void avatarMixerInPpsChanged(); + void avatarMixerOutKbpsChanged(); + void avatarMixerOutPpsChanged(); void audioMixerKbpsChanged(); void audioMixerPpsChanged(); void downloadsChanged(); diff --git a/libraries/networking/src/BandwidthRecorder.cpp b/libraries/networking/src/BandwidthRecorder.cpp index a415a9f477..5db987b236 100644 --- a/libraries/networking/src/BandwidthRecorder.cpp +++ b/libraries/networking/src/BandwidthRecorder.cpp @@ -27,9 +27,9 @@ float BandwidthRecorder::Channel::getAverageInputPacketsPerSecond() { } float BandwidthRecorder::Channel::getAverageOutputPacketsPerSecond() { - float delt = _input.getEventDeltaAverage(); + float delt = _output.getEventDeltaAverage(); if (delt > 0.0f) { - return (1.0f / _output.getEventDeltaAverage()); + return (1.0f / delt); } return 0.0f; } From 39d0d820673785ad71a2ee9b2fc5c52a059da6b0 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 15:39:32 -0700 Subject: [PATCH 17/34] adding some logging --- unpublishedScripts/hiddenEntityReset.js | 1 + unpublishedScripts/masterReset.js | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 0770f561cf..7591f3dbfe 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -15,6 +15,7 @@ var _this; var masterResetScript = Script.resolvePath("masterReset.js"); + print("masterResetScript PATH " + masterResetScript); Script.include(masterResetScript); ResetSwitch = function () { diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 477bd76985..a47b569cdd 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -23,9 +23,12 @@ var wandScriptURL = Script.resolvePath("../examples/toys/bubblewand/wand.js"); var dollScriptURL = Script.resolvePath("../examples/toys/doll/doll.js"); var lightsScriptURL = Script.resolvePath("../examples/toys/lightSwitch.js"); +print("hiddenEntityScript PATH OUTER " + hiddenEntityScriptURL); + + MasterReset = function () { - + print("hiddenEntityScript PATH INNER " + hiddenEntityScriptURL); var resetKey = "resetMe"; var GRABBABLE_DATA_KEY = "grabbableKey"; @@ -1167,4 +1170,6 @@ MasterReset = function () { Script.scriptEnding.connect(cleanup); } -}; \ No newline at end of file +}; + +MasterReset(); \ No newline at end of file From 3f3c91116bda96c749ee0dd9f4874adc5ba1df16 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 15:40:12 -0700 Subject: [PATCH 18/34] No calling within masterReset --- unpublishedScripts/masterReset.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index a47b569cdd..2d9cd47504 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -1170,6 +1170,4 @@ MasterReset = function () { Script.scriptEnding.connect(cleanup); } -}; - -MasterReset(); \ No newline at end of file +}; \ No newline at end of file From 00f3b7b1b5ff7b5af0a6f450a16f9b0a9d29a77e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 7 Oct 2015 15:46:42 -0700 Subject: [PATCH 19/34] Renamed delt to averageTimeBetweenPackets --- libraries/networking/src/BandwidthRecorder.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/networking/src/BandwidthRecorder.cpp b/libraries/networking/src/BandwidthRecorder.cpp index 5db987b236..d43d4cf21f 100644 --- a/libraries/networking/src/BandwidthRecorder.cpp +++ b/libraries/networking/src/BandwidthRecorder.cpp @@ -19,17 +19,17 @@ BandwidthRecorder::Channel::Channel() { } float BandwidthRecorder::Channel::getAverageInputPacketsPerSecond() { - float delt = _input.getEventDeltaAverage(); - if (delt > 0.0f) { - return (1.0f / delt); + float averageTimeBetweenPackets = _input.getEventDeltaAverage(); + if (averageTimeBetweenPackets > 0.0f) { + return (1.0f / averageTimeBetweenPackets); } return 0.0f; } float BandwidthRecorder::Channel::getAverageOutputPacketsPerSecond() { - float delt = _output.getEventDeltaAverage(); - if (delt > 0.0f) { - return (1.0f / delt); + float averageTimeBetweenPackets = _output.getEventDeltaAverage(); + if (averageTimeBetweenPackets > 0.0f) { + return (1.0f / averageTimeBetweenPackets); } return 0.0f; } From 3c8b1b2a4ea0c247d0d638eb0b11130a9a64528a Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 15:58:47 -0700 Subject: [PATCH 20/34] attempting duplicate script approach --- unpublishedScripts/hiddenEntityReset.js | 3 +- unpublishedScripts/immediateClientReset.js | 34 + unpublishedScripts/masterReset.js | 33 - unpublishedScripts/masterResetFromEntity.js | 1138 +++++++++++++++++++ 4 files changed, 1173 insertions(+), 35 deletions(-) create mode 100644 unpublishedScripts/masterResetFromEntity.js diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 7591f3dbfe..7cae5cf088 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -14,8 +14,7 @@ var _this; - var masterResetScript = Script.resolvePath("masterReset.js"); - print("masterResetScript PATH " + masterResetScript); + var masterResetScript = Script.resolvePath("masterResetFromEntity.js"); Script.include(masterResetScript); ResetSwitch = function () { diff --git a/unpublishedScripts/immediateClientReset.js b/unpublishedScripts/immediateClientReset.js index 3748f06bf5..f70ecf87d2 100644 --- a/unpublishedScripts/immediateClientReset.js +++ b/unpublishedScripts/immediateClientReset.js @@ -3,6 +3,40 @@ /*global MasterReset */ var masterResetScript = Script.resolvePath("masterReset.js"); +var hiddenEntityScriptURL = Script.resolvePath("hiddenEntityReset.js"); + Script.include(masterResetScript); + + +function createHiddenMasterSwitch() { + + var resetKey = "resetMe"; + var masterSwitch = Entities.addEntity({ + type: "Box", + name: "Master Switch", + script: hiddenEntityScriptURL, + dimensions: { + x: 0.2, + y: 0.2, + z: 0.2 + }, + color: { + red: 42, + green: 36, + blue: 30 + }, + position: { + x: 554, + y: 495.5, + z: 503.2 + } + }); + + setEntityCustomData(resetKey, masterSwitch, { + resetMe: true + }); +} + +createHiddenMasterSwitch(); MasterReset(); \ No newline at end of file diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 2d9cd47504..95f538316a 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -14,7 +14,6 @@ var utilitiesScript = Script.resolvePath("../examples/libraries/utils.js"); Script.include(utilitiesScript); -var hiddenEntityScriptURL = Script.resolvePath("hiddenEntityReset.js"); var sprayPaintScriptURL = Script.resolvePath("../examples/toys/sprayPaintCan.js"); var catScriptURL = Script.resolvePath("../examples/toys/cat.js"); var flashlightScriptURL = Script.resolvePath('../examples/toys/flashlight/flashlight.js'); @@ -23,12 +22,9 @@ var wandScriptURL = Script.resolvePath("../examples/toys/bubblewand/wand.js"); var dollScriptURL = Script.resolvePath("../examples/toys/doll/doll.js"); var lightsScriptURL = Script.resolvePath("../examples/toys/lightSwitch.js"); -print("hiddenEntityScript PATH OUTER " + hiddenEntityScriptURL); - MasterReset = function () { - print("hiddenEntityScript PATH INNER " + hiddenEntityScriptURL); var resetKey = "resetMe"; var GRABBABLE_DATA_KEY = "grabbableKey"; @@ -130,35 +126,6 @@ MasterReset = function () { - function createHiddenMasterSwitch() { - - - var masterSwitch = Entities.addEntity({ - type: "Box", - name: "Master Switch", - script: hiddenEntityScriptURL, - dimensions: { - x: 0.2, - y: 0.2, - z: 0.2 - }, - color: { - red: 42, - green: 36, - blue: 30 - }, - position: { - x: 554, - y: 495.5, - z: 503.2 - } - }); - - setEntityCustomData(resetKey, masterSwitch, { - resetMe: true - }); - } - function createFire() { diff --git a/unpublishedScripts/masterResetFromEntity.js b/unpublishedScripts/masterResetFromEntity.js new file mode 100644 index 0000000000..95218b995b --- /dev/null +++ b/unpublishedScripts/masterResetFromEntity.js @@ -0,0 +1,1138 @@ +// masterReset.js +// Created by Eric Levin on 9/23/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 +// + +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ +//per script + + +/*global deleteAllToys, createAllToys, createGates, createPingPongBallGun, createFire, createPottedPlant, createCombinedArmChair, createBasketballHoop, createBasketBall, createSprayCan, createDoll, createWand, createDice, createCat, deleteAllToys, createFlashlight, createBlocks, createMagballs, createLights */ +var utilitiesScript = Script.resolvePath("../examples/libraries/utils.js"); +Script.include(utilitiesScript); + +var sprayPaintScriptURL = Script.resolvePath("../examples/toys/sprayPaintCan.js"); +var catScriptURL = Script.resolvePath("../examples/toys/cat.js"); +var flashlightScriptURL = Script.resolvePath('../examples/toys/flashlight/flashlight.js'); +var pingPongScriptURL = Script.resolvePath('../examples/toys/ping_pong_gun/pingPongGun.js'); +var wandScriptURL = Script.resolvePath("../examples/toys/bubblewand/wand.js"); +var dollScriptURL = Script.resolvePath("../examples/toys/doll/doll.js"); +var lightsScriptURL = Script.resolvePath("../examples/toys/lightSwitch.js"); + + + +MasterReset = function () { + var resetKey = "resetMe"; + var GRABBABLE_DATA_KEY = "grabbableKey"; + + var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + + var shouldDeleteOnEndScript = false; + + //Before creating anything, first search a radius and delete all the things that should be deleted + deleteAllToys(); + createAllToys(); + + function createAllToys() { + createBlocks({ + x: 548.3, + y: 495.55, + z: 504.4 + }); + + createBasketBall({ + x: 547.73, + y: 495.5, + z: 505.47 + }); + + createDoll({ + x: 546.67, + y: 495.41, + z: 505.09 + }); + + createWand({ + x: 546.71, + y: 495.55, + z: 506.15 + }); + + createDice(); + + createFlashlight({ + x: 545.72, + y: 495.41, + z: 505.78 + }); + + + + createCombinedArmChair({ + x: 549.29, + y: 494.9, + z: 508.22 + }); + + createPottedPlant({ + x: 554.26, + y: 495.2, + z: 504.53 + }); + + createPingPongBallGun(); + + createBasketballHoop(); + createBasketballRack(); + + createGates(); + + createFire(); + // Handles toggling of all sconce lights + createLights(); + + + + createCat({ + x: 551.09, + y: 494.98, + z: 503.49 + }); + + + createSprayCan({ + x: 549.7, + y: 495.6, + z: 503.91 + }); + + } + + function deleteAllToys() { + var entities = Entities.findEntities(MyAvatar.position, 100); + + entities.forEach(function (entity) { + //params: customKey, id, defaultValue + var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe; + if (shouldReset === true) { + Entities.deleteEntity(entity); + } + }); + } + + + function createFire() { + + + var myOrientation = Quat.fromPitchYawRollDegrees(-90, 0, 0.0); + + var animationSettings = JSON.stringify({ + fps: 30, + running: true, + loop: true, + firstFrame: 1, + lastFrame: 10000 + }); + + + var fire = Entities.addEntity({ + type: "ParticleEffect", + name: "fire", + animationSettings: animationSettings, + textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + position: { + x: 551.45, + y: 494.82, + z: 502.05 + }, + emitRate: 100, + colorStart: { + red: 70, + green: 70, + blue: 137 + }, + color: { + red: 200, + green: 99, + blue: 42 + }, + colorFinish: { + red: 255, + green: 99, + blue: 32 + }, + radiusSpread: 0.01, + radiusStart: 0.02, + radiusEnd: 0.001, + particleRadius: 0.05, + radiusFinish: 0.0, + emitOrientation: myOrientation, + emitSpeed: 0.3, + speedSpread: 0.1, + alphaStart: 0.05, + alpha: 0.1, + alphaFinish: 0.05, + emitDimensions: { + x: 1, + y: 1, + z: 0.1 + }, + polarFinish: 0.1, + emitAcceleration: { + x: 0.0, + y: 0.0, + z: 0.0 + }, + accelerationSpread: { + x: 0.1, + y: 0.01, + z: 0.1 + }, + lifespan: 1 + }); + + + setEntityCustomData(resetKey, fire, { + resetMe: true + }); + } + + function createBasketballRack() { + var NUMBER_OF_BALLS = 4; + var DIAMETER = 0.30; + var RESET_DISTANCE = 1; + var MINIMUM_MOVE_LENGTH = 0.05; + var basketballURL = HIFI_PUBLIC_BUCKET + "models/content/basketball2.fbx"; + var basketballCollisionSoundURL = HIFI_PUBLIC_BUCKET + "sounds/basketball/basketball.wav"; + var rackURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/basketball_rack.fbx"; + var rackCollisionHullURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/rack_collision_hull.obj"; + + var rackRotation = Quat.fromPitchYawRollDegrees(0, -90, 0); + + var rackStartPosition = { + x: 542.86, + y: 494.84, + z: 475.06 + }; + var rack = Entities.addEntity({ + name: 'Basketball Rack', + type: "Model", + modelURL: rackURL, + position: rackStartPosition, + rotation: rackRotation, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + linearDamping: 1, + dimensions: { + x: 0.4, + y: 1.37, + z: 1.73 + }, + collisionsWillMove: true, + ignoreForCollisions: false, + compoundShapeURL: rackCollisionHullURL + }); + + setEntityCustomData(resetKey, rack, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, rack, { + grabbable: false + }); + + var collidingBalls = []; + var originalBallPositions = []; + + function createCollidingBalls() { + var position = rackStartPosition; + + var i; + for (i = 0; i < NUMBER_OF_BALLS; i++) { + var ballPosition = { + x: position.x, + y: position.y + DIAMETER * 2, + z: position.z + (DIAMETER) - (DIAMETER * i) + }; + + var collidingBall = Entities.addEntity({ + type: "Model", + name: 'Colliding Basketball', + shapeType: 'Sphere', + position: { + x: position.x + (DIAMETER * 2) - (DIAMETER * i), + y: position.y + DIAMETER * 2, + z: position.z + }, + dimensions: { + x: DIAMETER, + y: DIAMETER, + z: DIAMETER + }, + restitution: 1.0, + linearDamping: 0.00001, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + collisionsWillMove: true, + ignoreForCollisions: false, + modelURL: basketballURL, + }); + + collidingBalls.push(collidingBall); + originalBallPositions.push(position); + } + } + + function testBallDistanceFromStart() { + var resetCount = 0; + + collidingBalls.forEach(function (ball, index) { + var currentPosition = Entities.getEntityProperties(ball, "position").position; + var originalPosition = originalBallPositions[index]; + var distance = Vec3.subtract(originalPosition, currentPosition); + var length = Vec3.length(distance); + + if (length > RESET_DISTANCE) { + Script.setTimeout(function () { + var newPosition = Entities.getEntityProperties(ball, "position").position; + var moving = Vec3.length(Vec3.subtract(currentPosition, newPosition)); + if (moving < MINIMUM_MOVE_LENGTH) { + resetCount++; + if (resetCount === NUMBER_OF_BALLS) { + deleteCollidingBalls(); + createCollidingBalls(); + } + } + }, 200); + } + }); + } + + function deleteEntity(entityID) { + if (entityID === rack) { + deleteCollidingBalls(); + Script.clearInterval(distanceCheckInterval); + Entities.deletingEntity.disconnect(deleteEntity); + } + } + + function deleteCollidingBalls() { + while (collidingBalls.length > 0) { + Entities.deleteEntity(collidingBalls.pop()); + } + } + + createCollidingBalls(); + Entities.deletingEntity.connect(deleteEntity); + + var distanceCheckInterval = Script.setInterval(testBallDistanceFromStart, 1000); + } + + function createCat(position) { + + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx"; + var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx"; + var animationSettings = JSON.stringify({ + running: true, + }); + var cat = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "cat", + script: catScriptURL, + animationURL: animationURL, + animationSettings: animationSettings, + position: position, + rotation: { + w: 0.35020983219146729, + x: -4.57763671875e-05, + y: 0.93664455413818359, + z: -1.52587890625e-05 + }, + dimensions: { + x: 0.15723302960395813, + y: 0.50762706995010376, + z: 0.90716040134429932 + }, + }); + + setEntityCustomData(resetKey, cat, { + resetMe: true + }); + } + + function createFlashlight(position) { + var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx"; + + var flashlight = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "flashlight", + script: flashlightScriptURL, + position: position, + dimensions: { + x: 0.08, + y: 0.30, + z: 0.08 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -3.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + shapeType: 'box', + }); + + setEntityCustomData(resetKey, flashlight, { + resetMe: true + }); + + } + + function createLights() { + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx"; + + + var rotation = { + w: 0.63280689716339111, + x: 0.63280689716339111, + y: -0.31551080942153931, + z: 0.31548023223876953 + }; + var axis = { + x: 0, + y: 1, + z: 0 + }; + var dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); + + var lightSwitchHall = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Hall", + script: lightsScriptURL, + position: { + x: 543.27764892578125, + y: 495.67999267578125, + z: 511.00564575195312 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + } + }); + setEntityCustomData(resetKey, lightSwitchHall, { + resetMe: true, + on: true, + type: "Hall Light" + }); + + var sconceLight1 = Entities.addEntity({ + type: "Light", + position: { + x: 543.75, + y: 496.24, + z: 511.13 + }, + name: "Sconce 1 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight1, { + resetMe: true, + type: "Hall Light", + }); + + var sconceLight2 = Entities.addEntity({ + type: "Light", + position: { + x: 540.1, + y: 496.24, + z: 505.57 + }, + name: "Sconce 2 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight2, { + resetMe: true, + type: "Hall Light", + }); + + + rotation = { + w: 0.20082402229309082, + x: 0.20082402229309082, + y: -0.67800414562225342, + z: 0.67797362804412842 + }; + axis = { + x: 0, + y: 1, + z: 0 + }; + dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); + + var lightSwitchGarage = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Garage", + script: lightsScriptURL, + position: { + x: 545.62, + y: 495.68, + z: 500.21 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + } + }); + + setEntityCustomData(resetKey, lightSwitchGarage, { + resetMe: true, + on: true, + type: "Garage Light" + }); + + + var sconceLight3 = Entities.addEntity({ + type: "Light", + position: { + x: 545.49468994140625, + y: 496.24026489257812, + z: 500.63516235351562 + }, + + name: "Sconce 3 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + + + setEntityCustomData(resetKey, sconceLight3, { + resetMe: true, + type: "Garage Light", + }); + + var sconceLight4 = Entities.addEntity({ + type: "Light", + position: { + x: 550.90399169921875, + y: 496.24026489257812, + z: 507.90237426757812 + }, + name: "Sconce 4 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight4, { + resetMe: true, + type: "Garage Light", + }); + + var sconceLight5 = Entities.addEntity({ + type: "Light", + position: { + x: 548.407958984375, + y: 496.24026489257812, + z: 509.5504150390625 + }, + name: "Sconce 5 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight5, { + resetMe: true, + type: "Garage Light", + }); + + } + + + + function createDice() { + var diceProps = { + type: "Model", + modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx", + collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", + name: "dice", + position: { + x: 541, + y: 494.96, + z: 509.1 + }, + dimensions: { + x: 0.09, + y: 0.09, + z: 0.09 + }, + gravity: { + x: 0, + y: -3.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + shapeType: "box", + collisionsWillMove: true + }; + var dice1 = Entities.addEntity(diceProps); + + diceProps.position = { + x: 541.05, + y: 494.96, + z: 509.0 + }; + + var dice2 = Entities.addEntity(diceProps); + + setEntityCustomData(resetKey, dice1, { + resetMe: true + }); + + setEntityCustomData(resetKey, dice2, { + resetMe: true + }); + } + + + function createGates() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; + + var rotation1 = Quat.fromPitchYawRollDegrees(0, 36, 0); + + var gate1 = Entities.addEntity({ + name: 'Back Door Gate', + type: 'Model', + shapeType: 'box', + modelURL: MODEL_URL, + position: { + x: 546.52, + y: 494.76, + z: 498.87 + }, + dimensions: { + x: 1.42, + y: 1.13, + z: 0.25 + }, + rotation: rotation1, + collisionsWillMove: true, + gravity: { + x: 0, + y: -50, + z: 0 + }, + linearDamping: 1, + angularDamping: 10, + mass: 10, + + }); + + setEntityCustomData(resetKey, gate1, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, gate1, { + grabbable: false + }); + + var rotation2 = Quat.fromPitchYawRollDegrees(0, -16, 0); + var gate2 = Entities.addEntity({ + name: 'Front Door Fence', + type: 'Model', + modelURL: MODEL_URL, + shapeType: 'box', + position: { + x: 531.15, + y: 495.11, + z: 520.20 + }, + dimensions: { + x: 1.42, + y: 1.13, + z: 0.2 + }, + rotation: rotation2, + collisionsWillMove: true, + gravity: { + x: 0, + y: -100, + z: 0 + }, + linearDamping: 1, + angularDamping: 10, + mass: 10, + }); + + setEntityCustomData(resetKey, gate2, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, gate2, { + grabbable: false + }); + } + + function createPingPongBallGun() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'; + var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; + + var position = { + x: 548.6, + y: 495.4, + z: 503.39 + }; + + var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); + + var pingPongGun = Entities.addEntity({ + type: "Model", + modelURL: MODEL_URL, + shapeType: 'box', + script: pingPongScriptURL, + position: position, + rotation: rotation, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 0.08, + y: 0.21, + z: 0.47 + }, + collisionsWillMove: true, + }); + + setEntityCustomData(resetKey, pingPongGun, { + resetMe: true + }); + } + + function createBasketballHoop() { + var position = { + x: 539.23, + y: 496.13, + z: 475.89 + }; + var rotation = Quat.fromPitchYawRollDegrees(0, 58.49, 0); + + var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; + var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; + + var hoop = Entities.addEntity({ + type: "Model", + modelURL: hoopURL, + position: position, + rotation: rotation, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 1.89, + y: 3.99, + z: 3.79 + }, + compoundShapeURL: hoopCollisionHullURL + }); + + setEntityCustomData(resetKey, hoop, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, hoop, { + grabbable: false + }); + } + + function createWand(position) { + var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; + var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/actual_no_top_collision_hull.obj'; + + var entity = Entities.addEntity({ + name: 'Bubble Wand', + type: "Model", + modelURL: WAND_MODEL, + position: position, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 0.05, + y: 0.25, + z: 0.05 + }, + //must be enabled to be grabbable in the physics engine + shapeType: 'compound', + collisionsWillMove: true, + compoundShapeURL: WAND_COLLISION_SHAPE, + //Look into why bubble wand is going through table when gravity is enabled + // gravity: {x: 0, y: -3.5, z: 0}, + // velocity: {x: 0, y: -0.01, z:0}, + script: wandScriptURL + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + + function createBasketBall(position) { + + var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: position, + collisionsWillMove: true, + shapeType: "sphere", + name: "basketball", + dimensions: { + x: 0.25, + y: 0.26, + z: 0.25 + }, + gravity: { + x: 0, + y: -7, + z: 0 + }, + restitution: 10, + linearDamping: 0.0, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/basketball/basketball.wav" + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + + function createDoll(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"; + + var naturalDimensions = { + x: 1.63, + y: 1.67, + z: 0.26 + }; + var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15); + var entity = Entities.addEntity({ + type: "Model", + name: "doll", + modelURL: modelURL, + script: dollScriptURL, + position: position, + shapeType: 'box', + dimensions: desiredDimensions, + gravity: { + x: 0, + y: -5, + z: 0 + }, + velocity: { + x: 0, + y: -0.1, + z: 0 + }, + collisionsWillMove: true + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + + function createSprayCan(position) { + + var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + name: "spraycan", + script: sprayPaintScriptURL, + modelURL: modelURL, + position: position, + dimensions: { + x: 0.07, + y: 0.17, + z: 0.07 + }, + collisionsWillMove: true, + shapeType: 'box', + gravity: { + x: 0, + y: -0.5, + z: 0 + }, + velocity: { + x: 0, + y: -1, + z: 0 + } + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + + } + + function createPottedPlant(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/potted_plant/potted_plant.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + name: "Potted Plant", + modelURL: modelURL, + position: position, + dimensions: { + x: 1.10, + y: 2.18, + z: 1.07 + }, + collisionsWillMove: true, + shapeType: 'box', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.4 + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + + + setEntityCustomData(GRABBABLE_DATA_KEY, entity, { + grabbable: false + }); + } + + + function createCombinedArmChair(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/combined_chair.fbx"; + var RED_ARM_CHAIR_COLLISION_HULL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/red_arm_chair_collision_hull.obj"; + + var rotation = Quat.fromPitchYawRollDegrees(0, -143, 0); + + var entity = Entities.addEntity({ + type: "Model", + name: "Red Arm Chair", + modelURL: modelURL, + shapeType: 'compound', + compoundShapeURL: RED_ARM_CHAIR_COLLISION_HULL, + position: position, + rotation: rotation, + dimensions: { + x: 1.26, + y: 1.56, + z: 1.35 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -0.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.2 + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, entity, { + grabbable: false + }); + } + + function createBlocks(position) { + var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/"; + var collisionSoundURL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/ToyWoodBlock.L.wav"; + var NUM_BLOCKS_PER_COLOR = 4; + var i, j; + + var blockTypes = [{ + url: "planky_blue.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_green.fbx", + dimensions: { + x: 0.1, + y: 0.1, + z: 0.25 + } + }, { + url: "planky_natural.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.05 + } + }, { + url: "planky_yellow.fbx", + dimensions: { + x: 0.03, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_red.fbx", + dimensions: { + x: 0.1, + y: 0.05, + z: 0.25 + } + }, ]; + + var modelURL, entity; + for (i = 0; i < blockTypes.length; i++) { + for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) { + modelURL = baseURL + blockTypes[i].url; + entity = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: Vec3.sum(position, { + x: j / 10, + y: i / 10, + z: 0 + }), + shapeType: 'box', + name: "block", + dimensions: blockTypes[i].dimensions, + collisionsWillMove: true, + collisionSoundURL: collisionSoundURL, + gravity: { + x: 0, + y: -2.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + } + }); + + //customKey, id, data + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + } + } + + function cleanup() { + deleteAllToys(); + } + + if (shouldDeleteOnEndScript) { + + Script.scriptEnding.connect(cleanup); + } +}; \ No newline at end of file From 7e7c6bca8d275cf05380b27d20f1d90b9abda788 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 16:01:08 -0700 Subject: [PATCH 21/34] deleting switch from client script --- unpublishedScripts/immediateClientReset.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/unpublishedScripts/immediateClientReset.js b/unpublishedScripts/immediateClientReset.js index f70ecf87d2..3debcdea82 100644 --- a/unpublishedScripts/immediateClientReset.js +++ b/unpublishedScripts/immediateClientReset.js @@ -38,5 +38,15 @@ function createHiddenMasterSwitch() { }); } + +var entities = Entities.findEntities(MyAvatar.position, 100); + +entities.forEach(function (entity) { + //params: customKey, id, defaultValue + var name = Entities.getEntityProperties(entity, "name").name + if (name === "Master Switch") { + Entities.deleteEntity(entity); + } +}); createHiddenMasterSwitch(); MasterReset(); \ No newline at end of file From bfde77747a4515d4131d5738efcb98315eddda2c Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 16:03:11 -0700 Subject: [PATCH 22/34] Not deleting reset switch unless client script runs --- unpublishedScripts/immediateClientReset.js | 4 ---- unpublishedScripts/masterReset.js | 1 - 2 files changed, 5 deletions(-) diff --git a/unpublishedScripts/immediateClientReset.js b/unpublishedScripts/immediateClientReset.js index 3debcdea82..567ef85b76 100644 --- a/unpublishedScripts/immediateClientReset.js +++ b/unpublishedScripts/immediateClientReset.js @@ -32,10 +32,6 @@ function createHiddenMasterSwitch() { z: 503.2 } }); - - setEntityCustomData(resetKey, masterSwitch, { - resetMe: true - }); } diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 95f538316a..26d57c714c 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -108,7 +108,6 @@ MasterReset = function () { y: 495.6, z: 503.91 }); - createHiddenMasterSwitch(); } From 54d82e6cc69be7bfabb9140d7c511134248a77a7 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 16:10:21 -0700 Subject: [PATCH 23/34] testing one --- unpublishedScripts/hiddenEntityReset.js | 2 +- unpublishedScripts/masterReset.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 7cae5cf088..0770f561cf 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -14,7 +14,7 @@ var _this; - var masterResetScript = Script.resolvePath("masterResetFromEntity.js"); + var masterResetScript = Script.resolvePath("masterReset.js"); Script.include(masterResetScript); ResetSwitch = function () { diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 26d57c714c..e70096ac9f 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -123,8 +123,6 @@ MasterReset = function () { }); } - - function createFire() { From 032e503be68655946b5d7aadf7e75fa0909b5066 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 16:22:13 -0700 Subject: [PATCH 24/34] change --- unpublishedScripts/hiddenEntityReset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 0770f561cf..7cae5cf088 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -14,7 +14,7 @@ var _this; - var masterResetScript = Script.resolvePath("masterReset.js"); + var masterResetScript = Script.resolvePath("masterResetFromEntity.js"); Script.include(masterResetScript); ResetSwitch = function () { From 18155f968bc2354fb01c1f69cdfd207fc1042674 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 16:29:55 -0700 Subject: [PATCH 25/34] adding logging --- unpublishedScripts/masterResetFromEntity.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/unpublishedScripts/masterResetFromEntity.js b/unpublishedScripts/masterResetFromEntity.js index 95218b995b..8ac0dd2faf 100644 --- a/unpublishedScripts/masterResetFromEntity.js +++ b/unpublishedScripts/masterResetFromEntity.js @@ -22,6 +22,8 @@ var wandScriptURL = Script.resolvePath("../examples/toys/bubblewand/wand.js"); var dollScriptURL = Script.resolvePath("../examples/toys/doll/doll.js"); var lightsScriptURL = Script.resolvePath("../examples/toys/lightSwitch.js"); +print("SPRAY CAN SCRIPT URL " + sprayPaintScriptURL); + MasterReset = function () { @@ -290,6 +292,10 @@ MasterReset = function () { collidingBalls.push(collidingBall); originalBallPositions.push(position); + + setEntityCustomData(resetKey, collidingBall, { + resetMe: true + }); } } From 3dd74a33d3c776668afd18c77f10987d4cbcb92b Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 16:50:10 -0700 Subject: [PATCH 26/34] new attempt --- unpublishedScripts/hiddenEntityReset.js | 1129 +++++++++++++++++- unpublishedScripts/immediateClientReset.js | 1 + unpublishedScripts/masterReset.js | 4 + unpublishedScripts/masterResetFromEntity.js | 1144 ------------------- 4 files changed, 1131 insertions(+), 1147 deletions(-) delete mode 100644 unpublishedScripts/masterResetFromEntity.js diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 7cae5cf088..0db85ca8bf 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -14,8 +14,13 @@ var _this; - var masterResetScript = Script.resolvePath("masterResetFromEntity.js"); - Script.include(masterResetScript); + var sprayPaintScriptURL = Script.resolvePath("../examples/toys/sprayPaintCan.js"); + var catScriptURL = Script.resolvePath("../examples/toys/cat.js"); + var flashlightScriptURL = Script.resolvePath('../examples/toys/flashlight/flashlight.js'); + var pingPongScriptURL = Script.resolvePath('../examples/toys/ping_pong_gun/pingPongGun.js'); + var wandScriptURL = Script.resolvePath("../examples/toys/bubblewand/wand.js"); + var dollScriptURL = Script.resolvePath("../examples/toys/doll/doll.js"); + var lightsScriptURL = Script.resolvePath("../examples/toys/lightSwitch.js"); ResetSwitch = function () { _this = this; @@ -45,6 +50,1124 @@ }; + + MasterReset = function () { + print("SHNUR"); + var resetKey = "resetMe"; + var GRABBABLE_DATA_KEY = "grabbableKey"; + + var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + + var shouldDeleteOnEndScript = false; + + //Before creating anything, first search a radius and delete all the things that should be deleted + deleteAllToys(); + createAllToys(); + + function createAllToys() { + createBlocks({ + x: 548.3, + y: 495.55, + z: 504.4 + }); + + createBasketBall({ + x: 547.73, + y: 495.5, + z: 505.47 + }); + + createDoll({ + x: 546.67, + y: 495.41, + z: 505.09 + }); + + createWand({ + x: 546.71, + y: 495.55, + z: 506.15 + }); + + createDice(); + + createFlashlight({ + x: 545.72, + y: 495.41, + z: 505.78 + }); + + + + createCombinedArmChair({ + x: 549.29, + y: 494.9, + z: 508.22 + }); + + createPottedPlant({ + x: 554.26, + y: 495.2, + z: 504.53 + }); + + createPingPongBallGun(); + + createBasketballHoop(); + createBasketballRack(); + + createGates(); + + createFire(); + // Handles toggling of all sconce lights + createLights(); + + + + createCat({ + x: 551.09, + y: 494.98, + z: 503.49 + }); + + + createSprayCan({ + x: 549.7, + y: 495.6, + z: 503.91 + }); + + } + + function deleteAllToys() { + var entities = Entities.findEntities(MyAvatar.position, 100); + + entities.forEach(function (entity) { + //params: customKey, id, defaultValue + var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe; + if (shouldReset === true) { + Entities.deleteEntity(entity); + } + }); + } + + function createFire() { + + + var myOrientation = Quat.fromPitchYawRollDegrees(-90, 0, 0.0); + + var animationSettings = JSON.stringify({ + fps: 30, + running: true, + loop: true, + firstFrame: 1, + lastFrame: 10000 + }); + + + var fire = Entities.addEntity({ + type: "ParticleEffect", + name: "fire", + animationSettings: animationSettings, + textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", + position: { + x: 551.45, + y: 494.82, + z: 502.05 + }, + emitRate: 100, + colorStart: { + red: 70, + green: 70, + blue: 137 + }, + color: { + red: 200, + green: 99, + blue: 42 + }, + colorFinish: { + red: 255, + green: 99, + blue: 32 + }, + radiusSpread: 0.01, + radiusStart: 0.02, + radiusEnd: 0.001, + particleRadius: 0.05, + radiusFinish: 0.0, + emitOrientation: myOrientation, + emitSpeed: 0.3, + speedSpread: 0.1, + alphaStart: 0.05, + alpha: 0.1, + alphaFinish: 0.05, + emitDimensions: { + x: 1, + y: 1, + z: 0.1 + }, + polarFinish: 0.1, + emitAcceleration: { + x: 0.0, + y: 0.0, + z: 0.0 + }, + accelerationSpread: { + x: 0.1, + y: 0.01, + z: 0.1 + }, + lifespan: 1 + }); + + + setEntityCustomData(resetKey, fire, { + resetMe: true + }); + } + + function createBasketballRack() { + var NUMBER_OF_BALLS = 4; + var DIAMETER = 0.30; + var RESET_DISTANCE = 1; + var MINIMUM_MOVE_LENGTH = 0.05; + var basketballURL = HIFI_PUBLIC_BUCKET + "models/content/basketball2.fbx"; + var basketballCollisionSoundURL = HIFI_PUBLIC_BUCKET + "sounds/basketball/basketball.wav"; + var rackURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/basketball_rack.fbx"; + var rackCollisionHullURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/rack_collision_hull.obj"; + + var rackRotation = Quat.fromPitchYawRollDegrees(0, -90, 0); + + var rackStartPosition = { + x: 542.86, + y: 494.84, + z: 475.06 + }; + var rack = Entities.addEntity({ + name: 'Basketball Rack', + type: "Model", + modelURL: rackURL, + position: rackStartPosition, + rotation: rackRotation, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + linearDamping: 1, + dimensions: { + x: 0.4, + y: 1.37, + z: 1.73 + }, + collisionsWillMove: true, + ignoreForCollisions: false, + compoundShapeURL: rackCollisionHullURL + }); + + setEntityCustomData(resetKey, rack, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, rack, { + grabbable: false + }); + + var collidingBalls = []; + var originalBallPositions = []; + + function createCollidingBalls() { + var position = rackStartPosition; + + var i; + for (i = 0; i < NUMBER_OF_BALLS; i++) { + var ballPosition = { + x: position.x, + y: position.y + DIAMETER * 2, + z: position.z + (DIAMETER) - (DIAMETER * i) + }; + + var collidingBall = Entities.addEntity({ + type: "Model", + name: 'Colliding Basketball', + shapeType: 'Sphere', + position: { + x: position.x + (DIAMETER * 2) - (DIAMETER * i), + y: position.y + DIAMETER * 2, + z: position.z + }, + dimensions: { + x: DIAMETER, + y: DIAMETER, + z: DIAMETER + }, + restitution: 1.0, + linearDamping: 0.00001, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + collisionsWillMove: true, + ignoreForCollisions: false, + modelURL: basketballURL, + }); + + collidingBalls.push(collidingBall); + originalBallPositions.push(position); + + setEntityCustomData(resetKey, collidingBall, { + resetMe: true + }); + } + } + + function testBallDistanceFromStart() { + var resetCount = 0; + + collidingBalls.forEach(function (ball, index) { + var currentPosition = Entities.getEntityProperties(ball, "position").position; + var originalPosition = originalBallPositions[index]; + var distance = Vec3.subtract(originalPosition, currentPosition); + var length = Vec3.length(distance); + + if (length > RESET_DISTANCE) { + Script.setTimeout(function () { + var newPosition = Entities.getEntityProperties(ball, "position").position; + var moving = Vec3.length(Vec3.subtract(currentPosition, newPosition)); + if (moving < MINIMUM_MOVE_LENGTH) { + resetCount++; + if (resetCount === NUMBER_OF_BALLS) { + deleteCollidingBalls(); + createCollidingBalls(); + } + } + }, 200); + } + }); + } + + function deleteEntity(entityID) { + if (entityID === rack) { + deleteCollidingBalls(); + Script.clearInterval(distanceCheckInterval); + Entities.deletingEntity.disconnect(deleteEntity); + } + } + + function deleteCollidingBalls() { + while (collidingBalls.length > 0) { + Entities.deleteEntity(collidingBalls.pop()); + } + } + + createCollidingBalls(); + Entities.deletingEntity.connect(deleteEntity); + + var distanceCheckInterval = Script.setInterval(testBallDistanceFromStart, 1000); + } + + function createCat(position) { + + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx"; + var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx"; + var animationSettings = JSON.stringify({ + running: true, + }); + var cat = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "cat", + script: catScriptURL, + animationURL: animationURL, + animationSettings: animationSettings, + position: position, + rotation: { + w: 0.35020983219146729, + x: -4.57763671875e-05, + y: 0.93664455413818359, + z: -1.52587890625e-05 + }, + dimensions: { + x: 0.15723302960395813, + y: 0.50762706995010376, + z: 0.90716040134429932 + }, + }); + + setEntityCustomData(resetKey, cat, { + resetMe: true + }); + } + + function createFlashlight(position) { + var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx"; + + var flashlight = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "flashlight", + script: flashlightScriptURL, + position: position, + dimensions: { + x: 0.08, + y: 0.30, + z: 0.08 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -3.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + shapeType: 'box', + }); + + setEntityCustomData(resetKey, flashlight, { + resetMe: true + }); + + } + + function createLights() { + var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx"; + + + var rotation = { + w: 0.63280689716339111, + x: 0.63280689716339111, + y: -0.31551080942153931, + z: 0.31548023223876953 + }; + var axis = { + x: 0, + y: 1, + z: 0 + }; + var dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); + + var lightSwitchHall = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Hall", + script: lightsScriptURL, + position: { + x: 543.27764892578125, + y: 495.67999267578125, + z: 511.00564575195312 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + } + }); + setEntityCustomData(resetKey, lightSwitchHall, { + resetMe: true, + on: true, + type: "Hall Light" + }); + + var sconceLight1 = Entities.addEntity({ + type: "Light", + position: { + x: 543.75, + y: 496.24, + z: 511.13 + }, + name: "Sconce 1 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight1, { + resetMe: true, + type: "Hall Light", + }); + + var sconceLight2 = Entities.addEntity({ + type: "Light", + position: { + x: 540.1, + y: 496.24, + z: 505.57 + }, + name: "Sconce 2 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight2, { + resetMe: true, + type: "Hall Light", + }); + + + rotation = { + w: 0.20082402229309082, + x: 0.20082402229309082, + y: -0.67800414562225342, + z: 0.67797362804412842 + }; + axis = { + x: 0, + y: 1, + z: 0 + }; + dQ = Quat.angleAxis(180, axis); + rotation = Quat.multiply(rotation, dQ); + + var lightSwitchGarage = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + name: "Light Switch Garage", + script: lightsScriptURL, + position: { + x: 545.62, + y: 495.68, + z: 500.21 + }, + rotation: rotation, + dimensions: { + x: 0.10546875, + y: 0.032372996211051941, + z: 0.16242524981498718 + } + }); + + setEntityCustomData(resetKey, lightSwitchGarage, { + resetMe: true, + on: true, + type: "Garage Light" + }); + + + var sconceLight3 = Entities.addEntity({ + type: "Light", + position: { + x: 545.49468994140625, + y: 496.24026489257812, + z: 500.63516235351562 + }, + + name: "Sconce 3 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + + + setEntityCustomData(resetKey, sconceLight3, { + resetMe: true, + type: "Garage Light", + }); + + var sconceLight4 = Entities.addEntity({ + type: "Light", + position: { + x: 550.90399169921875, + y: 496.24026489257812, + z: 507.90237426757812 + }, + name: "Sconce 4 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight4, { + resetMe: true, + type: "Garage Light", + }); + + var sconceLight5 = Entities.addEntity({ + type: "Light", + position: { + x: 548.407958984375, + y: 496.24026489257812, + z: 509.5504150390625 + }, + name: "Sconce 5 Light", + dimensions: { + x: 2.545, + y: 2.545, + z: 2.545 + }, + cutoff: 90, + color: { + red: 217, + green: 146, + blue: 24 + } + }); + + setEntityCustomData(resetKey, sconceLight5, { + resetMe: true, + type: "Garage Light", + }); + + } + + + + function createDice() { + var diceProps = { + type: "Model", + modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx", + collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", + name: "dice", + position: { + x: 541, + y: 494.96, + z: 509.1 + }, + dimensions: { + x: 0.09, + y: 0.09, + z: 0.09 + }, + gravity: { + x: 0, + y: -3.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + shapeType: "box", + collisionsWillMove: true + }; + var dice1 = Entities.addEntity(diceProps); + + diceProps.position = { + x: 541.05, + y: 494.96, + z: 509.0 + }; + + var dice2 = Entities.addEntity(diceProps); + + setEntityCustomData(resetKey, dice1, { + resetMe: true + }); + + setEntityCustomData(resetKey, dice2, { + resetMe: true + }); + } + + + function createGates() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; + + var rotation1 = Quat.fromPitchYawRollDegrees(0, 36, 0); + + var gate1 = Entities.addEntity({ + name: 'Back Door Gate', + type: 'Model', + shapeType: 'box', + modelURL: MODEL_URL, + position: { + x: 546.52, + y: 494.76, + z: 498.87 + }, + dimensions: { + x: 1.42, + y: 1.13, + z: 0.25 + }, + rotation: rotation1, + collisionsWillMove: true, + gravity: { + x: 0, + y: -50, + z: 0 + }, + linearDamping: 1, + angularDamping: 10, + mass: 10, + + }); + + setEntityCustomData(resetKey, gate1, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, gate1, { + grabbable: false + }); + + var rotation2 = Quat.fromPitchYawRollDegrees(0, -16, 0); + var gate2 = Entities.addEntity({ + name: 'Front Door Fence', + type: 'Model', + modelURL: MODEL_URL, + shapeType: 'box', + position: { + x: 531.15, + y: 495.11, + z: 520.20 + }, + dimensions: { + x: 1.42, + y: 1.13, + z: 0.2 + }, + rotation: rotation2, + collisionsWillMove: true, + gravity: { + x: 0, + y: -100, + z: 0 + }, + linearDamping: 1, + angularDamping: 10, + mass: 10, + }); + + setEntityCustomData(resetKey, gate2, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, gate2, { + grabbable: false + }); + } + + function createPingPongBallGun() { + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'; + var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; + + var position = { + x: 548.6, + y: 495.4, + z: 503.39 + }; + + var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); + + var pingPongGun = Entities.addEntity({ + type: "Model", + modelURL: MODEL_URL, + shapeType: 'box', + script: pingPongScriptURL, + position: position, + rotation: rotation, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 0.08, + y: 0.21, + z: 0.47 + }, + collisionsWillMove: true, + }); + + setEntityCustomData(resetKey, pingPongGun, { + resetMe: true + }); + } + + function createBasketballHoop() { + var position = { + x: 539.23, + y: 496.13, + z: 475.89 + }; + var rotation = Quat.fromPitchYawRollDegrees(0, 58.49, 0); + + var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; + var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; + + var hoop = Entities.addEntity({ + type: "Model", + modelURL: hoopURL, + position: position, + rotation: rotation, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 1.89, + y: 3.99, + z: 3.79 + }, + compoundShapeURL: hoopCollisionHullURL + }); + + setEntityCustomData(resetKey, hoop, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, hoop, { + grabbable: false + }); + } + + function createWand(position) { + var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; + var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/actual_no_top_collision_hull.obj'; + + var entity = Entities.addEntity({ + name: 'Bubble Wand', + type: "Model", + modelURL: WAND_MODEL, + position: position, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 0.05, + y: 0.25, + z: 0.05 + }, + //must be enabled to be grabbable in the physics engine + shapeType: 'compound', + collisionsWillMove: true, + compoundShapeURL: WAND_COLLISION_SHAPE, + //Look into why bubble wand is going through table when gravity is enabled + // gravity: {x: 0, y: -3.5, z: 0}, + // velocity: {x: 0, y: -0.01, z:0}, + script: wandScriptURL + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + + function createBasketBall(position) { + + var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: position, + collisionsWillMove: true, + shapeType: "sphere", + name: "basketball", + dimensions: { + x: 0.25, + y: 0.26, + z: 0.25 + }, + gravity: { + x: 0, + y: -7, + z: 0 + }, + restitution: 10, + linearDamping: 0.0, + velocity: { + x: 0, + y: -0.01, + z: 0 + }, + collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/basketball/basketball.wav" + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + + function createDoll(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"; + + var naturalDimensions = { + x: 1.63, + y: 1.67, + z: 0.26 + }; + var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15); + var entity = Entities.addEntity({ + type: "Model", + name: "doll", + modelURL: modelURL, + script: dollScriptURL, + position: position, + shapeType: 'box', + dimensions: desiredDimensions, + gravity: { + x: 0, + y: -5, + z: 0 + }, + velocity: { + x: 0, + y: -0.1, + z: 0 + }, + collisionsWillMove: true + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + + function createSprayCan(position) { + + var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + name: "spraycan", + script: sprayPaintScriptURL, + modelURL: modelURL, + position: position, + dimensions: { + x: 0.07, + y: 0.17, + z: 0.07 + }, + collisionsWillMove: true, + shapeType: 'box', + gravity: { + x: 0, + y: -0.5, + z: 0 + }, + velocity: { + x: 0, + y: -1, + z: 0 + } + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + + } + + function createPottedPlant(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/potted_plant/potted_plant.fbx"; + + var entity = Entities.addEntity({ + type: "Model", + name: "Potted Plant", + modelURL: modelURL, + position: position, + dimensions: { + x: 1.10, + y: 2.18, + z: 1.07 + }, + collisionsWillMove: true, + shapeType: 'box', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.4 + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + + + setEntityCustomData(GRABBABLE_DATA_KEY, entity, { + grabbable: false + }); + } + + + function createCombinedArmChair(position) { + var modelURL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/combined_chair.fbx"; + var RED_ARM_CHAIR_COLLISION_HULL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/red_arm_chair_collision_hull.obj"; + + var rotation = Quat.fromPitchYawRollDegrees(0, -143, 0); + + var entity = Entities.addEntity({ + type: "Model", + name: "Red Arm Chair", + modelURL: modelURL, + shapeType: 'compound', + compoundShapeURL: RED_ARM_CHAIR_COLLISION_HULL, + position: position, + rotation: rotation, + dimensions: { + x: 1.26, + y: 1.56, + z: 1.35 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -0.8, + z: 0 + }, + velocity: { + x: 0, + y: 0, + z: 0 + }, + linearDamping: 0.2 + }); + + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + + setEntityCustomData(GRABBABLE_DATA_KEY, entity, { + grabbable: false + }); + } + + function createBlocks(position) { + var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/"; + var collisionSoundURL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/ToyWoodBlock.L.wav"; + var NUM_BLOCKS_PER_COLOR = 4; + var i, j; + + var blockTypes = [{ + url: "planky_blue.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_green.fbx", + dimensions: { + x: 0.1, + y: 0.1, + z: 0.25 + } + }, { + url: "planky_natural.fbx", + dimensions: { + x: 0.05, + y: 0.05, + z: 0.05 + } + }, { + url: "planky_yellow.fbx", + dimensions: { + x: 0.03, + y: 0.05, + z: 0.25 + } + }, { + url: "planky_red.fbx", + dimensions: { + x: 0.1, + y: 0.05, + z: 0.25 + } + }, ]; + + var modelURL, entity; + for (i = 0; i < blockTypes.length; i++) { + for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) { + modelURL = baseURL + blockTypes[i].url; + entity = Entities.addEntity({ + type: "Model", + modelURL: modelURL, + position: Vec3.sum(position, { + x: j / 10, + y: i / 10, + z: 0 + }), + shapeType: 'box', + name: "block", + dimensions: blockTypes[i].dimensions, + collisionsWillMove: true, + collisionSoundURL: collisionSoundURL, + gravity: { + x: 0, + y: -2.5, + z: 0 + }, + velocity: { + x: 0, + y: -0.01, + z: 0 + } + }); + + //customKey, id, data + setEntityCustomData(resetKey, entity, { + resetMe: true + }); + } + } + } + + function cleanup() { + deleteAllToys(); + } + + if (shouldDeleteOnEndScript) { + + Script.scriptEnding.connect(cleanup); + } + }; + // entity scripts always need to return a newly constructed object of our type return new ResetSwitch(); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/unpublishedScripts/immediateClientReset.js b/unpublishedScripts/immediateClientReset.js index 567ef85b76..f88a9dcda7 100644 --- a/unpublishedScripts/immediateClientReset.js +++ b/unpublishedScripts/immediateClientReset.js @@ -5,6 +5,7 @@ var masterResetScript = Script.resolvePath("masterReset.js"); var hiddenEntityScriptURL = Script.resolvePath("hiddenEntityReset.js"); + Script.include(masterResetScript); diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index e70096ac9f..89f9fd3e1e 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -289,6 +289,10 @@ MasterReset = function () { collidingBalls.push(collidingBall); originalBallPositions.push(position); + + setEntityCustomData(resetKey, collidingBall, { + resetMe: true + }); } } diff --git a/unpublishedScripts/masterResetFromEntity.js b/unpublishedScripts/masterResetFromEntity.js deleted file mode 100644 index 8ac0dd2faf..0000000000 --- a/unpublishedScripts/masterResetFromEntity.js +++ /dev/null @@ -1,1144 +0,0 @@ -// masterReset.js -// Created by Eric Levin on 9/23/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 -// - -/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ -//per script - - -/*global deleteAllToys, createAllToys, createGates, createPingPongBallGun, createFire, createPottedPlant, createCombinedArmChair, createBasketballHoop, createBasketBall, createSprayCan, createDoll, createWand, createDice, createCat, deleteAllToys, createFlashlight, createBlocks, createMagballs, createLights */ -var utilitiesScript = Script.resolvePath("../examples/libraries/utils.js"); -Script.include(utilitiesScript); - -var sprayPaintScriptURL = Script.resolvePath("../examples/toys/sprayPaintCan.js"); -var catScriptURL = Script.resolvePath("../examples/toys/cat.js"); -var flashlightScriptURL = Script.resolvePath('../examples/toys/flashlight/flashlight.js'); -var pingPongScriptURL = Script.resolvePath('../examples/toys/ping_pong_gun/pingPongGun.js'); -var wandScriptURL = Script.resolvePath("../examples/toys/bubblewand/wand.js"); -var dollScriptURL = Script.resolvePath("../examples/toys/doll/doll.js"); -var lightsScriptURL = Script.resolvePath("../examples/toys/lightSwitch.js"); - -print("SPRAY CAN SCRIPT URL " + sprayPaintScriptURL); - - - -MasterReset = function () { - var resetKey = "resetMe"; - var GRABBABLE_DATA_KEY = "grabbableKey"; - - var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; - - var shouldDeleteOnEndScript = false; - - //Before creating anything, first search a radius and delete all the things that should be deleted - deleteAllToys(); - createAllToys(); - - function createAllToys() { - createBlocks({ - x: 548.3, - y: 495.55, - z: 504.4 - }); - - createBasketBall({ - x: 547.73, - y: 495.5, - z: 505.47 - }); - - createDoll({ - x: 546.67, - y: 495.41, - z: 505.09 - }); - - createWand({ - x: 546.71, - y: 495.55, - z: 506.15 - }); - - createDice(); - - createFlashlight({ - x: 545.72, - y: 495.41, - z: 505.78 - }); - - - - createCombinedArmChair({ - x: 549.29, - y: 494.9, - z: 508.22 - }); - - createPottedPlant({ - x: 554.26, - y: 495.2, - z: 504.53 - }); - - createPingPongBallGun(); - - createBasketballHoop(); - createBasketballRack(); - - createGates(); - - createFire(); - // Handles toggling of all sconce lights - createLights(); - - - - createCat({ - x: 551.09, - y: 494.98, - z: 503.49 - }); - - - createSprayCan({ - x: 549.7, - y: 495.6, - z: 503.91 - }); - - } - - function deleteAllToys() { - var entities = Entities.findEntities(MyAvatar.position, 100); - - entities.forEach(function (entity) { - //params: customKey, id, defaultValue - var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe; - if (shouldReset === true) { - Entities.deleteEntity(entity); - } - }); - } - - - function createFire() { - - - var myOrientation = Quat.fromPitchYawRollDegrees(-90, 0, 0.0); - - var animationSettings = JSON.stringify({ - fps: 30, - running: true, - loop: true, - firstFrame: 1, - lastFrame: 10000 - }); - - - var fire = Entities.addEntity({ - type: "ParticleEffect", - name: "fire", - animationSettings: animationSettings, - textures: "https://hifi-public.s3.amazonaws.com/alan/Particles/Particle-Sprite-Smoke-1.png", - position: { - x: 551.45, - y: 494.82, - z: 502.05 - }, - emitRate: 100, - colorStart: { - red: 70, - green: 70, - blue: 137 - }, - color: { - red: 200, - green: 99, - blue: 42 - }, - colorFinish: { - red: 255, - green: 99, - blue: 32 - }, - radiusSpread: 0.01, - radiusStart: 0.02, - radiusEnd: 0.001, - particleRadius: 0.05, - radiusFinish: 0.0, - emitOrientation: myOrientation, - emitSpeed: 0.3, - speedSpread: 0.1, - alphaStart: 0.05, - alpha: 0.1, - alphaFinish: 0.05, - emitDimensions: { - x: 1, - y: 1, - z: 0.1 - }, - polarFinish: 0.1, - emitAcceleration: { - x: 0.0, - y: 0.0, - z: 0.0 - }, - accelerationSpread: { - x: 0.1, - y: 0.01, - z: 0.1 - }, - lifespan: 1 - }); - - - setEntityCustomData(resetKey, fire, { - resetMe: true - }); - } - - function createBasketballRack() { - var NUMBER_OF_BALLS = 4; - var DIAMETER = 0.30; - var RESET_DISTANCE = 1; - var MINIMUM_MOVE_LENGTH = 0.05; - var basketballURL = HIFI_PUBLIC_BUCKET + "models/content/basketball2.fbx"; - var basketballCollisionSoundURL = HIFI_PUBLIC_BUCKET + "sounds/basketball/basketball.wav"; - var rackURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/basketball_rack.fbx"; - var rackCollisionHullURL = HIFI_PUBLIC_BUCKET + "models/basketball_hoop/rack_collision_hull.obj"; - - var rackRotation = Quat.fromPitchYawRollDegrees(0, -90, 0); - - var rackStartPosition = { - x: 542.86, - y: 494.84, - z: 475.06 - }; - var rack = Entities.addEntity({ - name: 'Basketball Rack', - type: "Model", - modelURL: rackURL, - position: rackStartPosition, - rotation: rackRotation, - shapeType: 'compound', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - linearDamping: 1, - dimensions: { - x: 0.4, - y: 1.37, - z: 1.73 - }, - collisionsWillMove: true, - ignoreForCollisions: false, - compoundShapeURL: rackCollisionHullURL - }); - - setEntityCustomData(resetKey, rack, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, rack, { - grabbable: false - }); - - var collidingBalls = []; - var originalBallPositions = []; - - function createCollidingBalls() { - var position = rackStartPosition; - - var i; - for (i = 0; i < NUMBER_OF_BALLS; i++) { - var ballPosition = { - x: position.x, - y: position.y + DIAMETER * 2, - z: position.z + (DIAMETER) - (DIAMETER * i) - }; - - var collidingBall = Entities.addEntity({ - type: "Model", - name: 'Colliding Basketball', - shapeType: 'Sphere', - position: { - x: position.x + (DIAMETER * 2) - (DIAMETER * i), - y: position.y + DIAMETER * 2, - z: position.z - }, - dimensions: { - x: DIAMETER, - y: DIAMETER, - z: DIAMETER - }, - restitution: 1.0, - linearDamping: 0.00001, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - collisionsWillMove: true, - ignoreForCollisions: false, - modelURL: basketballURL, - }); - - collidingBalls.push(collidingBall); - originalBallPositions.push(position); - - setEntityCustomData(resetKey, collidingBall, { - resetMe: true - }); - } - } - - function testBallDistanceFromStart() { - var resetCount = 0; - - collidingBalls.forEach(function (ball, index) { - var currentPosition = Entities.getEntityProperties(ball, "position").position; - var originalPosition = originalBallPositions[index]; - var distance = Vec3.subtract(originalPosition, currentPosition); - var length = Vec3.length(distance); - - if (length > RESET_DISTANCE) { - Script.setTimeout(function () { - var newPosition = Entities.getEntityProperties(ball, "position").position; - var moving = Vec3.length(Vec3.subtract(currentPosition, newPosition)); - if (moving < MINIMUM_MOVE_LENGTH) { - resetCount++; - if (resetCount === NUMBER_OF_BALLS) { - deleteCollidingBalls(); - createCollidingBalls(); - } - } - }, 200); - } - }); - } - - function deleteEntity(entityID) { - if (entityID === rack) { - deleteCollidingBalls(); - Script.clearInterval(distanceCheckInterval); - Entities.deletingEntity.disconnect(deleteEntity); - } - } - - function deleteCollidingBalls() { - while (collidingBalls.length > 0) { - Entities.deleteEntity(collidingBalls.pop()); - } - } - - createCollidingBalls(); - Entities.deletingEntity.connect(deleteEntity); - - var distanceCheckInterval = Script.setInterval(testBallDistanceFromStart, 1000); - } - - function createCat(position) { - - var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx"; - var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx"; - var animationSettings = JSON.stringify({ - running: true, - }); - var cat = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "cat", - script: catScriptURL, - animationURL: animationURL, - animationSettings: animationSettings, - position: position, - rotation: { - w: 0.35020983219146729, - x: -4.57763671875e-05, - y: 0.93664455413818359, - z: -1.52587890625e-05 - }, - dimensions: { - x: 0.15723302960395813, - y: 0.50762706995010376, - z: 0.90716040134429932 - }, - }); - - setEntityCustomData(resetKey, cat, { - resetMe: true - }); - } - - function createFlashlight(position) { - var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx"; - - var flashlight = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "flashlight", - script: flashlightScriptURL, - position: position, - dimensions: { - x: 0.08, - y: 0.30, - z: 0.08 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -3.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - shapeType: 'box', - }); - - setEntityCustomData(resetKey, flashlight, { - resetMe: true - }); - - } - - function createLights() { - var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx"; - - - var rotation = { - w: 0.63280689716339111, - x: 0.63280689716339111, - y: -0.31551080942153931, - z: 0.31548023223876953 - }; - var axis = { - x: 0, - y: 1, - z: 0 - }; - var dQ = Quat.angleAxis(180, axis); - rotation = Quat.multiply(rotation, dQ); - - var lightSwitchHall = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "Light Switch Hall", - script: lightsScriptURL, - position: { - x: 543.27764892578125, - y: 495.67999267578125, - z: 511.00564575195312 - }, - rotation: rotation, - dimensions: { - x: 0.10546875, - y: 0.032372996211051941, - z: 0.16242524981498718 - } - }); - setEntityCustomData(resetKey, lightSwitchHall, { - resetMe: true, - on: true, - type: "Hall Light" - }); - - var sconceLight1 = Entities.addEntity({ - type: "Light", - position: { - x: 543.75, - y: 496.24, - z: 511.13 - }, - name: "Sconce 1 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - setEntityCustomData(resetKey, sconceLight1, { - resetMe: true, - type: "Hall Light", - }); - - var sconceLight2 = Entities.addEntity({ - type: "Light", - position: { - x: 540.1, - y: 496.24, - z: 505.57 - }, - name: "Sconce 2 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - setEntityCustomData(resetKey, sconceLight2, { - resetMe: true, - type: "Hall Light", - }); - - - rotation = { - w: 0.20082402229309082, - x: 0.20082402229309082, - y: -0.67800414562225342, - z: 0.67797362804412842 - }; - axis = { - x: 0, - y: 1, - z: 0 - }; - dQ = Quat.angleAxis(180, axis); - rotation = Quat.multiply(rotation, dQ); - - var lightSwitchGarage = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - name: "Light Switch Garage", - script: lightsScriptURL, - position: { - x: 545.62, - y: 495.68, - z: 500.21 - }, - rotation: rotation, - dimensions: { - x: 0.10546875, - y: 0.032372996211051941, - z: 0.16242524981498718 - } - }); - - setEntityCustomData(resetKey, lightSwitchGarage, { - resetMe: true, - on: true, - type: "Garage Light" - }); - - - var sconceLight3 = Entities.addEntity({ - type: "Light", - position: { - x: 545.49468994140625, - y: 496.24026489257812, - z: 500.63516235351562 - }, - - name: "Sconce 3 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - - - setEntityCustomData(resetKey, sconceLight3, { - resetMe: true, - type: "Garage Light", - }); - - var sconceLight4 = Entities.addEntity({ - type: "Light", - position: { - x: 550.90399169921875, - y: 496.24026489257812, - z: 507.90237426757812 - }, - name: "Sconce 4 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - setEntityCustomData(resetKey, sconceLight4, { - resetMe: true, - type: "Garage Light", - }); - - var sconceLight5 = Entities.addEntity({ - type: "Light", - position: { - x: 548.407958984375, - y: 496.24026489257812, - z: 509.5504150390625 - }, - name: "Sconce 5 Light", - dimensions: { - x: 2.545, - y: 2.545, - z: 2.545 - }, - cutoff: 90, - color: { - red: 217, - green: 146, - blue: 24 - } - }); - - setEntityCustomData(resetKey, sconceLight5, { - resetMe: true, - type: "Garage Light", - }); - - } - - - - function createDice() { - var diceProps = { - type: "Model", - modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx", - collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", - name: "dice", - position: { - x: 541, - y: 494.96, - z: 509.1 - }, - dimensions: { - x: 0.09, - y: 0.09, - z: 0.09 - }, - gravity: { - x: 0, - y: -3.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - shapeType: "box", - collisionsWillMove: true - }; - var dice1 = Entities.addEntity(diceProps); - - diceProps.position = { - x: 541.05, - y: 494.96, - z: 509.0 - }; - - var dice2 = Entities.addEntity(diceProps); - - setEntityCustomData(resetKey, dice1, { - resetMe: true - }); - - setEntityCustomData(resetKey, dice2, { - resetMe: true - }); - } - - - function createGates() { - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; - - var rotation1 = Quat.fromPitchYawRollDegrees(0, 36, 0); - - var gate1 = Entities.addEntity({ - name: 'Back Door Gate', - type: 'Model', - shapeType: 'box', - modelURL: MODEL_URL, - position: { - x: 546.52, - y: 494.76, - z: 498.87 - }, - dimensions: { - x: 1.42, - y: 1.13, - z: 0.25 - }, - rotation: rotation1, - collisionsWillMove: true, - gravity: { - x: 0, - y: -50, - z: 0 - }, - linearDamping: 1, - angularDamping: 10, - mass: 10, - - }); - - setEntityCustomData(resetKey, gate1, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, gate1, { - grabbable: false - }); - - var rotation2 = Quat.fromPitchYawRollDegrees(0, -16, 0); - var gate2 = Entities.addEntity({ - name: 'Front Door Fence', - type: 'Model', - modelURL: MODEL_URL, - shapeType: 'box', - position: { - x: 531.15, - y: 495.11, - z: 520.20 - }, - dimensions: { - x: 1.42, - y: 1.13, - z: 0.2 - }, - rotation: rotation2, - collisionsWillMove: true, - gravity: { - x: 0, - y: -100, - z: 0 - }, - linearDamping: 1, - angularDamping: 10, - mass: 10, - }); - - setEntityCustomData(resetKey, gate2, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, gate2, { - grabbable: false - }); - } - - function createPingPongBallGun() { - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'; - var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; - - var position = { - x: 548.6, - y: 495.4, - z: 503.39 - }; - - var rotation = Quat.fromPitchYawRollDegrees(0, 36, 0); - - var pingPongGun = Entities.addEntity({ - type: "Model", - modelURL: MODEL_URL, - shapeType: 'box', - script: pingPongScriptURL, - position: position, - rotation: rotation, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - dimensions: { - x: 0.08, - y: 0.21, - z: 0.47 - }, - collisionsWillMove: true, - }); - - setEntityCustomData(resetKey, pingPongGun, { - resetMe: true - }); - } - - function createBasketballHoop() { - var position = { - x: 539.23, - y: 496.13, - z: 475.89 - }; - var rotation = Quat.fromPitchYawRollDegrees(0, 58.49, 0); - - var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; - var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; - - var hoop = Entities.addEntity({ - type: "Model", - modelURL: hoopURL, - position: position, - rotation: rotation, - shapeType: 'compound', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - dimensions: { - x: 1.89, - y: 3.99, - z: 3.79 - }, - compoundShapeURL: hoopCollisionHullURL - }); - - setEntityCustomData(resetKey, hoop, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, hoop, { - grabbable: false - }); - } - - function createWand(position) { - var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx'; - var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/actual_no_top_collision_hull.obj'; - - var entity = Entities.addEntity({ - name: 'Bubble Wand', - type: "Model", - modelURL: WAND_MODEL, - position: position, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - dimensions: { - x: 0.05, - y: 0.25, - z: 0.05 - }, - //must be enabled to be grabbable in the physics engine - shapeType: 'compound', - collisionsWillMove: true, - compoundShapeURL: WAND_COLLISION_SHAPE, - //Look into why bubble wand is going through table when gravity is enabled - // gravity: {x: 0, y: -3.5, z: 0}, - // velocity: {x: 0, y: -0.01, z:0}, - script: wandScriptURL - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); - } - - function createBasketBall(position) { - - var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - position: position, - collisionsWillMove: true, - shapeType: "sphere", - name: "basketball", - dimensions: { - x: 0.25, - y: 0.26, - z: 0.25 - }, - gravity: { - x: 0, - y: -7, - z: 0 - }, - restitution: 10, - linearDamping: 0.0, - velocity: { - x: 0, - y: -0.01, - z: 0 - }, - collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/basketball/basketball.wav" - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); - } - - function createDoll(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx"; - - var naturalDimensions = { - x: 1.63, - y: 1.67, - z: 0.26 - }; - var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15); - var entity = Entities.addEntity({ - type: "Model", - name: "doll", - modelURL: modelURL, - script: dollScriptURL, - position: position, - shapeType: 'box', - dimensions: desiredDimensions, - gravity: { - x: 0, - y: -5, - z: 0 - }, - velocity: { - x: 0, - y: -0.1, - z: 0 - }, - collisionsWillMove: true - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); - } - - function createSprayCan(position) { - - var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - name: "spraycan", - script: sprayPaintScriptURL, - modelURL: modelURL, - position: position, - dimensions: { - x: 0.07, - y: 0.17, - z: 0.07 - }, - collisionsWillMove: true, - shapeType: 'box', - gravity: { - x: 0, - y: -0.5, - z: 0 - }, - velocity: { - x: 0, - y: -1, - z: 0 - } - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); - - } - - function createPottedPlant(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/potted_plant/potted_plant.fbx"; - - var entity = Entities.addEntity({ - type: "Model", - name: "Potted Plant", - modelURL: modelURL, - position: position, - dimensions: { - x: 1.10, - y: 2.18, - z: 1.07 - }, - collisionsWillMove: true, - shapeType: 'box', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - velocity: { - x: 0, - y: 0, - z: 0 - }, - linearDamping: 0.4 - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); - - - setEntityCustomData(GRABBABLE_DATA_KEY, entity, { - grabbable: false - }); - } - - - function createCombinedArmChair(position) { - var modelURL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/combined_chair.fbx"; - var RED_ARM_CHAIR_COLLISION_HULL = "http://hifi-public.s3.amazonaws.com/models/red_arm_chair/red_arm_chair_collision_hull.obj"; - - var rotation = Quat.fromPitchYawRollDegrees(0, -143, 0); - - var entity = Entities.addEntity({ - type: "Model", - name: "Red Arm Chair", - modelURL: modelURL, - shapeType: 'compound', - compoundShapeURL: RED_ARM_CHAIR_COLLISION_HULL, - position: position, - rotation: rotation, - dimensions: { - x: 1.26, - y: 1.56, - z: 1.35 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -0.8, - z: 0 - }, - velocity: { - x: 0, - y: 0, - z: 0 - }, - linearDamping: 0.2 - }); - - setEntityCustomData(resetKey, entity, { - resetMe: true - }); - - setEntityCustomData(GRABBABLE_DATA_KEY, entity, { - grabbable: false - }); - } - - function createBlocks(position) { - var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/"; - var collisionSoundURL = "https://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/ToyWoodBlock.L.wav"; - var NUM_BLOCKS_PER_COLOR = 4; - var i, j; - - var blockTypes = [{ - url: "planky_blue.fbx", - dimensions: { - x: 0.05, - y: 0.05, - z: 0.25 - } - }, { - url: "planky_green.fbx", - dimensions: { - x: 0.1, - y: 0.1, - z: 0.25 - } - }, { - url: "planky_natural.fbx", - dimensions: { - x: 0.05, - y: 0.05, - z: 0.05 - } - }, { - url: "planky_yellow.fbx", - dimensions: { - x: 0.03, - y: 0.05, - z: 0.25 - } - }, { - url: "planky_red.fbx", - dimensions: { - x: 0.1, - y: 0.05, - z: 0.25 - } - }, ]; - - var modelURL, entity; - for (i = 0; i < blockTypes.length; i++) { - for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) { - modelURL = baseURL + blockTypes[i].url; - entity = Entities.addEntity({ - type: "Model", - modelURL: modelURL, - position: Vec3.sum(position, { - x: j / 10, - y: i / 10, - z: 0 - }), - shapeType: 'box', - name: "block", - dimensions: blockTypes[i].dimensions, - collisionsWillMove: true, - collisionSoundURL: collisionSoundURL, - gravity: { - x: 0, - y: -2.5, - z: 0 - }, - velocity: { - x: 0, - y: -0.01, - z: 0 - } - }); - - //customKey, id, data - setEntityCustomData(resetKey, entity, { - resetMe: true - }); - } - } - } - - function cleanup() { - deleteAllToys(); - } - - if (shouldDeleteOnEndScript) { - - Script.scriptEnding.connect(cleanup); - } -}; \ No newline at end of file From f230dcd1c0b5f7cdb8c9b4f5e7c33e9e5afd5ada Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 17:07:43 -0700 Subject: [PATCH 27/34] Fixed headers --- unpublishedScripts/hiddenEntityReset.js | 3 +-- unpublishedScripts/immediateClientReset.js | 9 ++++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 0db85ca8bf..d053caa2ff 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -1,5 +1,5 @@ // -// ResetSwitch.js +// hiddenEntityReset.js // // Created by Eric Levin on 10/2/15. // Copyright 2015 High Fidelity, Inc. @@ -52,7 +52,6 @@ MasterReset = function () { - print("SHNUR"); var resetKey = "resetMe"; var GRABBABLE_DATA_KEY = "grabbableKey"; diff --git a/unpublishedScripts/immediateClientReset.js b/unpublishedScripts/immediateClientReset.js index f88a9dcda7..89464b8c6b 100644 --- a/unpublishedScripts/immediateClientReset.js +++ b/unpublishedScripts/immediateClientReset.js @@ -1,6 +1,13 @@ +// immediateClientReset.js +// Created by Eric Levin on 9/23/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 +// + /*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ -/*global MasterReset */ var masterResetScript = Script.resolvePath("masterReset.js"); var hiddenEntityScriptURL = Script.resolvePath("hiddenEntityReset.js"); From 3e822dbfc64561d3d37bd799b47c09459137ddce Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 18:03:17 -0700 Subject: [PATCH 28/34] Adding far grab event to reset switch --- unpublishedScripts/hiddenEntityReset.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index d053caa2ff..90e4bc1bf8 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -40,6 +40,10 @@ this.triggerReset(); }, + startFarGrabNonColliding: function () { + this.triggerReset(); + }, + triggerReset: function () { MasterReset(); }, From efc2dfb68fcc65a4333dd1e38fda1fc5f96b9d32 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 7 Oct 2015 18:06:37 -0700 Subject: [PATCH 29/34] Added grab far events for non physical objects --- examples/controllers/handControllerGrab.js | 219 +++++++++++++-------- 1 file changed, 137 insertions(+), 82 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index cdcb15d9dc..7df88a68ca 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -77,7 +77,9 @@ var STATE_NEAR_GRABBING = 4; var STATE_CONTINUE_NEAR_GRABBING = 5; var STATE_NEAR_GRABBING_NON_COLLIDING = 6; var STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING = 7; -var STATE_RELEASE = 8; +var STATE_FAR_GRABBING_NON_COLLIDING = 8; +var STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING = 9; +var STATE_RELEASE = 10; var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js @@ -120,7 +122,7 @@ function MyController(hand, triggerAction) { var TIP_CONTROLLER_OFFSET = 1; this.triggerAction = triggerAction; this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand; - this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; + this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET; this.actionID = null; // action this script created... this.grabbedEntity = null; // on this entity. @@ -131,49 +133,55 @@ function MyController(hand, triggerAction) { var _this = this; - this.update = function() { + this.update = function () { this.updateSmoothedTrigger(); switch (this.state) { - case STATE_OFF: - this.off(); - this.touchTest(); - break; - case STATE_SEARCHING: - this.search(); - break; - case STATE_DISTANCE_HOLDING: - this.distanceHolding(); - break; - case STATE_CONTINUE_DISTANCE_HOLDING: - this.continueDistanceHolding(); - break; - case STATE_NEAR_GRABBING: - this.nearGrabbing(); - break; - case STATE_CONTINUE_NEAR_GRABBING: - this.continueNearGrabbing(); - break; - case STATE_NEAR_GRABBING_NON_COLLIDING: - this.nearGrabbingNonColliding(); - break; - case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: - this.continueNearGrabbingNonColliding(); - break; - case STATE_RELEASE: - this.release(); - break; + case STATE_OFF: + this.off(); + this.touchTest(); + break; + case STATE_SEARCHING: + this.search(); + break; + case STATE_DISTANCE_HOLDING: + this.distanceHolding(); + break; + case STATE_CONTINUE_DISTANCE_HOLDING: + this.continueDistanceHolding(); + break; + case STATE_NEAR_GRABBING: + this.nearGrabbing(); + break; + case STATE_CONTINUE_NEAR_GRABBING: + this.continueNearGrabbing(); + break; + case STATE_NEAR_GRABBING_NON_COLLIDING: + this.nearGrabbingNonColliding(); + break; + case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: + this.continueNearGrabbingNonColliding(); + break; + case STATE_FAR_GRABBING_NON_COLLIDING: + this.farGrabbingNonColliding(); + break; + case STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING: + this.continueFarGrabbingNonColliding(); + break; + case STATE_RELEASE: + this.release(); + break; } }; - this.setState = function(newState) { + this.setState = function (newState) { // print("STATE: " + this.state + " --> " + newState); this.state = newState; } - this.lineOn = function(closePoint, farPoint, color) { + this.lineOn = function (closePoint, farPoint, color) { // draw a line if (this.pointer === null) { this.pointer = Entities.addEntity({ @@ -197,41 +205,41 @@ function MyController(hand, triggerAction) { }; - this.lineOff = function() { + this.lineOff = function () { if (this.pointer !== null) { Entities.deleteEntity(this.pointer); } this.pointer = null; }; - this.updateSmoothedTrigger = function() { + this.updateSmoothedTrigger = function () { var triggerValue = Controller.getActionValue(this.triggerAction); // smooth out trigger value this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); } - - this.triggerSmoothedSqueezed = function() { + + this.triggerSmoothedSqueezed = function () { return this.triggerValue > TRIGGER_ON_VALUE; }; - this.triggerSmoothedReleased = function() { + this.triggerSmoothedReleased = function () { return this.triggerValue < TRIGGER_OFF_VALUE; }; - this.triggerSqueezed = function() { + this.triggerSqueezed = function () { var triggerValue = Controller.getActionValue(this.triggerAction); return triggerValue > TRIGGER_ON_VALUE; }; - this.off = function() { + this.off = function () { if (this.triggerSmoothedSqueezed()) { this.setState(STATE_SEARCHING); return; } } - this.search = function() { + this.search = function () { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -251,9 +259,7 @@ function MyController(hand, triggerAction) { }; var intersection = Entities.findRayIntersection(pickRay, true); - if (intersection.intersects && - intersection.properties.collisionsWillMove === 1 && - intersection.properties.locked === 0) { + if (intersection.intersects && intersection.properties.locked === 0) { // the ray is intersecting something we can move. var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var intersectionDistance = Vec3.distance(handControllerPosition, intersection.intersection); @@ -266,14 +272,22 @@ function MyController(hand, triggerAction) { } if (intersectionDistance < NEAR_PICK_MAX_DISTANCE) { // the hand is very close to the intersected object. go into close-grabbing mode. - this.setState(STATE_NEAR_GRABBING); + if (intersection.properties.collisionsWillMove === 1) { + this.setState(STATE_NEAR_GRABBING); + } else { + this.setState(STATE_NEAR_GRABBING_NON_COLLIDING); + } } else { // don't allow two people to distance grab the same object if (entityIsGrabbedByOther(intersection.entityID)) { this.grabbedEntity = null; } else { // the hand is far from the intersected object. go into distance-holding mode - this.setState(STATE_DISTANCE_HOLDING); + if (intersection.properties.collisionsWillMove === 1) { + this.setState(STATE_DISTANCE_HOLDING); + } else { + this.setState(STATE_FAR_GRABBING_NON_COLLIDING); + } } } } else { @@ -308,12 +322,13 @@ function MyController(hand, triggerAction) { } }; - this.distanceHolding = function() { + this.distanceHolding = function () { var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", - "gravity", "ignoreForCollisions"]); + "gravity", "ignoreForCollisions" + ]); // add the action and initialize some variables this.currentObjectPosition = grabbedProperties.position; @@ -351,7 +366,7 @@ function MyController(hand, triggerAction) { }; - this.continueDistanceHolding = function() { + this.continueDistanceHolding = function () { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -369,19 +384,19 @@ function MyController(hand, triggerAction) { // how far did avatar move this timestep? var currentPosition = MyAvatar.position; - var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition); + var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition); this.currentAvatarPosition = currentPosition; - + // How far did the avatar turn this timestep? // Note: The following code is too long because we need a Quat.quatBetween() function // that returns the minimum quaternion between two quaternions. var currentOrientation = MyAvatar.orientation; if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) { - var negativeCurrentOrientation = { - x: -currentOrientation.x, - y: -currentOrientation.y, - z: -currentOrientation.z, - w: -currentOrientation.w + var negativeCurrentOrientation = { + x: -currentOrientation.x, + y: -currentOrientation.y, + z: -currentOrientation.z, + w: -currentOrientation.w }; var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation)); } else { @@ -389,8 +404,8 @@ function MyController(hand, triggerAction) { } var handToAvatar = Vec3.subtract(handControllerPosition, this.currentAvatarPosition); var objectToAvatar = Vec3.subtract(this.currentObjectPosition, this.currentAvatarPosition); - var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar); - var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar); + var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar); + var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar); this.currentAvatarOrientation = currentOrientation; // how far did hand move this timestep? @@ -411,7 +426,7 @@ function MyController(hand, triggerAction) { var now = Date.now(); var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds this.computeReleaseVelocity(deltaPosition, deltaTime, false); - + this.currentObjectPosition = newObjectPosition; this.currentObjectTime = now; @@ -431,7 +446,7 @@ function MyController(hand, triggerAction) { }); }; - this.nearGrabbing = function() { + this.nearGrabbing = function () { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); @@ -440,8 +455,7 @@ function MyController(hand, triggerAction) { this.lineOff(); - var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, - ["position", "rotation", "gravity", "ignoreForCollisions"]); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity", "ignoreForCollisions"]); this.activateEntity(this.grabbedEntity, grabbedProperties); var handRotation = this.getHandRotation(); @@ -480,7 +494,7 @@ function MyController(hand, triggerAction) { this.currentObjectTime = Date.now(); }; - this.continueNearGrabbing = function() { + this.continueNearGrabbing = function () { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -504,10 +518,12 @@ function MyController(hand, triggerAction) { this.currentObjectTime = now; Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab"); - Entities.updateAction(this.grabbedEntity, this.actionID, {lifetime: ACTION_LIFETIME}); + Entities.updateAction(this.grabbedEntity, this.actionID, { + lifetime: ACTION_LIFETIME + }); }; - this.nearGrabbingNonColliding = function() { + this.nearGrabbingNonColliding = function () { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -521,16 +537,48 @@ function MyController(hand, triggerAction) { this.setState(STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING); }; - this.continueNearGrabbingNonColliding = function() { + this.farGrabbingNonColliding = function () { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; } + + if (this.hand === RIGHT_HAND) { + Entities.callEntityMethod(this.grabbedEntity, "setRightHand"); + } else { + Entities.callEntityMethod(this.grabbedEntity, "setLeftHand"); + } + Entities.callEntityMethod(this.grabbedEntity, "startFarGrabNonColliding"); + this.setState(STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING); + }; + + this.continueNearGrabbingNonColliding = function () { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + return; + } + Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabbingNonColliding"); }; + this.continueFarGrabbingNonColliding = function () { + if (this.triggerSmoothedReleased()) { + this.setState(STATE_RELEASE); + return; + } + + var handPosition = this.getHandPosition(); + var pickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()) + }; + + this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); + Entities.callEntityMethod(this.grabbedEntity, "continueFarGrabbingNonColliding"); + }; + _this.allTouchedIDs = {}; - this.touchTest = function() { + this.touchTest = function () { var maxDistance = 0.05; var leftHandPosition = MyAvatar.getLeftPalmPosition(); var rightHandPosition = MyAvatar.getRightPalmPosition(); @@ -539,19 +587,19 @@ function MyController(hand, triggerAction) { var ids = []; if (leftEntities.length !== 0) { - leftEntities.forEach(function(entity) { + leftEntities.forEach(function (entity) { ids.push(entity); }); } if (rightEntities.length !== 0) { - rightEntities.forEach(function(entity) { + rightEntities.forEach(function (entity) { ids.push(entity); }); } - ids.forEach(function(id) { + ids.forEach(function (id) { var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); if (props.name === 'pointer') { @@ -584,19 +632,19 @@ function MyController(hand, triggerAction) { }; - this.startTouch = function(entityID) { + this.startTouch = function (entityID) { Entities.callEntityMethod(entityID, "startTouch"); }; - this.continueTouch = function(entityID) { + this.continueTouch = function (entityID) { Entities.callEntityMethod(entityID, "continueTouch"); }; - this.stopTouch = function(entityID) { + this.stopTouch = function (entityID) { Entities.callEntityMethod(entityID, "stopTouch"); }; - this.computeReleaseVelocity = function(deltaPosition, deltaTime, useMultiplier) { + this.computeReleaseVelocity = function (deltaPosition, deltaTime, useMultiplier) { if (deltaTime > 0.0 && !vec3equal(deltaPosition, ZERO_VEC)) { var grabbedVelocity = Vec3.multiply(deltaPosition, 1.0 / deltaTime); // don't update grabbedVelocity if the trigger is off. the smoothing of the trigger @@ -613,13 +661,13 @@ function MyController(hand, triggerAction) { } }; - this.release = function() { + this.release = function () { this.lineOff(); if (this.grabbedEntity !== null) { - if(this.actionID !== null) { - Entities.deleteAction(this.grabbedEntity, this.actionID); + if (this.actionID !== null) { + Entities.deleteAction(this.grabbedEntity, this.actionID); } Entities.callEntityMethod(this.grabbedEntity, "releaseGrab"); } @@ -637,11 +685,11 @@ function MyController(hand, triggerAction) { this.setState(STATE_OFF); }; - this.cleanup = function() { + this.cleanup = function () { this.release(); }; - this.activateEntity = function(entityID, grabbedProperties) { + this.activateEntity = function (entityID, grabbedProperties) { var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); data["activated"] = true; data["avatarId"] = MyAvatar.sessionUUID; @@ -650,12 +698,19 @@ function MyController(hand, triggerAction) { if (data["refCount"] == 1) { data["gravity"] = grabbedProperties.gravity; data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions; - Entities.editEntity(entityID, {gravity: {x:0, y:0, z:0}, ignoreForCollisions: true}); + Entities.editEntity(entityID, { + gravity: { + x: 0, + y: 0, + z: 0 + }, + ignoreForCollisions: true + }); } setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); }; - this.deactivateEntity = function(entityID) { + this.deactivateEntity = function (entityID) { var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); if (data && data["refCount"]) { data["refCount"] = data["refCount"] - 1; @@ -687,4 +742,4 @@ function cleanup() { } Script.scriptEnding.connect(cleanup); -Script.update.connect(update); +Script.update.connect(update); \ No newline at end of file From 99d1e17ae8a08fd41c340cbd23ede360da0e117f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 7 Oct 2015 19:18:59 -0700 Subject: [PATCH 30/34] Support reload-on-change for local scripts --- libraries/script-engine/src/ScriptEngine.cpp | 61 ++++++++++++++++++-- libraries/script-engine/src/ScriptEngine.h | 2 + 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index b8a97f0902..3906d68c42 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -11,12 +11,13 @@ #include #include +#include #include #include #include #include -#include -#include +#include +#include #include #include @@ -942,6 +943,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co #endif auto scriptCache = DependencyManager::get(); + bool isFileUrl = isURL && scriptOrURL.startsWith("file://"); // first check the syntax of the script contents QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(contents); @@ -950,7 +952,9 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co qCDebug(scriptengine) << " " << syntaxCheck.errorMessage() << ":" << syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber(); qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL; - scriptCache->addScriptToBadScriptList(scriptOrURL); + if (!isFileUrl) { + scriptCache->addScriptToBadScriptList(scriptOrURL); + } return; // done processing script } @@ -965,14 +969,21 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID; qCDebug(scriptengine) << " NOT CONSTRUCTOR"; qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL; - scriptCache->addScriptToBadScriptList(scriptOrURL); + if (!isFileUrl) { + scriptCache->addScriptToBadScriptList(scriptOrURL); + } return; // done processing script } - QScriptValue entityScriptConstructor = evaluate(contents); + int64_t lastModified = 0; + if (isFileUrl) { + QString file = QUrl(scriptOrURL).toLocalFile(); + lastModified = (quint64)QFileInfo(file).lastModified().toMSecsSinceEpoch(); + } + QScriptValue entityScriptConstructor = evaluate(contents); QScriptValue entityScriptObject = entityScriptConstructor.construct(); - EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject }; + EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified }; _entityScripts[entityID] = newDetails; if (isURL) { setParentURL(""); @@ -1022,6 +1033,41 @@ void ScriptEngine::unloadAllEntityScripts() { _entityScripts.clear(); } +void ScriptEngine::refreshFileScript(const EntityItemID& entityID) { + if (!_entityScripts.contains(entityID)) { + return; + } + + static bool recurseGuard = false; + if (recurseGuard) { + return; + } + recurseGuard = true; + + EntityScriptDetails details = _entityScripts[entityID]; + // Check to see if a file based script needs to be reloaded (easier debugging) + if (details.lastModified > 0) { + QString filePath = QUrl(details.scriptText).toLocalFile(); + auto lastModified = QFileInfo(filePath).lastModified().toMSecsSinceEpoch(); + if (lastModified > details.lastModified) { + qDebug() << "Reloading modified script " << details.scriptText; + + QFile file(filePath); + file.open(QIODevice::ReadOnly); + QString scriptContents = QTextStream(&file).readAll(); + this->unloadEntityScript(entityID); + this->entityScriptContentAvailable(entityID, details.scriptText, scriptContents, true, true); + if (!_entityScripts.contains(entityID)) { + qWarning() << "Reload script " << details.scriptText << " failed"; + } else { + details = _entityScripts[entityID]; + } + } + } + recurseGuard = false; +} + + void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) { if (QThread::currentThread() != thread()) { #ifdef THREAD_DEBUGGING @@ -1039,6 +1085,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS "entityID:" << entityID << "methodName:" << methodName; #endif + refreshFileScript(entityID); if (_entityScripts.contains(entityID)) { EntityScriptDetails details = _entityScripts[entityID]; QScriptValue entityScript = details.scriptObject; // previously loaded @@ -1069,6 +1116,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS "entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent"; #endif + refreshFileScript(entityID); if (_entityScripts.contains(entityID)) { EntityScriptDetails details = _entityScripts[entityID]; QScriptValue entityScript = details.scriptObject; // previously loaded @@ -1101,6 +1149,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS "entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision"; #endif + refreshFileScript(entityID); if (_entityScripts.contains(entityID)) { EntityScriptDetails details = _entityScripts[entityID]; QScriptValue entityScript = details.scriptObject; // previously loaded diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 3cfeb3447e..3ff397e98d 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -45,6 +45,7 @@ class EntityScriptDetails { public: QString scriptText; QScriptValue scriptObject; + int64_t lastModified; }; class ScriptEngine : public QScriptEngine, public ScriptUser, public EntitiesScriptEngineProvider { @@ -171,6 +172,7 @@ private: bool evaluatePending() const { return _evaluatesPending > 0; } void timerFired(); void stopAllTimers(); + void refreshFileScript(const EntityItemID& entityID); void setParentURL(const QString& parentURL) { _parentURL = parentURL; } From 50592a87a6b372981a621ea9e68c04f259f30fde Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 7 Oct 2015 19:44:08 -0700 Subject: [PATCH 31/34] Fix mouse events for entity scripts --- interface/src/Application.cpp | 62 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 781f65b649..1f25d7d6fa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1825,17 +1825,16 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { } #endif + auto offscreenUi = DependencyManager::get(); + QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget); + QMouseEvent mappedEvent(event->type(), + transformedPos, + event->screenPos(), event->button(), + event->buttons(), event->modifiers()); - _entities.mouseMoveEvent(event, deviceID); - { - auto offscreenUi = DependencyManager::get(); - QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget); - QMouseEvent mappedEvent(event->type(), - transformedPos, - event->screenPos(), event->button(), - event->buttons(), event->modifiers()); - _controllerScriptingInterface.emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts - } + + _entities.mouseMoveEvent(&mappedEvent, deviceID); + _controllerScriptingInterface.emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface.isMouseCaptured()) { @@ -1851,19 +1850,19 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { // Inhibit the menu if the user is using alt-mouse dragging _altPressed = false; + + auto offscreenUi = DependencyManager::get(); + QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget); + QMouseEvent mappedEvent(event->type(), + transformedPos, + event->screenPos(), event->button(), + event->buttons(), event->modifiers()); + if (!_aboutToQuit) { - _entities.mousePressEvent(event, deviceID); + _entities.mousePressEvent(&mappedEvent, deviceID); } - { - auto offscreenUi = DependencyManager::get(); - QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget); - QMouseEvent mappedEvent(event->type(), - transformedPos, - event->screenPos(), event->button(), - event->buttons(), event->modifiers()); - _controllerScriptingInterface.emitMousePressEvent(&mappedEvent); // send events to any registered scripts - } + _controllerScriptingInterface.emitMousePressEvent(&mappedEvent); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface.isMouseCaptured()) { @@ -1879,7 +1878,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { if (event->button() == Qt::LeftButton) { // nobody handled this - make it an action event on the _window object HFActionEvent actionEvent(HFActionEvent::startType(), - computePickRay(event->x(), event->y())); + computePickRay(mappedEvent.x(), mappedEvent.y())); sendEvent(this, &actionEvent); } else if (event->button() == Qt::RightButton) { @@ -1907,19 +1906,18 @@ void Application::mouseDoublePressEvent(QMouseEvent* event, unsigned int deviceI void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { + auto offscreenUi = DependencyManager::get(); + QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget); + QMouseEvent mappedEvent(event->type(), + transformedPos, + event->screenPos(), event->button(), + event->buttons(), event->modifiers()); + if (!_aboutToQuit) { - _entities.mouseReleaseEvent(event, deviceID); + _entities.mouseReleaseEvent(&mappedEvent, deviceID); } - { - auto offscreenUi = DependencyManager::get(); - QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget); - QMouseEvent mappedEvent(event->type(), - transformedPos, - event->screenPos(), event->button(), - event->buttons(), event->modifiers()); - _controllerScriptingInterface.emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts - } + _controllerScriptingInterface.emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface.isMouseCaptured()) { @@ -1934,7 +1932,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { if (event->button() == Qt::LeftButton) { // fire an action end event HFActionEvent actionEvent(HFActionEvent::endType(), - computePickRay(event->x(), event->y())); + computePickRay(mappedEvent.x(), mappedEvent.y())); sendEvent(this, &actionEvent); } } From aac372cc8ab8645d4aee00cad9cb2d39e55dfca2 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 8 Oct 2015 09:53:06 -0700 Subject: [PATCH 32/34] Fixed styling errors --- examples/controllers/handControllerGrab.js | 136 ++++++++++----------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 7df88a68ca..47bcc0083c 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -32,7 +32,7 @@ var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to thei var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did var NO_INTERSECT_COLOR = { red: 10, green: 10, blue: 255}; // line color when pick misses var INTERSECT_COLOR = { red: 250, green: 10, blue: 10}; // line color when pick hits -var LINE_ENTITY_DIMENSIONS = { x: 1000, y: 1000, z: 1000}; +var LINE_ENTITY_DIMENSIONS = { x: 1000, y: 1000,z: 1000}; var LINE_LENGTH = 500; @@ -133,55 +133,55 @@ function MyController(hand, triggerAction) { var _this = this; - this.update = function () { + this.update = function() { this.updateSmoothedTrigger(); switch (this.state) { - case STATE_OFF: - this.off(); - this.touchTest(); - break; - case STATE_SEARCHING: - this.search(); - break; - case STATE_DISTANCE_HOLDING: - this.distanceHolding(); - break; - case STATE_CONTINUE_DISTANCE_HOLDING: - this.continueDistanceHolding(); - break; - case STATE_NEAR_GRABBING: - this.nearGrabbing(); - break; - case STATE_CONTINUE_NEAR_GRABBING: - this.continueNearGrabbing(); - break; - case STATE_NEAR_GRABBING_NON_COLLIDING: - this.nearGrabbingNonColliding(); - break; - case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: - this.continueNearGrabbingNonColliding(); - break; - case STATE_FAR_GRABBING_NON_COLLIDING: - this.farGrabbingNonColliding(); - break; - case STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING: - this.continueFarGrabbingNonColliding(); - break; - case STATE_RELEASE: - this.release(); - break; + case STATE_OFF: + this.off(); + this.touchTest(); + break; + case STATE_SEARCHING: + this.search(); + break; + case STATE_DISTANCE_HOLDING: + this.distanceHolding(); + break; + case STATE_CONTINUE_DISTANCE_HOLDING: + this.continueDistanceHolding(); + break; + case STATE_NEAR_GRABBING: + this.nearGrabbing(); + break; + case STATE_CONTINUE_NEAR_GRABBING: + this.continueNearGrabbing(); + break; + case STATE_NEAR_GRABBING_NON_COLLIDING: + this.nearGrabbingNonColliding(); + break; + case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING: + this.continueNearGrabbingNonColliding(); + break; + case STATE_FAR_GRABBING_NON_COLLIDING: + this.farGrabbingNonColliding(); + break; + case STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING: + this.continueFarGrabbingNonColliding(); + break; + case STATE_RELEASE: + this.release(); + break; } }; - this.setState = function (newState) { + this.setState = function(newState) { // print("STATE: " + this.state + " --> " + newState); this.state = newState; } - this.lineOn = function (closePoint, farPoint, color) { + this.lineOn = function(closePoint, farPoint, color) { // draw a line if (this.pointer === null) { this.pointer = Entities.addEntity({ @@ -205,41 +205,41 @@ function MyController(hand, triggerAction) { }; - this.lineOff = function () { + this.lineOff = function() { if (this.pointer !== null) { Entities.deleteEntity(this.pointer); } this.pointer = null; }; - this.updateSmoothedTrigger = function () { + this.updateSmoothedTrigger = function() { var triggerValue = Controller.getActionValue(this.triggerAction); // smooth out trigger value this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) + (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); } - this.triggerSmoothedSqueezed = function () { + this.triggerSmoothedSqueezed = function() { return this.triggerValue > TRIGGER_ON_VALUE; }; - this.triggerSmoothedReleased = function () { + this.triggerSmoothedReleased = function() { return this.triggerValue < TRIGGER_OFF_VALUE; }; - this.triggerSqueezed = function () { + this.triggerSqueezed = function() { var triggerValue = Controller.getActionValue(this.triggerAction); return triggerValue > TRIGGER_ON_VALUE; }; - this.off = function () { + this.off = function() { if (this.triggerSmoothedSqueezed()) { this.setState(STATE_SEARCHING); return; } } - this.search = function () { + this.search = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -322,13 +322,12 @@ function MyController(hand, triggerAction) { } }; - this.distanceHolding = function () { + this.distanceHolding = function() { var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm)); var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", - "gravity", "ignoreForCollisions" - ]); + "gravity", "ignoreForCollisions"]); // add the action and initialize some variables this.currentObjectPosition = grabbedProperties.position; @@ -366,7 +365,7 @@ function MyController(hand, triggerAction) { }; - this.continueDistanceHolding = function () { + this.continueDistanceHolding = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -446,7 +445,7 @@ function MyController(hand, triggerAction) { }); }; - this.nearGrabbing = function () { + this.nearGrabbing = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); @@ -455,7 +454,8 @@ function MyController(hand, triggerAction) { this.lineOff(); - var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation", "gravity", "ignoreForCollisions"]); + var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, + ["position", "rotation", "gravity", "ignoreForCollisions"]); this.activateEntity(this.grabbedEntity, grabbedProperties); var handRotation = this.getHandRotation(); @@ -494,7 +494,7 @@ function MyController(hand, triggerAction) { this.currentObjectTime = Date.now(); }; - this.continueNearGrabbing = function () { + this.continueNearGrabbing = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -523,7 +523,7 @@ function MyController(hand, triggerAction) { }); }; - this.nearGrabbingNonColliding = function () { + this.nearGrabbingNonColliding = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -537,7 +537,7 @@ function MyController(hand, triggerAction) { this.setState(STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING); }; - this.farGrabbingNonColliding = function () { + this.farGrabbingNonColliding = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -552,7 +552,7 @@ function MyController(hand, triggerAction) { this.setState(STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING); }; - this.continueNearGrabbingNonColliding = function () { + this.continueNearGrabbingNonColliding = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -561,7 +561,7 @@ function MyController(hand, triggerAction) { Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabbingNonColliding"); }; - this.continueFarGrabbingNonColliding = function () { + this.continueFarGrabbingNonColliding = function() { if (this.triggerSmoothedReleased()) { this.setState(STATE_RELEASE); return; @@ -578,7 +578,7 @@ function MyController(hand, triggerAction) { }; _this.allTouchedIDs = {}; - this.touchTest = function () { + this.touchTest = function() { var maxDistance = 0.05; var leftHandPosition = MyAvatar.getLeftPalmPosition(); var rightHandPosition = MyAvatar.getRightPalmPosition(); @@ -587,19 +587,19 @@ function MyController(hand, triggerAction) { var ids = []; if (leftEntities.length !== 0) { - leftEntities.forEach(function (entity) { + leftEntities.forEach(function(entity) { ids.push(entity); }); } if (rightEntities.length !== 0) { - rightEntities.forEach(function (entity) { + rightEntities.forEach(function(entity) { ids.push(entity); }); } - ids.forEach(function (id) { + ids.forEach(function(id) { var props = Entities.getEntityProperties(id, ["boundingBox", "name"]); if (props.name === 'pointer') { @@ -632,19 +632,19 @@ function MyController(hand, triggerAction) { }; - this.startTouch = function (entityID) { + this.startTouch = function(entityID) { Entities.callEntityMethod(entityID, "startTouch"); }; - this.continueTouch = function (entityID) { + this.continueTouch = function(entityID) { Entities.callEntityMethod(entityID, "continueTouch"); }; - this.stopTouch = function (entityID) { + this.stopTouch = function(entityID) { Entities.callEntityMethod(entityID, "stopTouch"); }; - this.computeReleaseVelocity = function (deltaPosition, deltaTime, useMultiplier) { + this.computeReleaseVelocity = function(deltaPosition, deltaTime, useMultiplier) { if (deltaTime > 0.0 && !vec3equal(deltaPosition, ZERO_VEC)) { var grabbedVelocity = Vec3.multiply(deltaPosition, 1.0 / deltaTime); // don't update grabbedVelocity if the trigger is off. the smoothing of the trigger @@ -661,7 +661,7 @@ function MyController(hand, triggerAction) { } }; - this.release = function () { + this.release = function() { this.lineOff(); @@ -685,11 +685,11 @@ function MyController(hand, triggerAction) { this.setState(STATE_OFF); }; - this.cleanup = function () { + this.cleanup = function() { this.release(); }; - this.activateEntity = function (entityID, grabbedProperties) { + this.activateEntity = function(entityID, grabbedProperties) { var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); data["activated"] = true; data["avatarId"] = MyAvatar.sessionUUID; @@ -710,7 +710,7 @@ function MyController(hand, triggerAction) { setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data); }; - this.deactivateEntity = function (entityID) { + this.deactivateEntity = function(entityID) { var data = getEntityCustomData(GRAB_USER_DATA_KEY, entityID, {}); if (data && data["refCount"]) { data["refCount"] = data["refCount"] - 1; From b7f52ea542ac3f456dab3f9a8877c15e0a76100b Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 8 Oct 2015 10:11:21 -0700 Subject: [PATCH 33/34] Moved entity reset switch, fixed some style issues --- unpublishedScripts/hiddenEntityReset.js | 24 +++++++++------------- unpublishedScripts/immediateClientReset.js | 21 +++++-------------- 2 files changed, 15 insertions(+), 30 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 90e4bc1bf8..a9e97db518 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -10,7 +10,7 @@ // -(function () { +(function() { var _this; @@ -22,13 +22,13 @@ var dollScriptURL = Script.resolvePath("../examples/toys/doll/doll.js"); var lightsScriptURL = Script.resolvePath("../examples/toys/lightSwitch.js"); - ResetSwitch = function () { + ResetSwitch = function() { _this = this; }; ResetSwitch.prototype = { - clickReleaseOnEntity: function (entityId, mouseEvent) { + clickReleaseOnEntity: function(entityId, mouseEvent) { if (!mouseEvent.isLeftButton) { return; } @@ -36,26 +36,22 @@ }, - startNearGrabNonColliding: function () { + startNearGrabNonColliding: function() { this.triggerReset(); }, - startFarGrabNonColliding: function () { - this.triggerReset(); - }, - - triggerReset: function () { + triggerReset: function() { MasterReset(); }, - preload: function (entityID) { + preload: function(entityID) { this.entityID = entityID; } }; - MasterReset = function () { + MasterReset = function() { var resetKey = "resetMe"; var GRABBABLE_DATA_KEY = "grabbableKey"; @@ -145,7 +141,7 @@ function deleteAllToys() { var entities = Entities.findEntities(MyAvatar.position, 100); - entities.forEach(function (entity) { + entities.forEach(function(entity) { //params: customKey, id, defaultValue var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe; if (shouldReset === true) { @@ -330,14 +326,14 @@ function testBallDistanceFromStart() { var resetCount = 0; - collidingBalls.forEach(function (ball, index) { + collidingBalls.forEach(function(ball, index) { var currentPosition = Entities.getEntityProperties(ball, "position").position; var originalPosition = originalBallPositions[index]; var distance = Vec3.subtract(originalPosition, currentPosition); var length = Vec3.length(distance); if (length > RESET_DISTANCE) { - Script.setTimeout(function () { + Script.setTimeout(function() { var newPosition = Entities.getEntityProperties(ball, "position").position; var moving = Vec3.length(Vec3.subtract(currentPosition, newPosition)); if (moving < MINIMUM_MOVE_LENGTH) { diff --git a/unpublishedScripts/immediateClientReset.js b/unpublishedScripts/immediateClientReset.js index 89464b8c6b..0a2e9383a2 100644 --- a/unpublishedScripts/immediateClientReset.js +++ b/unpublishedScripts/immediateClientReset.js @@ -24,28 +24,17 @@ function createHiddenMasterSwitch() { type: "Box", name: "Master Switch", script: hiddenEntityScriptURL, - dimensions: { - x: 0.2, - y: 0.2, - z: 0.2 - }, - color: { - red: 42, - green: 36, - blue: 30 - }, - position: { - x: 554, - y: 495.5, - z: 503.2 - } + dimensions: {x: 0.7, y: 0.2, z: 0.1}, + position: {x: 543.9, y: 496.05, z: 502.43}, + rotation: Quat.fromPitchYawRollDegrees(0, 33, 0), + visible: false }); } var entities = Entities.findEntities(MyAvatar.position, 100); -entities.forEach(function (entity) { +entities.forEach(function(entity) { //params: customKey, id, defaultValue var name = Entities.getEntityProperties(entity, "name").name if (name === "Master Switch") { From 3db148f3dcbd5882877dc924a793f03414783f70 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 8 Oct 2015 11:13:52 -0700 Subject: [PATCH 34/34] fix obj model meshes --- libraries/fbx/src/FBXReader.cpp | 2 +- libraries/fbx/src/FBXReader.h | 2 +- libraries/fbx/src/FBXReader_Mesh.cpp | 20 ++++++++++---------- libraries/fbx/src/OBJReader.cpp | 2 ++ 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 4b3b3b0fea..ca9f126cba 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1512,7 +1512,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex); - buildModelMesh(extracted, url); + buildModelMesh(extracted.mesh, url); if (extracted.mesh.isEye) { if (maxJointIndex == geometry.leftEyeJointIndex) { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index c0cbf5fb18..0af7b28136 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -388,7 +388,7 @@ public: ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex); QHash meshes; - void buildModelMesh(ExtractedMesh& extracted, const QString& url); + static void buildModelMesh(FBXMesh& extractedMesh, const QString& url); FBXTexture getTexture(const QString& textureID); diff --git a/libraries/fbx/src/FBXReader_Mesh.cpp b/libraries/fbx/src/FBXReader_Mesh.cpp index 097862ef38..dbada15588 100644 --- a/libraries/fbx/src/FBXReader_Mesh.cpp +++ b/libraries/fbx/src/FBXReader_Mesh.cpp @@ -386,11 +386,11 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn return data.extracted; } -void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) { +void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) { static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("buildModelMesh failed -- .*"); unsigned int totalSourceIndices = 0; - foreach(const FBXMeshPart& part, extracted.mesh.parts) { + foreach(const FBXMeshPart& part, extractedMesh.parts) { totalSourceIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size()); } @@ -399,18 +399,18 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) { return; } - if (extracted.mesh.vertices.size() == 0) { + if (extractedMesh.vertices.size() == 0) { qCDebug(modelformat) << "buildModelMesh failed -- no vertices, url = " << url; return; } - FBXMesh& fbxMesh = extracted.mesh; + FBXMesh& fbxMesh = extractedMesh; model::MeshPointer mesh(new model::Mesh()); // Grab the vertices in a buffer auto vb = std::make_shared(); - vb->setData(extracted.mesh.vertices.size() * sizeof(glm::vec3), - (const gpu::Byte*) extracted.mesh.vertices.data()); + vb->setData(extractedMesh.vertices.size() * sizeof(glm::vec3), + (const gpu::Byte*) extractedMesh.vertices.data()); gpu::BufferView vbv(vb, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); mesh->setVertexBuffer(vbv); @@ -486,7 +486,7 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) { unsigned int totalIndices = 0; - foreach(const FBXMeshPart& part, extracted.mesh.parts) { + foreach(const FBXMeshPart& part, extractedMesh.parts) { totalIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size()); } @@ -502,10 +502,10 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) { int offset = 0; std::vector< model::Mesh::Part > parts; - if (extracted.mesh.parts.size() > 1) { + if (extractedMesh.parts.size() > 1) { indexNum = 0; } - foreach(const FBXMeshPart& part, extracted.mesh.parts) { + foreach(const FBXMeshPart& part, extractedMesh.parts) { model::Mesh::Part modelPart(indexNum, 0, 0, model::Mesh::TRIANGLES); if (part.quadTrianglesIndices.size()) { @@ -545,5 +545,5 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) { // model::Box box = mesh->evalPartBound(0); - extracted.mesh._mesh = mesh; + extractedMesh._mesh = mesh; } diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index a9275e2d4a..835bb1a9b6 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -532,6 +532,8 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, mesh.meshExtents.addPoint(vertex); geometry.meshExtents.addPoint(vertex); } + + FBXReader::buildModelMesh(mesh, url.toString()); // fbxDebugDump(geometry); } catch(const std::exception& e) { qCDebug(modelformat) << "OBJ reader fail: " << e.what();