diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 53e62ee35f..1261604e29 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -141,7 +141,7 @@ std::shared_ptr make_renderer(const EntityItemPointer& entity) { return std::shared_ptr(new T(entity), [](T* ptr) { ptr->deleteLater(); }); } -EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _entity(entity) { +EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entity->getCreated()), _entity(entity) { connect(entity.get(), &EntityItem::requestRenderUpdate, this, [&] { _needsRenderUpdate = true; emit requestRenderUpdate(); @@ -468,3 +468,32 @@ void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const st std::lock_guard lock(_materialsLock); _materials[parentMaterialName].remove(material); } + +glm::vec4 EntityRenderer::calculatePulseColor(const glm::vec4& color, const PulsePropertyGroup& pulseProperties, quint64 start) { + if (pulseProperties.getPeriod() == 0.0f || (pulseProperties.getColorMode() == PulseMode::NONE && pulseProperties.getAlphaMode() == PulseMode::NONE)) { + return color; + } + + float t = ((float)(usecTimestampNow() - start)) / ((float)USECS_PER_SECOND); + float pulse = 0.5f * (cosf(t * (2.0f * (float)M_PI) / pulseProperties.getPeriod()) + 1.0f) * (pulseProperties.getMax() - pulseProperties.getMin()) + pulseProperties.getMin(); + float outPulse = (1.0f - pulse); + + glm::vec4 result = color; + if (pulseProperties.getColorMode() == PulseMode::IN_PHASE) { + result.r *= pulse; + result.g *= pulse; + result.b *= pulse; + } else if (pulseProperties.getColorMode() == PulseMode::OUT_PHASE) { + result.r *= outPulse; + result.g *= outPulse; + result.b *= outPulse; + } + + if (pulseProperties.getAlphaMode() == PulseMode::IN_PHASE) { + result.a *= pulse; + } else if (pulseProperties.getAlphaMode() == PulseMode::OUT_PHASE) { + result.a *= outPulse; + } + + return result; +} \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index fde63f78fa..d5e236a76a 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -62,6 +62,8 @@ public: virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); } + static glm::vec4 calculatePulseColor(const glm::vec4& color, const PulsePropertyGroup& pulseProperties, quint64 start); + protected: virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); } virtual void onAddToScene(const EntityItemPointer& entity); @@ -151,6 +153,8 @@ protected: std::unordered_map _materials; std::mutex _materialsLock; + quint64 _created; + private: // The base class relies on comparing the model transform to the entity transform in order // to trigger an update, so the member must not be visible to derived classes as a modifiable diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp index 4576358699..f05ba35c79 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.cpp @@ -26,7 +26,7 @@ GridEntityRenderer::~GridEntityRenderer() { } bool GridEntityRenderer::isTransparent() const { - return Parent::isTransparent() || _alpha < 1.0f; + return Parent::isTransparent() || _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE; } bool GridEntityRenderer::needsRenderUpdate() const { @@ -55,6 +55,10 @@ bool GridEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint return true; } + if (_pulseProperties != entity->getPulseProperties()) { + return true; + } + return false; }); @@ -65,6 +69,7 @@ void GridEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen withWriteLock([&] { _color = entity->getColor(); _alpha = entity->getAlpha(); + _pulseProperties = entity->getPulseProperties(); _followCamera = entity->getFollowCamera(); _majorGridEvery = entity->getMajorGridEvery(); @@ -105,11 +110,12 @@ ShapeKey GridEntityRenderer::getShapeKey() { } void GridEntityRenderer::doRender(RenderArgs* args) { - glm::u8vec3 color; + glm::vec4 color; glm::vec3 dimensions; Transform renderTransform; withReadLock([&] { - color = _color; + color = glm::vec4(toGlm(_color), _alpha); + color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); dimensions = _dimensions; renderTransform = _renderTransform; }); @@ -141,12 +147,11 @@ void GridEntityRenderer::doRender(RenderArgs* args) { float majorGridColDivisions = dimensions.y / _majorGridEvery; float minorGridRowDivisions = dimensions.x / _minorGridEvery; float minorGridColDivisions = dimensions.y / _minorGridEvery; - glm::vec4 gridColor(toGlm(color), _alpha); const float MINOR_GRID_EDGE = 0.0025f; const float MAJOR_GRID_EDGE = 0.005f; DependencyManager::get()->renderGrid(*batch, minCorner, maxCorner, minorGridRowDivisions, minorGridColDivisions, MINOR_GRID_EDGE, majorGridRowDivisions, majorGridColDivisions, MAJOR_GRID_EDGE, - gridColor, _geometryId); + color, _geometryId); } \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableGridEntityItem.h b/libraries/entities-renderer/src/RenderableGridEntityItem.h index 23f1f03d0d..45124fdb94 100644 --- a/libraries/entities-renderer/src/RenderableGridEntityItem.h +++ b/libraries/entities-renderer/src/RenderableGridEntityItem.h @@ -36,6 +36,7 @@ private: glm::u8vec3 _color; float _alpha; + PulsePropertyGroup _pulseProperties; bool _followCamera; uint32_t _majorGridEvery; diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index c1d6d3211d..c565eb1f0a 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -26,7 +26,7 @@ ImageEntityRenderer::~ImageEntityRenderer() { } bool ImageEntityRenderer::isTransparent() const { - return Parent::isTransparent() || (_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()) || _alpha < 1.0f; + return Parent::isTransparent() || (_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()) || _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE; } bool ImageEntityRenderer::needsRenderUpdate() const { @@ -71,6 +71,10 @@ bool ImageEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return true; } + if (_pulseProperties != entity->getPulseProperties()) { + return true; + } + return false; }); @@ -97,6 +101,7 @@ void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _color = entity->getColor(); _alpha = entity->getAlpha(); + _pulseProperties = entity->getPulseProperties(); if (!_textureIsLoaded && _texture && _texture->isLoaded()) { _textureIsLoaded = true; @@ -135,13 +140,14 @@ ShapeKey ImageEntityRenderer::getShapeKey() { void ImageEntityRenderer::doRender(RenderArgs* args) { NetworkTexturePointer texture; QRect subImage; - glm::u8vec3 color; + glm::vec4 color; glm::vec3 dimensions; Transform transform; withReadLock([&] { texture = _texture; subImage = _subImage; - color = _color; + color = glm::vec4(toGlm(_color), _alpha); + color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); dimensions = _dimensions; transform = _renderTransform; }); @@ -211,11 +217,9 @@ void ImageEntityRenderer::doRender(RenderArgs* args) { glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth, (fromImage.y() + fromImage.height() - 0.5f) / imageHeight); - glm::vec4 imageColor(toGlm(color), _alpha); - DependencyManager::get()->renderQuad( *batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, - imageColor, _geometryId + color, _geometryId ); batch->setResourceTexture(0, nullptr); diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.h b/libraries/entities-renderer/src/RenderableImageEntityItem.h index 9bc990f6fa..a20533cc8c 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.h +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.h @@ -44,6 +44,7 @@ private: glm::u8vec3 _color; float _alpha; + PulsePropertyGroup _pulseProperties; glm::vec3 _dimensions; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 351d72baf5..4ede5e5057 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -71,8 +71,11 @@ bool ParticleEffectEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedE return true; } - auto particleProperties = entity->getParticleProperties(); - if (particleProperties != _particleProperties) { + if (_particleProperties != entity->getParticleProperties()) { + return true; + } + + if (_pulseProperties != entity->getPulseProperties()) { return true; } @@ -95,6 +98,10 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi } }); } + + withWriteLock([&] { + _pulseProperties = entity->getPulseProperties(); + }); _emitting = entity->getIsEmitting(); bool hasTexture = resultWithReadLock([&]{ return _particleProperties.textures.isEmpty(); }); @@ -142,10 +149,6 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn particleUniforms.radius.middle = _particleProperties.radius.gradient.target; particleUniforms.radius.finish = _particleProperties.radius.range.finish; particleUniforms.radius.spread = _particleProperties.radius.gradient.spread; - particleUniforms.color.start = _particleProperties.getColorStart(); - particleUniforms.color.middle = _particleProperties.getColorMiddle(); - particleUniforms.color.finish = _particleProperties.getColorFinish(); - particleUniforms.color.spread = _particleProperties.getColorSpread(); particleUniforms.spin.start = _particleProperties.spin.range.start; particleUniforms.spin.middle = _particleProperties.spin.gradient.target; particleUniforms.spin.finish = _particleProperties.spin.range.finish; @@ -158,6 +161,7 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn } ItemKey ParticleEffectEntityRenderer::getKey() { + // FIXME: implement isTransparent() for particles and an opaque pipeline if (_visible) { return ItemKey::Builder::transparentShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } else { @@ -334,12 +338,18 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) { gpu::Batch& batch = *args->_batch; batch.setResourceTexture(0, _networkTexture->getGPUTexture()); - Transform transform; + Transform transform; // The particles are in world space, so the transform is unused, except for the rotation, which we use // if the particles are marked rotateWithEntity withReadLock([&] { transform.setRotation(_renderTransform.getRotation()); + auto& color = _uniformBuffer.edit().color; + color.start = EntityRenderer::calculatePulseColor(_particleProperties.getColorStart(), _pulseProperties, _created); + color.middle = EntityRenderer::calculatePulseColor(_particleProperties.getColorMiddle(), _pulseProperties, _created); + color.finish = EntityRenderer::calculatePulseColor(_particleProperties.getColorFinish(), _pulseProperties, _created); + color.spread = EntityRenderer::calculatePulseColor(_particleProperties.getColorSpread(), _pulseProperties, _created); }); + batch.setModelTransform(transform); batch.setUniformBuffer(0, _uniformBuffer); batch.setInputFormat(_vertexFormat); diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 7655918c58..853d5cac29 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -94,6 +94,8 @@ private: BufferView _uniformBuffer; quint64 _lastSimulated { 0 }; + PulsePropertyGroup _pulseProperties; + NetworkTexturePointer _networkTexture; ScenePointer _scene; }; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index d5a8aaafe2..192c6cfd49 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -85,6 +85,10 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return true; } + if (_pulseProperties != entity->getPulseProperties()) { + return true; + } + return false; } @@ -97,6 +101,7 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce } _shape = entity->getShape(); + _pulseProperties = entity->getPulseProperties(); }); void* key = (void*)this; @@ -141,6 +146,10 @@ void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint } bool ShapeEntityRenderer::isTransparent() const { + if (_pulseProperties.getAlphaMode() != PulseMode::NONE) { + return true; + } + if (_procedural.isEnabled() && _procedural.isFading()) { return Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; } @@ -248,6 +257,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { materials = _materials["0"]; auto& schema = materials.getSchemaBuffer().get(); outColor = glm::vec4(schema._albedo, schema._opacity); + outColor = EntityRenderer::calculatePulseColor(outColor, _pulseProperties, _created); if (_procedural.isReady()) { outColor = _procedural.getColor(outColor); outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index ece13fabe9..c9fd4801d5 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -40,9 +40,12 @@ private: Procedural _procedural; QString _lastUserData; entity::Shape _shape { entity::Sphere }; + + PulsePropertyGroup _pulseProperties; std::shared_ptr _material { std::make_shared() }; glm::u8vec3 _color; float _alpha; + glm::vec3 _position; glm::vec3 _dimensions; glm::quat _orientation; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index d7da8e7e1a..5614e976b5 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -41,7 +41,7 @@ TextEntityRenderer::~TextEntityRenderer() { } bool TextEntityRenderer::isTransparent() const { - return Parent::isTransparent() || _textAlpha < 1.0f || _backgroundAlpha < 1.0f; + return Parent::isTransparent() || _textAlpha < 1.0f || _backgroundAlpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE; } ShapeKey TextEntityRenderer::getShapeKey() { @@ -104,6 +104,10 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint return true; } + if (_pulseProperties != entity->getPulseProperties()) { + return true; + } + return false; } @@ -119,32 +123,39 @@ void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen } void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { - _text = entity->getText(); - _lineHeight = entity->getLineHeight(); - _textColor = toGlm(entity->getTextColor()); - _textAlpha = entity->getTextAlpha(); - _backgroundColor = toGlm(entity->getBackgroundColor()); - _backgroundAlpha = entity->getBackgroundAlpha(); - _billboardMode = entity->getBillboardMode(); - _leftMargin = entity->getLeftMargin(); - _rightMargin = entity->getRightMargin(); - _topMargin = entity->getTopMargin(); - _bottomMargin = entity->getBottomMargin(); + withWriteLock([&] { + _pulseProperties = entity->getPulseProperties(); + _text = entity->getText(); + _lineHeight = entity->getLineHeight(); + _textColor = toGlm(entity->getTextColor()); + _textAlpha = entity->getTextAlpha(); + _backgroundColor = toGlm(entity->getBackgroundColor()); + _backgroundAlpha = entity->getBackgroundAlpha(); + _billboardMode = entity->getBillboardMode(); + _leftMargin = entity->getLeftMargin(); + _rightMargin = entity->getRightMargin(); + _topMargin = entity->getTopMargin(); + _bottomMargin = entity->getBottomMargin(); + }); } void TextEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderableTextEntityItem::render"); + glm::vec4 textColor; + glm::vec4 backgroundColor; Transform modelTransform; glm::vec3 dimensions; withReadLock([&] { modelTransform = _renderTransform; dimensions = _dimensions; - }); - float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; - glm::vec4 textColor = glm::vec4(_textColor, fadeRatio * _textAlpha); - glm::vec4 backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha); + float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; + textColor = glm::vec4(_textColor, fadeRatio * _textAlpha); + textColor = EntityRenderer::calculatePulseColor(textColor, _pulseProperties, _created); + backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha); + backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created); + }); // Render background static const float SLIGHTLY_BEHIND = -0.005f; diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 6b20705209..6c9e8324f8 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -38,6 +38,8 @@ private: int _geometryID{ 0 }; std::shared_ptr _textRenderer; + PulsePropertyGroup _pulseProperties; + QString _text; float _lineHeight; glm::vec3 _textColor; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 38d1320aa2..2510e41780 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -97,7 +97,7 @@ WebEntityRenderer::~WebEntityRenderer() { bool WebEntityRenderer::isTransparent() const { float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; - return fadeRatio < OPAQUE_ALPHA_THRESHOLD || _alpha < 1.0f; + return fadeRatio < OPAQUE_ALPHA_THRESHOLD || _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE; } bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { @@ -143,6 +143,10 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe return true; } + if (_pulseProperties != entity->getPulseProperties()) { + return true; + } + return false; } @@ -201,6 +205,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene _dpi = entity->getDPI(); _color = entity->getColor(); _alpha = entity->getAlpha(); + _pulseProperties = entity->getPulseProperties(); if (_contentType == ContentType::NoContent) { return; @@ -293,6 +298,7 @@ void WebEntityRenderer::doRender(RenderArgs* args) { withReadLock([&] { float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; color = glm::vec4(toGlm(_color), _alpha * fadeRatio); + color = EntityRenderer::calculatePulseColor(color, _pulseProperties, _created); batch.setModelTransform(_renderTransform); }); batch.setResourceTexture(0, _texture); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 4affb5819d..5d97eb5b8e 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -84,6 +84,7 @@ private: glm::u8vec3 _color; float _alpha { 1.0f }; + PulsePropertyGroup _pulseProperties; QString _sourceURL; uint16_t _dpi; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 871fbe9cf3..32c7eb29dd 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -98,9 +98,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_RENDER_LAYER; requestedProperties += PROP_PRIMITIVE_MODE; requestedProperties += PROP_IGNORE_PICK_INTERSECTION; - withReadLock([&] { - requestedProperties += _grabProperties.getEntityProperties(params); - }); + requestedProperties += _grabProperties.getEntityProperties(params); // Physics requestedProperties += PROP_DENSITY; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index a79ba40a49..4e3dd21a4c 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -42,6 +42,7 @@ BloomPropertyGroup EntityItemProperties::_staticBloom; KeyLightPropertyGroup EntityItemProperties::_staticKeyLight; AmbientLightPropertyGroup EntityItemProperties::_staticAmbientLight; GrabPropertyGroup EntityItemProperties::_staticGrab; +PulsePropertyGroup EntityItemProperties::_staticPulse; EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - 1); @@ -514,6 +515,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL); CHECK_PROPERTY_CHANGE(PROP_COLOR, color); CHECK_PROPERTY_CHANGE(PROP_ALPHA, alpha); + changedProperties += _pulse.getChangedProperties(); CHECK_PROPERTY_CHANGE(PROP_TEXTURES, textures); // Particles @@ -1115,6 +1117,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * and spinSpread == PI/2, each particle will have a spin in the range PI/23*PI/2. * @property {boolean} rotateWithEntity=false - Whether or not the particles' spin will rotate with the entity. If false, when particleSpin == 0, the particles will point * up in the world. If true, they will point towards the entity's up vector, based on its orientation. + * @property {Entities.Pulse} pulse - The pulse-related properties. Deprecated. * * @property {ShapeType} shapeType="none" - Currently not used. Read-only. * @@ -1242,6 +1245,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Entities.Shape} shape="Sphere" - The shape of the entity. * @property {Vec3} dimensions=0.1,0.1,0.1 - The dimensions of the entity. * @property {Color} color=255,255,255 - The color of the entity. + * @property {number} alpha=1 - The alpha of the shape. + * @property {Entities.Pulse} pulse - The pulse-related properties. Deprecated. * @example Create a cylinder. * var shape = Entities.addEntity({ * type: "Shape", @@ -1281,6 +1286,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} rightMargin=0.0 - The right margin, in meters. * @property {number} topMargin=0.0 - The top margin, in meters. * @property {number} bottomMargin=0.0 - The bottom margin, in meters. + * @property {Entities.Pulse} pulse - The pulse-related properties. Deprecated. * @example Create a text entity. * var text = Entities.addEntity({ * type: "Text", @@ -1310,6 +1316,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {string} scriptURL="" - The URL of a JavaScript file to inject into the Web page. * @property {number} maxFPS=10 - The maximum update rate for the Web content, in frames/second. * @property {WebInputMode} inputMode="touch" - The user input mode to use. + * @property {Entities.Pulse} pulse - The pulse-related properties. Deprecated. * @example Create a Web entity displaying at 1920 x 1080 resolution. * var METERS_TO_INCHES = 39.3701; * var entity = Entities.addEntity({ @@ -1419,6 +1426,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * the full image in that dimension. * @property {Color} color=255,255,255 - The color of the image. * @property {number} alpha=1 - The alpha of the image. + * @property {Entities.Pulse} pulse - The pulse-related properties. Deprecated. * @example Create a image entity. * var image = Entities.addEntity({ * type: "Image", @@ -1442,6 +1450,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * line. Minimum value = 1. * @property {number} minorGridEvery=1 - Real number of meters at which to draw thin grid lines. Minimum value = * 0.001. + * @property {Entities.Pulse} pulse - The pulse-related properties. Deprecated. * @example Create a grid entity. * var grid = Entities.addEntity({ * type: "Grid", @@ -1579,6 +1588,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SHAPE_TYPE, shapeType, getShapeTypeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); + _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXTURES, textures); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_PARTICLES, maxParticles); @@ -1652,6 +1662,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool if (_type == EntityTypes::Box || _type == EntityTypes::Sphere || _type == EntityTypes::Shape) { COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); + _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SHAPE, shape); } @@ -1667,6 +1678,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool // Text only if (_type == EntityTypes::Text) { + _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_TEXT, text); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_HEIGHT, lineHeight); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_TYPED(PROP_TEXT_COLOR, textColor, getTextColor(), u8vec3Color); @@ -1708,6 +1721,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool if (_type == EntityTypes::Web) { COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); + _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOURCE_URL, sourceUrl); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DPI, dpi); @@ -1772,6 +1786,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool if (_type == EntityTypes::Image) { COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); + _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMISSIVE, emissive); @@ -1792,6 +1807,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool if (_type == EntityTypes::Grid) { COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); + _pulse.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GRID_FOLLOW_CAMERA, followCamera); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAJOR_GRID_EVERY, majorGridEvery); @@ -1972,6 +1988,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(compoundShapeURL, QString, setCompoundShapeURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(color, u8vec3Color, setColor); COPY_PROPERTY_FROM_QSCRIPTVALUE(alpha, float, setAlpha); + _pulse.copyFromScriptValue(object, _defaultSettings); COPY_PROPERTY_FROM_QSCRIPTVALUE(textures, QString, setTextures); // Particles @@ -2245,6 +2262,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(compoundShapeURL); COPY_PROPERTY_IF_CHANGED(color); COPY_PROPERTY_IF_CHANGED(alpha); + _pulse.merge(other._pulse); COPY_PROPERTY_IF_CHANGED(textures); // Particles @@ -2552,6 +2570,13 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString); ADD_PROPERTY_TO_MAP(PROP_COLOR, Color, color, u8vec3Color); ADD_PROPERTY_TO_MAP_WITH_RANGE(PROP_ALPHA, Alpha, alpha, float, particle::MINIMUM_ALPHA, particle::MAXIMUM_ALPHA); + { // Pulse + ADD_GROUP_PROPERTY_TO_MAP(PROP_PULSE_MIN, Pulse, pulse, Min, min); + ADD_GROUP_PROPERTY_TO_MAP(PROP_PULSE_MAX, Pulse, pulse, Max, max); + ADD_GROUP_PROPERTY_TO_MAP(PROP_PULSE_PERIOD, Pulse, pulse, Period, period); + ADD_GROUP_PROPERTY_TO_MAP(PROP_PULSE_COLOR_MODE, Pulse, pulse, ColorMode, colorMode); + ADD_GROUP_PROPERTY_TO_MAP(PROP_PULSE_ALPHA_MODE, Pulse, pulse, AlphaMode, alphaMode); + } ADD_PROPERTY_TO_MAP(PROP_TEXTURES, Textures, textures, QString); // Particles @@ -2952,6 +2977,9 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)(properties.getShapeType())); APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha()); + _staticPulse.setProperties(properties); + _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, + propertiesDidntFit, propertyCount, appendState); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures()); APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, properties.getMaxParticles()); @@ -3023,6 +3051,10 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy } if (properties.getType() == EntityTypes::Text) { + _staticPulse.setProperties(properties); + _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, + propertiesDidntFit, propertyCount, appendState); + APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight()); APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, properties.getTextColor()); @@ -3084,6 +3116,9 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy if (properties.getType() == EntityTypes::Web) { APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha()); + _staticPulse.setProperties(properties); + _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, + propertiesDidntFit, propertyCount, appendState); APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl()); APPEND_ENTITY_PROPERTY(PROP_DPI, properties.getDPI()); @@ -3118,6 +3153,9 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy properties.getType() == EntityTypes::Sphere) { APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha()); + _staticPulse.setProperties(properties); + _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, + propertiesDidntFit, propertyCount, appendState); APPEND_ENTITY_PROPERTY(PROP_SHAPE, properties.getShape()); } @@ -3138,6 +3176,9 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy if (properties.getType() == EntityTypes::Image) { APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha()); + _staticPulse.setProperties(properties); + _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, + propertiesDidntFit, propertyCount, appendState); APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, properties.getImageURL()); APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, properties.getEmissive()); @@ -3150,6 +3191,9 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy if (properties.getType() == EntityTypes::Grid) { APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha()); + _staticPulse.setProperties(properties); + _staticPulse.appendToEditPacket(packetData, requestedProperties, propertyFlags, + propertiesDidntFit, propertyCount, appendState); APPEND_ENTITY_PROPERTY(PROP_GRID_FOLLOW_CAMERA, properties.getFollowCamera()); APPEND_ENTITY_PROPERTY(PROP_MAJOR_GRID_EVERY, properties.getMajorGridEvery()); @@ -3401,6 +3445,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); + properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, quint32, setMaxParticles); @@ -3472,6 +3517,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int } if (properties.getType() == EntityTypes::Text) { + properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT_COLOR, u8vec3Color, setTextColor); @@ -3524,6 +3571,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Web) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); + properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI); @@ -3558,6 +3606,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int properties.getType() == EntityTypes::Sphere) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); + properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE, QString, setShape); } @@ -3578,6 +3628,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Image) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); + properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IMAGE_URL, QString, setImageURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMISSIVE, bool, setEmissive); @@ -3590,6 +3641,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Grid) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha); + properties.getPulse().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_GRID_FOLLOW_CAMERA, bool, setFollowCamera); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAJOR_GRID_EVERY, uint32_t, setMajorGridEvery); @@ -3793,6 +3845,7 @@ void EntityItemProperties::markAllChanged() { _shapeTypeChanged = true; _colorChanged = true; _alphaChanged = true; + _pulse.markAllChanged(); _texturesChanged = true; _compoundShapeURLChanged = true; @@ -4257,6 +4310,7 @@ QList EntityItemProperties::listChangedProperties() { if (alphaChanged()) { out += "alpha"; } + getPulse().listChangedProperties(out); if (texturesChanged()) { out += "textures"; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 654c8e2ab8..1a3cd205ce 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -51,6 +51,7 @@ #include "SkyboxPropertyGroup.h" #include "HazePropertyGroup.h" #include "BloomPropertyGroup.h" +#include "PulsePropertyGroup.h" #include "MaterialMappingMode.h" #include "BillboardMode.h" @@ -235,6 +236,7 @@ public: DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString, ""); DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, u8vec3Color, particle::DEFAULT_COLOR); DEFINE_PROPERTY(PROP_ALPHA, Alpha, alpha, float, particle::DEFAULT_ALPHA); + DEFINE_PROPERTY_GROUP(Pulse, pulse, PulsePropertyGroup); DEFINE_PROPERTY_REF(PROP_TEXTURES, Textures, textures, QString, ""); // Particles diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index fa14f52b48..7064f3e62e 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -383,13 +383,29 @@ inline QRect QRect_convertFromScriptValue(const QScriptValue& v, bool& isValid) } \ } -#define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S) \ - QScriptValue P = object.property(#P); \ - if (P.isValid()) { \ - QString newValue = P.toVariant().toString(); \ - if (_defaultSettings || newValue != get##S##AsString()) { \ - set##S##FromString(newValue); \ - } \ +#define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S) \ + { \ + QScriptValue P = object.property(#P); \ + if (P.isValid()) { \ + QString newValue = P.toVariant().toString(); \ + if (_defaultSettings || newValue != get##S##AsString()) { \ + set##S##FromString(newValue); \ + } \ + } \ + } + +#define COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_ENUM(G, P, S) \ + { \ + QScriptValue G = object.property(#G); \ + if (G.isValid()) { \ + QScriptValue P = G.property(#P); \ + if (P.isValid()) { \ + QString newValue = P.toVariant().toString(); \ + if (_defaultSettings || newValue != get##S##AsString()) { \ + set##S##FromString(newValue); \ + } \ + } \ + } \ } #define DEFINE_PROPERTY_GROUP(N, n, T) \ diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 5c136c4820..a59cbe854f 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -106,12 +106,17 @@ enum EntityPropertyList { PROP_LOCAL_VELOCITY, PROP_LOCAL_ANGULAR_VELOCITY, PROP_LOCAL_DIMENSIONS, - + // These properties are used by multiple subtypes but aren't in the base EntityItem PROP_SHAPE_TYPE, PROP_COMPOUND_SHAPE_URL, PROP_COLOR, PROP_ALPHA, + PROP_PULSE_MIN, + PROP_PULSE_MAX, + PROP_PULSE_PERIOD, + PROP_PULSE_COLOR_MODE, + PROP_PULSE_ALPHA_MODE, PROP_TEXTURES, //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/libraries/entities/src/GridEntityItem.cpp b/libraries/entities/src/GridEntityItem.cpp index b4709239ed..d8d070416b 100644 --- a/libraries/entities/src/GridEntityItem.cpp +++ b/libraries/entities/src/GridEntityItem.cpp @@ -35,6 +35,9 @@ EntityItemProperties GridEntityItem::getProperties(const EntityPropertyFlags& de COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); + withReadLock([&] { + _pulseProperties.getProperties(properties); + }); COPY_ENTITY_PROPERTY_TO_PROPERTIES(followCamera, getFollowCamera); COPY_ENTITY_PROPERTY_TO_PROPERTIES(majorGridEvery, getMajorGridEvery); @@ -48,6 +51,10 @@ bool GridEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha); + withWriteLock([&] { + bool pulsePropertiesChanged = _pulseProperties.setProperties(properties); + somethingChanged |= pulsePropertiesChanged; + }); SET_ENTITY_PROPERTY_FROM_PROPERTIES(followCamera, setFollowCamera); SET_ENTITY_PROPERTY_FROM_PROPERTIES(majorGridEvery, setMajorGridEvery); @@ -76,6 +83,13 @@ int GridEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha); + withWriteLock([&] { + int bytesFromPulse = _pulseProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, + somethingChanged); + bytesRead += bytesFromPulse; + dataAt += bytesFromPulse; + }); READ_ENTITY_PROPERTY(PROP_GRID_FOLLOW_CAMERA, bool, setFollowCamera); READ_ENTITY_PROPERTY(PROP_MAJOR_GRID_EVERY, uint32_t, setMajorGridEvery); @@ -89,6 +103,7 @@ EntityPropertyFlags GridEntityItem::getEntityProperties(EncodeBitstreamParams& p requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; + requestedProperties += _pulseProperties.getEntityProperties(params); requestedProperties += PROP_GRID_FOLLOW_CAMERA; requestedProperties += PROP_MAJOR_GRID_EVERY; @@ -98,7 +113,7 @@ EntityPropertyFlags GridEntityItem::getEntityProperties(EncodeBitstreamParams& p } void GridEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -109,6 +124,10 @@ void GridEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); + withReadLock([&] { + _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + }); APPEND_ENTITY_PROPERTY(PROP_GRID_FOLLOW_CAMERA, getFollowCamera()); APPEND_ENTITY_PROPERTY(PROP_MAJOR_GRID_EVERY, getMajorGridEvery()); @@ -175,4 +194,10 @@ float GridEntityItem::getMinorGridEvery() const { return resultWithReadLock([&] { return _minorGridEvery; }); +} + +PulsePropertyGroup GridEntityItem::getPulseProperties() const { + return resultWithReadLock([&] { + return _pulseProperties; + }); } \ No newline at end of file diff --git a/libraries/entities/src/GridEntityItem.h b/libraries/entities/src/GridEntityItem.h index 6209aee73d..165d9b50f5 100644 --- a/libraries/entities/src/GridEntityItem.h +++ b/libraries/entities/src/GridEntityItem.h @@ -11,6 +11,8 @@ #include "EntityItem.h" +#include "PulsePropertyGroup.h" + class GridEntityItem : public EntityItem { using Pointer = std::shared_ptr; public: @@ -29,7 +31,7 @@ public: EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -59,9 +61,13 @@ public: void setMinorGridEvery(float minorGridEvery); float getMinorGridEvery() const; + PulsePropertyGroup getPulseProperties() const; + protected: glm::u8vec3 _color; float _alpha; + PulsePropertyGroup _pulseProperties; + bool _followCamera { true }; uint32_t _majorGridEvery { DEFAULT_MAJOR_GRID_EVERY }; float _minorGridEvery { DEFAULT_MINOR_GRID_EVERY }; diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index cdff1b5390..1e8e4511cf 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -32,6 +32,9 @@ EntityItemProperties ImageEntityItem::getProperties(const EntityPropertyFlags& d COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); + withReadLock([&] { + _pulseProperties.getProperties(properties); + }); COPY_ENTITY_PROPERTY_TO_PROPERTIES(imageURL, getImageURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emissive, getEmissive); @@ -47,6 +50,10 @@ bool ImageEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha); + withWriteLock([&] { + bool pulsePropertiesChanged = _pulseProperties.setProperties(properties); + somethingChanged |= pulsePropertiesChanged; + }); SET_ENTITY_PROPERTY_FROM_PROPERTIES(imageURL, setImageURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emissive, setEmissive); @@ -77,6 +84,13 @@ int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha); + withWriteLock([&] { + int bytesFromPulse = _pulseProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, + somethingChanged); + bytesRead += bytesFromPulse; + dataAt += bytesFromPulse; + }); READ_ENTITY_PROPERTY(PROP_IMAGE_URL, QString, setImageURL); READ_ENTITY_PROPERTY(PROP_EMISSIVE, bool, setEmissive); @@ -92,6 +106,7 @@ EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; + requestedProperties += _pulseProperties.getEntityProperties(params); requestedProperties += PROP_IMAGE_URL; requestedProperties += PROP_EMISSIVE; @@ -103,7 +118,7 @@ EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& } void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -114,6 +129,10 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); + withReadLock([&] { + _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + }); APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, getImageURL()); APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, getEmissive()); @@ -266,4 +285,10 @@ float ImageEntityItem::getAlpha() const { return resultWithReadLock([&] { return _alpha; }); +} + +PulsePropertyGroup ImageEntityItem::getPulseProperties() const { + return resultWithReadLock([&] { + return _pulseProperties; + }); } \ No newline at end of file diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index 228f86ca03..05218016b3 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -11,6 +11,8 @@ #include "EntityItem.h" +#include "PulsePropertyGroup.h" + class ImageEntityItem : public EntityItem { using Pointer = std::shared_ptr; public: @@ -29,7 +31,7 @@ public: EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -72,6 +74,8 @@ public: void setAlpha(float alpha); float getAlpha() const; + PulsePropertyGroup getPulseProperties() const; + protected: QString _imageURL; bool _emissive { false }; @@ -81,6 +85,7 @@ protected: glm::u8vec3 _color; float _alpha; + PulsePropertyGroup _pulseProperties; }; #endif // hifi_ImageEntityItem_h diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 7426318979..b916ecc3de 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -412,6 +412,9 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(const EntityPropert COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); + withReadLock([&] { + _pulseProperties.getProperties(properties); + }); COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures); COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles); @@ -463,6 +466,10 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType); SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha); + withWriteLock([&] { + bool pulsePropertiesChanged = _pulseProperties.setProperties(properties); + somethingChanged |= pulsePropertiesChanged; + }); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxParticles, setMaxParticles); @@ -535,6 +542,13 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType); READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor); READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha); + withWriteLock([&] { + int bytesFromPulse = _pulseProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, + somethingChanged); + bytesRead += bytesFromPulse; + dataAt += bytesFromPulse; + }); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); @@ -586,6 +600,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_SHAPE_TYPE; requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; + requestedProperties += _pulseProperties.getEntityProperties(params); requestedProperties += PROP_TEXTURES; requestedProperties += PROP_MAX_PARTICLES; @@ -643,6 +658,10 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType()); APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); + withReadLock([&] { + _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + }); APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures()); APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, getMaxParticles()); @@ -786,4 +805,10 @@ particle::Properties ParticleEffectEntityItem::getParticleProperties() const { } return result; +} + +PulsePropertyGroup ParticleEffectEntityItem::getPulseProperties() const { + return resultWithReadLock([&] { + return _pulseProperties; + }); } \ No newline at end of file diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 89f1e834ea..88ebd47d6e 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -16,6 +16,7 @@ #include "EntityItem.h" #include "ColorUtils.h" +#include "PulsePropertyGroup.h" namespace particle { static const float SCRIPT_MAXIMUM_PI = 3.1416f; // Round up so that reasonable property values work @@ -341,9 +342,11 @@ public: virtual bool supportsDetailedIntersection() const override { return false; } particle::Properties getParticleProperties() const; + PulsePropertyGroup getPulseProperties() const; protected: particle::Properties _particleProperties; + PulsePropertyGroup _pulseProperties; bool _isEmitting { true }; ShapeType _shapeType { SHAPE_TYPE_NONE }; diff --git a/libraries/entities/src/PulsePropertyGroup.cpp b/libraries/entities/src/PulsePropertyGroup.cpp new file mode 100644 index 0000000000..54f81750da --- /dev/null +++ b/libraries/entities/src/PulsePropertyGroup.cpp @@ -0,0 +1,249 @@ +// +// PulsePropertyGroup.cpp +// +// Created by Sam Gondelman on 1/15/19 +// Copyright 2019 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 "PulsePropertyGroup.h" + +#include + +#include "EntityItemProperties.h" +#include "EntityItemPropertiesMacros.h" + +QHash stringToPulseModeLookup; + +void addPulseMode(PulseMode mode) { + stringToPulseModeLookup[PulseModeHelpers::getNameForPulseMode(mode)] = mode; +} + +void buildStringToPulseModeLookup() { + addPulseMode(PulseMode::NONE); + addPulseMode(PulseMode::IN_PHASE); + addPulseMode(PulseMode::OUT_PHASE); +} + +QString PulsePropertyGroup::getColorModeAsString() const { + return PulseModeHelpers::getNameForPulseMode(_colorMode); +} + +void PulsePropertyGroup::setColorModeFromString(const QString& pulseMode) { + if (stringToPulseModeLookup.empty()) { + buildStringToPulseModeLookup(); + } + auto pulseModeItr = stringToPulseModeLookup.find(pulseMode.toLower()); + if (pulseModeItr != stringToPulseModeLookup.end()) { + _colorMode = pulseModeItr.value(); + _colorModeChanged = true; + } +} + +QString PulsePropertyGroup::getAlphaModeAsString() const { + return PulseModeHelpers::getNameForPulseMode(_alphaMode); +} + +void PulsePropertyGroup::setAlphaModeFromString(const QString& pulseMode) { + if (stringToPulseModeLookup.empty()) { + buildStringToPulseModeLookup(); + } + auto pulseModeItr = stringToPulseModeLookup.find(pulseMode.toLower()); + if (pulseModeItr != stringToPulseModeLookup.end()) { + _alphaMode = pulseModeItr.value(); + _alphaModeChanged = true; + } +} + +void PulsePropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, + QScriptEngine* engine, bool skipDefaults, + EntityItemProperties& defaultEntityProperties) const { + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_MIN, Pulse, pulse, Min, min); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_MAX, Pulse, pulse, Max, max); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_PULSE_PERIOD, Pulse, pulse, Period, period); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_PULSE_COLOR_MODE, Pulse, pulse, ColorMode, colorMode, getColorModeAsString); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_PULSE_ALPHA_MODE, Pulse, pulse, AlphaMode, alphaMode, getAlphaModeAsString); +} + +void PulsePropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(pulse, min, float, setMin); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(pulse, max, float, setMax); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(pulse, period, float, setPeriod); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_ENUM(pulse, colorMode, ColorMode); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE_ENUM(pulse, alphaMode, AlphaMode); +} + +void PulsePropertyGroup::merge(const PulsePropertyGroup& other) { + COPY_PROPERTY_IF_CHANGED(min); + COPY_PROPERTY_IF_CHANGED(max); + COPY_PROPERTY_IF_CHANGED(period); + COPY_PROPERTY_IF_CHANGED(colorMode); + COPY_PROPERTY_IF_CHANGED(alphaMode); +} + +void PulsePropertyGroup::debugDump() const { + qCDebug(entities) << " PulsePropertyGroup: ---------------------------------------------"; + qCDebug(entities) << " _min:" << _min; + qCDebug(entities) << " _max:" << _max; + qCDebug(entities) << " _period:" << _period; + qCDebug(entities) << " _colorMode:" << getColorModeAsString(); + qCDebug(entities) << " _alphaMode:" << getAlphaModeAsString(); +} + +void PulsePropertyGroup::listChangedProperties(QList& out) { + if (minChanged()) { + out << "pulse-min"; + } + if (maxChanged()) { + out << "pulse-max"; + } + if (periodChanged()) { + out << "pulse-period"; + } + if (colorModeChanged()) { + out << "pulse-colorMode"; + } + if (alphaModeChanged()) { + out << "pulse-alphaMode"; + } +} + +bool PulsePropertyGroup::appendToEditPacket(OctreePacketData* packetData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + + bool successPropertyFits = true; + + APPEND_ENTITY_PROPERTY(PROP_PULSE_MIN, getMin()); + APPEND_ENTITY_PROPERTY(PROP_PULSE_MAX, getMax()); + APPEND_ENTITY_PROPERTY(PROP_PULSE_PERIOD, getPeriod()); + APPEND_ENTITY_PROPERTY(PROP_PULSE_COLOR_MODE, (uint32_t)getColorMode()); + APPEND_ENTITY_PROPERTY(PROP_PULSE_ALPHA_MODE, (uint32_t)getAlphaMode()); + + return true; +} + +bool PulsePropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, + const unsigned char*& dataAt , int& processedBytes) { + + int bytesRead = 0; + bool overwriteLocalData = true; + bool somethingChanged = false; + + READ_ENTITY_PROPERTY(PROP_PULSE_MIN, float, setMin); + READ_ENTITY_PROPERTY(PROP_PULSE_MAX, float, setMax); + READ_ENTITY_PROPERTY(PROP_PULSE_PERIOD, float, setPeriod); + READ_ENTITY_PROPERTY(PROP_PULSE_COLOR_MODE, PulseMode, setColorMode); + READ_ENTITY_PROPERTY(PROP_PULSE_ALPHA_MODE, PulseMode, setAlphaMode); + + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_PULSE_MIN, Min); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_PULSE_MAX, Max); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_PULSE_PERIOD, Period); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_PULSE_COLOR_MODE, ColorMode); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_PULSE_ALPHA_MODE, AlphaMode); + + processedBytes += bytesRead; + + Q_UNUSED(somethingChanged); + + return true; +} + +void PulsePropertyGroup::markAllChanged() { + _minChanged = true; + _maxChanged = true; + _periodChanged = true; + _colorModeChanged = true; + _alphaModeChanged = true; +} + +EntityPropertyFlags PulsePropertyGroup::getChangedProperties() const { + EntityPropertyFlags changedProperties; + + CHECK_PROPERTY_CHANGE(PROP_PULSE_MIN, min); + CHECK_PROPERTY_CHANGE(PROP_PULSE_MAX, max); + CHECK_PROPERTY_CHANGE(PROP_PULSE_PERIOD, period); + CHECK_PROPERTY_CHANGE(PROP_PULSE_COLOR_MODE, colorMode); + CHECK_PROPERTY_CHANGE(PROP_PULSE_ALPHA_MODE, alphaMode); + + return changedProperties; +} + +void PulsePropertyGroup::getProperties(EntityItemProperties& properties) const { + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Pulse, Min, getMin); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Pulse, Max, getMax); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Pulse, Period, getPeriod); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Pulse, ColorMode, getColorMode); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Pulse, AlphaMode, getAlphaMode); +} + +bool PulsePropertyGroup::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = false; + + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Pulse, Min, min, setMin); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Pulse, Max, max, setMax); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Pulse, Period, period, setPeriod); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Pulse, ColorMode, colorMode, setColorMode); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Pulse, AlphaMode, alphaMode, setAlphaMode); + + return somethingChanged; +} + +EntityPropertyFlags PulsePropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties; + + requestedProperties += PROP_PULSE_MIN; + requestedProperties += PROP_PULSE_MAX; + requestedProperties += PROP_PULSE_PERIOD; + requestedProperties += PROP_PULSE_COLOR_MODE; + requestedProperties += PROP_PULSE_ALPHA_MODE; + + return requestedProperties; +} + +void PulsePropertyGroup::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + + bool successPropertyFits = true; + + APPEND_ENTITY_PROPERTY(PROP_PULSE_MIN, getMin()); + APPEND_ENTITY_PROPERTY(PROP_PULSE_MAX, getMax()); + APPEND_ENTITY_PROPERTY(PROP_PULSE_PERIOD, getPeriod()); + APPEND_ENTITY_PROPERTY(PROP_PULSE_COLOR_MODE, (uint32_t)getColorMode()); + APPEND_ENTITY_PROPERTY(PROP_PULSE_ALPHA_MODE, (uint32_t)getAlphaMode()); +} + +int PulsePropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData, + bool& somethingChanged) { + + int bytesRead = 0; + const unsigned char* dataAt = data; + + READ_ENTITY_PROPERTY(PROP_PULSE_MIN, float, setMin); + READ_ENTITY_PROPERTY(PROP_PULSE_MAX, float, setMax); + READ_ENTITY_PROPERTY(PROP_PULSE_PERIOD, float, setPeriod); + READ_ENTITY_PROPERTY(PROP_PULSE_COLOR_MODE, PulseMode, setColorMode); + READ_ENTITY_PROPERTY(PROP_PULSE_ALPHA_MODE, PulseMode, setAlphaMode); + + return bytesRead; +} + +bool PulsePropertyGroup::operator==(const PulsePropertyGroup& a) const { + return (a._min == _min) && + (a._max == _max) && + (a._period == _period) && + (a._colorMode == _colorMode) && + (a._alphaMode == _alphaMode); +} \ No newline at end of file diff --git a/libraries/entities/src/PulsePropertyGroup.h b/libraries/entities/src/PulsePropertyGroup.h new file mode 100644 index 0000000000..f54db39149 --- /dev/null +++ b/libraries/entities/src/PulsePropertyGroup.h @@ -0,0 +1,99 @@ +// +// PulsePropertyGroup.h +// +// Created by Sam Gondelman on 1/15/19 +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_PulsePropertyGroup_h +#define hifi_PulsePropertyGroup_h + +#include + +#include + +#include + +#include "PropertyGroup.h" +#include "EntityItemPropertiesMacros.h" + +class EntityItemProperties; +class EncodeBitstreamParams; +class OctreePacketData; +class ReadBitstreamToTreeParams; + +/**jsdoc + * Pulse is defined by the following properties. + * @typedef {object} Entities.Pulse + * + * @property {number} min=0 - The minimum value of the pulse multiplier. + * @property {number} max=1 - The maximum value of the pulse multiplier. + * @property {number} period=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from + * min to max, then max to min in one period. + * @property {PulseMode} colorMode="none" - If "in", the color is pulsed in phase with the pulse period; if "out" + * the color is pulsed out of phase with the pulse period. + * @property {PulseMode} alphaMode="none" - If "in", the alpha is pulsed in phase with the pulse period; if "out" + * the alpha is pulsed out of phase with the pulse period. + */ + +class PulsePropertyGroup : public PropertyGroup { +public: + // EntityItemProperty related helpers + virtual void copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, + QScriptEngine* engine, bool skipDefaults, + EntityItemProperties& defaultEntityProperties) const override; + virtual void copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) override; + + void merge(const PulsePropertyGroup& other); + + virtual void debugDump() const override; + virtual void listChangedProperties(QList& out) override; + + virtual bool appendToEditPacket(OctreePacketData* packetData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const override; + + virtual bool decodeFromEditPacket(EntityPropertyFlags& propertyFlags, + const unsigned char*& dataAt, int& processedBytes) override; + virtual void markAllChanged() override; + virtual EntityPropertyFlags getChangedProperties() const override; + + // EntityItem related helpers + // methods for getting/setting all properties of an entity + virtual void getProperties(EntityItemProperties& propertiesOut) const override; + + // returns true if something changed + virtual bool setProperties(const EntityItemProperties& properties) override; + + virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; + + virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const override; + + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData, + bool& somethingChanged) override; + + bool operator==(const PulsePropertyGroup& a) const; + bool operator!=(const PulsePropertyGroup& a) const { return !(*this == a); } + + DEFINE_PROPERTY(PROP_PULSE_MIN, Min, min, float, 0.0f); + DEFINE_PROPERTY(PROP_PULSE_MAX, Max, max, float, 1.0f); + DEFINE_PROPERTY(PROP_PULSE_PERIOD, Period, period, float, 1.0f); + DEFINE_PROPERTY_REF_ENUM(PROP_PULSE_COLOR_MODE, ColorMode, colorMode, PulseMode, PulseMode::NONE); + DEFINE_PROPERTY_REF_ENUM(PROP_PULSE_ALPHA_MODE, AlphaMode, alphaMode, PulseMode, PulseMode::NONE); +}; + +#endif // hifi_PulsePropertyGroup_h diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 819cbf9dad..869ae2985f 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -119,6 +119,9 @@ EntityItemProperties ShapeEntityItem::getProperties(const EntityPropertyFlags& d COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); + withReadLock([&] { + _pulseProperties.getProperties(properties); + }); properties.setShape(entity::stringFromShape(getShape())); properties._shapeChanged = false; @@ -159,6 +162,10 @@ bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha); + withWriteLock([&] { + bool pulsePropertiesChanged = _pulseProperties.setProperties(properties); + somethingChanged |= pulsePropertiesChanged; + }); SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape); if (somethingChanged) { @@ -184,6 +191,13 @@ int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, READ_ENTITY_PROPERTY(PROP_COLOR, glm::u8vec3, setColor); READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha); + withWriteLock([&] { + int bytesFromPulse = _pulseProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, + somethingChanged); + bytesRead += bytesFromPulse; + dataAt += bytesFromPulse; + }); READ_ENTITY_PROPERTY(PROP_SHAPE, QString, setShape); return bytesRead; @@ -193,12 +207,13 @@ EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; + requestedProperties += _pulseProperties.getEntityProperties(params); requestedProperties += PROP_SHAPE; return requestedProperties; } void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -208,6 +223,10 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); + withReadLock([&] { + _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + }); APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape())); } @@ -416,4 +435,10 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { // This value specifies how the shape should be treated by physics calculations. ShapeType ShapeEntityItem::getShapeType() const { return _collisionShapeType; +} + +PulsePropertyGroup ShapeEntityItem::getPulseProperties() const { + return resultWithReadLock([&] { + return _pulseProperties; + }); } \ No newline at end of file diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 417f0c6173..28edf2e1a2 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -11,6 +11,8 @@ #include "EntityItem.h" +#include "PulsePropertyGroup.h" + namespace entity { enum Shape { Triangle, @@ -58,7 +60,7 @@ public: EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -99,9 +101,12 @@ public: virtual void computeShapeInfo(ShapeInfo& info) override; virtual ShapeType getShapeType() const override; + PulsePropertyGroup getPulseProperties() const; + protected: glm::u8vec3 _color; float _alpha { 1.0f }; + PulsePropertyGroup _pulseProperties; entity::Shape _shape { entity::Shape::Sphere }; //! This is SHAPE_TYPE_ELLIPSOID rather than SHAPE_TYPE_NONE to maintain diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 80c4c896bd..a743d0a7a9 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -49,6 +49,10 @@ void TextEntityItem::setUnscaledDimensions(const glm::vec3& value) { EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class + withReadLock([&] { + _pulseProperties.getProperties(properties); + }); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight); COPY_ENTITY_PROPERTY_TO_PROPERTIES(textColor, getTextColor); @@ -67,6 +71,11 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class + withWriteLock([&] { + bool pulsePropertiesChanged = _pulseProperties.setProperties(properties); + somethingChanged |= pulsePropertiesChanged; + }); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(text, setText); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textColor, setTextColor); @@ -101,6 +110,14 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesRead = 0; const unsigned char* dataAt = data; + withWriteLock([&] { + int bytesFromPulse = _pulseProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, + somethingChanged); + bytesRead += bytesFromPulse; + dataAt += bytesFromPulse; + }); + READ_ENTITY_PROPERTY(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, setLineHeight); READ_ENTITY_PROPERTY(PROP_TEXT_COLOR, glm::u8vec3, setTextColor); @@ -118,6 +135,8 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); + + requestedProperties += _pulseProperties.getEntityProperties(params); requestedProperties += PROP_TEXT; requestedProperties += PROP_LINE_HEIGHT; requestedProperties += PROP_TEXT_COLOR; @@ -129,11 +148,12 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p requestedProperties += PROP_RIGHT_MARGIN; requestedProperties += PROP_TOP_MARGIN; requestedProperties += PROP_BOTTOM_MARGIN; + return requestedProperties; } void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -142,6 +162,11 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits bool successPropertyFits = true; + withReadLock([&] { + _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + }); + APPEND_ENTITY_PROPERTY(PROP_TEXT, getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, getLineHeight()); APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, getTextColor()); @@ -345,3 +370,9 @@ float TextEntityItem::getBottomMargin() const { return _bottomMargin; }); } + +PulsePropertyGroup TextEntityItem::getPulseProperties() const { + return resultWithReadLock([&] { + return _pulseProperties; + }); +} \ No newline at end of file diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 5c22d8edf0..5ca6823052 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -14,6 +14,8 @@ #include "EntityItem.h" +#include "PulsePropertyGroup.h" + class TextEntityItem : public EntityItem { public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -33,7 +35,7 @@ public: virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -94,6 +96,8 @@ public: float getBottomMargin() const; void setBottomMargin(float value); + PulsePropertyGroup getPulseProperties() const; + private: QString _text; float _lineHeight; @@ -101,6 +105,7 @@ private: float _textAlpha; glm::u8vec3 _backgroundColor; float _backgroundAlpha; + PulsePropertyGroup _pulseProperties; BillboardMode _billboardMode; float _leftMargin; float _rightMargin; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index c0cdb081a2..459d512311 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -45,6 +45,9 @@ EntityItemProperties WebEntityItem::getProperties(const EntityPropertyFlags& des COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); + withReadLock([&] { + _pulseProperties.getProperties(properties); + }); COPY_ENTITY_PROPERTY_TO_PROPERTIES(sourceUrl, getSourceUrl); COPY_ENTITY_PROPERTY_TO_PROPERTIES(dpi, getDPI); @@ -60,6 +63,10 @@ bool WebEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha); + withWriteLock([&] { + bool pulsePropertiesChanged = _pulseProperties.setProperties(properties); + somethingChanged |= pulsePropertiesChanged; + }); SET_ENTITY_PROPERTY_FROM_PROPERTIES(sourceUrl, setSourceUrl); SET_ENTITY_PROPERTY_FROM_PROPERTIES(dpi, setDPI); @@ -91,6 +98,13 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i READ_ENTITY_PROPERTY(PROP_COLOR, glm::u8vec3, setColor); READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha); + withWriteLock([&] { + int bytesFromPulse = _pulseProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, + propertyFlags, overwriteLocalData, + somethingChanged); + bytesRead += bytesFromPulse; + dataAt += bytesFromPulse; + }); READ_ENTITY_PROPERTY(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY(PROP_DPI, uint16_t, setDPI); @@ -105,6 +119,7 @@ EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& pa EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_COLOR; requestedProperties += PROP_ALPHA; + requestedProperties += _pulseProperties.getEntityProperties(params); requestedProperties += PROP_SOURCE_URL; requestedProperties += PROP_DPI; @@ -115,7 +130,7 @@ EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& pa } void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -125,6 +140,10 @@ void WebEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitst bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha()); + withReadLock([&] { + _pulseProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, + propertyFlags, propertiesDidntFit, propertyCount, appendState); + }); APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, getSourceUrl()); APPEND_ENTITY_PROPERTY(PROP_DPI, getDPI()); @@ -285,4 +304,10 @@ WebInputMode WebEntityItem::getInputMode() const { return resultWithReadLock([&] { return _inputMode; }); +} + +PulsePropertyGroup WebEntityItem::getPulseProperties() const { + return resultWithReadLock([&] { + return _pulseProperties; + }); } \ No newline at end of file diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index c566bcb5f7..a0a2d65253 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -11,6 +11,8 @@ #include "EntityItem.h" +#include "PulsePropertyGroup.h" + class WebEntityItem : public EntityItem { public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); @@ -30,7 +32,7 @@ public: virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertiesDidntFit, @@ -75,9 +77,12 @@ public: void setInputMode(const WebInputMode& value); WebInputMode getInputMode() const; + PulsePropertyGroup getPulseProperties() const; + protected: glm::u8vec3 _color; float _alpha { 1.0f }; + PulsePropertyGroup _pulseProperties; QString _sourceUrl; uint16_t _dpi; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 68830a2f6b..105e9d116b 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -258,6 +258,7 @@ enum class EntityVersion : PacketVersion { FixProtocolVersionBumpMismatch, MigrateOverlayRenderProperties, MissingWebEntityProperties, + PulseProperties, // Add new versions above here NUM_PACKET_TYPE, diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 1dbb564fe9..7c299eb14a 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -38,6 +38,7 @@ #include "RenderLayer.h" #include "PrimitiveMode.h" #include "WebInputMode.h" +#include "PulseMode.h" #include "OctreeConstants.h" #include "OctreeElement.h" @@ -269,6 +270,7 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, RenderLayer& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, PrimitiveMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, WebInputMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } + static int unpackDataFromBytes(const unsigned char* dataBytes, PulseMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result); static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result); static int unpackDataFromBytes(const unsigned char* dataBytes, glm::u8vec3& result); diff --git a/libraries/shared/src/PulseMode.cpp b/libraries/shared/src/PulseMode.cpp new file mode 100644 index 0000000000..d8e938350a --- /dev/null +++ b/libraries/shared/src/PulseMode.cpp @@ -0,0 +1,25 @@ +// +// Created by Sam Gondelman on 1/15/19 +// Copyright 2019 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 "PulseMode.h" + +const char* pulseModeNames[] = { + "none", + "in", + "out" +}; + +static const size_t PULSE_MODE_NAMES = (sizeof(pulseModeNames) / sizeof(pulseModeNames[0])); + +QString PulseModeHelpers::getNameForPulseMode(PulseMode mode) { + if (((int)mode <= 0) || ((int)mode >= (int)PULSE_MODE_NAMES)) { + mode = (PulseMode)0; + } + + return pulseModeNames[(int)mode]; +} \ No newline at end of file diff --git a/libraries/shared/src/PulseMode.h b/libraries/shared/src/PulseMode.h new file mode 100644 index 0000000000..7c823db68c --- /dev/null +++ b/libraries/shared/src/PulseMode.h @@ -0,0 +1,41 @@ +// +// Created by Sam Gondelman on 1/15/19. +// Copyright 2019 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_PulseMode_h +#define hifi_PulseMode_h + +#include "QString" + +/**jsdoc + *

Pulse modes for color and alpha pulsing.

+ * + * + * + * + * + * + * + * + * + *
ValueDescription
noneNo pulsing.
inPulse in phase with the pulse period.
outPulse out of phase with the pulse period.
+ * @typedef {string} PulseMode + */ + +enum class PulseMode { + NONE = 0, + IN_PHASE, + OUT_PHASE +}; + +class PulseModeHelpers { +public: + static QString getNameForPulseMode(PulseMode mode); +}; + +#endif // hifi_PulseMode_h +