diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index c14f4ea895..c0a6b64421 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -25,12 +25,12 @@ float ClipboardScriptingInterface::getClipboardContentsLargestDimension() { return qApp->getEntityClipboard()->getContentsLargestDimension(); } -bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector& entityIDs) { +bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector& entityIDs) { bool retVal; BLOCKING_INVOKE_METHOD(qApp, "exportEntities", Q_RETURN_ARG(bool, retVal), Q_ARG(const QString&, filename), - Q_ARG(const QVector&, entityIDs)); + Q_ARG(const QVector&, entityIDs)); return retVal; } diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 60b6ca2e03..f6a0b29779 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -63,7 +63,7 @@ public: * @param {Uuid[]} entityIDs Array of IDs of the entities to export. * @returns {boolean} true if the export was successful, otherwise false. */ - Q_INVOKABLE bool exportEntities(const QString& filename, const QVector& entityIDs); + Q_INVOKABLE bool exportEntities(const QString& filename, const QVector& entityIDs); /**jsdoc * Export the entities with centers within a cube to a JSON file. diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 50c6301c7f..0676454b29 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -390,7 +390,7 @@ void Avatar::updateAvatarEntities() { QVariantMap asMap = variantProperties.toMap(); QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine); EntityItemProperties properties; - EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, properties); + EntityItemPropertiesFromScriptValueIgnoreReadOnly(scriptProperties, properties); properties.setEntityHostType(entity::HostType::AVATAR); properties.setOwningAvatarID(getID()); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 0d9e948db8..d4a10e551d 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -19,66 +19,39 @@ #include #include -//#define POLYLINE_ENTITY_USE_FADE_EFFECT -#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT -# include -#endif +#include "paintStroke_Shared.slh" using namespace render; using namespace render::entities; -static uint8_t CUSTOM_PIPELINE_NUMBER { 0 }; -static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 }; -static gpu::Stream::FormatPointer polylineFormat; -static gpu::PipelinePointer polylinePipeline; -#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT -static gpu::PipelinePointer polylineFadePipeline; -#endif +gpu::PipelinePointer PolyLineEntityRenderer::_pipeline = nullptr; -static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key, gpu::Batch& batch) { - if (!polylinePipeline) { - gpu::ShaderPointer program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke); -#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT - auto fadeVS = gpu::Shader::createVertex(std::string(paintStroke_fade_vert)); - auto fadePS = gpu::Shader::createPixel(std::string(paintStroke_fade_frag)); - gpu::ShaderPointer fadeProgram = gpu::Shader::createProgram(fadeVS, fadePS); -#endif - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - PrepareStencil::testMask(*state); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - polylinePipeline = gpu::Pipeline::create(program, state); -#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT - _fadePipeline = gpu::Pipeline::create(fadeProgram, state); -#endif - } - -#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT - if (key.isFaded()) { - auto fadeEffect = DependencyManager::get(); - return std::make_shared(_fadePipeline, nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); - } else { -#endif - return std::make_shared(polylinePipeline, nullptr, nullptr, nullptr); -#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT - } -#endif -} +static const QUrl DEFAULT_POLYLINE_TEXTURE = PathUtils::resourcesUrl("images/paintStroke.png"); PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { - static std::once_flag once; - std::call_once(once, [&] { - CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(shapePipelineFactory); - polylineFormat.reset(new gpu::Stream::Format()); - polylineFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), offsetof(Vertex, position)); - polylineFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), offsetof(Vertex, normal)); - polylineFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), offsetof(Vertex, uv)); - polylineFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB), offsetof(Vertex, color)); - }); + _texture = DependencyManager::get()->getTexture(DEFAULT_POLYLINE_TEXTURE); - _verticesBuffer = std::make_shared(); + { // Initialize our buffers + _polylineDataBuffer = std::make_shared(); + _polylineDataBuffer->resize(sizeof(PolylineData)); + PolylineData data { glm::vec2(_faceCamera, _glow), glm::vec2(0.0f) }; + _polylineDataBuffer->setSubData(0, data); + + _polylineGeometryBuffer = std::make_shared(); + } +} + +void PolyLineEntityRenderer::buildPipeline() { + // FIXME: opaque pipeline + gpu::ShaderPointer program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setCullMode(gpu::State::CullMode::CULL_NONE); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + PrepareStencil::testMask(*state); + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + _pipeline = gpu::Pipeline::create(program, state); } ItemKey PolyLineEntityRenderer::getKey() { @@ -86,152 +59,164 @@ ItemKey PolyLineEntityRenderer::getKey() { } ShapeKey PolyLineEntityRenderer::getShapeKey() { - return ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER).build(); + return ShapeKey::Builder().withOwnPipeline().withTranslucent().withoutCullFace(); +} + +bool PolyLineEntityRenderer::needsRenderUpdate() const { + bool textureLoadedChanged = resultWithReadLock([&] { + return (!_textureLoaded && _texture && _texture->isLoaded()); + }); + + if (textureLoadedChanged) { + return true; + } + + return Parent::needsRenderUpdate(); } bool PolyLineEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { return ( entity->pointsChanged() || - entity->strokeWidthsChanged() || + entity->widthsChanged() || entity->normalsChanged() || entity->texturesChanged() || - entity->strokeColorsChanged() + entity->colorsChanged() || + _isUVModeStretch != entity->getIsUVModeStretch() || + _glow != entity->getGlow() || + _faceCamera != entity->getFaceCamera() ); } -void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { - static const QUrl DEFAULT_POLYLINE_TEXTURE = QUrl(PathUtils::resourcesPath() + "images/paintStroke.png"); - QUrl entityTextures = DEFAULT_POLYLINE_TEXTURE; +void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { + auto pointsChanged = entity->pointsChanged(); + auto widthsChanged = entity->widthsChanged(); + auto normalsChanged = entity->normalsChanged(); + auto colorsChanged = entity->colorsChanged(); + + bool isUVModeStretch = entity->getIsUVModeStretch(); + bool glow = entity->getGlow(); + bool faceCamera = entity->getFaceCamera(); + + entity->resetPolyLineChanged(); + + // Transform + updateModelTransformAndBound(); + _renderTransform = getModelTransform(); + + // Textures if (entity->texturesChanged()) { entity->resetTexturesChanged(); + QUrl entityTextures = DEFAULT_POLYLINE_TEXTURE; auto textures = entity->getTextures(); if (!textures.isEmpty()) { entityTextures = QUrl(textures); } _texture = DependencyManager::get()->getTexture(entityTextures); + _textureAspectRatio = 1.0f; + _textureLoaded = false; } - - - if (!_texture) { - _texture = DependencyManager::get()->getTexture(entityTextures); + + bool textureChanged = false; + if (!_textureLoaded && _texture && _texture->isLoaded()) { + textureChanged = true; + _textureAspectRatio = (float)_texture->getOriginalHeight() / (float)_texture->getOriginalWidth(); + _textureLoaded = true; } -} -void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { - auto pointsChanged = entity->pointsChanged(); - auto strokeWidthsChanged = entity->strokeWidthsChanged(); - auto normalsChanged = entity->normalsChanged(); - auto strokeColorsChanged = entity->strokeColorsChanged(); - - - bool isUVModeStretch = entity->getIsUVModeStretch(); - entity->resetPolyLineChanged(); - - _polylineTransform = Transform(); - _polylineTransform.setTranslation(entity->getWorldPosition()); - _polylineTransform.setRotation(entity->getWorldOrientation()); + // Data + if (faceCamera != _faceCamera || glow != _glow) { + _faceCamera = faceCamera; + _glow = glow; + updateData(); + } + // Geometry if (pointsChanged) { - _lastPoints = entity->getLinePoints(); + _points = entity->getLinePoints(); } - if (strokeWidthsChanged) { - _lastStrokeWidths = entity->getStrokeWidths(); + if (widthsChanged) { + _widths = entity->getStrokeWidths(); } if (normalsChanged) { - _lastNormals = entity->getNormals(); + _normals = entity->getNormals(); } - if (strokeColorsChanged) { - _lastStrokeColors = entity->getStrokeColors(); - _lastStrokeColors = _lastNormals.size() == _lastStrokeColors.size() ? _lastStrokeColors : QVector({ toGlm(entity->getColor()) }); + if (colorsChanged) { + _colors = entity->getStrokeColors(); + _color = toGlm(entity->getColor()); } - if (pointsChanged || strokeWidthsChanged || normalsChanged || strokeColorsChanged) { - _empty = std::min(_lastPoints.size(), std::min(_lastNormals.size(), _lastStrokeWidths.size())) < 2; - if (!_empty) { - updateGeometry(updateVertices(_lastPoints, _lastNormals, _lastStrokeWidths, _lastStrokeColors, isUVModeStretch, _textureAspectRatio)); - } + if (_isUVModeStretch != isUVModeStretch || pointsChanged || widthsChanged || normalsChanged || colorsChanged || textureChanged) { + _isUVModeStretch = isUVModeStretch; + updateGeometry(); } } -void PolyLineEntityRenderer::updateGeometry(const std::vector& vertices) { - _numVertices = (uint32_t)vertices.size(); - auto bufferSize = _numVertices * sizeof(Vertex); - if (bufferSize > _verticesBuffer->getSize()) { - _verticesBuffer->resize(bufferSize); - } - _verticesBuffer->setSubData(0, vertices); -} +void PolyLineEntityRenderer::updateGeometry() { + int maxNumVertices = std::min(_points.length(), _normals.length()); -std::vector PolyLineEntityRenderer::updateVertices(const QVector& points, - const QVector& normals, - const QVector& strokeWidths, - const QVector& strokeColors, - const bool isUVModeStretch, - const float textureAspectRatio) { - // Calculate the minimum vector size out of normals, points, and stroke widths - int size = std::min(points.size(), std::min(normals.size(), strokeWidths.size())); - - std::vector vertices; - - // Guard against an empty polyline - if (size <= 0) { - return vertices; - } - - float uCoordInc = 1.0f / size; - float uCoord = 0.0f; - int finalIndex = size - 1; - glm::vec3 binormal; - float accumulatedDistance = 0.0f; - float distanceToLastPoint = 0.0f; - float accumulatedStrokeWidth = 0.0f; - float strokeWidth = 0.0f; bool doesStrokeWidthVary = false; - - - for (int i = 1; i < strokeWidths.size(); i++) { - if (strokeWidths[i] != strokeWidths[i - 1]) { - doesStrokeWidthVary = true; - break; + if (_widths.size() >= 0) { + for (int i = 1; i < maxNumVertices; i++) { + float width = PolyLineEntityItem::DEFAULT_LINE_WIDTH; + if (i < _widths.length()) { + width = _widths[i]; + } + if (width != _widths[i - 1]) { + doesStrokeWidthVary = true; + break; + } } } - for (int i = 0; i <= finalIndex; i++) { - const float& width = strokeWidths.at(i); - const auto& point = points.at(i); - const auto& normal = normals.at(i); - const auto& color = strokeColors.size() == normals.size() ? strokeColors.at(i) : strokeColors.at(0); - int vertexIndex = i * 2; - + float uCoordInc = 1.0f / maxNumVertices; + float uCoord = 0.0f; + float accumulatedDistance = 0.0f; + float accumulatedStrokeWidth = 0.0f; + glm::vec3 binormal; - if (!isUVModeStretch && i >= 1) { - distanceToLastPoint = glm::distance(points.at(i), points.at(i - 1)); - accumulatedDistance += distanceToLastPoint; - strokeWidth = 2 * strokeWidths[i]; + std::vector vertices; + vertices.reserve(maxNumVertices); + for (int i = 0; i < maxNumVertices; i++) { + // Position + glm::vec3 point = _points[i]; - if (doesStrokeWidthVary) { - //If the stroke varies along the line the texture will stretch more or less depending on the speed - //because it looks better than using the same method as below - accumulatedStrokeWidth += strokeWidth; - float increaseValue = 1; - if (accumulatedStrokeWidth != 0) { - float newUcoord = glm::ceil(((1.0f / textureAspectRatio) * accumulatedDistance) / (accumulatedStrokeWidth / i)); - increaseValue = newUcoord - uCoord; + // uCoord + float width = i < _widths.size() ? _widths[i] : PolyLineEntityItem::DEFAULT_LINE_WIDTH; + if (i > 0) { // First uCoord is 0.0f + if (!_isUVModeStretch) { + accumulatedDistance += glm::distance(point, _points[i - 1]); + + if (doesStrokeWidthVary) { + //If the stroke varies along the line the texture will stretch more or less depending on the speed + //because it looks better than using the same method as below + accumulatedStrokeWidth += width; + float increaseValue = 1; + if (accumulatedStrokeWidth != 0) { + float newUcoord = glm::ceil((_textureAspectRatio * accumulatedDistance) / (accumulatedStrokeWidth / i)); + increaseValue = newUcoord - uCoord; + } + + increaseValue = increaseValue > 0 ? increaseValue : 1; + uCoord += increaseValue; + } else { + // If the stroke width is constant then the textures should keep the aspect ratio along the line + uCoord = (_textureAspectRatio * accumulatedDistance) / width; } - - increaseValue = increaseValue > 0 ? increaseValue : 1; - uCoord += increaseValue; } else { - //If the stroke width is constant then the textures should keep the aspect ratio along the line - uCoord = ((1.0f / textureAspectRatio) * accumulatedDistance) / strokeWidth; + uCoord += uCoordInc; } - } else if (vertexIndex >= 2) { - uCoord += uCoordInc; } + // Color + glm::vec3 color = i < _colors.length() ? _colors[i] : _color; + + // Normal + glm::vec3 normal = _normals[i]; + + // Binormal // For last point we can assume binormals are the same since it represents the last two vertices of quad - if (i < finalIndex) { - const auto tangent = points.at(i + 1) - point; - binormal = glm::normalize(glm::cross(tangent, normal)) * width; + if (i < maxNumVertices - 1) { + glm::vec3 tangent = _points[i + 1] - point; + binormal = glm::normalize(glm::cross(tangent, normal)); // Check to make sure binormal is not a NAN. If it is, don't add to vertices vector if (binormal.x != binormal.x) { @@ -239,54 +224,36 @@ std::vector PolyLineEntityRenderer::updateVertic } } - const auto v1 = points.at(i) + binormal; - const auto v2 = points.at(i) - binormal; - vertices.emplace_back(v1, normal, vec2(uCoord, 0.0f), color); - vertices.emplace_back(v2, normal, vec2(uCoord, 1.0f), color); + PolylineVertex vertex = { glm::vec4(point, uCoord), glm::vec4(color, 1.0f), glm::vec4(normal, 0.0f), glm::vec4(binormal, 0.5f * width) }; + vertices.push_back(vertex); } - return vertices; + _numVertices = vertices.size(); + _polylineGeometryBuffer->setData(vertices.size() * sizeof(PolylineVertex), (const gpu::Byte*) vertices.data()); } -scriptable::ScriptableModelBase PolyLineEntityRenderer::getScriptableModel() { - // TODO: adapt polyline into a triangles mesh... - return EntityRenderer::getScriptableModel(); +void PolyLineEntityRenderer::updateData() { + PolylineData data { glm::vec2(_faceCamera, _glow), glm::vec2(0.0f) }; + _polylineDataBuffer->setSubData(0, data); } void PolyLineEntityRenderer::doRender(RenderArgs* args) { - if (_empty) { + if (_numVertices < 2) { return; } PerformanceTimer perfTimer("RenderablePolyLineEntityItem::render"); Q_ASSERT(args->_batch); - gpu::Batch& batch = *args->_batch; - batch.setModelTransform(_polylineTransform); - if (_texture && _texture->isLoaded()) { - batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, _texture->getGPUTexture()); - } else { - batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, DependencyManager::get()->getWhiteTexture()); + if (!_pipeline) { + buildPipeline(); } - float textureWidth = (float)_texture->getOriginalWidth(); - float textureHeight = (float)_texture->getOriginalHeight(); - if (textureWidth != 0 && textureHeight != 0) { - _textureAspectRatio = textureWidth / textureHeight; - } - - batch.setInputFormat(polylineFormat); - batch.setInputBuffer(0, _verticesBuffer, 0, sizeof(Vertex)); - -#ifndef POLYLINE_ENTITY_USE_FADE_EFFECT - // glColor4f must be called after setInputFormat if it must be taken into account - if (_isFading) { - batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime)); - } else { - batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } -#endif - - batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0); + batch.setPipeline(_pipeline); + batch.setModelTransform(_renderTransform); + batch.setResourceTexture(0, _textureLoaded ? _texture->getGPUTexture() : DependencyManager::get()->getWhiteTexture()); + batch.setResourceBuffer(0, _polylineGeometryBuffer); + batch.setUniformBuffer(0, _polylineDataBuffer); + batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * _numVertices), 0); } diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h index 8130171da8..fd37a49598 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h @@ -25,52 +25,40 @@ class PolyLineEntityRenderer : public TypedEntityRenderer { public: PolyLineEntityRenderer(const EntityItemPointer& entity); - virtual scriptable::ScriptableModelBase getScriptableModel() override; + // FIXME: shouldn't always be transparent: take into account texture and glow + virtual bool isTransparent() const override { return true; } + protected: + virtual bool needsRenderUpdate() const override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; - virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, - Transaction& transaction, - const TypedEntityPointer& entity) override; virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual ItemKey getKey() override; virtual ShapeKey getShapeKey() override; virtual void doRender(RenderArgs* args) override; - virtual bool isTransparent() const override { return true; } + void buildPipeline(); + void updateGeometry(); + void updateData(); - struct Vertex { - Vertex() {} - Vertex(const vec3& position, const vec3& normal, const vec2& uv, const vec3& color) : position(position), - normal(normal), - uv(uv), - color(color) {} - vec3 position; - vec3 normal; - vec2 uv; - vec3 color; - }; + QVector _points; + QVector _normals; + QVector _colors; + glm::vec3 _color; + QVector _widths; - void updateGeometry(const std::vector& vertices); - static std::vector updateVertices(const QVector& points, - const QVector& normals, - const QVector& strokeWidths, - const QVector& strokeColors, - const bool isUVModeStretch, - const float textureAspectRatio); - - Transform _polylineTransform; - QVector _lastPoints; - QVector _lastNormals; - QVector _lastStrokeColors; - QVector _lastStrokeWidths; - gpu::BufferPointer _verticesBuffer; - - uint32_t _numVertices { 0 }; - bool _empty{ true }; NetworkTexturePointer _texture; float _textureAspectRatio { 1.0f }; + bool _textureLoaded { false }; + bool _isUVModeStretch; + bool _faceCamera; + bool _glow; + + size_t _numVertices; + gpu::BufferPointer _polylineDataBuffer; + gpu::BufferPointer _polylineGeometryBuffer; + static gpu::PipelinePointer _pipeline; }; } } // namespace diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index f2c0d5572d..6ea088751f 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -14,21 +14,27 @@ <@include DeferredBufferWrite.slh@> -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; +<@include paintStroke.slh@> +<$declarePolyLineBuffers()$> -// the interpolated normal -layout(location=0) in vec3 interpolatedNormal; -layout(location=1) in vec2 varTexcoord; -layout(location=2) in vec4 varColor; +LAYOUT(binding=0) uniform sampler2D _texture; + +layout(location=0) in vec3 _normalWS; +layout(location=1) in vec2 _texCoord; +layout(location=2) in vec4 _color; +layout(location=3) in float _distanceFromCenter; void main(void) { - vec4 texel = texture(originalTexture, varTexcoord); - int frontCondition = 1 -int(gl_FrontFacing) * 2; - vec3 color = varColor.rgb; + vec4 texel = texture(_texture, _texCoord); + int frontCondition = 1 - 2 * int(gl_FrontFacing); + vec3 color = _color.rgb * texel.rgb; + float alpha = texel.a * _color.a; + + alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y); + packDeferredFragmentTranslucent( - float(frontCondition) * interpolatedNormal, - texel.a * varColor.a, - color * texel.rgb, - 10.0); + float(frontCondition) * _normalWS, + alpha, + color, + DEFAULT_ROUGHNESS); } diff --git a/libraries/entities-renderer/src/paintStroke.slh b/libraries/entities-renderer/src/paintStroke.slh new file mode 100644 index 0000000000..6189ac461b --- /dev/null +++ b/libraries/entities-renderer/src/paintStroke.slh @@ -0,0 +1,48 @@ + + +<@if not PAINTSTROKE_SLH@> +<@def PAINTSTROKE_SLH@> + +<@include paintStroke_Shared.slh@> +<@include gpu/ShaderConstants.h@> + +<@func declarePolyLineBuffers() @> + +// Hack comment to absorb the extra '//' scribe prepends + +#if !defined(GPU_SSBO_TRANSFORM_OBJECT) +LAYOUT(binding=GPU_RESOURCE_BUFFER_SLOT0_TEXTURE) uniform samplerBuffer polylineVerticesBuffer; +PolylineVertex getPolylineVertex(int i) { + int offset = 4 * i; + PolylineVertex vertex; + vertex.positionAndUCoord = texelFetch(polylineVerticesBuffer, offset); + vertex.color = texelFetch(polylineVerticesBuffer, offset + 1); + vertex.normal = texelFetch(polylineVerticesBuffer, offset + 2); + vertex.binormalAndHalfWidth = texelFetch(polylineVerticesBuffer, offset + 3); + return vertex; +} +#else +LAYOUT_STD140(binding=GPU_RESOURCE_BUFFER_SLOT0_STORAGE) buffer polylineVerticesBuffer { + PolylineVertex _vertices[]; +}; +PolylineVertex getPolylineVertex(int i) { + PolylineVertex vertex = _vertices[i]; + return vertex; +} +#endif + +LAYOUT_STD140(binding=0) uniform polylineDataBuffer { + PolylineData _polylineData; +}; + +<@endfunc@> + +<@endif@> diff --git a/libraries/entities-renderer/src/paintStroke.slv b/libraries/entities-renderer/src/paintStroke.slv index ecf52d61cf..c033d2c247 100644 --- a/libraries/entities-renderer/src/paintStroke.slv +++ b/libraries/entities-renderer/src/paintStroke.slv @@ -17,23 +17,45 @@ <@include gpu/Transform.slh@> <$declareStandardTransform()$> -// the interpolated normal -layout(location=0) out vec3 interpolatedNormal; +<@include paintStroke.slh@> +<$declarePolyLineBuffers()$> -//the diffuse texture -layout(location=1) out vec2 varTexcoord; - -layout(location=2) out vec4 varColor; +layout(location=0) out vec3 _normalWS; +layout(location=1) out vec2 _texCoord; +layout(location=2) out vec4 _color; +layout(location=3) out float _distanceFromCenter; void main(void) { - varTexcoord = inTexCoord0.st; + PolylineVertex vertex = getPolylineVertex(gl_VertexID / 2); + float evenVertex = float(gl_VertexID % 2 == 0); - // pass along the diffuse color - varColor = color_sRGBAToLinear(inColor); + _texCoord = vec2(vertex.positionAndUCoord.w, mix(1.0, 0.0, evenVertex)); + _color = color_sRGBAToLinear(vertex.color); - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, interpolatedNormal)$> + _distanceFromCenter = -1.0 + 2.0 * evenVertex; + vec4 position = vec4(vertex.positionAndUCoord.xyz, 1.0); + vec3 normal = vertex.normal.xyz; + vec3 binormal = vertex.binormalAndHalfWidth.xyz; + if (_polylineData.faceCameraGlow.x != 0.0) { + vec4 posEye; + vec3 normalEye; + vec3 binormalEye; + <$transformModelToEyePos(cam, obj, position, posEye)$> + <$transformModelToEyeDir(cam, obj, normal, normalEye)$> + <$transformModelToEyeDir(cam, obj, binormal, binormalEye)$> + + vec3 tangentEye = cross(binormalEye, normalEye); + // new normal faces the camera + normalEye = normalize(posEye.xyz); + binormalEye = normalize(cross(normalEye, tangentEye)); + posEye.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormalEye; + <$transformEyeToClipPos(cam, posEye, gl_Position)$> + <$transformEyeToWorldDir(cam, normalEye, _normalWS)$> + } else { + position.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormal; + <$transformModelToClipPos(cam, obj, position, gl_Position)$> + <$transformModelToWorldDir(cam, obj, normal, _normalWS)$> + } } \ No newline at end of file diff --git a/libraries/entities-renderer/src/paintStroke_Shared.slh b/libraries/entities-renderer/src/paintStroke_Shared.slh new file mode 100644 index 0000000000..52c10df99b --- /dev/null +++ b/libraries/entities-renderer/src/paintStroke_Shared.slh @@ -0,0 +1,25 @@ +// glsl / C++ compatible source as interface for FadeEffect +#ifdef __cplusplus +# define _PL_VEC4 glm::vec4 +# define _PL_VEC2 glm::vec2 +#else +# define _PL_VEC4 vec4 +# define _PL_VEC2 vec2 +#endif + +struct PolylineVertex { + _PL_VEC4 positionAndUCoord; + _PL_VEC4 color; + _PL_VEC4 normal; + _PL_VEC4 binormalAndHalfWidth; +}; + +struct PolylineData { + _PL_VEC2 faceCameraGlow; + _PL_VEC2 spare; +}; + +// <@if 1@> +// Trigger Scribe include +// <@endif@> +// \ No newline at end of file diff --git a/libraries/entities-renderer/src/paintStroke_fade.slf b/libraries/entities-renderer/src/paintStroke_fade.slf deleted file mode 100644 index fa6d0aab75..0000000000 --- a/libraries/entities-renderer/src/paintStroke_fade.slf +++ /dev/null @@ -1,52 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// paintStroke_fade.frag -// fragment shader -// -// Created by Olivier Prat on 19/07/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include DeferredBufferWrite.slh@> - -<@include Fade.slh@> -<$declareFadeFragment()$> - -// the albedo texture -LAYOUT(binding=0) uniform sampler2D originalTexture; - -// the interpolated normal -layout(location=0) in vec3 interpolatedNormal; -layout(location=1) in vec2 varTexcoord; -layout(location=2) in vec4 varColor; -layout(location=3) in vec4 _worldPosition; - -struct PolyLineUniforms { - vec3 color; -}; - -LAYOUT(binding=0) uniform polyLineBuffer { - PolyLineUniforms polyline; -}; - -void main(void) { - vec3 fadeEmissive; - FadeObjectParams fadeParams; - - <$fetchFadeObjectParams(fadeParams)$> - applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); - - vec4 texel = texture(originalTexture, varTexcoord); - int frontCondition = 1 -int(gl_FrontFacing) * 2; - vec3 color = varColor.rgb; - packDeferredFragmentTranslucent( - interpolatedNormal * float(frontCondition), - texel.a * varColor.a, - polyline.color * texel.rgb + fadeEmissive, - 10.0); -} diff --git a/libraries/entities-renderer/src/paintStroke_fade.slv b/libraries/entities-renderer/src/paintStroke_fade.slv deleted file mode 100644 index f6fcb18c98..0000000000 --- a/libraries/entities-renderer/src/paintStroke_fade.slv +++ /dev/null @@ -1,43 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// paintStroke_fade.vert -// vertex shader -// -// Created by Olivier Prat on 19/07/17. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -<@include gpu/Inputs.slh@> -<@include gpu/Color.slh@> -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> - -// the interpolated normal -layout(location=0) out vec3 interpolatedNormal; - -//the diffuse texture -layout(location=1) out vec2 varTexcoord; - -layout(location=2) out vec4 varColor; -layout(location=3) out vec4 _worldPosition; - -void main(void) { - - varTexcoord = inTexCoord0.st; - - // pass along the diffuse color - varColor = color_sRGBAToLinear(inColor); - - - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, inNormal.xyz, interpolatedNormal)$> - <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> -} \ No newline at end of file diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index cf031f2d0f..7e97787ff2 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -182,14 +182,29 @@ void AnimationPropertyGroup::listChangedProperties(QList& out) { if (urlChanged()) { out << "animation-url"; } + if (allowTranslationChanged()) { + out << "animation-allowTranslation"; + } if (fpsChanged()) { out << "animation-fps"; } if (currentFrameChanged()) { out << "animation-currentFrame"; } - if (allowTranslationChanged()) { - out << "animation-allowTranslation"; + if (runningChanged()) { + out << "animation-running"; + } + if (loopChanged()) { + out << "animation-loop"; + } + if (firstFrameChanged()) { + out << "animation-firstFrame"; + } + if (lastFrameChanged()) { + out << "animation-lastFrame"; + } + if (holdChanged()) { + out << "animation-hold"; } } @@ -224,7 +239,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setURL); READ_ENTITY_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, bool, setAllowTranslation); - READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS); READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setRunning); @@ -234,6 +248,7 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF READ_ENTITY_PROPERTY(PROP_ANIMATION_HOLD, bool, setHold); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_URL, URL); + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FPS, FPS); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FRAME_INDEX, CurrentFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_PLAYING, Running); @@ -241,7 +256,6 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FIRST_FRAME, FirstFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LAST_FRAME, LastFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_HOLD, Hold); - DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation); processedBytes += bytesRead; @@ -252,6 +266,7 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF void AnimationPropertyGroup::markAllChanged() { _urlChanged = true; + _allowTranslationChanged = true; _fpsChanged = true; _currentFrameChanged = true; _runningChanged = true; @@ -259,13 +274,13 @@ void AnimationPropertyGroup::markAllChanged() { _firstFrameChanged = true; _lastFrameChanged = true; _holdChanged = true; - _allowTranslationChanged = true; } EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const { EntityPropertyFlags changedProperties; CHECK_PROPERTY_CHANGE(PROP_ANIMATION_URL, url); + CHECK_PROPERTY_CHANGE(PROP_ANIMATION_ALLOW_TRANSLATION, allowTranslation); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FPS, fps); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FRAME_INDEX, currentFrame); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_PLAYING, running); @@ -273,7 +288,6 @@ EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FIRST_FRAME, firstFrame); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LAST_FRAME, lastFrame); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_HOLD, hold); - CHECK_PROPERTY_CHANGE(PROP_ANIMATION_ALLOW_TRANSLATION, allowTranslation); return changedProperties; } @@ -309,6 +323,7 @@ EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamP EntityPropertyFlags requestedProperties; requestedProperties += PROP_ANIMATION_URL; + requestedProperties += PROP_ANIMATION_ALLOW_TRANSLATION; requestedProperties += PROP_ANIMATION_FPS; requestedProperties += PROP_ANIMATION_FRAME_INDEX; requestedProperties += PROP_ANIMATION_PLAYING; @@ -316,7 +331,6 @@ EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamP requestedProperties += PROP_ANIMATION_FIRST_FRAME; requestedProperties += PROP_ANIMATION_LAST_FRAME; requestedProperties += PROP_ANIMATION_HOLD; - requestedProperties += PROP_ANIMATION_ALLOW_TRANSLATION; return requestedProperties; } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index bfa238d695..8c71499b78 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -85,15 +85,15 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_DIMENSIONS; requestedProperties += PROP_ROTATION; requestedProperties += PROP_REGISTRATION_POINT; - // TODO: handle PROP_CREATED? + requestedProperties += PROP_CREATED; requestedProperties += PROP_LAST_EDITED_BY; - requestedProperties += PROP_ENTITY_HOST_TYPE; - requestedProperties += PROP_OWNING_AVATAR_ID; + //requestedProperties += PROP_ENTITY_HOST_TYPE; // not sent over the wire + //requestedProperties += PROP_OWNING_AVATAR_ID; // not sent over the wire requestedProperties += PROP_PARENT_ID; requestedProperties += PROP_PARENT_JOINT_INDEX; requestedProperties += PROP_QUERY_AA_CUBE; requestedProperties += PROP_CAN_CAST_SHADOW; - // requestedProperties += PROP_VISIBLE_IN_SECONDARY_CAMERA; // not sent over wire + // requestedProperties += PROP_VISIBLE_IN_SECONDARY_CAMERA; // not sent over the wire withReadLock([&] { requestedProperties += _grabProperties.getEntityProperties(params); }); @@ -178,9 +178,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); EntityPropertyFlags requestedProperties = getEntityProperties(params); - requestedProperties -= PROP_ENTITY_HOST_TYPE; - requestedProperties -= PROP_OWNING_AVATAR_ID; - // If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item, // then our entityTreeElementExtraEncodeData should include data about which properties we need to append. if (entityTreeElementExtraEncodeData && entityTreeElementExtraEncodeData->entities.contains(getEntityItemID())) { @@ -263,10 +260,10 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getUnscaledDimensions()); APPEND_ENTITY_PROPERTY(PROP_ROTATION, getLocalOrientation()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint()); - // TODO: handle created? + APPEND_ENTITY_PROPERTY(PROP_CREATED, getCreated()); APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, getLastEditedBy()); - // APPEND_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, getEntityHostType()); // not sent over wire - // APPEND_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, getOwningAvatarID()); // not sent over wire + // APPEND_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, getEntityHostType()); // not sent over the wire + // APPEND_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, getOwningAvatarID()); // not sent over the wire // convert AVATAR_SELF_ID to actual sessionUUID. QUuid actualParentID = getParentID(); if (actualParentID == AVATAR_SELF_ID) { @@ -277,7 +274,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex()); APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, getQueryAACube()); APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow()); - // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, getIsVisibleInSecondaryCamera()); // not sent over wire + // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, getIsVisibleInSecondaryCamera()); // not sent over the wire withReadLock([&] { _grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -314,13 +311,13 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, getServerScripts()); // Certifiable Properties - APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, getMarketplaceID()); APPEND_ENTITY_PROPERTY(PROP_ITEM_NAME, getItemName()); APPEND_ENTITY_PROPERTY(PROP_ITEM_DESCRIPTION, getItemDescription()); APPEND_ENTITY_PROPERTY(PROP_ITEM_CATEGORIES, getItemCategories()); APPEND_ENTITY_PROPERTY(PROP_ITEM_ARTIST, getItemArtist()); APPEND_ENTITY_PROPERTY(PROP_ITEM_LICENSE, getItemLicense()); APPEND_ENTITY_PROPERTY(PROP_LIMITED_RUN, getLimitedRun()); + APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, getMarketplaceID()); APPEND_ENTITY_PROPERTY(PROP_EDITION_NUMBER, getEditionNumber()); APPEND_ENTITY_PROPERTY(PROP_ENTITY_INSTANCE_NUMBER, getEntityInstanceNumber()); APPEND_ENTITY_PROPERTY(PROP_CERTIFICATE_ID, getCertificateID()); @@ -818,10 +815,10 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, customUpdateRotationFromNetwork); } READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint); - // READ_ENTITY_PROPERTY(PROP_CREATED, quint64, setCreated); // not sent over wire + READ_ENTITY_PROPERTY(PROP_CREATED, quint64, setCreated); READ_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy); - // READ_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, entity::HostType, setEntityHostType); // not sent over wire - // READ_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, QUuuid, setOwningAvatarID); // not sent over wire + // READ_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, entity::HostType, setEntityHostType); // not sent over the wire + // READ_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, QUuuid, setOwningAvatarID); // not sent over the wire { // parentID and parentJointIndex are protected by simulation ownership bool oldOverwrite = overwriteLocalData; overwriteLocalData = overwriteLocalData && !weOwnSimulation; @@ -840,7 +837,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, AACube, customUpdateQueryAACubeFromNetwork); } READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); - // READ_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // not sent over wire + // READ_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // not sent over the wire withWriteLock([&] { int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, @@ -904,18 +901,20 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // from being received by an entity script server running a script that continously updates an entity. // Basically, we'll allow recent changes to the server scripts even if there are local changes to other properties // that have been made more recently. - bool overwriteLocalData = !ignoreServerPacket || (lastEditedFromBufferAdjusted > _serverScriptsChangedTimestamp); + bool oldOverwrite = overwriteLocalData; + overwriteLocalData = !ignoreServerPacket || (lastEditedFromBufferAdjusted > _serverScriptsChangedTimestamp); READ_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, QString, setServerScripts); + overwriteLocalData = oldOverwrite; } // Certifiable props - READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID); READ_ENTITY_PROPERTY(PROP_ITEM_NAME, QString, setItemName); READ_ENTITY_PROPERTY(PROP_ITEM_DESCRIPTION, QString, setItemDescription); READ_ENTITY_PROPERTY(PROP_ITEM_CATEGORIES, QString, setItemCategories); READ_ENTITY_PROPERTY(PROP_ITEM_ARTIST, QString, setItemArtist); READ_ENTITY_PROPERTY(PROP_ITEM_LICENSE, QString, setItemLicense); READ_ENTITY_PROPERTY(PROP_LIMITED_RUN, quint32, setLimitedRun); + READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID); READ_ENTITY_PROPERTY(PROP_EDITION_NUMBER, quint32, setEditionNumber); READ_ENTITY_PROPERTY(PROP_ENTITY_INSTANCE_NUMBER, quint32, setEntityInstanceNumber); READ_ENTITY_PROPERTY(PROP_CERTIFICATE_ID, QString, setCertificateID); @@ -1309,7 +1308,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex); COPY_ENTITY_PROPERTY_TO_PROPERTIES(queryAACube, getQueryAACube); COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow); - // COPY_ENTITY_PROPERTY_TO_PROPERTIES(isVisibleInSecondaryCamera, getIsVisibleInSecondaryCamera); // not sent over wire + COPY_ENTITY_PROPERTY_TO_PROPERTIES(isVisibleInSecondaryCamera, isVisibleInSecondaryCamera); withReadLock([&] { _grabProperties.getProperties(properties); }); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1745658cf1..d1b1aa698f 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -63,10 +63,6 @@ void EntityItemProperties::calculateNaturalPosition(const vec3& min, const vec3& _naturalPosition = max - halfDimension; } -void EntityItemProperties::setCreated(QDateTime &v) { - _created = v.toMSecsSinceEpoch() * 1000; // usec per msec -} - void EntityItemProperties::debugDump() const { qCDebug(entities) << "EntityItemProperties..."; qCDebug(entities) << " _type=" << EntityTypes::getEntityTypeName(_type); @@ -358,7 +354,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_DIMENSIONS, dimensions); CHECK_PROPERTY_CHANGE(PROP_ROTATION, rotation); CHECK_PROPERTY_CHANGE(PROP_REGISTRATION_POINT, registrationPoint); - //CHECK_PROPERTY_CHANGE(PROP_CREATED, created); // can't change + CHECK_PROPERTY_CHANGE(PROP_CREATED, created); CHECK_PROPERTY_CHANGE(PROP_LAST_EDITED_BY, lastEditedBy); CHECK_PROPERTY_CHANGE(PROP_ENTITY_HOST_TYPE, entityHostType); CHECK_PROPERTY_CHANGE(PROP_OWNING_AVATAR_ID, owningAvatarID); @@ -527,6 +523,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_STROKE_NORMALS, normals); CHECK_PROPERTY_CHANGE(PROP_STROKE_COLORS, strokeColors); CHECK_PROPERTY_CHANGE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch); + CHECK_PROPERTY_CHANGE(PROP_LINE_GLOW, glow); + CHECK_PROPERTY_CHANGE(PROP_LINE_FACE_CAMERA, faceCamera); // Shape CHECK_PROPERTY_CHANGE(PROP_SHAPE, shape); @@ -1051,6 +1049,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * format. * @property {boolean} isUVModeStretch=true - If true, the texture is stretched to fill the whole line, otherwise * the texture repeats along the line. + * @property {bool} glow=false - If true, the alpha of the strokes will drop off farther from the center. + * @property {bool} faceCamera=false - If true, each line segment will rotate to face the camera. * @example Draw a textured "V". * var entity = Entities.addEntity({ * type: "PolyLine", @@ -1367,11 +1367,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::Type)) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(type, EntityTypes::getEntityTypeName(_type)); } - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::Created)) { - auto created = QDateTime::fromMSecsSinceEpoch(getCreated() / 1000.0f, Qt::UTC); // usec per msec - created.setTimeSpec(Qt::OffsetFromUTC); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(created, created.toString(Qt::ISODate)); - } if ((!skipDefaults || _lifetime != defaultEntityProperties._lifetime) && !strictSemantics) { if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::Age)) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(age, getAge()); // gettable, but not settable @@ -1400,7 +1395,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DIMENSIONS, dimensions); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ROTATION, rotation); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_REGISTRATION_POINT, registrationPoint); - //COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CREATED, created); // handled above + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CREATED, created); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LAST_EDITED_BY, lastEditedBy); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ENTITY_HOST_TYPE, entityHostType, getEntityHostTypeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); @@ -1634,6 +1629,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_STROKE_NORMALS, normals); COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_STROKE_COLORS, strokeColors, qVectorVec3Color); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_GLOW, glow); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_FACE_CAMERA, faceCamera); } // Materials @@ -1762,18 +1759,11 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool setType(typeScriptValue.toVariant().toString()); } - if (!honorReadOnly) { - // this is used by the json reader to set things that we don't want javascript to able to affect. - COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(created, QDateTime, setCreated, [this]() { - auto result = QDateTime::fromMSecsSinceEpoch(_created / 1000, Qt::UTC); // usec per msec - return result; - }); - // TODO: expose this to QScriptValue for JSON saves? - //COPY_PROPERTY_FROM_QSCRIPTVALUE(simulationOwner, ???, setSimulatorPriority); - } - // Core - // simluationOwner above + if (!honorReadOnly) { + // not handled yet + // COPY_PROPERTY_FROM_QSCRIPTVALUE(simulationOwner, SimulationOwner, setSimulationOwner); + } COPY_PROPERTY_FROM_QSCRIPTVALUE(visible, bool, setVisible); COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName); COPY_PROPERTY_FROM_QSCRIPTVALUE(locked, bool, setLocked); @@ -1784,10 +1774,12 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(dimensions, vec3, setDimensions); COPY_PROPERTY_FROM_QSCRIPTVALUE(rotation, quat, setRotation); COPY_PROPERTY_FROM_QSCRIPTVALUE(registrationPoint, vec3, setRegistrationPoint); - // created is read only - COPY_PROPERTY_FROM_QSCRIPTVALUE(lastEditedBy, QUuid, setLastEditedBy); - COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(entityHostType, EntityHostType); - COPY_PROPERTY_FROM_QSCRIPTVALUE(owningAvatarID, QUuid, setOwningAvatarID); + if (!honorReadOnly) { + COPY_PROPERTY_FROM_QSCRIPTVALUE(created, quint64, setCreated); + COPY_PROPERTY_FROM_QSCRIPTVALUE(lastEditedBy, QUuid, setLastEditedBy); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(entityHostType, EntityHostType); + COPY_PROPERTY_FROM_QSCRIPTVALUE(owningAvatarID, QUuid, setOwningAvatarID); + } COPY_PROPERTY_FROM_QSCRIPTVALUE(parentID, QUuid, setParentID); COPY_PROPERTY_FROM_QSCRIPTVALUE(parentJointIndex, quint16, setParentJointIndex); COPY_PROPERTY_FROM_QSCRIPTVALUE(queryAACube, AACube, setQueryAACube); // TODO: should scripts be able to set this? @@ -1813,7 +1805,9 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(collisionsWillMove, bool, setDynamic, getDynamic); // legacy support COPY_PROPERTY_FROM_QSCRIPTVALUE(dynamic, bool, setDynamic); COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionSoundURL, QString, setCollisionSoundURL); - COPY_PROPERTY_FROM_QSCRIPTVALUE(actionData, QByteArray, setActionData); // TODO: should scripts be able to set this? + if (!honorReadOnly) { + COPY_PROPERTY_FROM_QSCRIPTVALUE(actionData, QByteArray, setActionData); + } // Cloning COPY_PROPERTY_FROM_QSCRIPTVALUE(cloneable, bool, setCloneable); @@ -1956,6 +1950,8 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(normals, qVectorVec3, setNormals); COPY_PROPERTY_FROM_QSCRIPTVALUE(strokeColors, qVectorVec3, setStrokeColors); COPY_PROPERTY_FROM_QSCRIPTVALUE(isUVModeStretch, bool, setIsUVModeStretch); + COPY_PROPERTY_FROM_QSCRIPTVALUE(glow, bool, setGlow); + COPY_PROPERTY_FROM_QSCRIPTVALUE(faceCamera, bool, setFaceCamera); // Shape COPY_PROPERTY_FROM_QSCRIPTVALUE(shape, QString, setShape); @@ -2208,6 +2204,8 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(normals); COPY_PROPERTY_IF_CHANGED(strokeColors); COPY_PROPERTY_IF_CHANGED(isUVModeStretch); + COPY_PROPERTY_IF_CHANGED(glow); + COPY_PROPERTY_IF_CHANGED(faceCamera); // Shape COPY_PROPERTY_IF_CHANGED(shape); @@ -2290,13 +2288,13 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_DIMENSIONS, Dimensions, dimensions, vec3); ADD_PROPERTY_TO_MAP(PROP_ROTATION, Rotation, rotation, quat); ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, vec3); - //ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64); // not yet handled - //ADD_PROPERTY_TO_MAP(PROP_LAST_EDITED_BY, LastEditedBy, lastEditedBy, QUuid); // not yet handled + ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64); + ADD_PROPERTY_TO_MAP(PROP_LAST_EDITED_BY, LastEditedBy, lastEditedBy, QUuid); ADD_PROPERTY_TO_MAP(PROP_ENTITY_HOST_TYPE, EntityHostType, entityHostType, entity::HostType); ADD_PROPERTY_TO_MAP(PROP_OWNING_AVATAR_ID, OwningAvatarID, owningAvatarID, QUuid); ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid); ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t); - //ADD_PROPERTY_TO_MAP(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube); // not yet handled + ADD_PROPERTY_TO_MAP(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube); ADD_PROPERTY_TO_MAP(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool); ADD_PROPERTY_TO_MAP(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool); { // Grab @@ -2524,6 +2522,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_STROKE_NORMALS, Normals, normals, QVector); ADD_PROPERTY_TO_MAP(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector); ADD_PROPERTY_TO_MAP(PROP_IS_UV_MODE_STRETCH, IsUVModeStretch, isUVModeStretch, QVector); + ADD_PROPERTY_TO_MAP(PROP_LINE_GLOW, Glow, glow, bool); + ADD_PROPERTY_TO_MAP(PROP_LINE_FACE_CAMERA, FaceCamera, faceCamera, bool); // Shape ADD_PROPERTY_TO_MAP(PROP_SHAPE, Shape, shape, QString); @@ -2679,16 +2679,15 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, properties.getDimensions()); APPEND_ENTITY_PROPERTY(PROP_ROTATION, properties.getRotation()); APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, properties.getRegistrationPoint()); - // FIXME: deal with these - // APPEND_ENTITY_PROPERTY(PROP_CREATED, properties.getCreated()); - // APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, properties.getLastEditedBy()); - // APPEND_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, (uint32_t)properties.getEntityHostType()); - // APPEND_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, properties.getOwningAvatarID()); + APPEND_ENTITY_PROPERTY(PROP_CREATED, properties.getCreated()); + APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, properties.getLastEditedBy()); + // APPEND_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, (uint32_t)properties.getEntityHostType()); // not sent over the wire + // APPEND_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, properties.getOwningAvatarID()); // not sent over the wire APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, properties.getParentID()); APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, properties.getParentJointIndex()); APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, properties.getQueryAACube()); APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, properties.getCanCastShadow()); - // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, properties.getIsVisibleInSecondaryCamera()); // Not sent over the wire + // APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, properties.getIsVisibleInSecondaryCamera()); // not sent over the wire _staticGrab.setProperties(properties); _staticGrab.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -2888,6 +2887,8 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_STROKE_NORMALS, properties.getPackedNormals()); APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, properties.getPackedStrokeColors()); APPEND_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, properties.getIsUVModeStretch()); + APPEND_ENTITY_PROPERTY(PROP_LINE_GLOW, properties.getGlow()); + APPEND_ENTITY_PROPERTY(PROP_LINE_FACE_CAMERA, properties.getFaceCamera()); } // NOTE: Spheres and Boxes are just special cases of Shape, and they need to include their PROP_SHAPE @@ -3070,10 +3071,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int processedBytes += sizeof(lastEdited); properties.setLastEdited(lastEdited); - // NOTE: We intentionally do not send "created" times in edit messages. This is because: - // 1) if the edit is to an existing entity, the created time can not be changed - // 2) if the edit is to a new entity, the created time is the last edited time - // encoded id QUuid editID = QUuid::fromRfc4122(QByteArray::fromRawData(reinterpret_cast(dataAt), NUM_BYTES_RFC4122_UUID)); dataAt += NUM_BYTES_RFC4122_UUID; @@ -3123,16 +3120,15 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DIMENSIONS, vec3, setDimensions); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ROTATION, quat, setRotation); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_REGISTRATION_POINT, vec3, setRegistrationPoint); - // FIXME: deal with these - // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CREATED, quint64, setCreated); - // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy); - // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ENTITY_HOST_TYPE, entity::HostType, setEntityHostType); - // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_OWNING_AVATAR_ID, QUuid, setOwningAvatarID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CREATED, quint64, setCreated); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy); + // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ENTITY_HOST_TYPE, entity::HostType, setEntityHostType); // not sent over the wire + // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_OWNING_AVATAR_ID, QUuid, setOwningAvatarID); // not sent over the wire READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_ID, QUuid, setParentID); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_QUERY_AA_CUBE, AACube, setQueryAACube); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); - // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // Not sent over the wire + // READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // not sent over the wire properties.getGrab().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); // Physics @@ -3321,6 +3317,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STROKE_NORMALS, QByteArray, setPackedNormals); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STROKE_COLORS, QByteArray, setPackedStrokeColors); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_UV_MODE_STRETCH, bool, setIsUVModeStretch); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_GLOW, bool, setGlow); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_FACE_CAMERA, bool, setFaceCamera); } // NOTE: Spheres and Boxes are just special cases of Shape, and they need to include their PROP_SHAPE @@ -3666,6 +3664,8 @@ void EntityItemProperties::markAllChanged() { _normalsChanged = true; _strokeColorsChanged = true; _isUVModeStretchChanged = true; + _glowChanged = true; + _faceCameraChanged = true; // Shape _shapeChanged = true; @@ -3856,13 +3856,12 @@ QList EntityItemProperties::listChangedProperties() { if (registrationPointChanged()) { out += "registrationPoint"; } - // FIXME: handle these - //if (createdChanged()) { - // out += "created"; - //} - //if (lastEditedByChanged()) { - // out += "lastEditedBy"; - //} + if (createdChanged()) { + out += "created"; + } + if (lastEditedByChanged()) { + out += "lastEditedBy"; + } if (entityHostTypeChanged()) { out += "entityHostType"; } @@ -4277,6 +4276,12 @@ QList EntityItemProperties::listChangedProperties() { if (isUVModeStretchChanged()) { out += "isUVModeStretch"; } + if (glowChanged()) { + out += "glow"; + } + if (faceCameraChanged()) { + out += "faceCamera"; + } // Shape if (shapeChanged()) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index b741bb8ca4..35a70c6e39 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -309,6 +310,8 @@ public: DEFINE_PROPERTY(PROP_STROKE_NORMALS, Normals, normals, QVector, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC); DEFINE_PROPERTY(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC); DEFINE_PROPERTY(PROP_IS_UV_MODE_STRETCH, IsUVModeStretch, isUVModeStretch, bool, true); + DEFINE_PROPERTY(PROP_LINE_GLOW, Glow, glow, bool, false); + DEFINE_PROPERTY(PROP_LINE_FACE_CAMERA, FaceCamera, faceCamera, bool, false); // Shape DEFINE_PROPERTY_REF(PROP_SHAPE, Shape, shape, QString, "Sphere"); @@ -381,8 +384,6 @@ public: void setLocationDirty() { _positionChanged = true; _rotationChanged = true; } - void setCreated(QDateTime& v); - bool hasTransformOrVelocityChanges() const; void clearTransformOrVelocityChanges(); bool hasMiscPhysicsChanges() const; diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 76723526db..90dbd68f9f 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -13,8 +13,6 @@ #ifndef hifi_EntityItemPropertiesMacros_h #define hifi_EntityItemPropertiesMacros_h -#include - #include "EntityItemID.h" #include @@ -234,14 +232,6 @@ inline QString QString_convertFromScriptValue(const QScriptValue& v, bool& isVal inline QUuid QUuid_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toUuid(); } inline EntityItemID EntityItemID_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; return v.toVariant().toUuid(); } - -inline QDateTime QDateTime_convertFromScriptValue(const QScriptValue& v, bool& isValid) { - isValid = true; - auto result = QDateTime::fromString(v.toVariant().toString().trimmed(), Qt::ISODate); - // result.setTimeSpec(Qt::OffsetFromUTC); - return result; -} - inline QByteArray QByteArray_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; QString b64 = v.toVariant().toString().trimmed(); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 8e0f5eb387..5e4b27858c 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -32,13 +32,13 @@ enum EntityPropertyList { PROP_REGISTRATION_POINT, PROP_CREATED, PROP_LAST_EDITED_BY, - PROP_ENTITY_HOST_TYPE, // not sent over wire - PROP_OWNING_AVATAR_ID, // not sent over wire + PROP_ENTITY_HOST_TYPE, // not sent over the wire + PROP_OWNING_AVATAR_ID, // not sent over the wire PROP_PARENT_ID, PROP_PARENT_JOINT_INDEX, PROP_QUERY_AA_CUBE, PROP_CAN_CAST_SHADOW, - PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over wire + PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over the wire // Grab PROP_GRAB_GRABBABLE, PROP_GRAB_KINEMATIC, @@ -291,6 +291,8 @@ enum EntityPropertyList { PROP_STROKE_NORMALS = PROP_DERIVED_2, PROP_STROKE_COLORS = PROP_DERIVED_3, PROP_IS_UV_MODE_STRETCH = PROP_DERIVED_4, + PROP_LINE_GLOW = PROP_DERIVED_5, + PROP_LINE_FACE_CAMERA = PROP_DERIVED_6, // Shape PROP_SHAPE = PROP_DERIVED_0, diff --git a/libraries/entities/src/EntityPsuedoPropertyFlags.h b/libraries/entities/src/EntityPsuedoPropertyFlags.h index d0af945215..d6326ee1f5 100644 --- a/libraries/entities/src/EntityPsuedoPropertyFlags.h +++ b/libraries/entities/src/EntityPsuedoPropertyFlags.h @@ -23,7 +23,6 @@ namespace EntityPsuedoPropertyFlag { FlagsActive, ID, Type, - Created, Age, AgeAsText, LastEdited, @@ -31,7 +30,6 @@ namespace EntityPsuedoPropertyFlag { OriginalTextures, RenderInfo, ClientOnly, - OwningAvatarID, AvatarEntity, LocalEntity, FaceCamera, diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index cdeaf120ce..42fb2d23c4 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -492,10 +492,9 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties propertiesWithSimID.setCollisionless(true); } + // the created time will be set in EntityTree::addEntity by recordCreationTime() propertiesWithSimID.setLastEditedBy(sessionID); - propertiesWithSimID.setActionData(QByteArray()); - bool scalesWithParent = propertiesWithSimID.getScalesWithParent(); propertiesWithSimID = convertPropertiesFromScriptSemantics(propertiesWithSimID, scalesWithParent); @@ -676,8 +675,6 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::ID); } else if (extendedPropertyString == "type") { psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::Type); - } else if (extendedPropertyString == "created") { - psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::Created); } else if (extendedPropertyString == "age") { psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::Age); } else if (extendedPropertyString == "ageAsText") { @@ -692,8 +689,6 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::RenderInfo); } else if (extendedPropertyString == "clientOnly") { psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::ClientOnly); - } else if (extendedPropertyString == "owningAvatarID") { - psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::OwningAvatarID); } else if (extendedPropertyString == "avatarEntity") { psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::AvatarEntity); } else if (extendedPropertyString == "localEntity") { @@ -859,8 +854,6 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } properties.setOwningAvatarID(entity->getOwningAvatarID()); - properties.setActionData(entity->getDynamicData()); - // make sure the properties has a type, so that the encode can know which properties to include properties.setType(entity->getType()); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index c9e855f606..0957b226e9 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1828,7 +1828,6 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c } // this is a new entity... assign a new entityID - properties.setCreated(properties.getLastEdited()); properties.setLastEditedBy(senderNode->getUUID()); startCreate = usecTimestampNow(); EntityItemPointer newEntity = addEntity(entityItemID, properties); @@ -2831,6 +2830,13 @@ bool EntityTree::readFromMap(QVariantMap& map) { properties.setColorSpread({0, 0, 0}); } + if (contentVersion < (int)EntityVersion::FixPropertiesFromCleanup) { + if (entityMap.contains("created")) { + quint64 created = QDateTime::fromString(entityMap["created"].toString().trimmed(), Qt::ISODate).toMSecsSinceEpoch() * 1000; + properties.setCreated(created); + } + } + EntityItemPointer entity = addEntity(entityItemID, properties); if (!entity) { qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType(); diff --git a/libraries/entities/src/GrabPropertyGroup.cpp b/libraries/entities/src/GrabPropertyGroup.cpp index 73bc1ed2d0..7a9ba147d9 100644 --- a/libraries/entities/src/GrabPropertyGroup.cpp +++ b/libraries/entities/src/GrabPropertyGroup.cpp @@ -49,6 +49,7 @@ void GrabPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _d COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(grab, grabFollowsController, bool, setGrabFollowsController); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(grab, triggerable, bool, setTriggerable); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(grab, equippable, bool, setEquippable); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(grab, grabDelegateToParent, bool, setGrabDelegateToParent); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(grab, equippableLeftPosition, vec3, setEquippableLeftPosition); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(grab, equippableLeftRotation, quat, setEquippableLeftRotation); COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(grab, equippableRightPosition, vec3, setEquippableRightPosition); @@ -64,6 +65,7 @@ void GrabPropertyGroup::merge(const GrabPropertyGroup& other) { COPY_PROPERTY_IF_CHANGED(grabFollowsController); COPY_PROPERTY_IF_CHANGED(triggerable); COPY_PROPERTY_IF_CHANGED(equippable); + COPY_PROPERTY_IF_CHANGED(grabDelegateToParent); COPY_PROPERTY_IF_CHANGED(equippableLeftPosition); COPY_PROPERTY_IF_CHANGED(equippableLeftRotation); COPY_PROPERTY_IF_CHANGED(equippableRightPosition); @@ -106,6 +108,9 @@ void GrabPropertyGroup::listChangedProperties(QList& out) { if (equippableChanged()) { out << "grab-equippable"; } + if (grabDelegateToParentChanged()) { + out << "grab-grabDelegateToParent"; + } if (equippableLeftPositionChanged()) { out << "grab-equippableLeftPosition"; } @@ -203,6 +208,7 @@ void GrabPropertyGroup::markAllChanged() { _grabFollowsControllerChanged = true; _triggerableChanged = true; _equippableChanged = true; + _grabDelegateToParentChanged = true; _equippableLeftPositionChanged = true; _equippableLeftRotationChanged = true; _equippableRightPositionChanged = true; @@ -238,6 +244,7 @@ void GrabPropertyGroup::getProperties(EntityItemProperties& properties) const { COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Grab, GrabFollowsController, getGrabFollowsController); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Grab, Triggerable, getTriggerable); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Grab, Equippable, getEquippable); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Grab, GrabDelegateToParent, getGrabDelegateToParent); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Grab, EquippableLeftPosition, getEquippableLeftPosition); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Grab, EquippableLeftRotation, getEquippableLeftRotation); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Grab, EquippableRightPosition, getEquippableRightPosition); @@ -255,6 +262,7 @@ bool GrabPropertyGroup::setProperties(const EntityItemProperties& properties) { SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Grab, GrabFollowsController, grabFollowsController, setGrabFollowsController); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Grab, Triggerable, triggerable, setTriggerable); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Grab, Equippable, equippable, setEquippable); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Grab, GrabDelegateToParent, grabDelegateToParent, setGrabDelegateToParent); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Grab, EquippableLeftPosition, equippableLeftPosition, setEquippableLeftPosition); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Grab, EquippableLeftRotation, equippableLeftRotation, setEquippableLeftRotation); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Grab, EquippableRightPosition, equippableRightPosition, diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 88f2d14ae6..6ab885b32b 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -24,7 +24,6 @@ const float PolyLineEntityItem::DEFAULT_LINE_WIDTH = 0.1f; const int PolyLineEntityItem::MAX_POINTS_PER_LINE = 60; - EntityItemPointer PolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity(new PolyLineEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); entity->setProperties(properties); @@ -37,7 +36,6 @@ PolyLineEntityItem::PolyLineEntityItem(const EntityItemID& entityItemID) : Entit } EntityItemProperties PolyLineEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { - QWriteLocker lock(&_quadReadWriteLock); EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor); @@ -48,11 +46,13 @@ EntityItemProperties PolyLineEntityItem::getProperties(const EntityPropertyFlags COPY_ENTITY_PROPERTY_TO_PROPERTIES(normals, getNormals); COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeColors, getStrokeColors); COPY_ENTITY_PROPERTY_TO_PROPERTIES(isUVModeStretch, getIsUVModeStretch); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(glow, getGlow); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(faceCamera, getFaceCamera); + return properties; } bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) { - QWriteLocker lock(&_quadReadWriteLock); bool somethingChanged = false; somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class @@ -64,6 +64,8 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(normals, setNormals); SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeColors, setStrokeColors); SET_ENTITY_PROPERTY_FROM_PROPERTIES(isUVModeStretch, setIsUVModeStretch); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(glow, setGlow); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(faceCamera, setFaceCamera); if (somethingChanged) { bool wantDebug = false; @@ -78,125 +80,59 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) { return somethingChanged; } - -bool PolyLineEntityItem::appendPoint(const glm::vec3& point) { - if (_points.size() > MAX_POINTS_PER_LINE - 1) { - qCDebug(entities) << "MAX POINTS REACHED!"; - return false; - } - - _points << point; - _pointsChanged = true; - - calculateScaleAndRegistrationPoint(); - - return true; -} - - -bool PolyLineEntityItem::setStrokeWidths(const QVector& strokeWidths) { +void PolyLineEntityItem::setLinePoints(const QVector& points) { withWriteLock([&] { - _strokeWidths = strokeWidths; - _strokeWidthsChanged = true; + _points = points; + _pointsChanged = true; }); - return true; + computeAndUpdateDimensionsAndPosition(); } -bool PolyLineEntityItem::setNormals(const QVector& normals) { +void PolyLineEntityItem::setStrokeWidths(const QVector& strokeWidths) { + withWriteLock([&] { + _widths = strokeWidths; + _widthsChanged = true; + }); + computeAndUpdateDimensionsAndPosition(); +} + +void PolyLineEntityItem::setNormals(const QVector& normals) { withWriteLock([&] { _normals = normals; _normalsChanged = true; }); - return true; } -bool PolyLineEntityItem::setStrokeColors(const QVector& strokeColors) { +void PolyLineEntityItem::setStrokeColors(const QVector& strokeColors) { withWriteLock([&] { - _strokeColors = strokeColors; - _strokeColorsChanged = true; + _colors = strokeColors; + _colorsChanged = true; }); - return true; } +void PolyLineEntityItem::computeAndUpdateDimensionsAndPosition() { + QVector points; + QVector widths; -bool PolyLineEntityItem::setLinePoints(const QVector& points) { - if (points.size() > MAX_POINTS_PER_LINE) { - return false; - } - bool result = false; - withWriteLock([&] { - //Check to see if points actually changed. If they haven't, return before doing anything else - if (points.size() != _points.size()) { - _pointsChanged = true; - } else if (points.size() == _points.size()) { - //same number of points, so now compare every point - for (int i = 0; i < points.size(); i++) { - if (points.at(i) != _points.at(i)) { - _pointsChanged = true; - break; - } - } - } - if (!_pointsChanged) { - return; - } - - _points = points; - - result = true; - }); - - if (result) { - calculateScaleAndRegistrationPoint(); - } - - return result; -} - -void PolyLineEntityItem::calculateScaleAndRegistrationPoint() { - glm::vec3 high(0.0f, 0.0f, 0.0f); - glm::vec3 low(0.0f, 0.0f, 0.0f); - int pointCount = 0; - glm::vec3 firstPoint; withReadLock([&] { - pointCount = _points.size(); - if (pointCount > 0) { - firstPoint = _points.at(0); - } - for (int i = 0; i < pointCount; i++) { - const glm::vec3& point = _points.at(i); - high = glm::max(point, high); - low = glm::min(point, low); - } + points = _points; + widths = _widths; }); - float magnitudeSquared = glm::length2(low - high); - vec3 newScale { 1 }; - vec3 newRegistrationPoint { 0.5f }; + glm::vec3 maxHalfDim(0.5f * ENTITY_ITEM_DEFAULT_WIDTH); + float maxWidth = 0.0f; + for (int i = 0; i < points.length(); i++) { + maxHalfDim = glm::max(maxHalfDim, glm::abs(points[i])); + maxWidth = glm::max(maxWidth, i < widths.length() ? widths[i] : DEFAULT_LINE_WIDTH); + } - const float EPSILON = 0.0001f; - const float EPSILON_SQUARED = EPSILON * EPSILON; - const float HALF_LINE_WIDTH = 0.075f; // sadly _strokeWidths() don't seem to correspond to reality, so just use a flat assumption of the stroke width - const vec3 QUARTER_LINE_WIDTH { HALF_LINE_WIDTH * 0.5f }; - if (pointCount > 1 && magnitudeSquared > EPSILON_SQUARED) { - newScale = glm::abs(high) + glm::abs(low) + vec3(HALF_LINE_WIDTH); - // Center the poly line in the bounding box - glm::vec3 startPointInScaleSpace = firstPoint - low; - startPointInScaleSpace += QUARTER_LINE_WIDTH; - newRegistrationPoint = startPointInScaleSpace / newScale; - } - - // if Polyline has only one or fewer points, use default dimension settings - setScaledDimensions(newScale); - EntityItem::setRegistrationPoint(newRegistrationPoint); + setScaledDimensions(2.0f * (maxHalfDim + maxWidth)); } int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) { - - QWriteLocker lock(&_quadReadWriteLock); int bytesRead = 0; const unsigned char* dataAt = data; @@ -208,6 +144,8 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da READ_ENTITY_PROPERTY(PROP_STROKE_NORMALS, QVector, setNormals); READ_ENTITY_PROPERTY(PROP_STROKE_COLORS, QVector, setStrokeColors); READ_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, bool, setIsUVModeStretch); + READ_ENTITY_PROPERTY(PROP_LINE_GLOW, bool, setGlow); + READ_ENTITY_PROPERTY(PROP_LINE_FACE_CAMERA, bool, setFaceCamera); return bytesRead; } @@ -222,6 +160,8 @@ EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParam requestedProperties += PROP_STROKE_NORMALS; requestedProperties += PROP_STROKE_COLORS; requestedProperties += PROP_IS_UV_MODE_STRETCH; + requestedProperties += PROP_LINE_GLOW; + requestedProperties += PROP_LINE_FACE_CAMERA; return requestedProperties; } @@ -233,7 +173,6 @@ void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, Encode int& propertyCount, OctreeElement::AppendState& appendState) const { - QWriteLocker lock(&_quadReadWriteLock); bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor()); @@ -244,6 +183,8 @@ void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, Encode APPEND_ENTITY_PROPERTY(PROP_STROKE_NORMALS, getNormals()); APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, getStrokeColors()); APPEND_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, getIsUVModeStretch()); + APPEND_ENTITY_PROPERTY(PROP_LINE_GLOW, getGlow()); + APPEND_ENTITY_PROPERTY(PROP_LINE_FACE_CAMERA, getFaceCamera()); } void PolyLineEntityItem::debugDump() const { @@ -255,61 +196,49 @@ void PolyLineEntityItem::debugDump() const { qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } - - QVector PolyLineEntityItem::getLinePoints() const { - QVector result; - withReadLock([&] { - result = _points; + return resultWithReadLock>([&] { + return _points; }); - return result; } QVector PolyLineEntityItem::getNormals() const { - QVector result; - withReadLock([&] { - result = _normals; + return resultWithReadLock>([&] { + return _normals; }); - return result; } QVector PolyLineEntityItem::getStrokeColors() const { - QVector result; - withReadLock([&] { - result = _strokeColors; + return resultWithReadLock>([&] { + return _colors; }); - return result; } QVector PolyLineEntityItem::getStrokeWidths() const { - QVector result; - withReadLock([&] { - result = _strokeWidths; + return resultWithReadLock>([&] { + return _widths; }); - return result; } QString PolyLineEntityItem::getTextures() const { - QString result; - withReadLock([&] { - result = _textures; + return resultWithReadLock([&] { + return _textures; }); - return result; } void PolyLineEntityItem::setTextures(const QString& textures) { withWriteLock([&] { if (_textures != textures) { _textures = textures; - _texturesChangedFlag = true; + _texturesChanged = true; } }); } void PolyLineEntityItem::setColor(const glm::u8vec3& value) { withWriteLock([&] { - _strokeColorsChanged = true; _color = value; + _colorsChanged = true; }); } diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 4420a123c5..41acc6d6d8 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -44,35 +44,40 @@ class PolyLineEntityItem : public EntityItem { glm::u8vec3 getColor() const; void setColor(const glm::u8vec3& value); - bool setLinePoints(const QVector& points); - bool appendPoint(const glm::vec3& point); + static const int MAX_POINTS_PER_LINE; + void setLinePoints(const QVector& points); QVector getLinePoints() const; - bool setNormals(const QVector& normals); + static const float DEFAULT_LINE_WIDTH; + void setStrokeWidths(const QVector& strokeWidths); + QVector getStrokeWidths() const; + + void setNormals(const QVector& normals); QVector getNormals() const; - bool setStrokeColors(const QVector& strokeColors); + void setStrokeColors(const QVector& strokeColors); QVector getStrokeColors() const; - bool setStrokeWidths(const QVector& strokeWidths); - QVector getStrokeWidths() const; - void setIsUVModeStretch(bool isUVModeStretch){ _isUVModeStretch = isUVModeStretch; } bool getIsUVModeStretch() const{ return _isUVModeStretch; } QString getTextures() const; void setTextures(const QString& textures); - virtual ShapeType getShapeType() const override { return SHAPE_TYPE_NONE; } + void setGlow(bool glow) { _glow = glow; } + bool getGlow() const { return _glow; } + + void setFaceCamera(bool faceCamera) { _faceCamera = faceCamera; } + bool getFaceCamera() const { return _faceCamera; } bool pointsChanged() const { return _pointsChanged; } bool normalsChanged() const { return _normalsChanged; } - bool strokeColorsChanged() const { return _strokeColorsChanged; } - bool strokeWidthsChanged() const { return _strokeWidthsChanged; } - bool texturesChanged() const { return _texturesChangedFlag; } - void resetTexturesChanged() { _texturesChangedFlag = false; } - void resetPolyLineChanged() { _strokeColorsChanged = _strokeWidthsChanged = _normalsChanged = _pointsChanged = false; } + bool colorsChanged() const { return _colorsChanged; } + bool widthsChanged() const { return _widthsChanged; } + bool texturesChanged() const { return _texturesChanged; } + void resetTexturesChanged() { _texturesChanged = false; } + void resetPolyLineChanged() { _colorsChanged = _widthsChanged = _normalsChanged = _pointsChanged = false; } // never have a ray intersection pick a PolyLineEntityItem. virtual bool supportsDetailedIntersection() const override { return true; } @@ -85,29 +90,26 @@ class PolyLineEntityItem : public EntityItem { BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) const override { return false; } - // disable these external interfaces as PolyLineEntities caculate their own dimensions based on the points they contain - virtual void setRegistrationPoint(const glm::vec3& value) override {}; // FIXME: this is suspicious! - virtual void debugDump() const override; - static const float DEFAULT_LINE_WIDTH; - static const int MAX_POINTS_PER_LINE; private: - void calculateScaleAndRegistrationPoint(); + void computeAndUpdateDimensionsAndPosition(); protected: glm::u8vec3 _color; - bool _pointsChanged { true }; - bool _normalsChanged { true }; - bool _strokeColorsChanged { true }; - bool _strokeWidthsChanged { true }; QVector _points; QVector _normals; - QVector _strokeColors; - QVector _strokeWidths; + QVector _colors; + QVector _widths; QString _textures; bool _isUVModeStretch; - bool _texturesChangedFlag { false }; - mutable QReadWriteLock _quadReadWriteLock; + bool _glow; + bool _faceCamera; + + bool _pointsChanged { false }; + bool _normalsChanged { false }; + bool _colorsChanged { false }; + bool _widthsChanged { false }; + bool _texturesChanged { false }; }; #endif // hifi_PolyLineEntityItem_h diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 1641623794..aba3822883 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::MorePropertiesCleanup); + return static_cast(EntityVersion::FixProtocolVersionBumpMismatch); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index c7e81c1b93..6f019f39b6 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -252,7 +252,10 @@ enum class EntityVersion : PacketVersion { GridEntities, MissingTextProperties, GrabTraits, - MorePropertiesCleanup + MorePropertiesCleanup, + FixPropertiesFromCleanup, + UpdatedPolyLines, + FixProtocolVersionBumpMismatch }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 66dcecc83e..3ccc5359ff 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -2151,7 +2151,6 @@ function createColorProperty(property, elProperty) { submit: false, // We don't want to have a submission button onShow: function(colpick) { console.log("Showing"); - $(colorPickerID).attr('active', 'true'); // The original color preview within the picker needs to be updated on show because // prior to the picker being shown we don't have access to the selections' starting color. colorPickers[colorPickerID].colpickSetColor({ @@ -2159,13 +2158,18 @@ function createColorProperty(property, elProperty) { "g": elNumberG.elInput.value, "b": elNumberB.elInput.value }); + + // Set the color picker active after setting the color, otherwise an update will be sent on open. + $(colorPickerID).attr('active', 'true'); }, onHide: function(colpick) { $(colorPickerID).attr('active', 'false'); }, onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); - emitColorPropertyUpdate(propertyName, rgb.r, rgb.g, rgb.b); + if ($(colorPickerID).attr('active') === 'true') { + emitColorPropertyUpdate(propertyName, rgb.r, rgb.g, rgb.b); + } } }); @@ -3351,6 +3355,18 @@ function loaded() { property.elColorPicker.style.backgroundColor = "rgb(" + propertyValue.red + "," + propertyValue.green + "," + propertyValue.blue + ")"; + if ($(property.elColorPicker).attr('active') === 'true') { + // Set the color picker inactive before setting the color, + // otherwise an update will be sent directly after setting it here. + $(property.elColorPicker).attr('active', 'false'); + colorPickers['#' + property.elementID].colpickSetColor({ + "r": propertyValue.red, + "g": propertyValue.green, + "b": propertyValue.blue + }); + $(property.elColorPicker).attr('active', 'true'); + } + property.elNumberR.setValue(propertyValue.red); property.elNumberG.setValue(propertyValue.green); property.elNumberB.setValue(propertyValue.blue);