From 06491ef12fd07c6d2891ed4b4aabdab12761f26c Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 20 Sep 2018 19:34:00 +0200 Subject: [PATCH 1/8] API function for retrieving multiple entity properties with better performance --- .../src/RenderableModelEntityItem.cpp | 4 +- .../src/RenderableModelEntityItem.h | 2 +- libraries/entities/src/EntityItem.cpp | 5 +- libraries/entities/src/EntityItem.h | 2 +- .../entities/src/EntityItemProperties.cpp | 80 ++++++---- libraries/entities/src/EntityItemProperties.h | 8 +- .../entities/src/EntityItemPropertiesMacros.h | 6 +- .../entities/src/EntityPsuedoPropertyFlags.h | 35 +++++ .../entities/src/EntityScriptingInterface.cpp | 142 +++++++++++++++++- .../entities/src/EntityScriptingInterface.h | 4 +- libraries/entities/src/EntityTypes.h | 2 +- libraries/entities/src/LightEntityItem.cpp | 4 +- libraries/entities/src/LightEntityItem.h | 2 +- libraries/entities/src/LineEntityItem.cpp | 4 +- libraries/entities/src/LineEntityItem.h | 2 +- libraries/entities/src/MaterialEntityItem.cpp | 4 +- libraries/entities/src/MaterialEntityItem.h | 2 +- libraries/entities/src/ModelEntityItem.cpp | 4 +- libraries/entities/src/ModelEntityItem.h | 2 +- .../entities/src/ParticleEffectEntityItem.cpp | 4 +- .../entities/src/ParticleEffectEntityItem.h | 2 +- libraries/entities/src/PolyLineEntityItem.cpp | 4 +- libraries/entities/src/PolyLineEntityItem.h | 2 +- libraries/entities/src/PolyVoxEntityItem.cpp | 4 +- libraries/entities/src/PolyVoxEntityItem.h | 2 +- libraries/entities/src/ShapeEntityItem.cpp | 4 +- libraries/entities/src/ShapeEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.cpp | 4 +- libraries/entities/src/TextEntityItem.h | 2 +- libraries/entities/src/WebEntityItem.cpp | 4 +- libraries/entities/src/WebEntityItem.h | 2 +- libraries/entities/src/ZoneEntityItem.cpp | 4 +- libraries/entities/src/ZoneEntityItem.h | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 1 + 34 files changed, 280 insertions(+), 77 deletions(-) create mode 100644 libraries/entities/src/EntityPsuedoPropertyFlags.h diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 3a01650a04..afa03b5ddc 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -250,8 +250,8 @@ void RenderableModelEntityItem::updateModelBounds() { } -EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = ModelEntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties RenderableModelEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = ModelEntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class if (_originalTexturesRead) { properties.setTextureNames(_originalTextures); } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 75f35fae9c..fa49624f7e 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -62,7 +62,7 @@ public: virtual void setUnscaledDimensions(const glm::vec3& value) override; - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; void doInitialModelSimulation(); void updateModelBounds(); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8e382fabd4..fdc7b72ab2 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1251,9 +1251,10 @@ quint64 EntityItem::getExpiry() const { return getCreated() + (quint64)(getLifetime() * (float)USECS_PER_SECOND); } -EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProperties) const { +EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { EncodeBitstreamParams params; // unknown - EntityPropertyFlags propertyFlags = desiredProperties.isEmpty() ? getEntityProperties(params) : desiredProperties; + const EntityPropertyFlags propertyFlags = !allowEmptyDesiredProperties && desiredProperties.isEmpty() ? + getEntityProperties(params) : desiredProperties; EntityItemProperties properties(propertyFlags); properties._id = getID(); properties._idSet = true; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 490f9b9e6b..8daffc803e 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -88,7 +88,7 @@ public: EntityItemID getEntityItemID() const { return EntityItemID(_id); } // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties = EntityPropertyFlags(), bool allowEmptyDesiredProperties = false) const; /// returns true if something changed // This function calls setSubClass properties and detects if any property changes value. diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index dc29d4bb2a..96fbf6de9b 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1216,7 +1216,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * }); */ -QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool skipDefaults, bool allowUnknownCreateTime, bool strictSemantics) const { +QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool skipDefaults, bool allowUnknownCreateTime, + bool strictSemantics, EntityPsuedoPropertyFlags psueudoPropertyFlags) const { + // If strictSemantics is true and skipDefaults is false, then all and only those properties are copied for which the property flag // is included in _desiredProperties, or is one of the specially enumerated ALWAYS properties below. // (There may be exceptions, but if so, they are bugs.) @@ -1224,26 +1226,39 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool QScriptValue properties = engine->newObject(); EntityItemProperties defaultEntityProperties; + const bool psuedoPropertyFlagsActive = psueudoPropertyFlags & EntityPsuedoPropertyFlag::flagsActive; + // Fix to skip the default return all mechanism, when psuedoPropertyFlagsActive + const bool psuedoPropertyFlagsButDesiredEmpty = psuedoPropertyFlagsActive && _desiredProperties.isEmpty(); + if (_created == UNKNOWN_CREATED_TIME && !allowUnknownCreateTime) { // No entity properties can have been set so return without setting any default, zero property values. return properties; } - if (_idSet) { + if (_idSet && (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::id)) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(id, _id.toString()); } - - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(type, EntityTypes::getEntityTypeName(_type)); - 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) { - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(age, getAge()); // gettable, but not settable - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::type) { + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(type, EntityTypes::getEntityTypeName(_type)); + } + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & 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)); } - properties.setProperty("lastEdited", convertScriptValue(engine, _lastEdited)); + if ((!skipDefaults || _lifetime != defaultEntityProperties._lifetime) && !strictSemantics) { + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::age) { + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(age, getAge()); // gettable, but not settable + } + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::ageAsText) { + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable + } + } + + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::lastEdited) { + properties.setProperty("lastEdited", convertScriptValue(engine, _lastEdited)); + } COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LAST_EDITED_BY, lastEditedBy); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POSITION, position); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DIMENSIONS, dimensions); @@ -1340,7 +1355,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool // Models only if (_type == EntityTypes::Model) { COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MODEL_URL, modelURL); - _animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + if (!psuedoPropertyFlagsButDesiredEmpty) { + _animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + } COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS_SET, jointRotationsSet); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS, jointRotations); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS_SET, jointTranslationsSet); @@ -1393,21 +1410,24 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool // Zones only if (_type == EntityTypes::Zone) { - _keyLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - _ambientLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - - _skybox.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + if (!psuedoPropertyFlagsButDesiredEmpty) { + _keyLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + _ambientLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + _skybox.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + } COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FLYING_ALLOWED, flyingAllowed); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GHOSTING_ALLOWED, ghostingAllowed); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FILTER_URL, filterURL); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_HAZE_MODE, hazeMode, getHazeModeAsString()); - _haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - + if (!psuedoPropertyFlagsButDesiredEmpty) { + _haze.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + } COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_BLOOM_MODE, bloomMode, getBloomModeAsString()); - _bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); - + if (!psuedoPropertyFlagsButDesiredEmpty) { + _bloom.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + } COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_KEY_LIGHT_MODE, keyLightMode, getKeyLightModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_LIGHT_MODE, ambientLightMode, getAmbientLightModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SKYBOX_MODE, skyboxMode, getSkyboxModeAsString()); @@ -1468,7 +1488,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool * @property {Vec3} center - The center of the AA box. * @property {Vec3} dimensions - The dimensions of the AA box. */ - if (!skipDefaults && !strictSemantics) { + if (!skipDefaults && !strictSemantics && + (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::boundingBox)) { + AABox aaBox = getAABox(); QScriptValue boundingBox = engine->newObject(); QScriptValue bottomRightNear = vec3toScriptValue(engine, aaBox.getCorner()); @@ -1483,7 +1505,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool } QString textureNamesStr = QJsonDocument::fromVariant(_textureNames).toJson(); - if (!skipDefaults && !strictSemantics) { + if (!skipDefaults && !strictSemantics && (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::originalTextures)) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesStr); // gettable, but not settable } @@ -1509,7 +1531,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONE_ORIGIN_ID, cloneOriginID); // Rendering info - if (!skipDefaults && !strictSemantics) { + if (!skipDefaults && !strictSemantics && + (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::renderInfo)) { + QScriptValue renderInfo = engine->newObject(); /**jsdoc @@ -1535,8 +1559,12 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool } // FIXME: These properties should already have been set above. - properties.setProperty("clientOnly", convertScriptValue(engine, getClientOnly())); - properties.setProperty("owningAvatarID", convertScriptValue(engine, getOwningAvatarID())); + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::clientOnly) { + properties.setProperty("clientOnly", convertScriptValue(engine, getClientOnly())); + } + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::owningAvatarID) { + properties.setProperty("owningAvatarID", convertScriptValue(engine, getOwningAvatarID())); + } // FIXME - I don't think these properties are supported any more //COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 50305345de..b0dee5b6fa 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -35,6 +35,7 @@ #include "EntityItemPropertiesMacros.h" #include "EntityTypes.h" #include "EntityPropertyFlags.h" +#include "EntityPsuedoPropertyFlags.h" #include "LightEntityItem.h" #include "LineEntityItem.h" #include "ParticleEffectEntityItem.h" @@ -86,7 +87,8 @@ public: EntityTypes::EntityType getType() const { return _type; } void setType(EntityTypes::EntityType type) { _type = type; } - virtual QScriptValue copyToScriptValue(QScriptEngine* engine, bool skipDefaults, bool allowUnknownCreateTime = false, bool strictSemantics = false) const; + virtual QScriptValue copyToScriptValue(QScriptEngine* engine, bool skipDefaults, bool allowUnknownCreateTime = false, + bool strictSemantics = false, EntityPsuedoPropertyFlags psueudoPropertyFlags = EntityPsuedoPropertyFlags()) const; virtual void copyFromScriptValue(const QScriptValue& object, bool honorReadOnly); static QScriptValue entityPropertyFlagsToScriptValue(QScriptEngine* engine, const EntityPropertyFlags& flags); @@ -340,6 +342,9 @@ public: void setQueryAACubeDirty() { _queryAACubeChanged = true; } + // void setStrictProperties(bool strictProperties) { _strictProperties = strictProperties; } + // bool getStrictProperties() const { return _strictProperties; } + void setCreated(QDateTime& v); bool hasTerseUpdateChanges() const; @@ -420,6 +425,7 @@ private: bool _renderInfoHasTransparent { false }; EntityPropertyFlags _desiredProperties; // if set will narrow scopes of copy/to/from to just these properties + // bool _strictProperties { false }; }; Q_DECLARE_METATYPE(EntityItemProperties); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 213460ec50..ff4fb39354 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -155,7 +155,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { retu } #define COPY_PROPERTY_TO_QSCRIPTVALUE(p,P) \ - if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \ + if (((!psuedoPropertyFlagsButDesiredEmpty && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \ (!skipDefaults || defaultEntityProperties._##P != _##P)) { \ QScriptValue V = convertScriptValue(engine, _##P); \ properties.setProperty(#P, V); \ @@ -165,7 +165,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { retu properties.setProperty(#P, G); #define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(p, P, G) \ - if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \ + if (((!psuedoPropertyFlagsButDesiredEmpty && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \ (!skipDefaults || defaultEntityProperties._##P != _##P)) { \ QScriptValue V = convertScriptValue(engine, G); \ properties.setProperty(#P, V); \ @@ -173,7 +173,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { retu // same as COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER but uses #X instead of #P in the setProperty() step #define COPY_PROXY_PROPERTY_TO_QSCRIPTVALUE_GETTER(p, P, X, G) \ - if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \ + if (((!psuedoPropertyFlagsButDesiredEmpty && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \ (!skipDefaults || defaultEntityProperties._##P != _##P)) { \ QScriptValue V = convertScriptValue(engine, G); \ properties.setProperty(#X, V); \ diff --git a/libraries/entities/src/EntityPsuedoPropertyFlags.h b/libraries/entities/src/EntityPsuedoPropertyFlags.h new file mode 100644 index 0000000000..ce8c1625fb --- /dev/null +++ b/libraries/entities/src/EntityPsuedoPropertyFlags.h @@ -0,0 +1,35 @@ +// +// EntityPsuedoPropertyFlags.h +// libraries/entities/src +// +// Created by Thijs Wenker on 9/18/18. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once + +#ifndef hifi_EntityPsuedoPropertyFlag_h +#define hifi_EntityPsuedoPropertyFlag_h + +enum class EntityPsuedoPropertyFlag { + none = 0, + flagsActive = 1 << 0, + id = 1 << 1, + type = 1 << 2, + created = 1 << 3, + age = 1 << 4, + ageAsText = 1 << 5, + lastEdited = 1 << 6, + boundingBox = 1 << 7, + originalTextures = 1 << 8, + renderInfo = 1 << 9, + clientOnly = 1 << 10, + owningAvatarID = 1 << 11, + all = (1 << 12) - 1 +}; +Q_DECLARE_FLAGS(EntityPsuedoPropertyFlags, EntityPsuedoPropertyFlag) + +#endif // hifi_EntityPsuedoPropertyFlag_h diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index d9924cb9fd..84fabccdb3 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -42,7 +42,7 @@ const QString GRABBABLE_USER_DATA = "{\"grabbableKey\":{\"grabbable\":true}}"; const QString NOT_GRABBABLE_USER_DATA = "{\"grabbableKey\":{\"grabbable\":false}}"; EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership) : - _entityTree(NULL), + _entityTree(nullptr), _bidOnSimulationOwnership(bidOnSimulationOwnership) { auto nodeList = DependencyManager::get(); @@ -352,19 +352,19 @@ QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { } } -EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity) { - EntityPropertyFlags noSpecificProperties; - return getEntityProperties(identity, noSpecificProperties); +EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid entityID) { + const EntityPropertyFlags noSpecificProperties; + return getEntityProperties(entityID, noSpecificProperties); } -EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties) { +EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid entityID, EntityPropertyFlags desiredProperties) { PROFILE_RANGE(script_entities, __FUNCTION__); bool scalesWithParent { false }; EntityItemProperties results; if (_entityTree) { _entityTree->withReadLock([&] { - EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity)); + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(entityID)); if (entity) { scalesWithParent = entity->getScalesWithParent(); if (desiredProperties.getHasProperty(PROP_POSITION) || @@ -399,6 +399,136 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit return convertPropertiesToScriptSemantics(results, scalesWithParent); } + +struct EntityPropertiesResult { + EntityPropertiesResult(const EntityItemProperties& properties, bool scalesWithParent) : + properties(properties), + scalesWithParent(scalesWithParent) { + } + EntityPropertiesResult() = default; + EntityItemProperties properties; + bool scalesWithParent{ false }; +}; + +// Static method to make sure that we have the right script engine. +// Using sender() or QtScriptable::engine() does not work for classes used by multiple threads (script-engines) +QScriptValue EntityScriptingInterface::getMultipleEntityProperties(QScriptContext* context, QScriptEngine* engine) { + const int ARGUMENT_ENTITY_IDS = 0; + const int ARGUMENT_EXTENDED_DESIRED_PROPERTIES = 1; + + auto entityScriptingInterface = DependencyManager::get(); + const auto entityIDs = qScriptValueToValue>(context->argument(ARGUMENT_ENTITY_IDS)); + return entityScriptingInterface->getMultipleEntityPropertiesInternal(engine, entityIDs, context->argument(ARGUMENT_EXTENDED_DESIRED_PROPERTIES)); +} + +QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScriptEngine* engine, QVector entityIDs, const QScriptValue& extendedDesiredProperties) { + PROFILE_RANGE(script_entities, __FUNCTION__); + + EntityPsuedoPropertyFlags psuedoPropertyFlags; + const auto readExtendedPropertyStringValue = [&](QScriptValue extendedProperty) { + const auto extendedPropertyString = extendedProperty.toString(); + if (extendedPropertyString == QString("id")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::id; + } else if (extendedPropertyString == QString("type")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::type; + } else if (extendedPropertyString == QString("created")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::created; + } else if (extendedPropertyString == QString("age")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::age; + } else if (extendedPropertyString == QString("ageAsText")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::ageAsText; + } else if (extendedPropertyString == QString("lastEdited")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::lastEdited; + } else if (extendedPropertyString == QString("boundingBox")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::boundingBox; + } else if (extendedPropertyString == QString("originalTextures")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::originalTextures; + } else if (extendedPropertyString == QString("renderInfo")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::renderInfo; + } else if (extendedPropertyString == QString("clientOnly")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::clientOnly; + } else if (extendedPropertyString == QString("owningAvatarID")) { + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::owningAvatarID; + } + }; + + if (extendedDesiredProperties.isString()) { + readExtendedPropertyStringValue(extendedDesiredProperties); + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::flagsActive; + } else if (extendedDesiredProperties.isArray()) { + const quint32 length = extendedDesiredProperties.property("length").toInt32(); + for (quint32 i = 0; i < length; i++) { + readExtendedPropertyStringValue(extendedDesiredProperties.property(i)); + } + psuedoPropertyFlags |= EntityPsuedoPropertyFlag::flagsActive; + } + + EntityPropertyFlags desiredProperties = qScriptValueToValue(extendedDesiredProperties); + bool needsScriptSymantics = desiredProperties.getHasProperty(PROP_POSITION) || + desiredProperties.getHasProperty(PROP_ROTATION) || + desiredProperties.getHasProperty(PROP_LOCAL_POSITION) || + desiredProperties.getHasProperty(PROP_LOCAL_ROTATION) || + desiredProperties.getHasProperty(PROP_LOCAL_VELOCITY) || + desiredProperties.getHasProperty(PROP_LOCAL_ANGULAR_VELOCITY) || + desiredProperties.getHasProperty(PROP_LOCAL_DIMENSIONS); + if (needsScriptSymantics) { + // if we are explicitly getting position or rotation, we need parent information to make sense of them. + desiredProperties.setHasProperty(PROP_PARENT_ID); + desiredProperties.setHasProperty(PROP_PARENT_JOINT_INDEX); + } + QVector resultProperties; + if (_entityTree) { + PROFILE_RANGE(script_entities, "EntityScriptingInterface::getMultipleEntityProperties>Obtaining Properties"); + int i = 0; + const int lockAmount = 500; + int size = entityIDs.size(); + while (i < size) { + _entityTree->withReadLock([&] { + for (int j = 0; j < lockAmount && i < size; ++i, ++j) { + const auto& entityID = entityIDs.at(i); + const EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(entityID)); + if (entity) { + if (!psuedoPropertyFlags && desiredProperties.isEmpty()) { + // these are left out of EntityItem::getEntityProperties so that localPosition and localRotation + // don't end up in json saves, etc. We still want them here, though. + EncodeBitstreamParams params; // unknown + desiredProperties = entity->getEntityProperties(params); + desiredProperties.setHasProperty(PROP_LOCAL_POSITION); + desiredProperties.setHasProperty(PROP_LOCAL_ROTATION); + desiredProperties.setHasProperty(PROP_LOCAL_VELOCITY); + desiredProperties.setHasProperty(PROP_LOCAL_ANGULAR_VELOCITY); + desiredProperties.setHasProperty(PROP_LOCAL_DIMENSIONS); + psuedoPropertyFlags = EntityPsuedoPropertyFlag::all; + needsScriptSymantics = true; + } + + auto properties = entity->getProperties(desiredProperties, true); + EntityPropertiesResult result(properties, entity->getScalesWithParent()); + resultProperties.append(result); + } + } + }); + } + } + QScriptValue finalResult = engine->newArray(resultProperties.size()); + quint32 i = 0; + { + if (needsScriptSymantics) { + PROFILE_RANGE(script_entities, "EntityScriptingInterface::getMultipleEntityProperties>Script Semantics"); + foreach(auto result, resultProperties) { + finalResult.setProperty(i++, convertPropertiesToScriptSemantics(result.properties, result.scalesWithParent) + .copyToScriptValue(engine, false, false, false, psuedoPropertyFlags)); + } + } else { + PROFILE_RANGE(script_entities, "EntityScriptingInterface::getMultipleEntityProperties>Skip Script Semantics"); + foreach(auto result, resultProperties) { + finalResult.setProperty(i++, result.properties.copyToScriptValue(engine, false, false, false, psuedoPropertyFlags)); + } + } + } + return finalResult; +} + QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) { PROFILE_RANGE(script_entities, __FUNCTION__); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 3e0f040fd6..08f9e31e29 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -149,6 +149,8 @@ public: const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, bool visibleOnly, bool collidableOnly); + static QScriptValue getMultipleEntityProperties(QScriptContext* context, QScriptEngine* engine); + QScriptValue getMultipleEntityPropertiesInternal(QScriptEngine* engine, QVector entityIDs, const QScriptValue& extendedDesiredProperties); public slots: /**jsdoc @@ -270,7 +272,7 @@ public slots: * print("Entity color: " + JSON.stringify(properties.color)); */ Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID); - Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties); + Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID, EntityPropertyFlags desiredProperties); /**jsdoc * Update an entity with specified properties. diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 1f3434d254..3f9a538589 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -13,7 +13,7 @@ #define hifi_EntityTypes_h #include -#include +//#include #include #include diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index 1db67fc0b6..57a83a4173 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -69,8 +69,8 @@ void LightEntityItem::dimensionsChanged() { } -EntityItemProperties LightEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties LightEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(isSpotlight, getIsSpotlight); COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index 518cb18de2..f56b5ce624 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -35,7 +35,7 @@ public: virtual bool setSubClassProperties(const EntityItemProperties& properties) override; // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 92a1c25970..1b20922b7d 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -37,9 +37,9 @@ LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) : _type = EntityTypes::Line; } -EntityItemProperties LineEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { +EntityItemProperties LineEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class properties._color = getXColor(); diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 7c21b5c9d2..732d16b4b1 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -23,7 +23,7 @@ class LineEntityItem : public EntityItem { ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 489ba5772c..06afda4283 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -31,8 +31,8 @@ MaterialEntityItem::~MaterialEntityItem() { removeMaterial(); } -EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties MaterialEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingMode, getMaterialMappingMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(priority, getPriority); diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index 30743850dd..7177aaf718 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -29,7 +29,7 @@ public: bool needsToCallUpdate() const override { return true; } // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index f006692415..e3fca680f3 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -54,8 +54,8 @@ void ModelEntityItem::setTextures(const QString& textures) { _textures = textures; } -EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties ModelEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index ef758b9dde..8d34664a09 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -27,7 +27,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 238f41b05f..975acf153a 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -408,8 +408,8 @@ void ParticleEffectEntityItem::computeAndUpdateDimensions() { } -EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties ParticleEffectEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 02284768ce..a8e133942e 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -210,7 +210,7 @@ public: ParticleEffectEntityItem(const EntityItemID& entityItemID); // methods for getting/setting all properties of this entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 5b3167b9ba..2d0689b56a 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -36,9 +36,9 @@ PolyLineEntityItem::PolyLineEntityItem(const EntityItemID& entityItemID) : Entit _type = EntityTypes::PolyLine; } -EntityItemProperties PolyLineEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { +EntityItemProperties PolyLineEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { QWriteLocker lock(&_quadReadWriteLock); - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class properties._color = getXColor(); diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h index 52ec8e8c2d..94b46ac5e2 100644 --- a/libraries/entities/src/PolyLineEntityItem.h +++ b/libraries/entities/src/PolyLineEntityItem.h @@ -23,7 +23,7 @@ class PolyLineEntityItem : public EntityItem { ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index ed3372818a..484a6110c3 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -113,8 +113,8 @@ glm::vec3 PolyVoxEntityItem::getVoxelVolumeSize() const { } -EntityItemProperties PolyVoxEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties PolyVoxEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelVolumeSize, getVoxelVolumeSize); COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelData, getVoxelData); COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelSurfaceStyle, getVoxelSurfaceStyle); diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index d2ca4db124..ba238ab24f 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -23,7 +23,7 @@ class PolyVoxEntityItem : public EntityItem { ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 773a7059dc..a5e4e25e67 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -115,8 +115,8 @@ ShapeEntityItem::ShapeEntityItem(const EntityItemID& entityItemID) : EntityItem( _material = std::make_shared(); } -EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties ShapeEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class properties.setShape(entity::stringFromShape(getShape())); COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index ded5df15fe..d0326a3794 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -52,7 +52,7 @@ public: //ALLOW_INSTANTIATION // methods for getting/setting all properties of an entity - EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; bool setProperties(const EntityItemProperties& properties) override; EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index f130995bb5..da843256a0 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -46,8 +46,8 @@ void TextEntityItem::setUnscaledDimensions(const glm::vec3& value) { EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH)); } -EntityItemProperties TextEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight); diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 4ce5ef3297..cbddf87fda 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -27,7 +27,7 @@ public: virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; } // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 0070eb538c..d20d36cd71 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -41,8 +41,8 @@ void WebEntityItem::setUnscaledDimensions(const glm::vec3& value) { EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH)); } -EntityItemProperties WebEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties WebEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(sourceUrl, getSourceUrl); COPY_ENTITY_PROPERTY_TO_PROPERTIES(dpi, getDPI); return properties; diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 2fa2033445..10d06e6f4a 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -26,7 +26,7 @@ public: virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; } // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index c0ae61fdba..1b8675caac 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -45,8 +45,8 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID) : EntityItem(en _visuallyReady = false; } -EntityItemProperties ZoneEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class +EntityItemProperties ZoneEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class // Contain QString properties, must be synchronized withReadLock([&] { diff --git a/libraries/entities/src/ZoneEntityItem.h b/libraries/entities/src/ZoneEntityItem.h index e2ebf16f11..c2f4542aa6 100644 --- a/libraries/entities/src/ZoneEntityItem.h +++ b/libraries/entities/src/ZoneEntityItem.h @@ -30,7 +30,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual bool setSubClassProperties(const EntityItemProperties& properties) override; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index cfd155e14b..36d0a8866d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -721,6 +721,7 @@ void ScriptEngine::init() { registerGlobalObject("Midi", DependencyManager::get().data()); registerGlobalObject("Entities", entityScriptingInterface.data()); + registerFunction("Entities", "getMultipleEntityProperties", EntityScriptingInterface::getMultipleEntityProperties); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Mat4", &_mat4Library); From 6d72881f3f5fb305462d0b359c557d74139c958d Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 20 Sep 2018 21:14:30 +0200 Subject: [PATCH 2/8] remove commented out test code --- libraries/entities/src/EntityItemProperties.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index b0dee5b6fa..338ec5e071 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -342,9 +342,6 @@ public: void setQueryAACubeDirty() { _queryAACubeChanged = true; } - // void setStrictProperties(bool strictProperties) { _strictProperties = strictProperties; } - // bool getStrictProperties() const { return _strictProperties; } - void setCreated(QDateTime& v); bool hasTerseUpdateChanges() const; @@ -425,7 +422,6 @@ private: bool _renderInfoHasTransparent { false }; EntityPropertyFlags _desiredProperties; // if set will narrow scopes of copy/to/from to just these properties - // bool _strictProperties { false }; }; Q_DECLARE_METATYPE(EntityItemProperties); From e2cb96193d6c7b042490a820f3fdf9db77da80c7 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 20 Sep 2018 22:47:14 +0200 Subject: [PATCH 3/8] JSDocs --- libraries/entities/src/EntityScriptingInterface.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 08f9e31e29..df7b0df9a1 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -149,6 +149,19 @@ public: const QVector& entityIdsToInclude, const QVector& entityIdsToDiscard, bool visibleOnly, bool collidableOnly); + /**jsdoc + * Get the properties of multiple entities. + * @function Entities.getMultipleEntityProperties + * @param {Uuid[]} entityIDs - The IDs of the entities to get the properties of. + * @param {string[]|string} [desiredProperties=[]] - Either string with property name or array of the names of the properties + * to get. If the array is empty, all properties are returned. + * @returns {Entities.EntityProperties[]} The properties of the entity if the entity can be found, otherwise an empty object. + * @example Retrieve the names of the nearby entities + * var SEARCH_RADIUS = 50; // meters + * var entityIds = Entities.findEntities(MyAvatar.position, SEARCH_RADIUS); + * var propertySets = Entities.getMultipleEntityProperties(entityIds, "name"); + * print("Nearby entity names: " + JSON.stringify(propertySets)); + */ static QScriptValue getMultipleEntityProperties(QScriptContext* context, QScriptEngine* engine); QScriptValue getMultipleEntityPropertiesInternal(QScriptEngine* engine, QVector entityIDs, const QScriptValue& extendedDesiredProperties); public slots: From d1f35c8c542078e6cb51812772d6a36ddfcdcdeb Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 20 Sep 2018 22:48:56 +0200 Subject: [PATCH 4/8] update the entityList update with newly added Entities.getMultipleEntities function --- scripts/system/libraries/entityList.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index 27e079589b..30e952723f 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -150,11 +150,11 @@ EntityListTool = function(shouldUseEditTabletApp) { }); var cameraPosition = Camera.position; - PROFILE("getProperties", function() { - for (var i = 0; i < ids.length; i++) { - var id = ids[i]; - var properties = Entities.getEntityProperties(id, ['name', 'type', 'locked', - 'visible', 'renderInfo', 'type', 'modelURL', 'materialURL', 'script']); + PROFILE("getMultipleProperties", function () { + var multipleProperties = Entities.getMultipleEntityProperties(ids, ['name', 'type', 'locked', + 'visible', 'renderInfo', 'modelURL', 'materialURL', 'script']); + for (var i = 0; i < multipleProperties.length; i++) { + var properties = multipleProperties[i]; if (!filterInView || Vec3.distance(properties.position, cameraPosition) <= searchRadius) { var url = ""; @@ -164,7 +164,7 @@ EntityListTool = function(shouldUseEditTabletApp) { url = properties.materialURL; } entities.push({ - id: id, + id: ids[i], name: properties.name, type: properties.type, url: url, From 1094b6722f8815df19df409bc6e8299a7980ba0f Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 20 Sep 2018 23:36:53 +0200 Subject: [PATCH 5/8] self-CR --- libraries/entities/src/EntityTypes.h | 1 - libraries/entities/src/LineEntityItem.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 3f9a538589..954bdf8f17 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -13,7 +13,6 @@ #define hifi_EntityTypes_h #include -//#include #include #include diff --git a/libraries/entities/src/LineEntityItem.h b/libraries/entities/src/LineEntityItem.h index 732d16b4b1..06f7830e06 100644 --- a/libraries/entities/src/LineEntityItem.h +++ b/libraries/entities/src/LineEntityItem.h @@ -23,7 +23,7 @@ class LineEntityItem : public EntityItem { ALLOW_INSTANTIATION // This class can be instantiated // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; + virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; From 80beb6c444e3fd69e50788eb645b340c594847ce Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 25 Sep 2018 22:43:58 +0200 Subject: [PATCH 6/8] addressed CR feedback --- .../entities/src/EntityItemProperties.cpp | 24 +++--- .../entities/src/EntityPsuedoPropertyFlags.h | 40 ++++++---- .../entities/src/EntityScriptingInterface.cpp | 80 +++++++++---------- 3 files changed, 74 insertions(+), 70 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 96fbf6de9b..7e404afa3f 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1226,7 +1226,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool QScriptValue properties = engine->newObject(); EntityItemProperties defaultEntityProperties; - const bool psuedoPropertyFlagsActive = psueudoPropertyFlags & EntityPsuedoPropertyFlag::flagsActive; + const bool psuedoPropertyFlagsActive = psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::FlagsActive); // Fix to skip the default return all mechanism, when psuedoPropertyFlagsActive const bool psuedoPropertyFlagsButDesiredEmpty = psuedoPropertyFlagsActive && _desiredProperties.isEmpty(); @@ -1235,28 +1235,28 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool return properties; } - if (_idSet && (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::id)) { + if (_idSet && (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::ID))) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(id, _id.toString()); } - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::type) { + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::Type)) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(type, EntityTypes::getEntityTypeName(_type)); } - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::created) { + 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 & EntityPsuedoPropertyFlag::age) { + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::Age)) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(age, getAge()); // gettable, but not settable } - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::ageAsText) { + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::AgeAsText)) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable } } - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::lastEdited) { + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::LastEdited)) { properties.setProperty("lastEdited", convertScriptValue(engine, _lastEdited)); } COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LAST_EDITED_BY, lastEditedBy); @@ -1489,7 +1489,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool * @property {Vec3} dimensions - The dimensions of the AA box. */ if (!skipDefaults && !strictSemantics && - (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::boundingBox)) { + (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::BoundingBox))) { AABox aaBox = getAABox(); QScriptValue boundingBox = engine->newObject(); @@ -1505,7 +1505,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool } QString textureNamesStr = QJsonDocument::fromVariant(_textureNames).toJson(); - if (!skipDefaults && !strictSemantics && (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::originalTextures)) { + if (!skipDefaults && !strictSemantics && (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::OriginalTextures))) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesStr); // gettable, but not settable } @@ -1532,7 +1532,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool // Rendering info if (!skipDefaults && !strictSemantics && - (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::renderInfo)) { + (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::RenderInfo))) { QScriptValue renderInfo = engine->newObject(); @@ -1559,10 +1559,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool } // FIXME: These properties should already have been set above. - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::clientOnly) { + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::ClientOnly)) { properties.setProperty("clientOnly", convertScriptValue(engine, getClientOnly())); } - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags & EntityPsuedoPropertyFlag::owningAvatarID) { + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::OwningAvatarID)) { properties.setProperty("owningAvatarID", convertScriptValue(engine, getOwningAvatarID())); } diff --git a/libraries/entities/src/EntityPsuedoPropertyFlags.h b/libraries/entities/src/EntityPsuedoPropertyFlags.h index ce8c1625fb..0b051a4c74 100644 --- a/libraries/entities/src/EntityPsuedoPropertyFlags.h +++ b/libraries/entities/src/EntityPsuedoPropertyFlags.h @@ -14,22 +14,28 @@ #ifndef hifi_EntityPsuedoPropertyFlag_h #define hifi_EntityPsuedoPropertyFlag_h -enum class EntityPsuedoPropertyFlag { - none = 0, - flagsActive = 1 << 0, - id = 1 << 1, - type = 1 << 2, - created = 1 << 3, - age = 1 << 4, - ageAsText = 1 << 5, - lastEdited = 1 << 6, - boundingBox = 1 << 7, - originalTextures = 1 << 8, - renderInfo = 1 << 9, - clientOnly = 1 << 10, - owningAvatarID = 1 << 11, - all = (1 << 12) - 1 -}; -Q_DECLARE_FLAGS(EntityPsuedoPropertyFlags, EntityPsuedoPropertyFlag) +#include +#include + +namespace EntityPsuedoPropertyFlag { + enum { + None = 0, + FlagsActive, + ID, + Type, + Created, + Age, + AgeAsText, + LastEdited, + BoundingBox, + OriginalTextures, + RenderInfo, + ClientOnly, + OwningAvatarID, + + NumFlags + }; +} +typedef std::bitset EntityPsuedoPropertyFlags; #endif // hifi_EntityPsuedoPropertyFlag_h diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 84fabccdb3..9fc7942473 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -427,51 +427,51 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri EntityPsuedoPropertyFlags psuedoPropertyFlags; const auto readExtendedPropertyStringValue = [&](QScriptValue extendedProperty) { const auto extendedPropertyString = extendedProperty.toString(); - if (extendedPropertyString == QString("id")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::id; - } else if (extendedPropertyString == QString("type")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::type; - } else if (extendedPropertyString == QString("created")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::created; - } else if (extendedPropertyString == QString("age")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::age; - } else if (extendedPropertyString == QString("ageAsText")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::ageAsText; - } else if (extendedPropertyString == QString("lastEdited")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::lastEdited; - } else if (extendedPropertyString == QString("boundingBox")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::boundingBox; - } else if (extendedPropertyString == QString("originalTextures")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::originalTextures; - } else if (extendedPropertyString == QString("renderInfo")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::renderInfo; - } else if (extendedPropertyString == QString("clientOnly")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::clientOnly; - } else if (extendedPropertyString == QString("owningAvatarID")) { - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::owningAvatarID; + if (extendedPropertyString == "id") { + 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") { + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::AgeAsText); + } else if (extendedPropertyString == "lastEdited") { + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::LastEdited); + } else if (extendedPropertyString == "boundingBox") { + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::BoundingBox); + } else if (extendedPropertyString == "originalTextures") { + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::OriginalTextures); + } else if (extendedPropertyString == "renderInfo") { + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::RenderInfo); + } else if (extendedPropertyString == "clientOnly") { + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::ClientOnly); + } else if (extendedPropertyString == "owningAvatarID") { + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::OwningAvatarID); } }; if (extendedDesiredProperties.isString()) { readExtendedPropertyStringValue(extendedDesiredProperties); - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::flagsActive; + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::FlagsActive); } else if (extendedDesiredProperties.isArray()) { const quint32 length = extendedDesiredProperties.property("length").toInt32(); for (quint32 i = 0; i < length; i++) { readExtendedPropertyStringValue(extendedDesiredProperties.property(i)); } - psuedoPropertyFlags |= EntityPsuedoPropertyFlag::flagsActive; + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::FlagsActive); } EntityPropertyFlags desiredProperties = qScriptValueToValue(extendedDesiredProperties); - bool needsScriptSymantics = desiredProperties.getHasProperty(PROP_POSITION) || + bool needsScriptSemantics = desiredProperties.getHasProperty(PROP_POSITION) || desiredProperties.getHasProperty(PROP_ROTATION) || desiredProperties.getHasProperty(PROP_LOCAL_POSITION) || desiredProperties.getHasProperty(PROP_LOCAL_ROTATION) || desiredProperties.getHasProperty(PROP_LOCAL_VELOCITY) || desiredProperties.getHasProperty(PROP_LOCAL_ANGULAR_VELOCITY) || desiredProperties.getHasProperty(PROP_LOCAL_DIMENSIONS); - if (needsScriptSymantics) { + if (needsScriptSemantics) { // if we are explicitly getting position or rotation, we need parent information to make sense of them. desiredProperties.setHasProperty(PROP_PARENT_ID); desiredProperties.setHasProperty(PROP_PARENT_JOINT_INDEX); @@ -488,7 +488,7 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri const auto& entityID = entityIDs.at(i); const EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(entityID)); if (entity) { - if (!psuedoPropertyFlags && desiredProperties.isEmpty()) { + if (psuedoPropertyFlags.none() && desiredProperties.isEmpty()) { // these are left out of EntityItem::getEntityProperties so that localPosition and localRotation // don't end up in json saves, etc. We still want them here, though. EncodeBitstreamParams params; // unknown @@ -498,8 +498,8 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri desiredProperties.setHasProperty(PROP_LOCAL_VELOCITY); desiredProperties.setHasProperty(PROP_LOCAL_ANGULAR_VELOCITY); desiredProperties.setHasProperty(PROP_LOCAL_DIMENSIONS); - psuedoPropertyFlags = EntityPsuedoPropertyFlag::all; - needsScriptSymantics = true; + psuedoPropertyFlags.set(); + needsScriptSemantics = true; } auto properties = entity->getProperties(desiredProperties, true); @@ -512,18 +512,16 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri } QScriptValue finalResult = engine->newArray(resultProperties.size()); quint32 i = 0; - { - if (needsScriptSymantics) { - PROFILE_RANGE(script_entities, "EntityScriptingInterface::getMultipleEntityProperties>Script Semantics"); - foreach(auto result, resultProperties) { - finalResult.setProperty(i++, convertPropertiesToScriptSemantics(result.properties, result.scalesWithParent) - .copyToScriptValue(engine, false, false, false, psuedoPropertyFlags)); - } - } else { - PROFILE_RANGE(script_entities, "EntityScriptingInterface::getMultipleEntityProperties>Skip Script Semantics"); - foreach(auto result, resultProperties) { - finalResult.setProperty(i++, result.properties.copyToScriptValue(engine, false, false, false, psuedoPropertyFlags)); - } + if (needsScriptSemantics) { + PROFILE_RANGE(script_entities, "EntityScriptingInterface::getMultipleEntityProperties>Script Semantics"); + foreach(const auto& result, resultProperties) { + finalResult.setProperty(i++, convertPropertiesToScriptSemantics(result.properties, result.scalesWithParent) + .copyToScriptValue(engine, false, false, false, psuedoPropertyFlags)); + } + } else { + PROFILE_RANGE(script_entities, "EntityScriptingInterface::getMultipleEntityProperties>Skip Script Semantics"); + foreach(const auto& result, resultProperties) { + finalResult.setProperty(i++, result.properties.copyToScriptValue(engine, false, false, false, psuedoPropertyFlags)); } } return finalResult; From e266e2ebbfb4e48d4c1874fe0262ec787283cda8 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 29 Sep 2018 02:44:11 +0200 Subject: [PATCH 7/8] filter getEntity(Multiple)Properties entities unitTest --- .../tests/unit_tests/entityUnitTests.js | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/scripts/developer/tests/unit_tests/entityUnitTests.js b/scripts/developer/tests/unit_tests/entityUnitTests.js index f2c4b4871f..578f2fb75a 100644 --- a/scripts/developer/tests/unit_tests/entityUnitTests.js +++ b/scripts/developer/tests/unit_tests/entityUnitTests.js @@ -72,4 +72,49 @@ describe('Entity', function() { props = Entities.getEntityProperties(boxEntity); expect(props.lastEdited).toBeGreaterThan(prevLastEdited); }); + + it("filtering getEntityProperties seems to work correctly", function() { + var properties = Entities.getEntityProperties(boxEntity, 'position'); + expect(properties.id).toBe(boxEntity); + expect(properties.type).toBe(boxProps.type); + expect(properties.position).toBeDefined(); + }); + + it("filtering getMultipleEntityProperties seems to work correctly", function () { + var sphereProps = { + type: 'Sphere', + color: { + red: 255, + green: 255, + blue: 255, + }, + position: center, + dimensions: { + x: 1, + y: 1, + z: 1, + }, + }; + var sphereEntity = Entities.addEntity(sphereProps); + + var entityIDs = [boxEntity, sphereEntity]; + var filterTypes = 'type'; + var propertySets = Entities.getMultipleEntityProperties(entityIDs, filterTypes); + expect(propertySets.length).toBe(entityIDs.length); + expect(propertySets[0].type).toBe(boxProps.type); + expect(Object.keys(propertySets[0]).length).toBe(1); + expect(propertySets[1].type).toBe(sphereProps.type); + expect(Object.keys(propertySets[1]).length).toBe(1); + + filterTypes = ['id', 'type']; + propertySets = Entities.getMultipleEntityProperties(entityIDs, filterTypes); + expect(propertySets.length).toBe(entityIDs.length); + expect(Object.keys(propertySets[0]).length).toBe(filterTypes.length); + expect(propertySets[0].type).toBe(boxProps.type); + expect(Object.keys(propertySets[1]).length).toBe(filterTypes.length); + expect(propertySets[1].type).toBe(sphereProps.type); + + Entities.deleteEntity(sphereEntity); + }); + }); From eeda7400c99b1c61472e06d9642ae93b1878e361 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 1 Oct 2018 19:36:53 +0200 Subject: [PATCH 8/8] check if id matches in filtered getMultipleEntityProperties --- scripts/developer/tests/unit_tests/entityUnitTests.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/developer/tests/unit_tests/entityUnitTests.js b/scripts/developer/tests/unit_tests/entityUnitTests.js index 578f2fb75a..004cf48fe5 100644 --- a/scripts/developer/tests/unit_tests/entityUnitTests.js +++ b/scripts/developer/tests/unit_tests/entityUnitTests.js @@ -110,8 +110,10 @@ describe('Entity', function() { propertySets = Entities.getMultipleEntityProperties(entityIDs, filterTypes); expect(propertySets.length).toBe(entityIDs.length); expect(Object.keys(propertySets[0]).length).toBe(filterTypes.length); + expect(propertySets[0].id).toBe(boxEntity); expect(propertySets[0].type).toBe(boxProps.type); expect(Object.keys(propertySets[1]).length).toBe(filterTypes.length); + expect(propertySets[1].id).toBe(sphereEntity); expect(propertySets[1].type).toBe(sphereProps.type); Entities.deleteEntity(sphereEntity);