Merge pull request #14042 from thoys/perf/create/getMultipleEntities

Speed up Entity List properties fetching by adding Entities.getMultipleEntities API
This commit is contained in:
Brad Hefta-Gaub 2018-10-01 16:16:48 -07:00 committed by GitHub
commit edd5db7768
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 345 additions and 83 deletions

View file

@ -250,8 +250,8 @@ void RenderableModelEntityItem::updateModelBounds() {
} }
EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties RenderableModelEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
EntityItemProperties properties = ModelEntityItem::getProperties(desiredProperties); // get the properties from our base class EntityItemProperties properties = ModelEntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
if (_originalTexturesRead) { if (_originalTexturesRead) {
properties.setTextureNames(_originalTextures); properties.setTextureNames(_originalTextures);
} }

View file

@ -62,7 +62,7 @@ public:
virtual void setUnscaledDimensions(const glm::vec3& value) override; 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 doInitialModelSimulation();
void updateModelBounds(); void updateModelBounds();

View file

@ -1251,9 +1251,10 @@ quint64 EntityItem::getExpiry() const {
return getCreated() + (quint64)(getLifetime() * (float)USECS_PER_SECOND); 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 EncodeBitstreamParams params; // unknown
EntityPropertyFlags propertyFlags = desiredProperties.isEmpty() ? getEntityProperties(params) : desiredProperties; const EntityPropertyFlags propertyFlags = !allowEmptyDesiredProperties && desiredProperties.isEmpty() ?
getEntityProperties(params) : desiredProperties;
EntityItemProperties properties(propertyFlags); EntityItemProperties properties(propertyFlags);
properties._id = getID(); properties._id = getID();
properties._idSet = true; properties._idSet = true;

View file

@ -88,7 +88,7 @@ public:
EntityItemID getEntityItemID() const { return EntityItemID(_id); } EntityItemID getEntityItemID() const { return EntityItemID(_id); }
// methods for getting/setting all properties of an entity // 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 /// returns true if something changed
// This function calls setSubClass properties and detects if any property changes value. // This function calls setSubClass properties and detects if any property changes value.

View file

@ -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 // 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. // is included in _desiredProperties, or is one of the specially enumerated ALWAYS properties below.
// (There may be exceptions, but if so, they are bugs.) // (There may be exceptions, but if so, they are bugs.)
@ -1224,26 +1226,39 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
QScriptValue properties = engine->newObject(); QScriptValue properties = engine->newObject();
EntityItemProperties defaultEntityProperties; EntityItemProperties defaultEntityProperties;
const bool psuedoPropertyFlagsActive = psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::FlagsActive);
// Fix to skip the default return all mechanism, when psuedoPropertyFlagsActive
const bool psuedoPropertyFlagsButDesiredEmpty = psuedoPropertyFlagsActive && _desiredProperties.isEmpty();
if (_created == UNKNOWN_CREATED_TIME && !allowUnknownCreateTime) { if (_created == UNKNOWN_CREATED_TIME && !allowUnknownCreateTime) {
// No entity properties can have been set so return without setting any default, zero property values. // No entity properties can have been set so return without setting any default, zero property values.
return properties; return properties;
} }
if (_idSet) { if (_idSet && (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::ID))) {
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(id, _id.toString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(id, _id.toString());
} }
if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::Type)) {
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(type, EntityTypes::getEntityTypeName(_type)); 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); if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::Created)) {
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(created, created.toString(Qt::ISODate)); auto created = QDateTime::fromMSecsSinceEpoch(getCreated() / 1000.0f, Qt::UTC); // usec per msec
created.setTimeSpec(Qt::OffsetFromUTC);
if ((!skipDefaults || _lifetime != defaultEntityProperties._lifetime) && !strictSemantics) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(created, created.toString(Qt::ISODate));
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
} }
properties.setProperty("lastEdited", convertScriptValue(engine, _lastEdited)); 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
}
if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::AgeAsText)) {
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable
}
}
if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::LastEdited)) {
properties.setProperty("lastEdited", convertScriptValue(engine, _lastEdited));
}
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LAST_EDITED_BY, lastEditedBy); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LAST_EDITED_BY, lastEditedBy);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POSITION, position); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_POSITION, position);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DIMENSIONS, dimensions); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_DIMENSIONS, dimensions);
@ -1340,7 +1355,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
// Models only // Models only
if (_type == EntityTypes::Model) { if (_type == EntityTypes::Model) {
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MODEL_URL, modelURL); 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_SET, jointRotationsSet);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS, jointRotations); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS, jointRotations);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS_SET, jointTranslationsSet); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS_SET, jointTranslationsSet);
@ -1393,21 +1410,24 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
// Zones only // Zones only
if (_type == EntityTypes::Zone) { if (_type == EntityTypes::Zone) {
_keyLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); if (!psuedoPropertyFlagsButDesiredEmpty) {
_ambientLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); _keyLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
_ambientLight.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
_skybox.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_FLYING_ALLOWED, flyingAllowed);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GHOSTING_ALLOWED, ghostingAllowed); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GHOSTING_ALLOWED, ghostingAllowed);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FILTER_URL, filterURL); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FILTER_URL, filterURL);
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_HAZE_MODE, hazeMode, getHazeModeAsString()); 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()); 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_KEY_LIGHT_MODE, keyLightMode, getKeyLightModeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_LIGHT_MODE, ambientLightMode, getAmbientLightModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_AMBIENT_LIGHT_MODE, ambientLightMode, getAmbientLightModeAsString());
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SKYBOX_MODE, skyboxMode, getSkyboxModeAsString()); 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} center - The center of the AA box.
* @property {Vec3} dimensions - The dimensions of the AA box. * @property {Vec3} dimensions - The dimensions of the AA box.
*/ */
if (!skipDefaults && !strictSemantics) { if (!skipDefaults && !strictSemantics &&
(!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::BoundingBox))) {
AABox aaBox = getAABox(); AABox aaBox = getAABox();
QScriptValue boundingBox = engine->newObject(); QScriptValue boundingBox = engine->newObject();
QScriptValue bottomRightNear = vec3toScriptValue(engine, aaBox.getCorner()); QScriptValue bottomRightNear = vec3toScriptValue(engine, aaBox.getCorner());
@ -1483,7 +1505,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
} }
QString textureNamesStr = QJsonDocument::fromVariant(_textureNames).toJson(); QString textureNamesStr = QJsonDocument::fromVariant(_textureNames).toJson();
if (!skipDefaults && !strictSemantics) { if (!skipDefaults && !strictSemantics && (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::OriginalTextures))) {
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesStr); // gettable, but not settable 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); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONE_ORIGIN_ID, cloneOriginID);
// Rendering info // Rendering info
if (!skipDefaults && !strictSemantics) { if (!skipDefaults && !strictSemantics &&
(!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::RenderInfo))) {
QScriptValue renderInfo = engine->newObject(); QScriptValue renderInfo = engine->newObject();
/**jsdoc /**jsdoc
@ -1535,8 +1559,12 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
} }
// FIXME: These properties should already have been set above. // FIXME: These properties should already have been set above.
properties.setProperty("clientOnly", convertScriptValue(engine, getClientOnly())); if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::ClientOnly)) {
properties.setProperty("owningAvatarID", convertScriptValue(engine, getOwningAvatarID())); properties.setProperty("clientOnly", convertScriptValue(engine, getClientOnly()));
}
if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::OwningAvatarID)) {
properties.setProperty("owningAvatarID", convertScriptValue(engine, getOwningAvatarID()));
}
// FIXME - I don't think these properties are supported any more // FIXME - I don't think these properties are supported any more
//COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha); //COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha);

View file

@ -35,6 +35,7 @@
#include "EntityItemPropertiesMacros.h" #include "EntityItemPropertiesMacros.h"
#include "EntityTypes.h" #include "EntityTypes.h"
#include "EntityPropertyFlags.h" #include "EntityPropertyFlags.h"
#include "EntityPsuedoPropertyFlags.h"
#include "LightEntityItem.h" #include "LightEntityItem.h"
#include "LineEntityItem.h" #include "LineEntityItem.h"
#include "ParticleEffectEntityItem.h" #include "ParticleEffectEntityItem.h"
@ -86,7 +87,8 @@ public:
EntityTypes::EntityType getType() const { return _type; } EntityTypes::EntityType getType() const { return _type; }
void setType(EntityTypes::EntityType type) { _type = 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); virtual void copyFromScriptValue(const QScriptValue& object, bool honorReadOnly);
static QScriptValue entityPropertyFlagsToScriptValue(QScriptEngine* engine, const EntityPropertyFlags& flags); static QScriptValue entityPropertyFlagsToScriptValue(QScriptEngine* engine, const EntityPropertyFlags& flags);

View file

@ -155,7 +155,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { retu
} }
#define COPY_PROPERTY_TO_QSCRIPTVALUE(p,P) \ #define COPY_PROPERTY_TO_QSCRIPTVALUE(p,P) \
if ((_desiredProperties.isEmpty() || _desiredProperties.getHasProperty(p)) && \ if (((!psuedoPropertyFlagsButDesiredEmpty && _desiredProperties.isEmpty()) || _desiredProperties.getHasProperty(p)) && \
(!skipDefaults || defaultEntityProperties._##P != _##P)) { \ (!skipDefaults || defaultEntityProperties._##P != _##P)) { \
QScriptValue V = convertScriptValue(engine, _##P); \ QScriptValue V = convertScriptValue(engine, _##P); \
properties.setProperty(#P, V); \ properties.setProperty(#P, V); \
@ -165,7 +165,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { retu
properties.setProperty(#P, G); properties.setProperty(#P, G);
#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(p, 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)) { \ (!skipDefaults || defaultEntityProperties._##P != _##P)) { \
QScriptValue V = convertScriptValue(engine, G); \ QScriptValue V = convertScriptValue(engine, G); \
properties.setProperty(#P, V); \ 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 // 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) \ #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)) { \ (!skipDefaults || defaultEntityProperties._##P != _##P)) { \
QScriptValue V = convertScriptValue(engine, G); \ QScriptValue V = convertScriptValue(engine, G); \
properties.setProperty(#X, V); \ properties.setProperty(#X, V); \

View file

@ -0,0 +1,41 @@
//
// 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
#include <bitset>
#include <type_traits>
namespace EntityPsuedoPropertyFlag {
enum {
None = 0,
FlagsActive,
ID,
Type,
Created,
Age,
AgeAsText,
LastEdited,
BoundingBox,
OriginalTextures,
RenderInfo,
ClientOnly,
OwningAvatarID,
NumFlags
};
}
typedef std::bitset<EntityPsuedoPropertyFlag::NumFlags> EntityPsuedoPropertyFlags;
#endif // hifi_EntityPsuedoPropertyFlag_h

View file

@ -42,7 +42,7 @@ const QString GRABBABLE_USER_DATA = "{\"grabbableKey\":{\"grabbable\":true}}";
const QString NOT_GRABBABLE_USER_DATA = "{\"grabbableKey\":{\"grabbable\":false}}"; const QString NOT_GRABBABLE_USER_DATA = "{\"grabbableKey\":{\"grabbable\":false}}";
EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership) : EntityScriptingInterface::EntityScriptingInterface(bool bidOnSimulationOwnership) :
_entityTree(NULL), _entityTree(nullptr),
_bidOnSimulationOwnership(bidOnSimulationOwnership) _bidOnSimulationOwnership(bidOnSimulationOwnership)
{ {
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
@ -350,19 +350,19 @@ QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) {
} }
} }
EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity) { EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid entityID) {
EntityPropertyFlags noSpecificProperties; const EntityPropertyFlags noSpecificProperties;
return getEntityProperties(identity, noSpecificProperties); return getEntityProperties(entityID, noSpecificProperties);
} }
EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties) { EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid entityID, EntityPropertyFlags desiredProperties) {
PROFILE_RANGE(script_entities, __FUNCTION__); PROFILE_RANGE(script_entities, __FUNCTION__);
bool scalesWithParent { false }; bool scalesWithParent { false };
EntityItemProperties results; EntityItemProperties results;
if (_entityTree) { if (_entityTree) {
_entityTree->withReadLock([&] { _entityTree->withReadLock([&] {
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity)); EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(entityID));
if (entity) { if (entity) {
scalesWithParent = entity->getScalesWithParent(); scalesWithParent = entity->getScalesWithParent();
if (desiredProperties.getHasProperty(PROP_POSITION) || if (desiredProperties.getHasProperty(PROP_POSITION) ||
@ -397,6 +397,134 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit
return convertPropertiesToScriptSemantics(results, scalesWithParent); 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<EntityScriptingInterface>();
const auto entityIDs = qScriptValueToValue<QVector<QUuid>>(context->argument(ARGUMENT_ENTITY_IDS));
return entityScriptingInterface->getMultipleEntityPropertiesInternal(engine, entityIDs, context->argument(ARGUMENT_EXTENDED_DESIRED_PROPERTIES));
}
QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScriptEngine* engine, QVector<QUuid> entityIDs, const QScriptValue& extendedDesiredProperties) {
PROFILE_RANGE(script_entities, __FUNCTION__);
EntityPsuedoPropertyFlags psuedoPropertyFlags;
const auto readExtendedPropertyStringValue = [&](QScriptValue extendedProperty) {
const auto extendedPropertyString = extendedProperty.toString();
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.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.set(EntityPsuedoPropertyFlag::FlagsActive);
}
EntityPropertyFlags desiredProperties = qScriptValueToValue<EntityPropertyFlags>(extendedDesiredProperties);
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 (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);
}
QVector<EntityPropertiesResult> 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.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
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.set();
needsScriptSemantics = 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 (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;
}
QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) { QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) {
PROFILE_RANGE(script_entities, __FUNCTION__); PROFILE_RANGE(script_entities, __FUNCTION__);

View file

@ -149,6 +149,21 @@ public:
const QVector<EntityItemID>& entityIdsToInclude, const QVector<EntityItemID>& entityIdsToDiscard, const QVector<EntityItemID>& entityIdsToInclude, const QVector<EntityItemID>& entityIdsToDiscard,
bool visibleOnly, bool collidableOnly); 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 <caption>Retrieve the names of the nearby entities</caption>
* 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<QUuid> entityIDs, const QScriptValue& extendedDesiredProperties);
public slots: public slots:
/**jsdoc /**jsdoc
@ -270,7 +285,7 @@ public slots:
* print("Entity color: " + JSON.stringify(properties.color)); * print("Entity color: " + JSON.stringify(properties.color));
*/ */
Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID); Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID);
Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties); Q_INVOKABLE EntityItemProperties getEntityProperties(QUuid entityID, EntityPropertyFlags desiredProperties);
/**jsdoc /**jsdoc
* Update an entity with specified properties. * Update an entity with specified properties.

View file

@ -13,7 +13,6 @@
#define hifi_EntityTypes_h #define hifi_EntityTypes_h
#include <memory> #include <memory>
#include <stdint.h>
#include <QHash> #include <QHash>
#include <QString> #include <QString>

View file

@ -69,8 +69,8 @@ void LightEntityItem::dimensionsChanged() {
} }
EntityItemProperties LightEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties LightEntityItem::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
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isSpotlight, getIsSpotlight); COPY_ENTITY_PROPERTY_TO_PROPERTIES(isSpotlight, getIsSpotlight);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);

View file

@ -35,7 +35,7 @@ public:
virtual bool setSubClassProperties(const EntityItemProperties& properties) override; virtual bool setSubClassProperties(const EntityItemProperties& properties) override;
// methods for getting/setting all properties of an entity // 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; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -37,9 +37,9 @@ LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) :
_type = EntityTypes::Line; _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(); properties._color = getXColor();

View file

@ -23,7 +23,7 @@ class LineEntityItem : public EntityItem {
ALLOW_INSTANTIATION // This class can be instantiated ALLOW_INSTANTIATION // This class can be instantiated
// methods for getting/setting all properties of an entity // 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 setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -31,8 +31,8 @@ MaterialEntityItem::~MaterialEntityItem() {
removeMaterial(); removeMaterial();
} }
EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties MaterialEntityItem::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
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingMode, getMaterialMappingMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingMode, getMaterialMappingMode);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(priority, getPriority); COPY_ENTITY_PROPERTY_TO_PROPERTIES(priority, getPriority);

View file

@ -29,7 +29,7 @@ public:
bool needsToCallUpdate() const override { return true; } bool needsToCallUpdate() const override { return true; }
// methods for getting/setting all properties of an entity // 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 setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -54,8 +54,8 @@ void ModelEntityItem::setTextures(const QString& textures) {
_textures = textures; _textures = textures;
} }
EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties ModelEntityItem::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
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);

View file

@ -27,7 +27,7 @@ public:
ALLOW_INSTANTIATION // This class can be instantiated ALLOW_INSTANTIATION // This class can be instantiated
// methods for getting/setting all properties of an entity // 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 setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -408,8 +408,8 @@ void ParticleEffectEntityItem::computeAndUpdateDimensions() {
} }
EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties ParticleEffectEntityItem::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
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);

View file

@ -210,7 +210,7 @@ public:
ParticleEffectEntityItem(const EntityItemID& entityItemID); ParticleEffectEntityItem(const EntityItemID& entityItemID);
// methods for getting/setting all properties of this entity // 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 bool setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -36,9 +36,9 @@ PolyLineEntityItem::PolyLineEntityItem(const EntityItemID& entityItemID) : Entit
_type = EntityTypes::PolyLine; _type = EntityTypes::PolyLine;
} }
EntityItemProperties PolyLineEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties PolyLineEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
QWriteLocker lock(&_quadReadWriteLock); 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(); properties._color = getXColor();

View file

@ -23,7 +23,7 @@ class PolyLineEntityItem : public EntityItem {
ALLOW_INSTANTIATION // This class can be instantiated ALLOW_INSTANTIATION // This class can be instantiated
// methods for getting/setting all properties of an entity // 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 setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -113,8 +113,8 @@ glm::vec3 PolyVoxEntityItem::getVoxelVolumeSize() const {
} }
EntityItemProperties PolyVoxEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties PolyVoxEntityItem::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
COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelVolumeSize, getVoxelVolumeSize); COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelVolumeSize, getVoxelVolumeSize);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelData, getVoxelData); COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelData, getVoxelData);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelSurfaceStyle, getVoxelSurfaceStyle); COPY_ENTITY_PROPERTY_TO_PROPERTIES(voxelSurfaceStyle, getVoxelSurfaceStyle);

View file

@ -23,7 +23,7 @@ class PolyVoxEntityItem : public EntityItem {
ALLOW_INSTANTIATION // This class can be instantiated ALLOW_INSTANTIATION // This class can be instantiated
// methods for getting/setting all properties of an entity // 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 setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -115,8 +115,8 @@ ShapeEntityItem::ShapeEntityItem(const EntityItemID& entityItemID) : EntityItem(
_material = std::make_shared<graphics::Material>(); _material = std::make_shared<graphics::Material>();
} }
EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties ShapeEntityItem::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.setShape(entity::stringFromShape(getShape())); properties.setShape(entity::stringFromShape(getShape()));
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);

View file

@ -52,7 +52,7 @@ public:
//ALLOW_INSTANTIATION //ALLOW_INSTANTIATION
// methods for getting/setting all properties of an entity // 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; bool setProperties(const EntityItemProperties& properties) override;
EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -46,8 +46,8 @@ void TextEntityItem::setUnscaledDimensions(const glm::vec3& value) {
EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH)); EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH));
} }
EntityItemProperties TextEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties TextEntityItem::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
COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText); COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight);

View file

@ -27,7 +27,7 @@ public:
virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; } virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; }
// methods for getting/setting all properties of an entity // 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 setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -41,8 +41,8 @@ void WebEntityItem::setUnscaledDimensions(const glm::vec3& value) {
EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH)); EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH));
} }
EntityItemProperties WebEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties WebEntityItem::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
COPY_ENTITY_PROPERTY_TO_PROPERTIES(sourceUrl, getSourceUrl); COPY_ENTITY_PROPERTY_TO_PROPERTIES(sourceUrl, getSourceUrl);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(dpi, getDPI); COPY_ENTITY_PROPERTY_TO_PROPERTIES(dpi, getDPI);
return properties; return properties;

View file

@ -26,7 +26,7 @@ public:
virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; } virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; }
// methods for getting/setting all properties of an entity // 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 setProperties(const EntityItemProperties& properties) override;
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;

View file

@ -45,8 +45,8 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID) : EntityItem(en
_visuallyReady = false; _visuallyReady = false;
} }
EntityItemProperties ZoneEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties ZoneEntityItem::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
// Contain QString properties, must be synchronized // Contain QString properties, must be synchronized
withReadLock([&] { withReadLock([&] {

View file

@ -30,7 +30,7 @@ public:
ALLOW_INSTANTIATION // This class can be instantiated ALLOW_INSTANTIATION // This class can be instantiated
// methods for getting/setting all properties of an entity // 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 setProperties(const EntityItemProperties& properties) override;
virtual bool setSubClassProperties(const EntityItemProperties& properties) override; virtual bool setSubClassProperties(const EntityItemProperties& properties) override;

View file

@ -721,6 +721,7 @@ void ScriptEngine::init() {
registerGlobalObject("Midi", DependencyManager::get<Midi>().data()); registerGlobalObject("Midi", DependencyManager::get<Midi>().data());
registerGlobalObject("Entities", entityScriptingInterface.data()); registerGlobalObject("Entities", entityScriptingInterface.data());
registerFunction("Entities", "getMultipleEntityProperties", EntityScriptingInterface::getMultipleEntityProperties);
registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Quat", &_quatLibrary);
registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Vec3", &_vec3Library);
registerGlobalObject("Mat4", &_mat4Library); registerGlobalObject("Mat4", &_mat4Library);

View file

@ -72,4 +72,51 @@ describe('Entity', function() {
props = Entities.getEntityProperties(boxEntity); props = Entities.getEntityProperties(boxEntity);
expect(props.lastEdited).toBeGreaterThan(prevLastEdited); 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].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);
});
}); });

View file

@ -150,11 +150,11 @@ EntityListTool = function(shouldUseEditTabletApp) {
}); });
var cameraPosition = Camera.position; var cameraPosition = Camera.position;
PROFILE("getProperties", function() { PROFILE("getMultipleProperties", function () {
for (var i = 0; i < ids.length; i++) { var multipleProperties = Entities.getMultipleEntityProperties(ids, ['name', 'type', 'locked',
var id = ids[i]; 'visible', 'renderInfo', 'modelURL', 'materialURL', 'script']);
var properties = Entities.getEntityProperties(id, ['name', 'type', 'locked', for (var i = 0; i < multipleProperties.length; i++) {
'visible', 'renderInfo', 'type', 'modelURL', 'materialURL', 'script']); var properties = multipleProperties[i];
if (!filterInView || Vec3.distance(properties.position, cameraPosition) <= searchRadius) { if (!filterInView || Vec3.distance(properties.position, cameraPosition) <= searchRadius) {
var url = ""; var url = "";
@ -164,7 +164,7 @@ EntityListTool = function(shouldUseEditTabletApp) {
url = properties.materialURL; url = properties.materialURL;
} }
entities.push({ entities.push({
id: id, id: ids[i],
name: properties.name, name: properties.name,
type: properties.type, type: properties.type,
url: url, url: url,